web-dev-qa-db-fra.com

Demande JSON de printemps obtenant 406 (non acceptable)

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

En-têtes de demande

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:

Je reçois une erreur 406, mais la requête de veille prolongée fonctionne pendant ce temps. Voici ce que dit le journal Tomcat, à chaque fois que je change de sélection dans la liste déroulante:

 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 auparavant, j'ai essayé tous les conseils acceptés, mais ils ne fonctionnaient pas, je suppose ...

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

77
Jaanus

406 Inacceptable

La ressource identifiée par la requête est uniquement capable de générer des entités de réponse dont les caractéristiques de contenu ne sont pas acceptables selon les en-têtes d'acceptation envoyés dans la requête.

Ainsi, votre requête accept header est application/json et votre contrôleur ne peut pas la renvoyer. Cela se produit lorsque le HTTPMessageConverter correct ne peut pas être trouvé pour satisfaire la valeur de retour annotée @ResponseBody. HTTPMessageConverter est automatiquement enregistré lorsque vous utilisez le <mvc:annotation-driven>, en fonction de certaines bibliothèques de parties 3D dans le chemin d'accès aux classes.

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

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

  • jackson-core-asl-1.7.4.jar
  • jackson-mapper-asl-1.7.4.jar
103
Villu Sepman

J'ai eu le même problème, avec Latest Spring 4.1.1, vous devez ajouter les fichiers jars 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 bocal 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 la requête "accepter" les en-têtes

71
bekur

Il existe un autre cas où cet état sera renvoyé: si le mappeur de Jackson ne peut pas déterminer 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 Jackson appelle StdSerializerProvider de Jackson pour voir s'il peut convertir votre objet. Au bas de la chaîne d'appels, StdSerializerProvider._createAndCacheUntypedSerializer jette une JsonMappingException avec un message informatif. Cependant, cette exception est avalée par StdSerializerProvider._createAndCacheUntypedSerializer, qui indique à Spring qu'il ne peut pas convertir l'objet. Ayant épuisé ses convertisseurs, Spring signale qu’il ne peut pas utiliser d’en-tête Accept, ce qui bien sûr est faux lorsque vous lui donnez */*.

Il y a un bug pour ce comportement, mais il a été fermé car "ne peut pas reproduire": la méthode appelée ne déclare pas qu'elle peut lancer, donc avaler des exceptions est apparemment une solution appropriée ). Malheureusement, Jackson n’a pas de logging ... et il y a beaucoup de commentaires dans la base de code qui le souhaiteraient, alors je suppose que ce n’est pas le seul piège caché.

15
kdgregory

J'ai eu le même problème, ma méthode de contrôleur s'exécute mais la réponse est Erreur 406 . J'ai débogué AbstractMessageConverterMethodProcessor#writeWithMessageConverters et constaté que la méthode ContentNegotiationManager#resolveMediaTypes renvoie toujours text/html qui n'est pas pris en charge par MappingJacksonHttpMessageConverter. Le problème est que le org.springframework.web.accept.ServletPathExtensionContentNegotiationStrategy fonctionne avant le org.springframework.web.accept.HeaderContentNegotiationStrategy et que l'extension de ma requête /get-clients.html est la cause de mon problème avec l'erreur 406. Je viens de changer l'URL de la requête en /get-clients.

14
atott

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

Si un ou les deux sont manquants alors cette erreur viendra.

jackson-core-asl-1.9.X.jar jackson-mapper-asl-1.9.X.jar
9
Raju Rathi

Enfin trouvé la réponse d'ici:

Cartographie des demandes ajax reposantes pour le printemps

Je cite:

Les annotations @ RequestBody/@ ResponseBody n'utilisent pas les résolveurs de vue normaux, ils 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).

5
Jaanus

Vérifiez <mvc:annotation-driven /> dans dispatcherservlet.xml, sinon ajoutez-le . Et ajoutez 

<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 

3
SHIVA
<dependency>
    <groupId>com.fasterxml.jackson.jaxrs</groupId>
    <artifactId>jackson-jaxrs-base</artifactId>
    <version>2.6.3</version>
</dependency>
2
Rajan

Personne n’a probablement fait défiler la liste aussi loin, mais aucune des solutions ci-dessus n’a été corrigée, mais toutes mes méthodes getter public l’ont été.

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

1
Hazel Troost

Comme @atott mentionné .

Si vous avez ajouté la dernière version de Jackson dans votre pom.xml et que vous utilisez Spring 4.0 ou une version plus récente, utilisez @ResponseBody sur votre méthode d'action et @RequestMapping configuré avec produces="application/json;charset=utf-8". Toutefois, vous avez toujours 406 (Inacceptable), essayez 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.

1
Raven

J'avais le même problème car il me manquait l'annotation @EnableMvc. (Toute ma configuration printanière est basée sur des annotations, l'équivalent XML serait mvc: piloté par des annotations)

1
jambriz

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

@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 raw jquery.ajax et m'assurerais que contentType et dataType sont définis correctement.

Sur une note différente, je trouve la manipulation au printemps de json plutôt problématique. C'était plus facile quand j'ai tout fait moi-même en utilisant des chaînes et GSON.

1
NimChimpsky

Printemps 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, favorPathExtension a pour valeur true la configuration par défaut. De ce fait, si la requête a des extensions appropriées telles que .htm spring, la priorité sera donnée à l'extension. À l'étape 2, j'avais ajouté le bean contentNegotiationManager pour remplacer cela.

J'ai eu le même problème, malheureusement, pas de la solution ici 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 Ensuite, j'ai vérifié la requête/réponse transmise par les clients au serveur. Tous les en-têtes étaient correctement configurés par Jquery. J'ai ensuite vérifié la RequestMappingHandlerAdapterMessageConverters et les 7 d'entre eux étaient en place, j'ai vraiment commencé à détester le printemps! J'ai ensuite mis à jour à partir de Spring 4.0.6.RELEASE à 4.2.0.RELEASE J'ai une autre réponse plutôt que celle ci-dessus. C'était Request 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 consistait à faire en sorte que UploadPictureResult ne prolonge pas WebResponse 

Pour une raison quelconque, spring n'a pas pu déterminer comment convertir UploadPictureReslt lorsqu'il a étendu WebResponse. 

0
Adelin

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

Les réponses ci-dessus ne seront travaillées que par le passé springVersion <4.1 version . 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 qui utilise la dernière version du printemps.

En plus des problèmes évidents, j’en ai un autre que je ne pourrais pas résoudre, même si tous les fichiers JAR, dépendances et annotations possibles étaient inclus dans la servlet Spring. Finalement, j’ai trouvé que j’avais une mauvaise extension de fichier, c’est-à-dire que j’avais deux servlets distincts fonctionnant dans le même conteneur et que je devais mapper vers différentes extensions de fichiers où l’un était ".do" et l’autre utilisé pour les abonnements était nommé de manière aléatoire ". sous". Tout va bien, mais SUB est une extension de fichier valide normalement utilisée pour les fichiers de sous-titres de films. Tomcat remplaçait ainsi 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. tout ce que je devais faire était donc de changer le mappage dans mon fichier web.xml que j'avais ajouté:

<mime-mapping>
    <extension>sub</extension>
    <mime-type>application/json</mime-type>
</mime-mapping>
0
infinity

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

0
Dave G
<dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.8.0</version>
    </dependency>

je n'utilise pas l'authentification ssl et ce jackson-databind contient jackson-core.jar et jackson-databind.jar, puis change le contenu de RequestMapping de la manière suivante:

@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 du type "application/json" et que je ne l’avais pas remarqué et que j’ai eu une erreur 406, aidez-moi, cela peut vous aider.

0
Crabime

assurez-vous d'avoir la bonne version jackson dans votre classpath

0
joyfun

vérifier ce fil . spring mvc restcontroller retour json string p/s: vous devez ajouter la configuration de mappage de fils jack à 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()); }

0
Anh Lam

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

0
Riadh