JAX-RS - Comment renvoyer ensemble le code d'état JSON et HTTP?

248

J'écris une application Web REST (NetBeans 6.9, JAX-RS, TopLink Essentials) et j'essaie de renvoyer le code d'état JSON et HTTP. J'ai du code prêt et fonctionnel qui retourne JSON lorsque la méthode HTTP GET est appelée depuis le client. Essentiellement:

@Path("get/id")
@GET
@Produces("application/json")
public M_機械 getMachineToUpdate(@PathParam("id") String id) {

    // some code to return JSON ...

    return myJson;
}

Mais je veux également retourner un code d'état HTTP (500, 200, 204, etc.) avec les données JSON.

J'ai essayé d'utiliser HttpServletResponse:

response.sendError("error message", 500);

Mais cela a fait penser au navigateur qu'il s'agissait d'un "vrai" 500, donc la page Web de sortie était une page d'erreur HTTP 500 normale.

Je souhaite renvoyer un code d'état HTTP afin que mon JavaScript côté client puisse gérer une certaine logique en fonction de celui-ci (par exemple, afficher le code d'erreur et le message sur une page HTML). Est-ce possible ou les codes d'état HTTP ne doivent-ils pas être utilisés pour une telle chose?

Miaou
la source
2
Quelle est la différence entre 500 que vous voulez (irréel? :)) et 500 réels?
rasoir
@razor Ici, le vrai 500 signifie une page d'erreur HTML au lieu de la réponse JSON
Nupur
Le navigateur Web n'a pas été conçu pour fonctionner avec JSON, mais avec des pages HTML, donc si vous répondez avec 500 (et même un corps de message), le navigateur peut vous montrer juste un message d'erreur (dépend vraiment de l'implémentation du navigateur), juste parce que c'est utile pour un utilisateur normal.
rasoir

Réponses:

347

Voici un exemple:

@GET
@Path("retrieve/{uuid}")
public Response retrieveSomething(@PathParam("uuid") String uuid) {
    if(uuid == null || uuid.trim().length() == 0) {
        return Response.serverError().entity("UUID cannot be blank").build();
    }
    Entity entity = service.getById(uuid);
    if(entity == null) {
        return Response.status(Response.Status.NOT_FOUND).entity("Entity not found for UUID: " + uuid).build();
    }
    String json = //convert entity to json
    return Response.ok(json, MediaType.APPLICATION_JSON).build();
}

Jetez un œil à la classe Response .

Notez que vous devez toujours spécifier un type de contenu, surtout si vous transmettez plusieurs types de contenu, mais si chaque message sera représenté sous la forme JSON, vous pouvez simplement annoter la méthode avec @Produces("application/json")

son attrait
la source
12
Cela fonctionne, mais ce que je n'aime pas dans la valeur de retour de la réponse, c'est qu'à mon avis, cela pollue votre code, en particulier en ce qui concerne tout client essayant de l'utiliser. Si vous fournissez une interface renvoyant une réponse à un tiers, il ne sait pas quel type renvoyez-vous réellement. Spring le rend plus clair avec une annotation, très utile si vous retournez toujours un code d'état (par exemple HTTP 204)
Guido
19
Rendre cette classe générique (Response <T>) serait une amélioration intéressante de jax-rs, pour avoir les avantages des deux alternatives.
Guido
41
Il n'est pas nécessaire de convertir l'entité en json d'une manière ou d'une autre. Vous pouvez faire return Response.status(Response.Status.Forbidden).entity(myPOJO).build();Works comme si vous le vouliez return myPOJO;, mais avec un réglage supplémentaire du code HTTP-Status.
kratenko
1
Je pense que la séparation de la logique métier en une classe de service séparée fonctionne bien. Le point de terminaison utilise Response comme type de retour et ses méthodes sont principalement des appels aux méthodes de service plus le chemin et les annotations param. Il sépare proprement la logique du mappage url / type de contenu (où le caoutchouc prend la route pour ainsi dire).
Stijn de Witt
en fait, on peut simplement renvoyer l'objet non enveloppant à la réponse.
Ses
191

Il existe plusieurs cas d'utilisation pour définir des codes d'état HTTP dans un service Web REST, et au moins un n'était pas suffisamment documenté dans les réponses existantes (c'est-à-dire lorsque vous utilisez la sérialisation JSON / XML auto-magique à l'aide de JAXB et que vous souhaitez renvoyer un objet à sérialiser, mais aussi un code d'état différent du 200 par défaut).

Permettez-moi donc d'essayer d'énumérer les différents cas d'utilisation et les solutions pour chacun:

1. Code d'erreur (500, 404, ...)

Cas d'utilisation le plus courant lorsque vous souhaitez renvoyer un code d'état différent de celui d' 200 OKune erreur.

Par exemple:

  • une entité est demandée mais elle n'existe pas (404)
  • la demande est sémantiquement incorrecte (400)
  • l'utilisateur n'est pas autorisé (401)
  • il y a un problème avec la connexion à la base de données (500)
  • etc..

a) Lancez une exception

Dans ce cas, je pense que la façon la plus propre de gérer le problème est de lever une exception. Cette exception sera gérée par un ExceptionMapper, qui traduira l'exception en une réponse avec le code d'erreur approprié.

Vous pouvez utiliser la valeur par défaut ExceptionMapperpréconfigurée avec Jersey (et je suppose que c'est la même chose avec d'autres implémentations) et jeter n'importe laquelle des sous-classes existantes de javax.ws.rs.WebApplicationException. Ce sont des types d'exceptions prédéfinis qui sont mappés à différents codes d'erreur, par exemple:

  • BadRequestException (400)
  • InternalServerErrorException (500)
  • NotFoundException (404)

Etc. Vous pouvez trouver la liste ici: API

Vous pouvez également définir vos propres exceptions et ExceptionMapperclasses personnalisées et ajouter ces mappeurs à Jersey au moyen de l' @Providerannotation ( source de cet exemple ):

public class MyApplicationException extends Exception implements Serializable
{
    private static final long serialVersionUID = 1L;
    public MyApplicationException() {
        super();
    }
    public MyApplicationException(String msg)   {
        super(msg);
    }
    public MyApplicationException(String msg, Exception e)  {
        super(msg, e);
    }
}

Fournisseur:

    @Provider
    public class MyApplicationExceptionHandler implements ExceptionMapper<MyApplicationException> 
    {
        @Override
        public Response toResponse(MyApplicationException exception) 
        {
            return Response.status(Status.BAD_REQUEST).entity(exception.getMessage()).build();  
        }
    }

Remarque: vous pouvez également écrire des ExceptionMappers pour les types d'exceptions existants que vous utilisez.

b) Utilisez le générateur Réponse

Une autre façon de définir un code d'état consiste à utiliser un Responsegénérateur pour créer une réponse avec le code voulu.

Dans ce cas, le type de retour de votre méthode doit être javax.ws.rs.core.Response. Ceci est décrit dans diverses autres réponses telles que la réponse acceptée par son équipe et ressemble à ceci:

@GET
@Path("myresource({id}")
public Response retrieveSomething(@PathParam("id") String id) {
    ...
    Entity entity = service.getById(uuid);
    if(entity == null) {
        return Response.status(Response.Status.NOT_FOUND).entity("Resource not found for ID: " + uuid).build();
    }
    ...
}

2. Succès, mais pas 200

Un autre cas où vous souhaitez définir le statut de retour est lorsque l'opération a réussi, mais vous souhaitez renvoyer un code de réussite différent de 200, ainsi que le contenu que vous renvoyez dans le corps.

Un cas d'utilisation fréquent est lorsque vous créez une nouvelle entité ( POSTdemande) et que vous souhaitez renvoyer des informations sur cette nouvelle entité ou peut-être l'entité elle-même, avec un 201 Createdcode d'état.

Une approche consiste à utiliser l'objet de réponse comme décrit ci-dessus et à définir vous-même le corps de la demande. Cependant, ce faisant, vous perdez la possibilité d'utiliser la sérialisation automatique en XML ou JSON fournie par JAXB.

Il s'agit de la méthode d'origine renvoyant un objet entité qui sera sérialisé en JSON par JAXB:

@Path("/")
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public User addUser(User user){
    User newuser = ... do something like DB insert ...
    return newuser;
}

Cela renverra une représentation JSON de l'utilisateur nouvellement créé, mais le statut de retour sera 200, pas 201.

Maintenant, le problème est que si je veux utiliser le Responsegénérateur pour définir le code retour, je dois retourner un Responseobjet dans ma méthode. Comment puis-je toujours renvoyer l' Userobjet à sérialiser?

a) Définissez le code sur la réponse du servlet

Une approche pour résoudre ce problème consiste à obtenir un objet de demande de servlet et à définir manuellement le code de réponse, comme démontré dans la réponse de Garett Wilson:

@Path("/")
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public User addUser(User user, @Context final HttpServletResponse response){

    User newUser = ...

    //set HTTP code to "201 Created"
    response.setStatus(HttpServletResponse.SC_CREATED);
    try {
        response.flushBuffer();
    }catch(Exception e){}

    return newUser;
}

La méthode renvoie toujours un objet entité et le code d'état sera 201.

Notez que pour que cela fonctionne, j'ai dû vider la réponse. Il s'agit d'une résurgence désagréable du code API de servlet de bas niveau dans notre belle ressource JAX_RS, et pire encore, cela rend les en-têtes non modifiables après cela car ils ont déjà été envoyés sur le câble.

b) Utiliser l'objet de réponse avec l'entité

Dans ce cas, la meilleure solution consiste à utiliser l'objet Response et à définir l'entité à sérialiser sur cet objet Response. Ce serait bien de rendre l'objet Response générique pour indiquer le type de l'entité de charge utile dans ce cas, mais ce n'est pas le cas actuellement.

@Path("/")
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public Response addUser(User user){

    User newUser = ...

    return Response.created(hateoas.buildLinkUri(newUser, "entity")).entity(restResponse).build();
}

Dans ce cas, nous utilisons la méthode créée de la classe du générateur Réponse pour définir le code d'état sur 201. Nous passons l'objet entité (utilisateur) à la réponse via la méthode entity ().

Le résultat est que le code HTTP est 401 comme nous le voulions, et le corps de la réponse est exactement le même JSON que nous avions auparavant lorsque nous venions de renvoyer l'objet User. Il ajoute également un en-tête d'emplacement.

La classe Response a un certain nombre de méthodes de génération pour différents statuts (stati?) Tels que:

Response.accepted () Response.ok () Response.noContent () Response.notAcceptable ()

NB: l'objet hateoas est une classe d'aide que j'ai développée pour aider à générer des URI de ressources. Vous devrez trouver votre propre mécanisme ici;)

C'est à peu près ça.

J'espère que cette longue réponse aide quelqu'un :)

Pierre Henry
la source
Je me demande s'il existe un moyen propre de renvoyer l'objet de données lui-même au lieu de la réponse. Le flushest en effet sale.
AlikElzin-kilaka
1
Juste une bête noire: 401 ne signifie pas que l'utilisateur n'est pas autorisé. Cela signifie que le client n'est pas autorisé, car le serveur ne sait pas qui vous êtes. Si un utilisateur connecté / autrement reconnu n'est pas autorisé à effectuer une certaine action, le code de réponse correct est 403 interdit.
Demonblack
69

La réponse de hisdrewness fonctionnera, mais elle modifie toute l'approche permettant à un fournisseur tel que Jackson + JAXB de convertir automatiquement votre objet retourné dans un format de sortie tel que JSON. Inspiré par une publication Apache CXF (qui utilise une classe spécifique à CXF), j'ai trouvé un moyen de définir le code de réponse qui devrait fonctionner dans n'importe quelle implémentation JAX-RS: injectez un contexte HttpServletResponse et définissez manuellement le code de réponse. Par exemple, voici comment définir le code de réponse le CREATEDcas échéant.

@Path("/foos/{fooId}")
@PUT
@Consumes("application/json")
@Produces("application/json")
public Foo setFoo(@PathParam("fooID") final String fooID, final Foo foo, @Context final HttpServletResponse response)
{
  //TODO store foo in persistent storage
  if(itemDidNotExistBefore) //return 201 only if new object; TODO app-specific logic
  {
    response.setStatus(Response.Status.CREATED.getStatusCode());
  }
  return foo;  //TODO get latest foo from storage if needed
}

Amélioration: Après avoir trouvé une autre réponse connexe , j'ai appris que l'on peut injecter la HttpServletResponsevariable en tant que membre, même pour la classe de service singleton (au moins dans RESTEasy) !! C'est une bien meilleure approche que de polluer l'API avec des détails d'implémentation. Cela ressemblerait à ceci:

@Context  //injected response proxy supporting multiple threads
private HttpServletResponse response;

@Path("/foos/{fooId}")
@PUT
@Consumes("application/json")
@Produces("application/json")
public Foo setFoo(@PathParam("fooID") final String fooID, final Foo foo)
{
  //TODO store foo in persistent storage
  if(itemDidNotExistBefore) //return 201 only if new object; TODO app-specific logic
  {
    response.setStatus(Response.Status.CREATED.getStatusCode());
  }
  return foo;  //TODO get latest foo from storage if needed
}
Garret Wilson
la source
Vous pouvez réellement combiner les approches: annotez la méthode avec @Produces, et ne spécifiez pas le type de média dans la finale Response.ok, et vous obtiendrez votre objet de retour correctement JAXB sérialisé dans le type de média approprié pour correspondre à la demande. (Je viens d'essayer cela avec une seule méthode qui pourrait retourner XML ou JSON: la méthode elle-même n'a pas besoin de mentionner non plus, sauf dans l' @Producesannotation.)
Royston Shufflebotham
Tu as raison Garret. Mon exemple était davantage une illustration de l'accent mis sur la fourniture d'un type de contenu. Nos approches sont similaires, mais l'idée d'utiliser un MessageBodyWriteret Providerpermet une négociation de contenu implicite, bien qu'il semble que votre exemple manque de code. Voici une autre réponse que j'ai fournie qui illustre cela: stackoverflow.com/questions/5161466/…
hisdrewness
8
Je ne parviens pas à remplacer le code d'état dans response.setStatus(). La seule façon d'envoyer par exemple une réponse 404 Not Found est de définir le code d'état de la réponse response.setStatus(404)puis de fermer le flux de sortie response.getOutputStream().close()afin que JAX-RS ne puisse pas réinitialiser mon état.
Rob Juurlink
2
J'ai pu utiliser cette approche pour définir un code 201, mais j'ai dû ajouter un bloc try-catch avec response.flushBuffer()afin d'éviter que le framework ne remplace mon code de réponse. Pas très propre.
Pierre Henry
1
@RobJuurlink, si vous souhaitez spécifiquement retourner un 404 Not Found, il peut être plus simple à utiliser throw new NotFoundException().
Garret Wilson
34

Si vous aimez garder votre couche de ressources propre des Responseobjets, je vous recommande d'utiliser @NameBindinget de lier les implémentations de ContainerResponseFilter.

Voici la viande de l'annotation:

package my.webservice.annotations.status;

import javax.ws.rs.NameBinding;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@NameBinding
@Retention(RetentionPolicy.RUNTIME)
public @interface Status {
  int CREATED = 201;
  int value();
}

Voici la viande du filtre:

package my.webservice.interceptors.status;

import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.ext.Provider;
import java.io.IOException;

@Provider
public class StatusFilter implements ContainerResponseFilter {

  @Override
  public void filter(ContainerRequestContext containerRequestContext, ContainerResponseContext containerResponseContext) throws IOException {
    if (containerResponseContext.getStatus() == 200) {
      for (Annotation annotation : containerResponseContext.getEntityAnnotations()) {
        if(annotation instanceof Status){
          containerResponseContext.setStatus(((Status) annotation).value());
          break;
        }
      }
    }
  }
}

Et puis l'implémentation sur votre ressource devient simplement:

package my.webservice.resources;

import my.webservice.annotations.status.StatusCreated;
import javax.ws.rs.*;

@Path("/my-resource-path")
public class MyResource{
  @POST
  @Status(Status.CREATED)
  public boolean create(){
    return true;
  }
}
Nthalk
la source
Garde l'API propre, bonne réponse. Serait-il possible de paramétrer votre annotation comme @Status (code = 205) et demander à l'intercepteur de remplacer le code par ce que vous spécifiez? Je pense que cela vous donnerait essentiellement une annotation pour remplacer les codes chaque fois que vous en avez besoin.
user2800708
@ user2800708, je l'ai déjà fait pour mon code local, mis à jour la réponse comme vous l'avez suggéré.
Nthalk
Bien, merci. Avec cela et quelques autres astuces, je suis maintenant en mesure de nettoyer les API REST dans mon code, afin qu'il soit conforme à une interface Java simple sans aucune mention de REST; c'est juste un autre mécanisme RMI.
user2800708
6
Au lieu de boucler pour les annotations dans StatusFilter, vous pouvez annoter le filtre avec @ Status en plus de @ Provider. Ensuite, le filtre ne sera appelé que sur les ressources annotées avec @ Status. C'est le but de @ NameBinding
trevorism
1
Bonne légende @trevorism. Il y a un effet secondaire moins agréable de l'annotation StatusFilteravec @Status: vous devez soit fournir une valeur par défaut pour le valuechamp de l'annotation , soit en déclarer une lors de l'annotation de la classe (ex:) @Status(200). Ce n'est évidemment pas idéal.
Phil
6

Si vous souhaitez modifier le code d'état en raison d'une exception, avec JAX-RS 2.0, vous pouvez implémenter un ExceptionMapper comme celui-ci. Cela gère ce type d'exception pour l'ensemble de l'application.

@Provider
public class UnauthorizedExceptionMapper implements ExceptionMapper<EJBAccessException> {

    @Override
    public Response toResponse(EJBAccessException exception) {
        return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build();
    }

}
ercalamar
la source
6

Si votre WS-RS a besoin de générer une erreur, pourquoi ne pas simplement utiliser l'exception WebApplicationException?

@GET
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Path("{id}")
public MyEntity getFoo(@PathParam("id") long id,  @QueryParam("lang")long idLanguage) {

if (idLanguage== 0){
    // No URL parameter idLanguage was sent
    ResponseBuilder builder = Response.status(Response.Status.BAD_REQUEST);
    builder.entity("Missing idLanguage parameter on request");
    Response response = builder.build();
    throw new WebApplicationException(response);
    }
... //other stuff to return my entity
return myEntity;
}
Ariel
la source
4
À mon avis, les WebApplicationExceptions ne conviennent pas aux erreurs côté client car elles génèrent des traces de pile importantes. Les erreurs client ne doivent pas jeter de traces de pile côté serveur et polluer la journalisation avec.
Rob Juurlink
5

JAX-RS prend en charge les codes HTTP standard / personnalisés. Voir ResponseBuilder et ResponseStatus, par exemple:

http://jackson.codehaus.org/javadoc/jax-rs/1.0/javax/ws/rs/core/Response.ResponseBuilder.html#status%28javax.ws.rs.core.Response.Status%29

Gardez à l'esprit que les informations JSON concernent davantage les données associées à la ressource / application. Les codes HTTP concernent davantage l'état de l'opération CRUD demandée. (au moins c'est comme ça que c'est censé être dans les systèmes REST)

kvista
la source
le lien est rompu
Umpa
5

J'ai trouvé très utile de créer également un message json avec du code répété, comme ceci:

@POST
@Consumes("application/json")
@Produces("application/json")
public Response authUser(JsonObject authData) {
    String email = authData.getString("email");
    String password = authData.getString("password");
    JSONObject json = new JSONObject();
    if (email.equalsIgnoreCase(user.getEmail()) && password.equalsIgnoreCase(user.getPassword())) {
        json.put("status", "success");
        json.put("code", Response.Status.OK.getStatusCode());
        json.put("message", "User " + authData.getString("email") + " authenticated.");
        return Response.ok(json.toString()).build();
    } else {
        json.put("status", "error");
        json.put("code", Response.Status.NOT_FOUND.getStatusCode());
        json.put("message", "User " + authData.getString("email") + " not found.");
        return Response.status(Response.Status.NOT_FOUND).entity(json.toString()).build();
    }
}
Array
la source
4

Veuillez regarder l'exemple ici, il illustre le mieux le problème et comment il est résolu dans la dernière version (2.3.1) de Jersey.

https://jersey.java.net/documentation/latest/representations.html#d0e3586

Il s'agit essentiellement de définir une exception personnalisée et de conserver le type de retour comme entité. Lorsqu'il y a une erreur, l'exception est levée, sinon, vous retournez le POJO.

annouk
la source
Je voudrais ajouter que l'exemple d'intérêt est celui où ils définissent leur propre classe d'exception et en construisent une Response. Recherchez simplement la CustomNotFoundExceptionclasse et copiez-la sur votre message.
JBert
J'utilise cette approche pour les erreurs et j'aime ça. Mais il ne s'applique pas aux codes de réussite (différents de 200) tels que «201 créé».
Pierre Henry
3

Je n'utilise pas JAX-RS, mais j'ai un scénario similaire où j'utilise:

response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
Casquettes
la source
Cela fonctionne pour moi en utilisant Spring MVC mais il existe un moyen facile de le savoir!
Caps
1

Notez également que, par défaut, Jersey remplacera le corps de la réponse en cas de code http 400 ou plus.

Afin d'obtenir votre entité spécifiée comme corps de réponse, essayez d'ajouter le param-init suivant à votre Jersey dans votre fichier de configuration web.xml:

    <init-param>
        <!-- used to overwrite default 4xx state pages -->
        <param-name>jersey.config.server.response.setStatusOverSendError</param-name>
        <param-value>true</param-value>
    </init-param>
Maxime T
la source
0

Le code suivant a fonctionné pour moi. Injecter le messageContext via le setter annoté et définir le code d'état dans ma méthode "add".

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;

import org.apache.cxf.jaxrs.ext.MessageContext;

public class FlightReservationService {

    MessageContext messageContext;

    private final Map<Long, FlightReservation> flightReservations = new HashMap<>();

    @Context
    public void setMessageContext(MessageContext messageContext) {
        this.messageContext = messageContext;
    }

    @Override
    public Collection<FlightReservation> list() {
        return flightReservations.values();
    }

    @Path("/{id}")
    @Produces("application/json")
    @GET
    public FlightReservation get(Long id) {
        return flightReservations.get(id);
    }

    @Path("/")
    @Consumes("application/json")
    @Produces("application/json")
    @POST
    public void add(FlightReservation booking) {
        messageContext.getHttpServletResponse().setStatus(Response.Status.CREATED.getStatusCode());
        flightReservations.put(booking.getId(), booking);
    }

    @Path("/")
    @Consumes("application/json")
    @PUT
    public void update(FlightReservation booking) {
        flightReservations.remove(booking.getId());
        flightReservations.put(booking.getId(), booking);
    }

    @Path("/{id}")
    @DELETE
    public void remove(Long id) {
        flightReservations.remove(id);
    }
}
JBernhardt
la source
0

En développant la réponse de Nthalk avec Microprofile OpenAPI, vous pouvez aligner le code de retour avec votre documentation en utilisant l' annotation @APIResponse .

Cela permet de baliser une méthode JAX-RS comme

@GET
@APIResponse(responseCode = "204")
public Resource getResource(ResourceRequest request) 

Vous pouvez analyser cette annotation standardisée avec un ContainerResponseFilter

@Provider
public class StatusFilter implements ContainerResponseFilter {

    @Override
    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) {
        if (responseContext.getStatus() == 200) {
            for (final var annotation : responseContext.getEntityAnnotations()) {
                if (annotation instanceof APIResponse response) {
                    final var rawCode = response.responseCode();
                    final var statusCode = Integer.parseInt(rawCode);

                    responseContext.setStatus(statusCode);
                }
            }
        }
    }

}

Une mise en garde se produit lorsque vous mettez plusieurs annotations sur votre méthode comme

@APIResponse(responseCode = "201", description = "first use case")
@APIResponse(responseCode = "204", description = "because you can")
public Resource getResource(ResourceRequest request) 
thatsIch
la source
-1

J'utilise jersey 2.0 avec des lecteurs et des rédacteurs de corps de message. J'ai eu mon type de retour de méthode en tant qu'entité spécifique qui a également été utilisée dans la mise en œuvre de l'écrivain de corps de message et je retournais le même pojo, un SkuListDTO. @GET @Consumes ({"application / xml", "application / json"}) @Produces ({"application / xml", "application / json"}) @Path ("/ skuResync")

public SkuResultListDTO getSkuData()
    ....
return SkuResultListDTO;

tout ce que j'ai changé était ceci, j'ai laissé la mise en œuvre de l'écrivain seul et cela a toujours fonctionné.

public Response getSkuData()
...
return Response.status(Response.Status.FORBIDDEN).entity(dfCoreResultListDTO).build();
b. phillips
la source