Demande Spring JSON obtenant 406 (non acceptable)

85

c'est mon javascript:

    function getWeather() {
        $.getJSON('getTemperature/' + $('.data option:selected').val(), null, function(data) {
            alert('Success');                               
        });
    }

c'est mon contrôleur:

@RequestMapping(value="/getTemperature/{id}", headers="Accept=*/*", method = RequestMethod.GET)
@ResponseBody
public Weather getTemparature(@PathVariable("id") Integer id){
    Weather weather = weatherService.getCurrentWeather(id);
        return weather;
}

spring-servlet.xml

<context:annotation-config />
<tx:annotation-driven />

Obtenir cette erreur:

GET http://localhost:8080/web/getTemperature/2 406 (Not Acceptable)

En-têtes:

En-têtes de réponse

Server  Apache-Coyote/1.1
Content-Type    text/html;charset=utf-8
Content-Length  1070
Date    Sun, 18 Sep 2011 17:00:35 GMT

Demander des en-têtes

Host    localhost:8080
User-Agent  Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0.2) Gecko/20100101 Firefox/6.0.2
Accept  application/json, text/javascript, */*; q=0.01
Accept-Language en-us,en;q=0.5
Accept-Encoding gzip, deflate
Accept-Charset  ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection  keep-alive
X-Requested-With    XMLHttpRequest
Referer http://localhost:8080/web/weather
Cookie  JSESSIONID=7D27FAC18050ED84B58DAFB0A51CB7E4

Note intéressante:

J'obtiens une erreur 406, mais la requête d'hibernation fonctionne pendant ce temps. Voici ce que dit le journal tomcat, à chaque fois que je change de sélection dans Dropbox:

 select weather0_.ID as ID0_0_, weather0_.CITY_ID as CITY2_0_0_, weather0_.DATE as DATE0_0_, weather0_.TEMP as TEMP0_0_ from WEATHER weather0_ where weather0_.ID=?

Quel pourrait être le problème? Il y avait deux questions similaires dans SO avant, j'ai essayé tous les indices acceptés, mais ils n'ont pas fonctionné je suppose ...

Aucune suggestion? Sentez-vous libre de poser des questions...

Jaanus
la source

Réponses:

107

406 Non acceptable

La ressource identifiée par la demande est uniquement capable de générer des entités de réponse qui ont des caractéristiques de contenu non acceptables selon les en-têtes d'acceptation envoyés dans la demande.

Ainsi, votre en-tête d'acceptation de demande est application / json et votre contrôleur n'est pas en mesure de le renvoyer. Cela se produit lorsque le HTTPMessageConverter correct est introuvable pour satisfaire la valeur de retour annotée @ResponseBody. HTTPMessageConverter est automatiquement enregistré lorsque vous utilisez le <mvc:annotation-driven>, étant donné certaines bibliothèques tierces dans le chemin de classe.

Soit vous n'avez pas la bibliothèque Jackson correcte dans votre chemin de classe, soit vous n'avez pas utilisé la <mvc:annotation-driven>directive.

J'ai répliqué avec succès votre scénario et cela a bien fonctionné en utilisant ces deux bibliothèques et aucune headers="Accept=*/*"directive.

  • jackson-core-asl-1.7.4.jar
  • jackson-mapper-asl-1.7.4.jar
Villu Sepman
la source
Non, ce n'était pas le problème, vérifiez ma réponse.
Jaanus
Si la configuration de HttpMessageConverters a résolu manuellement votre problème, l'utilisation de mvc: annotation-driven aurait le même effet car elle configure automatiquement les convertisseurs et HandlerAdapters (HA). Notez que si vous configurez un HA explicitement, il annulera toutes les autres valeurs par défaut.
Villu Sepman
Hmm, qu'est-ce que c'est mvclà? J'ai utilisé <tx:annotation-driven />et tx estxmlns:tx="http://www.springframework.org/schema/tx"
Jaanus
1
Vous avez quelque chose comme: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">et les bocaux spring-web-3.0.x et spring-webmvc-3.0.x?
Villu Sepman
1
Ah je n'avais pas ce schéma là-bas ... mais merci, cela m'a aidé. Je pensais que c'était la tx:annotation-drivenmême chose que mvc:annotation-driveou smthin.
Jaanus
74

J'ai eu le même problème, avec le dernier printemps 4.1.1 et les versions ultérieures, vous devez ajouter les fichiers JAR suivants à pom.xml.

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.4.1</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.4.1.1</version>
</dependency>

assurez-vous également que vous avez le pot suivant:

<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-core-asl</artifactId>
    <version>1.9.13</version>
</dependency>

<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-mapper-asl</artifactId>
    <version>1.9.13</version>
</dependency>

406 Spring MVC Json, non acceptable selon les en-têtes de demande "accept"

AKB
la source
Cette réponse est la version Maven de la meilleure réponse, et cela fonctionne parfaitement! Les exceptions Maven pourraient être plus claires sur ce qui se passe réellement sous le capot.
Cotta
4
Pouvez-vous indiquer où cela est documenté sur la documentation officielle de Springs? Comment quelqu'un peut-il savoir que c'est là le problème?
Adelin
Il vous suffit de spécifier les dépendances à jackson-databind et jackson-mapper-asl, les deux autres sont des dépendances transitives et seront résolues de toute façon.
anre
1
Cela n'a fonctionné pour moi qu'après avoir ajouté les deux secondes dépendances. Merci.
DocWatson
Vous n'avez certainement pas besoin des deux. Spring ajoutera MappingJacksonHttpMessageConverterpour Jackson 1 et MappingJackson2HttpMessageConverterpour Jackson 2. Chacun d'eux est assez bon pour sérialiser / désérialiser JSON. Vous n'en avez besoin que d'un (optez pour Jackson 2 car il est plus riche en fonctionnalités).
Sotirios Delimanolis
16

Il y a un autre cas où ce statut sera retourné: si le mappeur Jackson ne peut pas comprendre comment sérialiser votre bean. Par exemple, si vous avez deux méthodes d'accès pour la même propriété booléenne, isFoo()et getFoo().

Ce qui se passe, c'est que MappingJackson2HttpMessageConverter de Spring appelle le StdSerializerProvider de Jackson pour voir s'il peut convertir votre objet. Au bas de la chaîne d'appels, StdSerializerProvider._createAndCacheUntypedSerializerjette un JsonMappingExceptionavec un message informatif. Cependant, cette exception est avalée StdSerializerProvider._createAndCacheUntypedSerializer, ce qui indique à Spring qu'il ne peut pas convertir l'objet. Ayant manqué de convertisseurs, Spring rapporte qu'il ne lui est pas donné d'en- Accepttête qu'il peut utiliser, ce qui est bien sûr faux lorsque vous le donnez */*.

Il y a un bogue pour ce comportement, mais il a été fermé comme "ne peut pas se reproduire": la méthode appelée ne déclare pas qu'elle peut lancer, donc avaler des exceptions est apparemment une solution appropriée (oui, c'était du sarcasme). Malheureusement, Jackson n'a pas de journalisation ... et il y a beaucoup de commentaires dans la base de code qui le souhaitent, donc je soupçonne que ce n'est pas le seul piège caché.

kdgregory
la source
Merci beaucoup! Je suis nouveau sur Spring MVC et j'avais vraiment du mal à trouver comment retourner JSON. Tout le monde mentionne les annotations @ResponseBody manquantes et les dépendances de Jackson comme étant la cause des erreurs 406. Dans mon cas, il s'est avéré que je manquais juste une méthode d'accesseur pour un champ public appartenant à l'objet que je voulais retourner en JSON.
Anthony Jack
Merci @kdgregory! J'ai oublié d'ajouter getter / setter pour un champ. Leur ajout a résolu ce problème.
Rubens Mariuzzo
16

J'ai eu le même problème, ma méthode de contrôleur s'exécute mais la réponse est l'erreur 406. J'ai débogué AbstractMessageConverterMethodProcessor#writeWithMessageConverterset j'ai trouvé que la méthode ContentNegotiationManager#resolveMediaTypesrenvoie toujours text/htmlce qui n'est pas pris en charge par MappingJacksonHttpMessageConverter. Le problème est que les org.springframework.web.accept.ServletPathExtensionContentNegotiationStrategytravaux antérieurs à org.springframework.web.accept.HeaderContentNegotiationStrategy, et l'extension de ma demande /get-clients.htmlest la cause de mon problème avec l'erreur 406. Je viens de changer l'URL de la demande en /get-clients.

atott
la source
Salut atott, j'ai le même problème et votre conseil sur la modification de l'extension de la demande a résolu mon problème. Merci beaucoup d'avoir partagé votre solution !!
jherranzm
Dans mon cas, c'était un identifiant de chemin de repos avec une extension (dans le test) qui a causé le 406 pour la même raison, tandis que le contrôleur normal fonctionne (même si vous deviez utiliser une extension dans l'identifiant de chemin de repos).
Jur_
9

Assurez-vous que les 2 suivants jarsont présents dans le chemin de classe.

Si l'un ou les deux sont manquants, cette erreur surviendra.

jackson-core-asl-1.9.X.jar jackson-mapper-asl-1.9.X.jar
Raju Rathi
la source
6

Enfin trouvé la réponse d'ici:

Cartographie des requêtes ajax reposantes au printemps

Je cite:

Les annotations @ RequestBody / @ ResponseBody n'utilisent pas de résolveurs de vue normaux, elles utilisent leurs propres HttpMessageConverters. Pour utiliser ces annotations, vous devez configurer ces convertisseurs dans AnnotationMethodHandlerAdapter, comme décrit dans la référence (vous avez probablement besoin de MappingJacksonHttpMessageConverter).

Jaanus
la source
3

Enregistrez-vous <mvc:annotation-driven />dans dispatcherservlet.xml, sinon ajoutez-le. Et ajouter

<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-core-asl</artifactId>
    <version>1.9.13</version>
</dependency>

<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-mapper-asl</artifactId>
    <version>1.9.13</version>
</dependency>

ces dépendances dans votre pom.xml

SHIVA
la source
2
<dependency>
    <groupId>com.fasterxml.jackson.jaxrs</groupId>
    <artifactId>jackson-jaxrs-base</artifactId>
    <version>2.6.3</version>
</dependency>
Rajan
la source
2
Bien que ce code puisse répondre à la question, fournir un contexte supplémentaire sur la manière et / ou la raison pour laquelle il résout le problème améliorerait la valeur à long terme de la réponse.
Francesco Menzani
2

Personne ne fait probablement défiler vers le bas aussi loin, mais aucune des solutions ci-dessus ne l'a résolu pour moi, mais toutes mes méthodes getter l'ont publicfait.

J'avais laissé ma visibilité getter à package-private; Jackson a décidé qu'il ne pouvait pas les trouver et a explosé. (En utilisant @JsonAutoDetect(getterVisibility=NON_PRIVATE)seulement partiellement corrigé.

Hazel Troost
la source
C'était exactement mon problème. Je change mes setters de public à protégé et Jackson a cessé de travailler.
JuanMiguel
Même problème ici, j'utilisais AbstractMap.SimpleImmutableEntrypuis rétrogradé à AbstractMap.SimpleEntry, toujours pas de dés car il n'a pas de setter pour la clé. Allé pojo là-dessus.
Robert Bain
2

Assurez-vous que l'objet envoyé (Weather dans ce cas) contient getter / setter

Riadh
la source
1

Dans le contrôleur, l'annotation du corps de la réponse ne devrait-elle pas être sur le type de retour et non sur la méthode, comme ceci:

@RequestMapping(value="/getTemperature/{id}", headers="Accept=*/*", method = RequestMethod.GET)
public @ResponseBody Weather getTemparature(@PathVariable("id") Integer id){
    Weather weather = weatherService.getCurrentWeather(id);
        return weather;
}

J'utiliserais également la fonction brute jquery.ajax et je m'assurerais que contentType et dataType sont définis correctement.

Sur une note différente, je trouve la manipulation du ressort de json plutôt problématique. C'était plus facile quand je faisais tout moi-même avec des cordes et GSON.

NimChimpsky
la source
Le placement de @ResponseBodyne devrait pas avoir d'importance ... Je vais examiner GSON ... mais j'aimerais toujours que ce JSON fonctionne si possible.
Jaanus
1

Comme @atott l'a mentionné .

Si vous avez ajouté la dernière version de Jackson dans votre pom.xml, et avec Spring 4.0 ou plus récent, en utilisant @ResponseBodyvotre méthode d'action et @RequestMappingconfigurée avec produces="application/json;charset=utf-8", cependant, vous avez toujours 406 (non acceptable), je suppose que vous devez essayer ceci dans votre configuration de contexte MVC DispatcherServlet:

<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager" />

<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
    <property name="favorPathExtension" value="false" />
</bean>

C'est ainsi que j'ai finalement résolu mon problème.

Corbeau
la source
1

Spring 4.3.10: J'ai utilisé les paramètres ci-dessous pour résoudre le problème.

Étape 1: ajoutez les dépendances ci-dessous

    <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.6.7</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.6.7</version>
</dependency>
<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-core-asl</artifactId>
    <version>1.9.13</version>
</dependency>
<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-mapper-asl</artifactId>
    <version>1.9.13</version>
</dependency>

Étape 2: ajoutez ce qui suit dans votre configuration de contexte MVC DispatcherServlet:

<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager"/>

<bean id="contentNegotiationManager"
    class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
    <property name="favorPathExtension" value="false"/>
    <property name="favorParameter" value="true"/>
    <property name="ignoreAcceptHeader" value="false" />
</bean>

Depuis le printemps 3.2, selon la configuration par défaut, favorPathExtension est défini sur true, à cause de cela, si l'URI de la requête a des extensions appropriées comme .htmspring donnera la priorité à l'extension. À l'étape 2, j'avais ajouté le bean contentNegotiationManager pour remplacer cela.

Kevin Sebastian Fernandez
la source
1

J'avais le même problème car il me manquait l'annotation @EnableWebMvc. (Toutes mes configurations de ressort sont basées sur les annotations, l'équivalent XML serait mvc: basé sur les annotations)

jambriz
la source
0

assurez-vous que vous avez la bonne version de jackson dans votre chemin de classe

joyfun
la source
J'ai ajouté jackson-all-1.8.5.jar à mon WEB-INF/libdossier, mais toujours le même problème: /
Jaanus
0

Vérifiez comme @joyfun l'a fait pour la bonne version de jackson mais vérifiez également nos en-têtes ... Acceptez / peut ne pas être transmis par le client ... utilisez firebug ou équivalent pour vérifier ce que votre demande get envoie réellement. Je pense que l'attribut headers de l'annotation / peut / vérifier les littéraux bien que je ne sois pas sûr à 100%.

Dave G
la source
J'ai ajouté les en-têtes de firebug au message principal. Est-ce qu'ils vont bien?
Jaanus
0

Outre les problèmes évidents, j'en avais un autre que je ne pouvais pas résoudre, sans tenir compte de tous les JAR, dépendances et annotations possibles dans le servlet Spring. Finalement, j'ai trouvé que j'avais une mauvaise extension de fichier, je veux dire que j'avais deux servlets séparés fonctionnant dans le même conteneur et que je devais mapper vers différentes extensions de fichiers où l'une était ".do" et l'autre, utilisée pour les abonnements, était nommée au hasard ". sous". Tout va bien mais SUB est une extension de fichier valide normalement utilisée pour les fichiers de sous-titres de films et donc Tomcat remplaçait l'en-tête et renvoyait quelque chose comme "text / x-dvd.sub ..." donc tout allait bien mais l'application attendait JSON mais obtenait des sous-titres donc tout ce que j'avais à faire est de changer le mappage dans mon web.xmlfichier que j'ai ajouté:

<mime-mapping>
    <extension>sub</extension>
    <mime-type>application/json</mime-type>
</mime-mapping>
Alex Rashkov
la source
0

J'ai eu le même problème, malheureusement, la solution ici n'a pas résolu mon problème car mon problème était quelque chose dans une classe différente.

J'ai d'abord vérifié que toutes les dépendances sont en place comme suggéré par @bekur, puis j'ai vérifié la demande / réponse qui voyage des clients au serveur, tous les en-têtes étaient en place et correctement définis par Jquery. J'ai ensuite vérifié RequestMappingHandlerAdapter MessageConverterset tous les 7 étaient en place, j'ai vraiment commencé à détester le printemps! J'ai ensuite mis à jour vers Spring 4.0.6.RELEASEpour 4.2.0.RELEASEavoir une autre réponse plutôt que celle ci-dessus. C'étaitRequest processing failed; nested exception is java.lang.IllegalArgumentException: No converter found for return value of type

Voici ma méthode de contrôleur

  @RequestMapping(value = "/upload", method = RequestMethod.POST,produces = "application/json")
    public ResponseEntity<UploadPictureResult> pictureUpload(FirewalledRequest initialRequest) {

        DefaultMultipartHttpServletRequest request = (DefaultMultipartHttpServletRequest) initialRequest.getRequest();

        try {
            Iterator<String> iterator = request.getFileNames();

            while (iterator.hasNext()) {
                MultipartFile file = request.getFile(iterator.next());
                session.save(toImage(file));
            }
        } catch (Exception e) {
            return new ResponseEntity<UploadPictureResult>(new UploadPictureResult(),HttpStatus.INTERNAL_SERVER_ERROR);
        }
        return new ResponseEntity<UploadPictureResult>(new UploadPictureResult(), HttpStatus.OK);
    } 




    public class UploadPictureResult extends WebResponse{

    private List<Image> images;

    public void setImages(List<Image> images) {
        this.images = images;
    }
}






    public class WebResponse implements Serializable {


    protected String message;

    public WebResponse() {
    }

    public WebResponse(String message) {

        this.message = message;
    }


    public void setMessage(String message) {
        this.message = message;
    }
}

La solution était de faire en sorte que UploadPictureResult ne prolonge pas WebResponse

Pour une raison quelconque, Spring n'a pas été en mesure de déterminer comment convertir UploadPictureReslt lors de l'extension de WebResponse

Adelin
la source
0
<dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.8.0</version>
    </dependency>

Je n'utilise pas d'authentification SSL et ce jackson-databind contient jackson-core.jar et jackson-databind.jar, puis changez le contenu RequestMapping comme ceci:

@RequestMapping(value = "/id/{number}", produces = "application/json; charset=UTF-8", method = RequestMethod.GET)
public @ResponseBody Customer findCustomer(@PathVariable int number){
    Customer result = customerService.findById(number);
    return result;
}

attention: si votre produit n'est pas de type "application / json" et que je ne l'avais pas remarqué et que j'avais une erreur 406, aidez-moi cela peut vous aider.

Crabe
la source
0

vérifiez ce fil. spring mvc restcontroller return json string p / s: vous devez ajouter la configuration de mappage jack son à votre classe WebMvcConfig

@Override protected void configureMessageConverters( List<HttpMessageConverter<?>> converters) { // put the jackson converter to the front of the list so that application/json content-type strings will be treated as JSON converters.add(new MappingJackson2HttpMessageConverter()); // and probably needs a string converter too for text/plain content-type strings to be properly handled converters.add(new StringHttpMessageConverter()); }

Anh Lam
la source
0

Ceci est la réponse de mise à jour pour springVersion = 5.0.3.RELEASE.

Les réponses ci-dessus ne seront traitées que dans les anciennes versions de springVersion <4.1 . pour le dernier printemps, vous devez ajouter les dépendances suivantes dans le fichier gradle:

compile group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: fasterxmljackson
compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: fasterxmljackson

fasterxmljackson=2.9.4

J'espère que cela sera utile pour ceux qui utilisent la dernière version du printemps.

Paraneetharan Saravanaperumal
la source
-3

Pouvez-vous supprimer l'élément headers dans @RequestMapping et essayer ...

Comme


@RequestMapping(value="/getTemperature/{id}", method = RequestMethod.GET)

Je suppose que le printemps fait un «contrôle contient» plutôt qu'une correspondance exacte pour accepter les en-têtes. Mais quand même, cela vaut la peine d'essayer de supprimer l'élément headers et de vérifier.

stratwine
la source
J'ai supprimé, mais toujours une erreur. Btw quand je regarde le journal tomcat, puis la requête avec cela a été weatherService.getCurrentWeather(id);"activée" ... donc quelque chose fonctionne ... est-il possible que 406 apparaisse et Hibernate SQL select fonctionne en même temps?
Jaanus
Veuillez essayer celui-ci, cela devrait fonctionner. Ajoutez cette annotation sur le contrôleur @RequestMapping (method = RequestMethod.GET, headers = {"Accept = text / xml, application / json"})
samedi