Spring MVC - HttpMediaTypeNotAcceptableException
Я продолжаю получать эту ошибку HttpMediaTypeNotAcceptableException для запросов AJAX при использовании с Spring MVC и JSON.. Полная трассировка стека ошибки...
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)
маленький googling. Я показал, что запрос должен содержать что-то вроде "accept: application/json", который есть.. вот заголовки запроса из firebug..
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
Теперь я полностью потерял то, что здесь происходит. Что еще может пойти не так, чтобы получить эту ошибку...
Ответы
Ответ 1
Пожалуйста, убедитесь, что в вашем 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 должны иметь геттеры/сеттеры.
Надеюсь, что это поможет.
Ответ 2
С:
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] довольно сложная: сервер приложений выполняет некоторое согласование контента и убеждает Spring, что браузер запросил контент "application/x-msdownload, несмотря на то, что он не встречается в запрос, отправленный браузером.
Решение состоит в том, чтобы указать менеджер согласования контента для контекста веб-приложения:
<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>
Ответ 3
Удостоверьтесь, что вы добавили банки Jackson в classpath:
- ДЖЕКСОНА-ядро-ASL-x.jar
- ДЖЕКСОНА-картографа-ASL-x.jar
Кроме того, в вашем Spring xml файле должно быть следующее:
<mvc:annotation-driven />
Ответ 4
Просто важно иметь в виду: Spring версии до 3.1.2 совместимы с JACKSON 1.x и NOT с JACKSON 2.x. Это происходит потому, что переход от JACKSON 1.x к 2.x был изменен имена пакетов классов. В JACKSON 1.x классы находятся под org.codehaus.jackson, тогда как в JACKSON 2.x они находятся под com.fasterxml.jackson.
Чтобы устранить эту проблему, начиная с Spring 3.1.2, они добавили новый MappingJackson2HttpMessageConverter для замены MappingJacksonHttpMessageConverter.
Вы можете найти более подробную информацию о проблемах совместимости в этой ссылке: Аннотации Джексона игнорируются в Spring
Ответ 5
Поскольку это первый хит Google для "HttpMediaTypeNotAcceptableException", мне нравится добавить еще одну проблему, на которую я наткнулся, в результате чего также возникло исключение HttpMediaTypeNotAcceptableException.
В моем случае это был контроллер, который указал "производит", например:
@RequestMapping(path = "/mypath/{filename}", method = RequestMethod.GET,
produces = { MediaType.APPLICATION_XML_VALUE }
потому что я хотел бы служить XML файлу. В то же время я использую класс с "@ControllerAdvice", чтобы поймать Исключения, например. если запрошенный файл не найден. Обработчик Exception возвращал JSON, поэтому приложение client (angular) могло отображать сообщение об ошибке где-то в SPA.
Теперь контроллер хотел вернуть XML, но обработчик исключений возвращал JSON, поэтому было создано исключение HttpMediaTypeNotAcceptableException. Я решил это, добавив JSON как возможное значение "производит":
produces = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE}
Надеюсь, это поможет кому-то другому.: -)
Ответ 6
в моем случае 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
}
}
Ответ 7
В классе 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");
}
И ошибка исчезнет.
Ответ 8
У меня была такая же проблема, но я понял, что в основном то, что происходит, когда spring пытается отобразить ответ, он попытается сериализовать его в соответствии с типом носителя, который вы указали, и используя методы getter и setter в ваш класс
, прежде чем мой класс будет выглядеть ниже
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;
}
}
как это сработало для меня
Ответ 9
Попробуйте добавить файлы "jackson-databind" в 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
Es. @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},...
Ответ 10
Как Alex, намеченный в одном из ответов, вы можете использовать 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 {
Вместо этого я решил изменить заголовок "Принять" запроса из браузера на "application/json", тем самым заставил SpringMVC найти мой метод.
Используя (еще не завершенный) API API для Javascript:
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
Et voilà! Теперь SpringMVC находит метод, проверяет форму и позволяет вернуть JJON POJO.
Ответ 11
В моем случае просто добавьте аннотацию @ResponseBody
, чтобы решить эту проблему.
Ответ 12
В моем случае
{"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}"
, но я передавал VariableName с суффиксом, например, "abc.xml", который заставляет его интерпретировать .xml как своего рода запрос формата вместо. Смотрите ответы там.
Ответ 13
Для меня проблемой был URL, к которому я пытался получить доступ. У меня был такой URL:
{{ip}}:{{port}}/{{path}}/person.html
Когда вы заканчиваете URL с помощью .html, это означает, что вы не примете никакой другой полезной нагрузки, кроме html. Мне нужно было удалить .html с конца, чтобы моя конечная точка работала правильно. (Вы также можете добавить .json в конце URL, и он тоже будет работать)
Кроме того, ваш URL-шаблон в web.xml
должен быть правильно настроен, чтобы вы могли получить доступ к ресурсу. Для меня это
<servlet-mapping>
<servlet-name>spring-mvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Раньше у меня был *.html*
, и он мешал мне получить доступ к конечной точке.
Ответ 14
Больше комментариев, чем ответа...
Я использую Lombok, и я разрабатывал (очень) скелетный API, и в моем ответе DTO не было никаких полей (пока), и я получил ошибку HttpMediaTypeNotAcceptableException
при выполнении моих интеграционных тестов.
Добавление поля в ответ DTO устранило проблему.
Ответ 15
response.setHeader("Accept", "application/json");