I am learning RESTful web services using JAX-RS.
I have a MessageResource
and a sub resource CommentResource
.
In my MessageResource
I mapped comment sub resource with test method, which I commented in the MessageResource
class because I don't want CommentResource
to be invoked.
package org.kaushik.javabrains.messenger.resource;
import java.net.URI;
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
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.Response.Status;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import org.glassfish.jersey.server.Uri;
import org.kaushik.javabrains.messenger.exception.DataNotFoundException;
import org.kaushik.javabrains.messenger.model.Message;
import org.kaushik.javabrains.messenger.services.MessageService;
@Path("/messages")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class MessageResource {
public MessageResource() {
// TODO Auto-generated constructor stub
}
@GET
public List<Message> getAllMessage() {
MessageService obj = new MessageService();
return obj.getAllMessages();
}
@GET
@Path("/{messageId}")
public Message getMessageById(@PathParam("messageId") String messageId) {
MessageService obj = new MessageService();
Message retrivedMessage = obj.getMessage(Long.parseLong(messageId));
return retrivedMessage;
}
/*
* This method is used to add new message in database returns created
* message with generated id
*/
/*
* @POST public Message postMessage(Message msg){
*
* MessageService obj = new MessageService(); msg = obj.addMessage(msg);
*
* return msg; }
*/
/**
* This method created the new message and sends new message with 201 status
* code using Response
*
* @param msg
* @return
*/
@POST
public Response postMessage(Message msg, @Context UriInfo uriInfo) {
MessageService obj = new MessageService();
msg = obj.addMessage(msg);
// This is to send only created status
// return Response.status(Status.CREATED).entity(msg).build();
// If we want to send status + new created resource path
String newId = msg.getId() + "";
URI uri = uriInfo.getAbsolutePathBuilder().path(newId).build();
return Response.created(uri).entity(msg).build();
}
@PUT
@Path("/{messageId}")
public Message updateMessage(Message msg, @PathParam("messageId") long id) {
MessageService obj = new MessageService();
msg.setId(id);
msg = obj.updateMessage(msg);
return msg;
}
@DELETE
@Path("/{messageId}")
public void deleteMessage(@PathParam("messageId") long id) {
MessageService obj = new MessageService();
obj.removeMessage(id);
}
/**
* This method is invoked if url asked for comments irrespective of http
* method, it will invoke the CommentResource which is a sub resouce of
* Message
*
* @return
*/
/*
* @Path("/{messageId}/comments") public CommentResource test() { return new
* CommentResource(); }
*/
}
I am having sub resource CommentResource
as following:
package org.kaushik.javabrains.messenger.resource;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
@Path("/")
public class CommentResource {
public CommentResource() {
// TODO Auto-generated constructor stub
}
@GET
public String test() {
return "new sub resource";
}
@GET
@Path("/{commentId}")
public String getCommentById(@PathParam("messageId") String messageId, @PathParam("commentId") String commentId) {
return commentId + " This is dummy comment for messageID=" + messageId;
}
}
I created a generic exception mapper, which is mapped to Throwable
class.
It is created for the purpose, if any exception happens at server end, rather displaying Tomcat error report page, meaningful message should be sent.
@Provider
public class GenericExceptionMapper implements ExceptionMapper<Throwable> {
@Override
public Response toResponse(Throwable ex) {
System.out.println("in Genereic mapper");
ErrorMessage message = new ErrorMessage(ex.getMessage(),"/Messenger/documentation",500);
return Response.status(Status.INTERNAL_SERVER_ERROR).entity(message).build();
}
}
Further, when I am testing my generic exception mapper by invoking a url
which is not mapped to any method in MessageResource
. It is invoking the CommentResource
following method:
@GET
@Path("/{commentId}")
public String getCommentById(@PathParam("messageId") String messageId, @PathParam("commentId") String commentId) {
return commentId + " This is dummy comment for messageID=" + messageId;
}
If I comment the above method I am getting proper response in Postman.
Can anybody explain this behavior. Thanks in advance.
Remove
@Path("/")
from theCommentResource
. It is being added as a root resource. So when you access/mesa
, theCommentResource
is mapped to/
, and it hits the resource method mapped to@Path("{whatever}")
.Sub resource locator classes should not have
@Path
. That is only for root resource classes. In a sub-resource locator request, it will be ignored, but on app startup, it is still registered like a regular root resource.