JAX-RS (Jersey) will throw a NotFoundException
if the resource isn't found. This exception will be mapped to a response containing a status code 404 Not Found (with no entity body), as this is normal REST behavior. But we are also allowed to change the response to our liking by creating an ExceptionMapper
. There we can set an entity body. You might have something like
import javax.ws.rs.NotFoundException;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
@Provider
public class NotFoundExceptionMapper
implements ExceptionMapper<NotFoundException> {
final String html
= "<p style='font-size:20px;font-family:Sans-serif'>"
+ "Service is unavailable message."
+ "</p>"
+ "<a href='http://www.stackoverflow.com'>"
+ "Check out Stackoverflow</a>";
@Override
public Response toResponse(NotFoundException e) {
return Response.status(Status.NOT_FOUND)
.entity(html).build();
}
}
We just need to register this provider with the Jersey (JAX-RS) application (possibly through the ResourceConfig
).
It seems as long as we have a entity body with the response, we'll get

Instead of a

- See Exception Mapping
Note: you could just as easily simply map 404 to an error page of your choosing, through the web.xml, without the need for any ExceptionMapper. Something like
<error-page>
<error-code>404</error-code>
<location>/error.html</location>
</error-page>
See here for more details
UPDATE
"One more doubt, when I set it, for all 404 same message. Can we customize too based on the request url or some otherway.(My intention is to provide different message for different services)"
You can inject different contexts into the ExceptionMapper
. For instance UriInfo
, and get the requested path
@Context
UriInfo uriInfo;
@Override
public Response toResponse(NotFoundException e) {
String html
= "<p style='font-size:20px;font-family:Sans-serif'>"
+ "Service is unavailable message."
+ "</p>"
+ "<a href='http://www.stackoverflow.com'>"
+ "Check out Stackoverflow</a>";
html += "<p>Requested URI: " + uriInfo.getAbsolutePath() + "</p>";
return Response.status(Status.NOT_FOUND)
.entity(html).build();
}

There are other contexts that can be injected. Whether they are inject-able into a class depends on the class (resource class / provider class) and its application scope (among other things). But here's a list of inject-able contexts (with the @Context
annotation).
javax.ws.rs.core.HttpHeaders
javax.ws.rs.core.UriInfo
javax.ws.rs.core.Request
javax.servlet.HttpServletRequest
javax.servlet.HttpServletResponse
javax.servlet.ServletConfig
javax.servlet.ServletContext
javax.ws.rs.core.SecurityContext
- Possible more :-)