4
votes

I am a complete beginner who is learning to build a RESTful web service. I would like to know how to set the path for sub resource within sub resource in JAX-RS.

I have three resources: profile, message and comment. I would like my URLs to be as follows.

For profiles

 /profiles

For Messages

/profiles/{profileName}/messages

For Comments

/profiles/{profileName}/messages/{messageId}/comments

My resources have paths as follows.

Profile Resource

@Path("/profiles")
public class ProfileResource {

    @Path("/{profileName}/messages")
    public MessageResource getMessageResource() {
        return new MessageResource();
    }

}

Message Resource

@Path("/")
public class MessageResource {
    @Path("/{messageId}/comments")
    public CommentResource getCommentResource() {
        return new CommentResource();
    }

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public Message addMessage(@PathParam("profileName") String profileName, Message message){
        return messageService.addMessage(profileName, message);
    }   
}

Comment Resource

@Path("/")
public class CommentResource {

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Comment postComment(@PathParam("messageId") long messageId, Comment comment) {
         return commentService.addComment(messageId, comment);
    }

}

But I get the following error,

SEVERE: Servlet [Jersey Web Application] in web application [/messenger] threw 
load() exception org.glassfish.jersey.server.model.ModelValidationException: 
Validation of the  application resource model has failed during application 
initialization.
[[FATAL] A resource model has ambiguous (sub-)resource method for HTTP method POST
  and input mime-types as defined by"@Consumes" and "@Produces" annotations at 
Java  methods public sokkalingam.restapi.messenger.model.Message 
sokkalingam.restapi.messenger.resources.MessageResource.addMessage(java.lang.Strin
 g,sokkalingam.restapi.messenger.model.Message) and public 
sokkalingam.restapi.messenger.model.Comment 
sokkalingam.restapi.messenger.resources.CommentResource.postComment(long,sokkaling
 am.restapi.messenger.model.Comment) at matching regular expression /. These two 
 methods produces and consumes exactly the same mime-types and therefore their 
 invocation as a resource methods will always fail.;

Questions:

  1. How should I set my paths for my sub resources?

  2. What is a better way to do sub resource within sub resource? Is it common to do sub-resource within sub-resource?

1

1 Answers

3
votes

How should I set my paths for my sub resources?

Get rid of the @Path on the Sub-resource classes. When the class is annotated with path, it is being added as root resource to the Jersey app. So you have a bunch of resources mapped to /, which is giving the error, as there are multiple @POST (with same @Consumes and @Produces) mapped to the same path

With sub-resource classes, you don't need the @Path. It will be ignored, as far as the sub-resource path is concerned.

What is a better way to do sub resource within sub resource? Is it common to do sub-resource within sub-resource?

I don't see any problem with what you are doing.