Spring MVC – HttpMediaTypeNotAcceptableException

Continuo a ricevere questo errore HttpMediaTypeNotAcceptableException per le richieste AJAX quando utilizzo con Spring MVC e JSON .. la traccia di stack completo dell’errore è ..

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 poco ho fatto mostra che la richiesta dovrebbe contenere qualcosa come “accept: application / json” che è ha .. ecco le intestazioni di richiesta da 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 

Ora sono completamente perso a quello che sta succedendo qui .. cos’altro può andare storto qui per ottenere questo errore …

Assicurati di avere quanto segue nel file xml di Spring:

          

e tutti gli oggetti del tuo POJO dovrebbero avere getter / setter. Spero che sia d’aiuto

Da: http://georgovassilis.blogspot.ca/2015/10/spring-mvc-rest-controller-says-406.html

Hai questo @RestController di spring e hai mappato un URL che contiene un’email come parte del percorso dell’URL. Hai astutamente lavorato attorno al problema del punto troncato [1] e sei pronto per il lancio. E improvvisamente, su alcuni URL, Spring restituirà un 406 [2] che dice che il browser ha richiesto un determinato tipo di contenuto e Spring non può serializzare la risposta a quel tipo di contenuto. Il punto è che hai fatto applicazioni Spring per anni e hai fatto tutte le dichiarazioni MVC giuste e hai incluso Jackson e sostanzialmente sei bloccato. Ancora peggio, sputerà questo errore solo su alcune e-mail nel percorso dell’URL, in particolare quelle che terminano con un dominio “.com”.

 @RequestMapping(value = "/agenda/{email:.+}", method = RequestMethod.GET) public List checkAgenda(@PathVariable("email") String email) 

Il problema [3] è piuttosto complicato: il server delle applicazioni esegue una parte della negoziazione del contenuto e convince Spring che il browser ha richiesto un contenuto “application / x-msdownload” , nonostante ciò non si sia verificato nella richiesta inoltrata dal browser.

La soluzione è specificare un gestore di negoziazione del contenuto per il contesto dell’applicazione Web:

          

Assicurati di aggiungere entrambi i vasi Jackson al classpath:

  • Jackson-core-asl-x.jar
  • jackson-mapper-ASL-x.jar

Inoltre, devi avere il seguente nel tuo file xml di Spring:

  

Solo qualcosa di importante da tenere a mente: le versioni Spring precedenti alla 3.1.2 sono compatibili con JACKSON 1.x e NOT con JACKSON 2.x. Questo perché passando da JACKSON 1.x a 2.x i nomi dei pacchetti delle classi sono stati modificati. Nelle classi JACKSON 1.x si trovano in org.codehaus.jackson mentre in JACKSON 2.x sono in com.fasterxml.jackson.

Per risolvere questo problema, a partire da Spring 3.1.2 è stato aggiunto un nuovo MappingJackson2HttpMessageConverter per sostituire MappingJacksonHttpMessageConverter.

Potresti trovare maggiori dettagli riguardo i problemi di compatibilità in questo link: le annotazioni di Jackson vengono ignorate in spring

Perché questo è il primo hit di Google per “HttpMediaTypeNotAcceptableException” Mi piace aggiungere un altro problema su cui sono incappato e che ha portato anche a HttpMediaTypeNotAcceptableException.

Nel mio caso è stato un controller che ha specificato “produce”, ad esempio:

 @RequestMapping(path = "/mypath/{filename}", method = RequestMethod.GET, produces = { MediaType.APPLICATION_XML_VALUE } 

perché volevo servire un file XML. Allo stesso tempo sto usando una class con “@ControllerAdvice” per catturare le eccezioni, ad esempio se il file richiesto non è stato trovato. Il gestore delle eccezioni stava restituendo JSON in modo che l’app client (angular) potesse visualizzare il messaggio di errore da qualche parte nella SPA.

Ora il controller voleva restituire XML, ma il gestore delle eccezioni restituiva JSON, quindi veniva sollevata l’eccezione HttpMediaTypeNotAcceptableException. Ho risolto questo aggiungendo JSON il più ansible valore “produce”:

 produces = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE} 

Spero che questo aiuti qualcun altro. 🙂

nel mio caso favorPathExtension (false) mi ha aiutato

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

}

Nella class Spring @Configuration che estende WebMvcConfigurerAdapter sovrascrive il metodo configureMessageConverters, ad esempio:

 @Override public void configureMessageConverters(List> 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"); } 

E l’errore sarà sparito.

Ho avuto lo stesso problema, ma avevo capito che in sostanza quello che succede quando Spring sta cercando di rendere la risposta cercherà di serializzarlo in base al tipo di media che hai specificato e usando i metodi getter e setter nella tua class

prima che la mia class assomigliasse di seguito

 public class MyRestResponse{ private String message; } 

la soluzione sembra di seguito

 public class MyRestResponse{ private String message; public void setMessage(String msg){ this.message = msg; } public String getMessage(){ return this.message; } } 

è così che ha funzionato per me

Prova ad aggiungere i vasi “jackson-databind” a pom.xml

 ` com.fasterxml.jackson.core jackson-databind ${jackson.databind-version} ` 

E produces ={MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE} su @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},...

Come Alex ha suggerito in una delle risposte, è ansible utilizzare ContentNegotiationManagerFactoryBean per impostare il tipo di contenuto predefinito su “application / json”, ma ho ritenuto che quell’approccio non fosse per me.

Quello che stavo cercando di fare era di pubblicare un modulo su un metodo come questo

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

Quello che invece ho scelto di fare è stato di cambiare l’intestazione “Accetta” della richiesta dal browser a “application / json”, facendo in modo che SpringMVC trovasse il mio metodo.

Utilizzo dell’API di recupero JavaScript (non ancora finalizzata):

 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à! Ora SpringMVC trova il metodo, convalida il modulo e consente di restituire un POJO JSON.

Nel mio caso, basta aggiungere @ResponseBody annotazione @ResponseBody per risolvere questo problema.

 response.setHeader("Accept", "application/json");