我无法使用子资源,这是我的错误
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,baseResource
和subResource
是相应的类。
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"}
我做错了什么?
答案 0 :(得分:0)
您的ActivitiesCtrlr
类是JAX-RS根资源,而不是子资源。您是否可以尝试删除此类中的@Path
注释,并将@Path
上的ActivitiesCtrlr#get()
注释更改为以下内容:
@GET
@Path( "/activities/{activity:" + Regex.UUID + "}" )
public Response get(
@PathParam( "activity" ) final UUID activityId
) {
...
}
我希望它能奏效。