JAX-RS jersey ExceptionMappers User-Defined Exception
Solution 1
You need to annotate your exception mapper with @Provider
, otherwise it will never get registered with the JAX-RS runtime.
@Provider
public class UserNotFoundMapper implements
ExceptionMapper<UserNotFoundException> {
@Override
public Response toResponse(UserNotFoundException ex) {
return Response.status(404).entity(ex.getMessage()).type("text/plain")
.build();
}
}
Solution 2
What I usually do when creating APIs is create my own exception that extends from RuntimeException so I don't necessarily have to catch my exception.
Here's an example:
NOTE: I'm using JAX-RS with Jersey
First: create my own Exception that extends from RuntimeException.
public class ExceptionName extends RuntimeException {
private int code;
private String message;
public int getCode(){
return code;
}
public String getMessage(){
return message;
}
public ExceptionName(int code, String message) {
this.code = code;
this.message = message;
}
}
Also implement a ExceptionMapper
@Provider
public class ExceptionName implements ExceptionMapper<ExceptionName>{
@Override
public Response toResponse(ExceptionName exception) {
return Response.status(exception.getCode()).entity(exception.getMessage()).build();
}
}
And every time that I want to throw an exception I just do it like this anywhere, the exception mapper will take care of returning a response to the client consuming the API
throw new ExceptionName(500,"there was an error with something here");
Comments
-
WhoAmI almost 4 years
I am new to this, trying to achieve reading some docs but its not working, please bear with me.
I have created a
UserNotFoundMapper
usingExceptionMappers
like this:public class UserNotFoundMapper implements ExceptionMapper<UserNotFoundException> { @Override public Response toResponse(UserNotFoundException ex) { return Response.status(404).entity(ex.getMessage()).type("text/plain").build(); } }
This in my service:
@GET @Path("/user") public Response getUser(@QueryParam("id") String id) throws UserNotFoundException{ //Some user validation code with DB hit, if not found then throw new UserNotFoundException(); }
The
UserNotFoundException
is anUser-Defined
Exception.I tried this:
public class UserNotFoundException extends Exception { //SOME block of code }
But when I invoke the service, the
UserDefinedExceptionMapper
is not getting invoked. It seems I might be missing something in theUserDefinedException
. How to define this exception then?Please let me know how to define the
UserNotFoundException
. -
Ryan Stewart about 11 yearsYou don't invoke the mapper manually, and you wouldn't use Jersey-specific classes in your service layer. That's the whole point of mappers.
-
WhoAmI about 11 yearsThanks for the reply. I need to know a few things related to this: Where lies the difference between using a WebApplicationException and using an ExceptionMapper? I am not sure under which circumstances which should be used :( Can you please provide your inputs on this?
-
WhoAmI about 11 years@RyanStewart Thanks for the inputs. I am new to this and trying to learn it. In teh above postedd code; if I remove the mapper invocation line with
throw new UserNotFoundException();
then it is fine right? I cant understand what you meant byyou wouldn't use Jersey-specific classes in your service layer
. Can you please explain it in a bit details? -
Perception about 11 years@WhoAmI - web application exceptions are automatically mapped by the JAX-RS provider. So, as opposed to using exception mappers, for example, you could extend
WebApplicationException
and override it'sgetResponse
method. Some people prefer to do this for all exceptions that they define solely for their JAX-RS implementation. Mappers are great though, for mapping exceptions that do not extend from WebApplicationException (e.g all the standard Java exceptions, exceptions from third party libraries etc etc). -
WhoAmI about 11 yearsThis statement:
web application exceptions are automatically mapped by the JAX-RS provider
I have seen it in a lot of docs I am reading around over the net. But not able to understand what actually it means in simple terms and what is the importance/usefulness of it :( Can you please explain? -
Ryan Stewart about 11 years@WhoAmI: The Jersey User Guide lays it out pretty clearly, if not in great detail. It means that a
WebApplicationException
holds aResponse
inside it, and when you throw one of them, thatResponse
is what gets returned to the user. -
Ryan Stewart about 11 years@WhoAmI: Which exception approach to use is up to you. The strength of the
ExceptionMapper
is that your code can remain independent of Jersey, and you can also map exceptions that are beyond your control (framework exceptions). The strength of theWebApplicationException
is that it's simpler to use. -
WhoAmI about 11 yearsOk so rather than returning a
Response
like we do in ExceptionMappers; we are supposed to use a super(Response.....) for theWebApplicationException
. Thats all right? -
Perception about 11 years@ryanstewart - actually the mapping behavior for WebApplicationException is part of the JAX-RS specification, so it's portable across providers. Which is a great thing.
-
Ryan Stewart about 11 years@Perception: Good call. I often forget to make that distinction.
s/Jersey/JAX-RS/
in my last comment! -
gaoagong about 4 years@WhoAmI The class you are in is called UserServiceImpl and is part of the service layer, not the controller layer. You don't want to force a particular implementation like jax-rs into the rest of your code. It's usage should be terminated at the controller layer. ExceptionMapper give you a way to handle exceptions via jersey without adding
Response.status
... throughout your code. Service layer code should only do business logic.