I have got a rather obscure issue which I am not able to figure out after days of debugging. The issue is one of our PUT REST API started throwing Unsupported Media type
in production. Here is the definition of method:
@RequestMapping(value = "/v1/put/user/profile", method = RequestMethod.PUT)
public String updateProfile(@RequestBody UserAndroid user, ModelMap model,
HttpServletRequest request, HttpServletResponse response) {
}
In the PUT request, we are just passing the mobile number as follows:
{ "mobile": "9999559848"}
Here is the UserAndroid entity:
https://gist.github.com/madhur/eb0d9d006f4e4da706d7
Now, the most surprising part. After tracing down the github commits, we traced down the error to this newly introduced field in User
(not the UserAndroid
. they are different but related) entity (https://gist.github.com/madhur/06bbcfe11c0e751ab4df) :
@OneToOne(mappedBy="user", fetch=FetchType.LAZY)
private FullContactDetails fullContactDetails;
If we remove this field, the API starts working fine. Can anyone enlighten me why is this happening?
Update: Here are the Spring MVC logs upon executing the request:
https://gist.github.com/madhur/ef357f614b18c6ed42cb
Using Spring 3.2.2. Yes, we have both gson-2.2.4.jar and jackson in classpath.
24 Mar 2015 20:15:14 > org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter - Opening JPA EntityManager in OpenEntityManagerInViewFilter
24 Mar 2015 20:15:14 > org.springframework.transaction.support.TransactionSynchronizationManager - Bound value [org.springframework.orm.jpa.EntityManagerHolder@6427300a] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@47672d99] to thread [http-bio-8080-exec-3]
24 Mar 2015 20:15:14 > org.springframework.web.servlet.DispatcherServlet - Bound request context to thread: org.apache.struts2.dispatcher.StrutsRequestWrapper@5927198c
24 Mar 2015 20:15:14 > org.springframework.web.servlet.DispatcherServlet - DispatcherServlet with name 'mvc' processing PUT request for [/mobileapp/v1/put/user/profile.json]
24 Mar 2015 20:15:14 > org.springframework.web.servlet.DispatcherServlet - Testing handler map [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping@3bf55f38] in DispatcherServlet with name 'mvc'
24 Mar 2015 20:15:14 > org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Looking up handler method for path /mobileapp/v1/put/user/profile.json
24 Mar 2015 20:15:14 > org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Found 1 matching mapping(s) for [/mobileapp/v1/put/user/profile.json] : [{[/mobileapp/v1/put/user/profile.*],methods=[PUT],params=[],headers=[],consumes=[],produces=[],custom=[]}]
24 Mar 2015 20:15:14 > org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Returning handler method [public java.lang.String com.lsa.akosha.webservices.MobileAppServiceController.updateProfile(com.lsa.akosha.entity.UserAndroid,org.springframework.ui.ModelMap,javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)]
24 Mar 2015 20:15:14 > org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'mobileAppServiceController'
24 Mar 2015 20:15:14 > org.springframework.web.servlet.DispatcherServlet - Testing handler adapter [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter@439ee876]
24 Mar 2015 20:15:14 > org.springframework.transaction.support.TransactionSynchronizationManager - Retrieved value [org.springframework.orm.jpa.EntityManagerHolder@6427300a] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@47672d99] bound to thread [http-bio-8080-exec-3]
24 Mar 2015 20:15:14 > org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy - Connecting to database for operation 'prepareStatement'
24 Mar 2015 20:15:14 > org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy - Using existing database connection for operation 'isClosed'
24 Mar 2015 20:15:14 > org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy - Using existing database connection for operation 'getAutoCommit'
24 Mar 2015 20:15:14 > org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy - Using existing database connection for operation 'isClosed'
24 Mar 2015 20:15:14 > org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy - Using existing database connection for operation 'getWarnings'
24 Mar 2015 20:15:14 > org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy - Using existing database connection for operation 'clearWarnings'
24 Mar 2015 20:15:14 > org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy - Using existing database connection for operation 'close'
24 Mar 2015 20:15:14 > org.springframework.web.method.support.HandlerMethodArgumentResolverComposite - Testing if argument resolver [org.springframework.web.method.annotation.RequestParamMethodArgumentResolver@18d649bf] supports [class com.lsa.akosha.entity.UserAndroid]
24 Mar 2015 20:15:14 > org.springframework.web.method.support.HandlerMethodArgumentResolverComposite - Testing if argument resolver [org.springframework.web.method.annotation.RequestParamMapMethodArgumentResolver@3d9c4ab3] supports [class com.lsa.akosha.entity.UserAndroid]
24 Mar 2015 20:15:14 > org.springframework.web.method.support.HandlerMethodArgumentResolverComposite - Testing if argument resolver [org.springframework.web.servlet.mvc.method.annotation.PathVariableMethodArgumentResolver@5fec4d5e] supports [class com.lsa.akosha.entity.UserAndroid]
24 Mar 2015 20:15:14 > org.springframework.web.method.support.HandlerMethodArgumentResolverComposite - Testing if argument resolver [org.springframework.web.servlet.mvc.method.annotation.PathVariableMapMethodArgumentResolver@7bd9d9bd] supports [class com.lsa.akosha.entity.UserAndroid]
24 Mar 2015 20:15:14 > org.springframework.web.method.support.HandlerMethodArgumentResolverComposite - Testing if argument resolver [org.springframework.web.servlet.mvc.method.annotation.MatrixVariableMethodArgumentResolver@1b6646d1] supports [class com.lsa.akosha.entity.UserAndroid]
24 Mar 2015 20:15:14 > org.springframework.web.method.support.HandlerMethodArgumentResolverComposite - Testing if argument resolver [org.springframework.web.servlet.mvc.method.annotation.MatrixVariableMapMethodArgumentResolver@426f839b] supports [class com.lsa.akosha.entity.UserAndroid]
24 Mar 2015 20:15:14 > org.springframework.web.method.support.HandlerMethodArgumentResolverComposite - Testing if argument resolver [org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor@27295730] supports [class com.lsa.akosha.entity.UserAndroid]
24 Mar 2015 20:15:14 > org.springframework.web.method.support.HandlerMethodArgumentResolverComposite - Testing if argument resolver [org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor@b1b2466] supports [class com.lsa.akosha.entity.UserAndroid]
24 Mar 2015 20:15:14 > org.springframework.web.method.HandlerMethod - Error resolving argument [0] [type=com.lsa.akosha.entity.UserAndroid]
HandlerMethod details:
Controller [com.lsa.akosha.webservices.MobileAppServiceController]
Method [public java.lang.String com.lsa.akosha.webservices.MobileAppServiceController.updateProfile(com.lsa.akosha.entity.UserAndroid,org.springframework.ui.ModelMap,javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)]
org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/json;charset=UTF-8' not supported
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.readWithMessageConverters(AbstractMessageConverterMethodArgumentResolver.java:149)
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.readWithMessageConverters(RequestResponseBodyMethodProcessor.java:180)
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:95)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:77)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:162)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:123)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:745)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:686)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936)
at org.springframework.web.servlet.FrameworkServlet.doPut(FrameworkServlet.java:849)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:649)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:96)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:180)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:503)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:421)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1070)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:611)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:314)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
24 Mar 2015 20:15:14 > org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver - Resolving exception from handler [public java.lang.String com.lsa.akosha.webservices.MobileAppServiceController.updateProfile(com.lsa.akosha.entity.UserAndroid,org.springframework.ui.ModelMap,javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)]: org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/json;charset=UTF-8' not supported
24 Mar 2015 20:15:14 > org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver - Resolving exception from handler [public java.lang.String com.lsa.akosha.webservices.MobileAppServiceController.updateProfile(com.lsa.akosha.entity.UserAndroid,org.springframework.ui.ModelMap,javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)]: org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/json;charset=UTF-8' not supported
24 Mar 2015 20:15:14 > org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver - Resolving exception from handler [public java.lang.String com.lsa.akosha.webservices.MobileAppServiceController.updateProfile(com.lsa.akosha.entity.UserAndroid,org.springframework.ui.ModelMap,javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)]: org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/json;charset=UTF-8' not supported
24 Mar 2015 20:15:14 > org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver - Resolving exception from handler [public java.lang.String com.lsa.akosha.webservices.MobileAppServiceController.updateProfile(com.lsa.akosha.entity.UserAndroid,org.springframework.ui.ModelMap,javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)]: org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/json;charset=UTF-8' not supported
24 Mar 2015 20:15:14 > org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver - Resolving exception from handler [public java.lang.String com.lsa.akosha.webservices.MobileAppServiceController.updateProfile(com.lsa.akosha.entity.UserAndroid,org.springframework.ui.ModelMap,javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)]: org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/json;charset=UTF-8' not supported
24 Mar 2015 20:15:14 > org.springframework.web.servlet.DispatcherServlet - Null ModelAndView returned to DispatcherServlet with name 'mvc': assuming HandlerAdapter completed request handling
24 Mar 2015 20:15:14 > org.springframework.web.servlet.DispatcherServlet - Cleared thread-bound request context: org.apache.struts2.dispatcher.StrutsRequestWrapper@5927198c
24 Mar 2015 20:15:14 > org.springframework.web.servlet.DispatcherServlet - Successfully completed request
24 Mar 2015 20:15:14 > org.springframework.web.context.support.XmlWebApplicationContext - Publishing event in WebApplicationContext for namespace 'mvc-servlet': ServletRequestHandledEvent: url=[/mobileapp/v1/put/user/profile.json]; client=[127.0.0.1]; method=[PUT]; servlet=[mvc]; session=[null]; user=[null]; time=[352ms]; status=[OK]
24 Mar 2015 20:15:14 > org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.context.annotation.internalScheduledAnnotationProcessor'
24 Mar 2015 20:15:14 > org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'incomingListener'
24 Mar 2015 20:15:14 > org.springframework.web.context.support.XmlWebApplicationContext - Publishing event in Root WebApplicationContext: ServletRequestHandledEvent: url=[/mobileapp/v1/put/user/profile.json]; client=[127.0.0.1]; method=[PUT]; servlet=[mvc]; session=[null]; user=[null]; time=[352ms]; status=[OK]
24 Mar 2015 20:15:14 > org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'incomingListener'
24 Mar 2015 20:15:14 > org.springframework.transaction.support.TransactionSynchronizationManager - Removed value [org.springframework.orm.jpa.EntityManagerHolder@6427300a] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@47672d99] from thread [http-bio-8080-exec-3]
24 Mar 2015 20:15:14 > org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter - Closing JPA EntityManager in OpenEntityManagerInViewFilter
24 Mar 2015 20:15:14 > org.springframework.orm.jpa.EntityManagerFactoryUtils - Closing JPA EntityManager
Fixing 415 Unsupported Media Type errorsEnsure that you are sending the proper Content-Type header value. Verify that your server is able to process the value defined in the Content-Type header. Check the Accept header to verify what the server is actually willing to process.
You need to set the content-type in postman as JSON (application/json). Go to the body inside your POST request, there you will find the raw option. Right next to it, there will be a drop down, select JSON (application. json).
To do this, open Postman and create a new request by selecting New->Request from the top left: Under Headers, select Key = Content-Type: For Value, select application/json: THANKS FOR READING.
In Spring REST APIs, Spring uses 'application/json' as a default media type. That is why, a REST controller can consume or produce JSON format payloads without having to specify the media types explicitly. Thus, in order to consume or produce data in a different form, the controller needs to specify that explicitly.
Please check the XML configuration where you have defined the contentnegotiating view resolver there you should have defined the mapping for json type media type . See if it works after updating those changes
This does not directly solves the issue but internally few dependencies resolve the mapping of content types for json as well try if it works
Reference Link
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With