AJAX Spring MVCおよびJSONで使用する場合のリクエストに対して、このHttpMediaTypeNotAcceptableExceptionエラーが発生し続けます。エラーの完全なスタックトレースは..
org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter$ServletHandlerMethodInvoker.writeWithMessageConverters(AnnotationMethodHandlerAdapter.Java:1032)
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter$ServletHandlerMethodInvoker.handleResponseBody(AnnotationMethodHandlerAdapter.Java:972)
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter$ServletHandlerMethodInvoker.getModelAndView(AnnotationMethodHandlerAdapter.Java:921)
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.Java:438)
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.Java:424)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.Java:863)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.Java:792)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.Java:851)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.Java:756)
javax.servlet.http.HttpServlet.service(HttpServlet.Java:617)
javax.servlet.http.HttpServlet.service(HttpServlet.Java:717)
私がやった小さなグーグルは、リクエストが持っている「accept:application/json」のようなものを含むべきであることを示しています。
Response Headers
Server Apache-Coyote/1.1
Content-Type text/html;charset=utf-8
Content-Length 2503
Date Thu, 25 Aug 2011 21:00:05 GMT
Connection close
Request Headers
Host localhost:8080
User-Agent Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.20) Gecko/20110803 Firefox/3.6.20 (.NET CLR 3.5.30729)
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
Keep-Alive 115
Connection keep-alive
X-Requested-With XMLHttpRequest
Referer http://localhost:8080/legaldirectory/index.html
Cookie JSESSIONID=5C97DA19AED4D5FA17F4A58470FAA93B
今、私はここで何が起こっているのか完全に失われています。
Spring xmlファイルに次のものがあることを確認してください。
<context:annotation-config/>
<bean id="jacksonMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="jacksonMessageConverter"/>
</list>
</property>
</bean>
また、POJOのすべてのアイテムにはゲッター/セッターが必要です。それが役に立てば幸い
From: http://georgovassilis.blogspot.ca/2015/10/spring-mvc-rest-controller-says-406.html
これはSpring@ RestControllerであり、URLパスの一部として電子メールを含むURLをマップしました。ドット切り捨ての問題を巧妙に回避し[1]、ロールする準備ができました。そして突然、一部のURLでSpringは406 [2]を返します。これは、ブラウザーが特定のコンテンツタイプを要求し、Springはそのコンテンツへの応答をシリアル化できないことを示しますタイプ。ポイントは、あなたが長年Spring申請をしていて、すべてのMVC宣言を正しく行い、ジャクソンを含めて、基本的に行き詰まっているということです。さらに悪いことに、URLパスの一部の電子メール、特に「.com」ドメインで終わる電子メールでのみエラーが発生します。
@RequestMapping(value = "/agenda/{email:.+}", method = RequestMethod.GET)
public List<AgendaEntryDTO> checkAgenda(@PathVariable("email") String email)
問題[3]は非常にトリッキーです。アプリケーションサーバーはコンテンツネゴシエーションを実行し、ブラウザが "application/x-msdownload"コンテンツを要求したことをSpringに納得させます。それにもかかわらず、ブラウザが実際に送信したリクエストのどこにも発生しません。
解決策は、Webアプリケーションコンテキストのコンテンツネゴシエーションマネージャーを指定することです。
<mvc:annotation-driven enable-matrix-variables="true"
content-negotiation-manager="contentNegotiationManager" />
<bean id="contentNegotiationManager"
class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="defaultContentType" value="application/json" />
<property name="favorPathExtension" value="false" />
<property name="favorParameter" value="false" />
<property name="parameterName" value="mediaType" />
<property name="ignoreAcceptHeader" value="false" />
<property name="useJaf" value="false" />
</bean>
両方のJackson jarをクラスパスに追加してください:
また、Spring xmlファイルには次のものが必要です。
<mvc:annotation-driven />
心に留めておくべき重要なこと:3.1.2より前のSpringバージョンはJACKSON 1.xと互換性があり、JACKSON 2.xとは互換性がありません。これは、JACKSON 1.xから2.xに移行すると、クラスのパッケージ名が変更されたためです。 JACKSON 1.xではクラスはorg.codehaus.jacksonの下にあり、JACKSON 2.xではクラスはcom.fasterxml.jacksonの下にあります。
この問題に対処するため、Spring 3.1.2以降では、MappingJacksonHttpMessageConverterに代わる新しいMappingJackson2HttpMessageConverterを追加しました。
このリンクで互換性の問題に関する詳細を見つけることができます: JacksonアノテーションはSpringでは無視されます
これは「HttpMediaTypeNotAcceptableException」の最初のグーグルヒットであるため、つまずき、HttpMediaTypeNotAcceptableExceptionも発生させた別の問題を追加したいと思います。
私の場合、それは「プロデュース」を指定したコントローラーでした。例えば:
@RequestMapping(path = "/mypath/{filename}", method = RequestMethod.GET,
produces = { MediaType.APPLICATION_XML_VALUE }
xMLファイルを提供したかったからです。同時に、「@ ControllerAdvice」を持つクラスを使用して例外をキャッチしています。要求されたファイルが見つからなかった場合。例外ハンドラーはJSONを返していたため、クライアント(角度付き)アプリはSPAのどこかにエラーメッセージを表示できました。
これで、コントローラーはXMLを返したいが、例外ハンドラーがJSONを返していたため、HttpMediaTypeNotAcceptableExceptionが発生しました。 JSONを可能な「プロデュース」値として追加することでこれを解決しました。
produces = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE}
これが他の誰かに役立つことを願っています。 :-)
私の場合favorPathExtension(false)助けて
@Configuration
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer
.setUseSuffixPatternMatch(false); // to use special character in path variables, for example, `[email protected]`
}
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer
.favorPathExtension(false); // to avoid HttpMediaTypeNotAcceptableException on standalone Tomcat
}
}
Springで@ Configurationを拡張するクラスWebMvcConfigurerAdapterメソッドconfigureMessageConvertersをオーバーライドします。たとえば:
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
// http
HttpMessageConverter converter = new StringHttpMessageConverter();
converters.add(converter);
logger.info("HttpMessageConverter added");
// string
converter = new FormHttpMessageConverter();
converters.add(converter);
logger.info("FormHttpMessageConverter added");
// json
converter = new MappingJackson2HttpMessageConverter();
converters.add(converter);
logger.info("MappingJackson2HttpMessageConverter added");
}
そして、エラーはなくなります。
私は同じ問題を抱えていましたが、基本的には、春が応答をレンダリングしようとすると、指定したメディアタイプに応じて、クラスでゲッターメソッドとセッターメソッドを使用してそれをシリアル化しようとすることがわかりました
私のクラスが以下のようになる前
public class MyRestResponse{
private String message;
}
解決策は以下のようになります
public class MyRestResponse{
private String message;
public void setMessage(String msg){
this.message = msg;
}
public String getMessage(){
return this.message;
}
}
それは私のために働いた方法です
「jackson-databind」jarをpom.xmlに追加してみてください
`<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.databind-version}</version>
</dependency>`
そして、produces ={MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE}
から@RequestMapping
エス@RequestMapping(value = "/api/xxx/{akey}/{md5}", produces ={MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE}
@RequestMapping(value = "/api/contrassegno/{akey}/{md5}", produces ={MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE},...
答えよりもコメントの方が...
私はLombokを使用しており、(非常に)スケルトンAPIを開発しており、応答DTOには(まだ)フィールドがなく、統合テストの実行中にHttpMediaTypeNotAcceptableException
エラーが発生しました。
応答DTOにフィールドを追加すると、問題が修正されました。
私の場合
{"timestamp":1537542856089,"status":406,"error":"Not Acceptable","exception":"org.springframework.web.HttpMediaTypeNotAcceptableException","message":"Could not find acceptable representation","path":"/a/101.xml"}
原因は:
path = "/path/{VariableName}"
しかし、 "abc.xml"のようなサフィックス付きのVariableNameを渡していました。これにより、.xmlを フォーマットリクエスト のようなものとして解釈します。回答をご覧ください。
Alex 回答の1つで示唆されているように、ContentNegotiationManagerFactoryBeanを使用してデフォルトのコンテンツタイプを「application/json」に設定できますが、そのアプローチは私には向かないと感じました。
私がやろうとしていたのは、このようなメソッドにフォームを投稿することでした
@RequestMapping(value = "/post/to/me", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public @ResponseBody MyJsonPOJO handlePostForm(@Valid @ModelAttribute("form") ValidateMeForm form, BindingResult bindingResult) throws ApiException {
私が代わりに選んだのは、ブラウザからのリクエストの「Accept」ヘッダーを「application/json」に変更し、SpringMVCに私のメソッドを見つけさせることでした。
(まだ完成していない)Javascript Fetch APIを使用する:
var form = new FormData();
form.append("myData", "data");
let fetchConfig = {
method: "POST",
body: form,
headers: {"Accept": "application/json"}
};
fetch("/post/to/me", fetchConfig)
.then(... // Javascript Promise API here
ほら!これで、SpringMVCはメソッドを見つけてフォームを検証し、JSON POJOを返すことができます。
私の場合、この問題を解決するには、@ResponseBody
注釈を追加するだけです。
私にとって問題は、アクセスしようとしたURLでした。私はこのようなURLを持っていました:
{{ip}}:{{port}}/{{path}}/person.html
Urlを.htmlで終了すると、html以外のペイロードを受け入れないことを意味します。エンドポイントが正しく機能するためには、末尾から.htmlを削除する必要がありました。 (URLの最後に.jsonを追加することもできます。これも機能します)
さらに、web.xml
のurl-patternを適切に構成して、リソースにアクセスできるようにする必要があります。私にとっては
<servlet-mapping>
<servlet-name>spring-mvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
以前は*.html*
があり、エンドポイントへのアクセスを妨げていました。