为什么我的子资源不匹配?

时间:2014-03-13 03:01:11

标签: java java-ee jax-rs resteasy wildfly

我无法使用子资源,这是我的错误

WARN  [org.jboss.resteasy.core.ExceptionHandler] (default task-1) failed to execute: javax.ws.rs.NotFoundException: Could not find resource for full path: http://127.0.0.1:8080/NornLM/individuals/f86e3400-5f56-4b28-af44-69a2ccfd908e/activities/a9da4e17-2ca4-4c02-a9ff-71638a92c318

以及一些其他有趣的日志数据

DEBUG [org.jboss.weld.Conversation] WELD-000327: Resuming conversation with id null
DEBUG [org.jboss.resteasy.core.SynchronousDispatcher] PathInfo: /individuals/cce937d3-7982-407b-ae64-909bf3710f4e/activities/d3bb56d5-610c-4c88-8688-a913ba1bdf01
DEBUG [org.jboss.resteasy.cdi.CdiConstructorInjector] Beans found for class com.lm.activity.rest.IndividualsCtrlr : [Managed Bean [class com.lm.activity.rest.IndividualsCtrlr] with qualifiers [@Any @Default]]
DEBUG [com.lm.activity.rest.IndividualsCtrlr] Individual Activities
DEBUG [org.jboss.resteasy.cdi.CdiInjectorFactory] Using CdiConstructorInjector for class class com.lm.activity.rest.ActivitiesCtrlr.
DEBUG [org.jboss.resteasy.cdi.CdiConstructorInjector] Beans found for class com.lm.activity.rest.ActivitiesCtrlr : [Managed Bean [class com.lm.activity.rest.ActivitiesCtrlr] with qualifiers [@Any @Default]]

这是我的基础资源

package com.lm.activity.rest;

import com.lm.activity.IndividualBuilder;
import com.lm.infrastructure.Regex;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.container.ResourceContext;
import javax.ws.rs.core.Context;
import org.slf4j.Logger;

@RequestScoped
@Path( "/individuals" )
public class IndividualsCtrlr {

    @Path( "{individual:" + Regex.UUID + "}" )
    public ActivitiesCtrlr activities(
          @PathParam( "individual" ) IndividualBuilder ib
    ) {
        log.debug( "Individual Activities" );
        ActivitiesCtrlr ctrl
              = resourceContext.getResource( ActivitiesCtrlr.class );

        ctrl.setIndividual( ib.build() );

        return ctrl;
    }

    @Context
    ResourceContext resourceContext;

    @Inject
    Logger log;
}

这是我的ActivtiesCtrlr

package com.lm.activity.rest;

import com.lm.activity.ActivitiesRepo;
import com.lm.activity.Activity;
import com.lm.activity.BuilderActivityPermaURI;
import com.lm.activity.DTOActivity;
import com.lm.activity.Individual;
import com.lm.infrastructure.Regex;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.slf4j.Logger;

// I've tried removing Path/RequestScoped from this and moving it to the base resource
@Path( "activities" )
@RequestScoped
@Produces( MediaType.APPLICATION_JSON )
@Consumes( MediaType.APPLICATION_JSON )
public class ActivitiesCtrlr {

    @GET
    @Path( "current" )
    public Response current(
          @Context final UriInfo uriInfo
    ) {
        final Activity current = repo.getActivityInventory( individual )
              .toDo( LocalDate.now() )
              .current();

        final BuilderActivityPermaURI uriBuilder
              = new BuilderActivityPermaURI( uriInfo.getBaseUriBuilder() );

        uriBuilder.fromActivity( current );

        responseBuilder = Response.temporaryRedirect( uriBuilder.build() );

        return responseBuilder.build();
    }

    @GET
    @Path( "{activity:" + Regex.UUID + "}" )
    public Response get(
          @PathParam( "activity" ) final UUID activityId
    ) {
        try {
            final Activity current
                  = repo.getActivityInventory( individual )
                  .toDo( LocalDate.now() )
                  .current();

            responseBuilder = Response.ok( current.toDTO() );
        }
        catch ( Exception e ) {
            log.warn( "GET: ", e );
        }


        return responseBuilder.build();
    }

    @PUT
    @Path( "{activity:" + Regex.UUID + "}" )
    public Response putActivity(
        @Context final UriInfo uri,
        @PathParam( "activity" ) final UUID activityId,
        final DTOActivity dtoa
    ) {
        final Activity activity
              = repo
              .instanceFromDTO( dtoa )
              .associateId( activityId )
              .setIndividual( individual )
              .build();

        try {
            if ( repo.add( activity ) ) {
                responseBuilder
                      = Response.created( uri.getAbsolutePath() )
                    .entity( activity.toDTO() );
            }
            else {
                responseBuilder = Response.ok( activity.toDTO() );
            }
        }
        catch ( Exception e ) {
            log.error( "add to repository error: {}", e );
            responseBuilder = Response.serverError();
        }

        return responseBuilder.build();
    }

    void setIndividual( final Individual individual ) {
        Objects.requireNonNull( individual );
        this.individual = individual;
    }

    Individual individual;

    Response.ResponseBuilder responseBuilder;

    @Inject
    ActivitiesRepo repo;

    @Inject
    Logger log;
}

我使用此代码构建请求uri,baseResourcesubResource是相应的类。

URI uri = UriBuilder
        .fromUri( deploymentURI )
        .path( baseResource )
        .path( baseResource, "activities" )
        .path( subResource )
        .path( subResource, "putActivity" )
        .build( randomUUID(), randomUUID() );

我还确认,如果我将@Path类的ActivitiesCtrlr更改为以下内容,则会匹配该路线。这证实了Regex.UUID

没有问题
@Path( "/individuals/{individual:" + Regex.UUID + "}/activities" )

虽然只是为了确定

package com.lm.infrastructure;

public class Regex {
    public static final String UUID
          = "[\\p{XDigit}]{8}"
          + "(-[\\p{XDigit}]{4}){3}"
          + "-[\\p{XDigit}]{12}";
}

这是实际提交的http

PUT /NornLM/individuals/e672cd0c-729d-4128-a118-aaf7fd8675d7/activities/251453ff-12d1-4a38-8b5a-00bf2557584b HTTP/1.1
Content-Length: 57
Content-Type: application/json; charset=UTF-8
Host: 127.0.0.1:8080
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.3.2 (java 1.5)
Accept-Encoding: gzip,deflate

{"completed":false,"created":null,"description":"testme"}

我做错了什么?

1 个答案:

答案 0 :(得分:0)

您的ActivitiesCtrlr类是JAX-RS根资源,而不是子资源。您是否可以尝试删除此类中的@Path注释,并将@Path上的ActivitiesCtrlr#get()注释更改为以下内容:

@GET
@Path( "/activities/{activity:" + Regex.UUID + "}" )
public Response get(
      @PathParam( "activity" ) final UUID activityId
) { 
  ... 
}

我希望它能奏效。