web-dev-qa-db-ja.com

Spring JSONリクエストは406を受け取ります(受け入れられません)

これは私のjavascriptです:

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

これは私のコントローラーです:

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

このエラーの取得:

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

ヘッダー:

応答ヘッダー

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

リクエストヘッダー

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

興味深いメモ:

406エラーが発生しますが、休止状態クエリはその間動作します。これは、Dropboxで選択を変更するたびにTomcatログに記録される内容です。

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

問題は何でしょうか? SOには2つの同様の質問がありました。受け入れられたすべてのヒントを試しましたが、うまくいかなかったと思います...

助言がありますか?気軽に質問してください...

81
Jaanus

406不可

要求によって識別されたリソースは、要求で送信された受け入れヘッダーに従って受け入れられないコンテンツ特性を持つ応答エンティティを生成することができるだけです。

したがって、リクエストの受け入れヘッダーはapplication/jsonであり、コントローラーはそれを返すことができません。これは、@ ResponseBodyアノテーション付きの戻り値を満たす正しいHTTPMessageConverterが見つからない場合に発生します。 HTTPMessageConverterは、<mvc:annotation-driven>を使用すると、クラスパスに特定の3-dパーティライブラリが指定されると自動的に登録されます。

クラスパスに正しいジャクソンライブラリがないか、<mvc:annotation-driven>ディレクティブを使用していません。

シナリオの複製に成功し、これらの2つのライブラリを使用してheaders="Accept=*/*"ディレクティブを使用せずに正常に機能しました。

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

最新のSpring 4.1.1以降では、pom.xmlに次のjarを追加する必要があるため、同じ問題がありました。

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

また、次のjarファイルがあることを確認してください。

<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、 "accept"ヘッダーの要求に従って受け入れられない

73
bekur

このステータスが返される別のケースがあります:ジャクソンマッパーがBeanをシリアル化する方法を見つけられない場合。たとえば、同じブール型プロパティに2つのアクセサメソッドがある場合、isFoo()getFoo()です。

起こっているのは、Springの MappingJackson2HttpMessageConverter がJacksonの StdSerializerProvider を呼び出して、オブジェクトを変換できるかどうかを確認することです。呼び出しチェーンの下部で、StdSerializerProvider._createAndCacheUntypedSerializerは情報メッセージを含むJsonMappingExceptionをスローします。ただし、この例外はStdSerializerProvider._createAndCacheUntypedSerializerによって飲み込まれ、オブジェクトを変換できないことをSpringに伝えます。 Springはコンバーターを使い果たして、使用できるAcceptヘッダーが与えられていないことを報告しています。もちろん、それを*/*に与えると、これは偽物です。

この動作には bug がありますが、「再現できない」として閉じられました:呼び出されているメソッドはスローできることを宣言していないため、例外を飲み込むことは明らかに適切な解決策です(はい、それは皮肉だった)。残念ながら、ジャクソンにはロギングがありません...そして、コードベースにはそれを望む多くのコメントがありますので、これが唯一の隠された落とし穴ではないと思います。

15
kdgregory

同じ問題があり、コントローラーメソッドは実行されますが、応答はエラー406です。AbstractMessageConverterMethodProcessor#writeWithMessageConvertersをデバッグすると、ContentNegotiationManager#resolveMediaTypesメソッドが常にMappingJacksonHttpMessageConverterでサポートされていないtext/htmlを返すことがわかりました。問題は、org.springframework.web.accept.ServletPathExtensionContentNegotiationStrategyorg.springframework.web.accept.HeaderContentNegotiationStrategyよりも早く動作し、リクエスト/get-clients.htmlの拡張がエラー406の問題の原因であるということです。リクエストURLを/get-clientsに変更しました。

14
atott

次の2 jarがクラスパスに存在することを確認してください。

いずれかまたは両方が欠落している場合、このエラーが発生します。

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

最後にここから答えを見つけました:

Restful AjaxリクエストをSpringにマッピングする

引用:

@ RequestBody/@ ResponseBodyアノテーションは通常のビューリゾルバーを使用せず、独自のHttpMessageConvertersを使用します。これらの注釈を使用するには、リファレンスで説明されているように、AnnotationMethodHandlerAdapterでこれらのコンバーターを構成する必要があります(おそらくMappingJacksonHttpMessageConverterが必要です)。

6
Jaanus

Dispatcherservlet.xmlの<mvc:annotation-driven />を確認します(追加しない場合)。そして追加

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

pom.xmlのこれらの依存関係

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

おそらくここまでスクロールダウンしている人はいないでしょうが、上記の解決策のどれも私のためにそれを修正しませんでしたが、すべてのゲッターメソッドをpublicにしました。

ゲッターの可視性はpackage-privateのままにしておきました。ジャクソンは彼らを見つけることができないと判断し、爆発した。 (@JsonAutoDetect(getterVisibility=NON_PRIVATE)を使用すると、部分的にのみ修正されます。

1
Hazel Troost

@atott 言及 として。

最新バージョンのJacksonをpom.xmlに追加し、Spring 4.0以降では、アクションメソッドで@ResponseBodyを使用し、@RequestMappingで構成されたproduces="application/json;charset=utf-8"を使用している場合でも、 406(Not Acceptable)になりました。MVCDispatcherServletコンテキスト構成でこれを試してみる必要があると思います。

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

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

それが最終的に私の問題を解決した方法です。

1
Raven

@EnableWebMvcアノテーションが欠落していたため、同じ問題が発生していました。 (私のスプリング構成はすべて注釈ベースであり、XMLに相当するものはmvc:annotation-drivenです)

1
jambriz

コントローラーでは、応答本体の注釈をメソッドではなく戻り値の型にしないでください。

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

また、生のjquery.ajax関数を使用し、contentTypeとdataTypeが正しく設定されていることを確認します。

別の注意として、jsonの春の扱いにはかなり問題があると思います。文字列とGSONを使用してすべて自分でやったほうが簡単でした。

1
NimChimpsky

送信されたオブジェクト(この場合は天気)にゲッター/セッターが含まれていることを確認します

1
Riadh

Spring 4.3.10:以下の設定を使用して問題を解決しました。

ステップ1:以下の依存関係を追加します

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

ステップ2: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>

Spring 3.2以降、デフォルトの設定では、favorPathExtensionがtrueに設定されています。このため、リクエストURIに.htm springのような適切な拡張機能がある場合、拡張機能が優先されます。ステップ2では、これをオーバーライドするためにcontentNegotiationManager Beanを追加しました。

私の問題は別のクラスのものであったため、残念ながらここでの解決策ではない同じ問題を抱えていました。

最初に、@ bekurが示唆するようにすべての依存関係が適切であることを確認し、クライアントからサーバーに移動する要求/応答を確認しました。すべてのヘッダーはJqueryによって適切に設定されました。それからRequestMappingHandlerAdapterMessageConvertersを確認しましたが、そのうちの7つがすべて揃っていたので、Springが嫌いになり始めました。その後、Spring 4.0.6.RELEASEから4.2.0.RELEASEに更新しました。上記以外の別の応答があります。 Request processing failed; nested exception is Java.lang.IllegalArgumentException: No converter found for return value of typeでした

ここに私のコントローラーメソッドがあります

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

解決策は、UploadPictureResultがWebResponseを拡張しないようにすることでした

何らかの理由で、SpringはWebResponseを拡張したときにUploadPictureResltを変換する方法を決定できませんでした

0
Adelin

これは、springVersion = 5.0.3.RELEASEの更新回答です

上記の回答は、古いspringVersion <4.1 versionでのみ機能します。最新の春には、次の依存関係を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

これが最新の春バージョンを使用している人に役立つことを願っています。

それ以外の明らかな問題は、SpringサーブレットにすべてのJAR、依存関係、および注釈を含めても修正できない別の問題がありました。最終的に、同じコンテナで実行されている2つの別個のサーブレットがあり、一方が「.do」で、もう一方がサブスクリプションに使用されるランダムな名前の「異なる」ファイル拡張子にマッピングする必要があるため、ファイル拡張子が間違っていることがわかりました。サブ"。 SUB以外はすべて良いが、通常は映画の字幕ファイルに使用される有効なファイル拡張子であるため、Tomcatはヘッダーをオーバーライドして「text/x-dvd.sub ...」などを返していたため、すべては正常でしたが、アプリケーションはJSONを期待していましたが、字幕を取得していましたしたがって、私がしなければならなかったのは、追加したweb.xmlファイルのマッピングを変更することだけです。

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

Jacksonの正しいバージョンについて@joyfunが行ったように確認しますが、ヘッダーも確認します... Accept /がクライアントによって送信されない可能性があります... firebugまたは同等のものを使用してgetリクエストが実際に何であるかを確認送信。注釈/ may /のheaders属性はリテラルをチェックしていると思いますが、100%確信はありません。

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

私はSSL認証を使用せず、このjackson-databindにはjackson-core.jarとjackson-databind.jarが含まれており、RequestMappingのコンテンツを次のように変更します。

@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:あなたのプロデュースが「application/json」タイプではなく、これに気づかずに406エラーが発生した場合、これがあなたを助けることができるのを助けてください。

0
Crabime

クラスパスに正しいジャクソンバージョンがあることを確認してください

0
joyfun

このスレッドを確認してください。 spring mvc restcontroller return json string p/s:ジャックソンマッピング設定を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