J'ai le code suivant:
@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;
}
Si je demande un utilisateur qui n'existe pas, tel que /users/1234
, avec "Accept: application/json
", ce code renvoie une réponse HTTP 404
comme on pourrait s'y attendre, mais renvoie les ensembles Content-Type
à text/html
et un message body de html. L'annotation @Produces
est ignorée.
Est-ce un problème de code ou un problème de configuration?
Votre annotation @Produces
est ignorée car les exceptions non capturées sont traitées par le runtime jax-rs à l'aide d'une variable prédéfinie (valeur par défaut) ExceptionMapper
. Si vous souhaitez personnaliser le message renvoyé en cas d'exception spécifique, vous pouvez créer votre propre ExceptionMapper
pour le gérer. Dans votre cas, vous en avez besoin d'un pour gérer l'exception NotFoundException
et interroger l'en-tête "accept" pour connaître le type de réponse demandé:
@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
}
}
}
Vous pouvez utiliser le retour de réponse. Exemple ci-dessous:
@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();
}
que 404 est renvoyé par votre serveur car il est prévu que vous transmettiez les éléments sous la forme suivante
/users/{id}
mais vous passez comme
/users/user/{id}
quelle ressource n'existe pas du tout
essayez d'accéder à la ressource en tant que /users/1234
MODIFIER:
créer une classe comme
class RestResponse<T>{
private String status;
private String message;
private List<T> objectList;
//gettrs and setters
}
maintenant, au cas où vous voudriez une réponse pour User
, vous pouvez le créer comme suit
RestResponse<User> resp = new RestResponse<User>();
resp.setStatus("400");
resp.setMessage("User does not exist");
et la signature de votre méthode de repos serait comme suit
public RestResponse<User> getUser(@PathParam("id") int id)
alors que dans le cas d'une réponse réussie, vous pouvez définir des paramètres
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);