Spring JSON-Anforderung mit 406 (nicht akzeptabel)

84

Das ist mein Javascript:

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

Das ist mein Controller:

@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 />

Diesen Fehler erhalten:

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

Überschriften:

Antwortheader

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

Header anfordern

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

Interessanter Hinweis:

Ich erhalte den Fehler 406, aber die Abfrage im Ruhezustand funktioniert inzwischen. Dies sagt das Tomcat-Protokoll jedes Mal, wenn ich die Auswahl in der Dropbox ändere:

 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=?

Was könnte das Problem sein? Es gab zwei ähnliche Fragen in SO, ich habe alle akzeptierten Hinweise dort ausprobiert, aber sie haben nicht funktioniert, denke ich ...

Irgendwelche Vorschläge? Fühlen Sie sich frei, Fragen zu stellen ...

Jaanus
quelle

Antworten:

107

406 Nicht akzeptabel

Die durch die Anforderung identifizierte Ressource kann nur Antwortentitäten generieren, deren Inhaltsmerkmale gemäß den in der Anforderung gesendeten Akzeptanzheadern nicht akzeptabel sind.

Der Header für die Annahme Ihrer Anfrage lautet also application / json, und Ihr Controller kann dies nicht zurückgeben. Dies geschieht, wenn der richtige HTTPMessageConverter nicht gefunden werden kann, um den mit @ResponseBody kommentierten Rückgabewert zu erfüllen. HTTPMessageConverter werden automatisch registriert, wenn Sie die <mvc:annotation-driven>angegebenen Bibliotheken von Drittanbietern im Klassenpfad verwenden.

Entweder haben Sie nicht die richtige Jackson-Bibliothek in Ihrem Klassenpfad oder Sie haben die <mvc:annotation-driven>Direktive nicht verwendet .

Ich habe Ihr Szenario erfolgreich repliziert und es hat mit diesen beiden Bibliotheken und ohne headers="Accept=*/*"Direktive einwandfrei funktioniert .

  • jackson-core-asl-1.7.4.jar
  • jackson-mapper-asl-1.7.4.jar
Villu Sepman
quelle
Nein, das war nicht das Problem, überprüfe meine Antwort.
Jaanus
Wenn die manuelle Konfiguration von HttpMessageConverters Ihr Problem löste, würde die Verwendung von mvc: annotation-powered dasselbe tun, wie die Konverter und HandlerAdapters (HA) automatisch konfiguriert werden. Beachten Sie, dass bei einer expliziten Konfiguration eines HA alle anderen Standardeinstellungen gelöscht werden.
Villu Sepman
Hmm, was ist das mvcda? Ich benutzte <tx:annotation-driven />und tx istxmlns:tx="http://www.springframework.org/schema/tx"
Jaanus
1
Sie haben so etwas wie: <?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">und Spring-Web-3.0.x und Spring-Webmvc-3.0.x Gläser?
Villu Sepman
1
Ah, ich hatte diesen Schema dort nicht ... aber danke, das hat mir geholfen. Ich dachte, das tx:annotation-drivenist das gleiche wie mvc:annotation-driveoder etwas.
Jaanus
74

Ich hatte das gleiche Problem, ab Latest Spring 4.1.1 müssen Sie pom.xml folgende Gläser hinzufügen.

<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>

Stellen Sie außerdem sicher, dass Sie folgendes Glas haben:

<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, gemäß der Anforderung "Accept" -Header nicht akzeptabel

AKB
quelle
Diese Antwort ist die Maven-fähige Version der Top-Antwort und funktioniert perfekt! Maven-Ausnahmen könnten klarer sein, was tatsächlich unter der Haube vor sich geht.
Cotta
4
Können Sie angeben, wo dies in der offiziellen Dokumentation von Springs dokumentiert ist? Wie kann jemand wissen, dass dies das Problem ist?
Adelin
Sie müssen nur die Abhängigkeiten zu jackson-database und jackson-mapper-asl angeben, die anderen beiden sind transitive Abhängigkeiten und werden trotzdem aufgelöst.
Anre
1
Dies funktionierte nur für mich, nachdem die zweiten beiden Abhängigkeiten hinzugefügt wurden. Vielen Dank.
DocWatson
Beides braucht man definitiv nicht. Spring wird MappingJacksonHttpMessageConverterfür Jackson 1 und MappingJackson2HttpMessageConverterfür Jackson 2 hinzugefügt . Jedes dieser Elemente ist gut genug, um JSON zu serialisieren / deserialisieren. Sie brauchen nur eine (gehen Sie mit Jackson 2, da es mehr Funktionen bietet).
Sotirios Delimanolis
16

Es gibt einen anderen Fall, in dem dieser Status zurückgegeben wird: Wenn der Jackson-Mapper nicht herausfinden kann, wie Ihre Bean serialisiert werden soll. Wenn Sie beispielsweise zwei Zugriffsmethoden für dieselbe boolesche Eigenschaft haben isFoo()und getFoo().

Was passiert ist, dass der MappingJackson2HttpMessageConverter von Spring Jacksons StdSerializerProvider aufruft, um zu prüfen , ob er Ihr Objekt konvertieren kann. StdSerializerProvider._createAndCacheUntypedSerializerWirft am Ende der Anrufkette ein JsonMappingExceptionmit einer informativen Nachricht. Diese Ausnahme wird jedoch verschluckt StdSerializerProvider._createAndCacheUntypedSerializer, was Spring mitteilt, dass das Objekt nicht konvertiert werden kann. Spring hat keine Konverter mehr und meldet, dass ihm kein AcceptHeader zugewiesen wird, den er verwenden kann. Dies ist natürlich falsch, wenn Sie ihn geben */*.

Es gibt einen Fehler für dieses Verhalten, aber es wurde als "kann nicht reproduzieren" geschlossen: Die aufgerufene Methode deklariert nicht, dass es werfen kann, daher ist das Schlucken von Ausnahmen anscheinend eine angemessene Lösung (ja, das war Sarkasmus). Leider hat Jackson keine Protokollierung ... und es gibt viele Kommentare in der Codebasis, die dies wünschen. Ich vermute, dass dies nicht das einzige versteckte Problem ist.

kdgregory
quelle
Ich danke dir sehr! Ich bin neu bei Spring MVC und hatte es wirklich schwer herauszufinden, wie ich JSON zurückgeben kann. Alle erwähnen fehlende @ ResponseBody-Annotationen und Jackson-Abhängigkeiten als Ursache für 406 Fehler. In meinem Fall stellte sich heraus, dass mir nur eine Zugriffsmethode für ein öffentliches Feld fehlte, das zu dem Objekt gehört, das ich als JSON zurückgeben wollte.
Anthony Jack
Danke @kdgregory! Ich habe vergessen, Getter / Setter für ein Feld hinzuzufügen. Durch Hinzufügen wurde dieses Problem behoben.
Rubens Mariuzzo
16

Ich hatte das gleiche Problem, meine Controller-Methode wird ausgeführt, aber die Antwort lautet Fehler 406. Ich debuggte AbstractMessageConverterMethodProcessor#writeWithMessageConvertersund stellte fest, dass die Methode ContentNegotiationManager#resolveMediaTypesimmer zurückgibt, text/htmlwas nicht unterstützt wird MappingJacksonHttpMessageConverter. Das Problem ist, dass das org.springframework.web.accept.ServletPathExtensionContentNegotiationStrategyfrüher funktioniert als org.springframework.web.accept.HeaderContentNegotiationStrategyund die Erweiterung meiner Anfrage /get-clients.htmldie Ursache für mein Problem mit Fehler 406 ist. Ich habe gerade die Anforderungs-URL in geändert /get-clients.

atott
quelle
Hallo atott, ich habe das gleiche Problem und Ihr Tipp zum Ändern der Erweiterung der Anfrage hat mein Problem gelöst. Vielen Dank für das Teilen Ihrer Lösung!
jherranzm
In meinem Fall war es eine Ruhepfad-ID mit einer Erweiterung (im Test), die den 406 aus demselben Grund verursachte, während der normale Controller funktioniert (selbst wenn Sie eine Erweiterung in der Ruhepfad-ID verwenden würden).
Jur_
9

Stellen Sie sicher, dass die folgenden 2 jarim Klassenpfad vorhanden sind.

Wenn einer oder beide fehlen, tritt dieser Fehler auf.

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

Endlich Antwort von hier gefunden:

Abbildung erholsamer Ajax-Anfragen auf den Frühling

Ich zitiere:

@ RequestBody / @ ResponseBody-Annotationen verwenden keine normalen Ansichtsauflöser, sondern ihre eigenen HttpMessageConverter. Um diese Annotationen verwenden zu können, sollten Sie diese Konverter in AnnotationMethodHandlerAdapter konfigurieren, wie in der Referenz beschrieben (wahrscheinlich benötigen Sie MappingJacksonHttpMessageConverter).

Jaanus
quelle
3

Checken Sie <mvc:annotation-driven />in dispatcherservlet.xml ein, wenn Sie es nicht hinzufügen. Und hinzufügen

<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>

diese Abhängigkeiten in Ihrer pom.xml

SHIVA
quelle
2
<dependency>
    <groupId>com.fasterxml.jackson.jaxrs</groupId>
    <artifactId>jackson-jaxrs-base</artifactId>
    <version>2.6.3</version>
</dependency>
Rajan
quelle
2
Während dieser Code die Frage möglicherweise beantwortet, würde die Bereitstellung eines zusätzlichen Kontexts darüber, wie und / oder warum das Problem gelöst wird, den langfristigen Wert der Antwort verbessern.
System
2

Wahrscheinlich scrollt niemand so weit nach unten, aber keine der oben genannten Lösungen hat es für mich behoben, aber alle meine Getter-Methoden haben publices geschafft.

Ich hatte meine Getter-Sichtbarkeit bei package-private belassen. Jackson entschied, dass es sie nicht finden konnte und explodierte. (Mit @JsonAutoDetect(getterVisibility=NON_PRIVATE)nur teilweise behoben.

Hazel Troost
quelle
Das war genau mein Problem. Ich ändere meine Setter von öffentlich auf geschützt und Jackson hat aufgehört zu arbeiten.
Juan Miguel
Das gleiche Problem hier, das ich verwendet habe, wurde AbstractMap.SimpleImmutableEntrydann auf herabgestuft AbstractMap.SimpleEntry, immer noch keine Würfel, da es keinen Setter für den Schlüssel hat. Pojo darüber gegangen.
Robert Bain
2

Stellen Sie sicher, dass das gesendete Objekt (in diesem Fall Wetter) Getter / Setter enthält

Riadh
quelle
1

Sollte sich in der Steuerung die Annotation des Antwortkörpers nicht auf den Rückgabetyp und nicht auf die Methode beziehen, wie folgt:

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

Ich würde auch die rohe Funktion jquery.ajax verwenden und sicherstellen, dass contentType und dataType richtig eingestellt sind.

In einem anderen Sinne finde ich das Federhandling von json ziemlich problematisch. Es war einfacher, wenn ich alles selbst mit Strings und GSON gemacht habe.

NimChimpsky
quelle
Die Platzierung von @ResponseBodysollte keine Rolle spielen ... Ich werde mich mit GSON befassen ... möchte aber trotzdem, dass dieser JSON funktioniert, wenn möglich.
Jaanus
1

Wie @atott erwähnt .

Wenn Sie die neueste Version von Jackson in Ihre pom.xml aufgenommen haben und mit Spring 4.0 oder neuer, die @ResponseBodyIhre Aktionsmethode verwendet und mit @RequestMappingkonfiguriert haben produces="application/json;charset=utf-8", jedoch immer noch 406 (nicht akzeptabel) haben, müssen Sie dies wahrscheinlich ausprobieren Ihre MVC DispatcherServlet-Kontextkonfiguration:

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

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

Auf diese Weise habe ich mein Problem endgültig gelöst.

Rabe
quelle
1

Frühling 4.3.10: Ich habe die folgenden Einstellungen verwendet, um das Problem zu beheben.

Schritt 1: Fügen Sie die folgenden Abhängigkeiten hinzu

    <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>

Schritt 2: Fügen Sie Folgendes in Ihre MVC DispatcherServlet-Kontextkonfiguration ein:

<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>

Seit Spring 3.2 ist favorPathExtension gemäß der Standardkonfiguration auf true gesetzt. Wenn die Anforderung uri über geeignete Erweiterungen wie .htmspring verfügt, wird der Erweiterung Priorität eingeräumt. In Schritt 2 hatte ich die contentNegotiationManager-Bean hinzugefügt, um dies zu überschreiben.

Kevin Sebastian Fernandez
quelle
1

Ich hatte das gleiche Problem, weil mir die Annotation @EnableWebMvc fehlte. (Alle meine Federkonfigurationen basieren auf Anmerkungen, das XML-Äquivalent wäre mvc: annotationsgesteuert.)

Jambriz
quelle
0

Stellen Sie sicher, dass Sie die richtige Jackson-Version in Ihrem Klassenpfad haben

joyfun
quelle
Ich habe jackson-all-1.8.5.jar zu meinem WEB-INF/libOrdner hinzugefügt , aber immer noch das gleiche Problem: /
Jaanus
0

Überprüfen Sie, wie @joyfun es für die richtige Version von Jackson getan hat, aber überprüfen Sie auch unsere Header ... Akzeptieren / möglicherweise nicht vom Client übertragen ... Verwenden Sie Firebug oder ein Äquivalent, um zu überprüfen, was Ihre Get-Anfrage tatsächlich sendet. Ich denke, dass das Header-Attribut der Annotation / möglicherweise / Literale überprüft, obwohl ich nicht 100% sicher bin.

Dave G.
quelle
Ich habe die Header von Firebug zum Hauptbeitrag hinzugefügt. Sind sie in Ordnung?
Jaanus
0

Abgesehen von den offensichtlichen Problemen hatte ich ein anderes, das ich nicht beheben konnte, obwohl ich alle möglichen JARs, Abhängigkeiten und Anmerkungen in Spring Servlet aufgenommen hatte. Schließlich stellte ich fest, dass ich eine falsche Dateierweiterung habe, da ich meine, dass zwei separate Servlets im selben Container ausgeführt wurden und ich verschiedenen Dateierweiterungen zuordnen musste, wobei eine ".do" und die andere, wie sie für Abonnements verwendet wurde, zufällig benannt wurde ". sub ". Alles gut, aber SUB ist eine gültige Dateierweiterung, die normalerweise für Untertiteldateien von Filmen verwendet wird. Daher hat Tomcat den Header überschrieben und so etwas wie "text / x-dvd.sub ..." zurückgegeben. Alles war in Ordnung, aber die Anwendung erwartete JSON, bekam aber Untertitel Daher musste ich nur die Zuordnung in meiner web.xmlDatei ändern, die ich hinzugefügt habe:

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

Ich hatte das gleiche Problem, leider löste keine der hier aufgeführten Lösungen mein Problem, da mein Problem etwas in einer anderen Klasse war.

Ich habe zuerst überprüft, ob alle Abhängigkeiten vorhanden sind, wie von @bekur vorgeschlagen, und dann überprüft, ob die Anforderung / Antwort, die von Clients zum Server gesendet wird, alle Header vorhanden sind und von Jquery ordnungsgemäß festgelegt wurden. Ich überprüfte dann die RequestMappingHandlerAdapter MessageConvertersund alle 7 waren an Ort und Stelle, ich fing wirklich an, den Frühling zu hassen! Ich habe dann von Frühling 4.0.6.RELEASEauf aktualisiert, 4.2.0.RELEASEum eine andere Antwort als die oben genannte zu erhalten. Es warRequest processing failed; nested exception is java.lang.IllegalArgumentException: No converter found for return value of type

Hier ist meine Controller-Methode

  @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;
    }
}

Die Lösung bestand darin, UploadPictureResult so zu gestalten, dass WebResponse nicht erweitert wird

Aus irgendeinem Grund konnte spring nicht bestimmen, wie UploadPictureReslt konvertiert werden soll, als WebResponse erweitert wurde

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

Ich verwende keine SSL-Authentifizierung und diese Jackson-Datenbank enthält jackson-core.jar und jackson-database.jar und ändere dann den RequestMapping-Inhalt wie folgt:

@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;
}

Achtung: Wenn Ihr Produkt nicht vom Typ "application / json" ist und ich dies nicht bemerkt habe und einen 406-Fehler erhalten habe, kann Ihnen dies helfen.

Crabime
quelle
0

Überprüfen Sie diesen Thread. spring mvc restcontroller return json string p / s: Sie sollten Ihrer WebMvcConfig-Klasse eine Jack Son Mapping-Konfiguration hinzufügen

@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
quelle
0

Dies ist die Update-Antwort für springVersion = 5.0.3.RELEASE.

Diese obigen Antworten werden nur mit älteren Versionen von springVersion <4.1 bearbeitet . Für den letzten Frühling müssen Sie folgende Abhängigkeiten in die Gradle-Datei einfügen:

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

Ich hoffe, dies ist hilfreich für diejenigen, die die neueste Frühlingsversion verwenden.

Paraneetharan Saravanaperumal
quelle
-3

Können Sie das Header-Element in @RequestMapping entfernen und versuchen ..

Mögen


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

Ich denke, Spring führt eher eine "enthält Prüfung" als eine genaue Übereinstimmung für die Annahme von Headern durch. Trotzdem lohnt es sich, das Header-Element zu entfernen und zu überprüfen.

Stratwine
quelle
Ich habe entfernt, aber immer noch Fehler. Übrigens, wenn ich mir das Tomcat-Protokoll ansehe, dann wurde die Abfrage mit diesem weatherService.getCurrentWeather(id);"aktiviert" ... also funktioniert etwas ... ist es möglich, dass 406 angezeigt wird und SQL-Auswahl im Ruhezustand gleichzeitig funktioniert?
Jaanus
Bitte versuchen Sie dieses, es sollte funktionieren. Fügen Sie diese Anmerkung auf dem Controller @RequestMapping hinzu (method = RequestMethod.GET, headers = {"Accept = text / xml, application / json"})
sats