I have the following code:
@Path("/users/{id}")
public class UserResource {
@Autowired
private UserDao userDao;
@GET
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public User getUser(@PathParam("id") int id) {
User user = userDao.getUserById(id);
if (user == null) {
throw new NotFoundException();
}
return user;
}
If I request for a user that doesn't exists, like /users/1234
, with "Accept: application/json
", this code returns an HTTP 404
response like one would expect, but returns Content-Type
sets to text/html
and a body message of html. Annotation @Produces
is ignored.
Is it a problem of code or a problem of configuration?
Your @Produces
annotation is ignored because uncaught exceptions are processed by the jax-rs runtime using a predefined (default) ExceptionMapper
If you want to customize the returned message in case of a specific exception you can create your own ExceptionMapper
to handle it. In your case you need one to handle the NotFoundException
exception and query the "accept" header for the requested type of the response:
@Provider
public class NotFoundExceptionHandler implements ExceptionMapper<NotFoundException>{
@Context
private HttpHeaders headers;
public Response toResponse(NotFoundException ex){
return Response.status(404).entity(yourMessage).type( getAcceptType()).build();
}
private String getAcceptType(){
List<MediaType> accepts = headers.getAcceptableMediaTypes();
if (accepts!=null && accepts.size() > 0) {
//choose one
}else {
//return a default one like Application/json
}
}
}
You can use the Response return. Example below:
@GET
@Path("{id}")
@Produces(MediaType.APPLICATION_JSON)
public Response get(@PathParam("id") Long id) {
ExampleEntity exampleEntity = getExampleEntityById(id);
if (exampleEntity != null) {
return Response.ok(exampleEntity).build();
}
return Response.status(Status.NOT_FOUND).build();
}
that 404 is returned by your server as it is expected that you will pass things in following form
/users/{id}
but you are passing it as
/users/user/{id}
which resource is not existing at all
try accessing resource as /users/1234
EDIT:
create a class like
class RestResponse<T>{
private String status;
private String message;
private List<T> objectList;
//gettrs and setters
}
now in case you want response for User
you can create it as following
RestResponse<User> resp = new RestResponse<User>();
resp.setStatus("400");
resp.setMessage("User does not exist");
and signature of your rest method would be like following
public RestResponse<User> getUser(@PathParam("id") int id)
while in case successful response you can set things like
RestResponse<User> resp = new RestResponse<User>();
List<User> userList = new ArrayList<User>();
userList.add(user);//the user object you want to return
resp.setStatus("200");
resp.setMessage("User exist");
resp.setObjectList(userList);