web-dev-qa-db-fra.com

Comment renvoyer la réponse HTTP 404 JSON/XML dans JAX-RS (Jersey) sur Tomcat?

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? 

30
IJR

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
         }
    }
}
30
Svetlin Zarev

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();
}
16
Tiago

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);
0
VD'