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?
la source
Réponses:
Voici un exemple:
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")
la source
return Response.status(Response.Status.Forbidden).entity(myPOJO).build();
Works comme si vous le vouliezreturn myPOJO;
, mais avec un réglage supplémentaire du code HTTP-Status.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 OK
une erreur.Par exemple:
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
ExceptionMapper
pré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 dejavax.ws.rs.WebApplicationException
. Ce sont des types d'exceptions prédéfinis qui sont mappés à différents codes d'erreur, par exemple:Etc. Vous pouvez trouver la liste ici: API
Vous pouvez également définir vos propres exceptions et
ExceptionMapper
classes personnalisées et ajouter ces mappeurs à Jersey au moyen de l'@Provider
annotation ( source de cet exemple ):Fournisseur:
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
Response
gé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: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é (
POST
demande) et que vous souhaitez renvoyer des informations sur cette nouvelle entité ou peut-être l'entité elle-même, avec un201 Created
code 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:
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
Response
générateur pour définir le code retour, je dois retourner unResponse
objet dans ma méthode. Comment puis-je toujours renvoyer l'User
objet à 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:
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.
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 :)
la source
flush
est en effet sale.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
CREATED
cas échéant.Amélioration: Après avoir trouvé une autre réponse connexe , j'ai appris que l'on peut injecter la
HttpServletResponse
variable 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:la source
@Produces
, et ne spécifiez pas le type de média dans la finaleResponse.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'@Produces
annotation.)MessageBodyWriter
etProvider
permet 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/…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éponseresponse.setStatus(404)
puis de fermer le flux de sortieresponse.getOutputStream().close()
afin que JAX-RS ne puisse pas réinitialiser mon état.response.flushBuffer()
afin d'éviter que le framework ne remplace mon code de réponse. Pas très propre.404 Not Found
, il peut être plus simple à utiliserthrow new NotFoundException()
.Si vous aimez garder votre couche de ressources propre des
Response
objets, je vous recommande d'utiliser@NameBinding
et de lier les implémentations deContainerResponseFilter
.Voici la viande de l'annotation:
Voici la viande du filtre:
Et puis l'implémentation sur votre ressource devient simplement:
la source
StatusFilter
avec@Status
: vous devez soit fournir une valeur par défaut pour levalue
champ 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.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.
la source
Si votre WS-RS a besoin de générer une erreur, pourquoi ne pas simplement utiliser l'exception WebApplicationException?
la source
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)
la source
J'ai trouvé très utile de créer également un message json avec du code répété, comme ceci:
la source
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.
la source
Response
. Recherchez simplement laCustomNotFoundException
classe et copiez-la sur votre message.Je n'utilise pas JAX-RS, mais j'ai un scénario similaire où j'utilise:
la source
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:
la source
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".
la source
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
Vous pouvez analyser cette annotation standardisée avec un ContainerResponseFilter
Une mise en garde se produit lorsque vous mettez plusieurs annotations sur votre méthode comme
la source
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")
tout ce que j'ai changé était ceci, j'ai laissé la mise en œuvre de l'écrivain seul et cela a toujours fonctionné.
la source