Reputation: 31235
I have a server which uses Spring to expose some RestServices. I have ~20 services which do almost always the same things : get, list, save...
Among all those services, I have ONE request that does not behave like the others :
@RequestMapping(value = {"/{id}"}, method = RequestMethod.GET)
@ResponseBody
public Line get(@PathVariable(value = "id") int id) {
return lineService.getById(id);
}
Problem :
When I restart the server and call this particular request for the very first time, I get a 406 Error Code.
After that, all other calls end in success, returning well-formed JSON with HTTP 200 code etc.
The Accept Headers of the request contains "application/json".
I tried to add this on the requestMapping :
produces="application/json"
It seems that somewhere, the server adapts the content/type of the reponse after the first fail but I definitely cannot understand where.
I tried with tomcat and jetty as backend server and I have the error on both.
Any ideas?
EDIT :
After further investigation, I detected this difference in tomcat logs. On the first call (HTTP 406), I can see this :
09:33:58.637 [http-bio-9090-exec-3] DEBUG o.s.o.jpa.EntityManagerFactoryUtils - Closing JPA EntityManager
09:33:58.637 [http-bio-9090-exec-3] DEBUG o.s.w.a.FixedContentNegotiationStrategy - Requested media types is application/json (based on default MediaType)
09:33:58.654 [http-bio-9090-exec-3] DEBUG o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver - Resolving exception from handler [public com.mycompany.myproject.dto.MyClass com.mycompany.myproject.controller.patrimoine.LigneMobileController.get(int)]: org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
09:33:58.657 [http-bio-9090-exec-3] DEBUG o.s.w.s.m.a.ResponseStatusExceptionResolver - Resolving exception from handler [public com.mycompany.myproject.dto.MyClass com.mycompany.myproject.controller.patrimoine.LigneMobileController.get(int)]: org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
09:33:58.657 [http-bio-9090-exec-3] DEBUG o.s.w.s.m.s.DefaultHandlerExceptionResolver - Resolving exception from handler [public com.mycompany.myproject.dto.MyClass com.mycompany.myproject.controller.patrimoine.LigneMobileController.get(int)]: org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
09:33:58.657 [http-bio-9090-exec-3] DEBUG o.s.web.servlet.DispatcherServlet - Null ModelAndView returned to DispatcherServlet with name 'springServlet': assuming HandlerAdapter completed request handling
09:33:58.657 [http-bio-9090-exec-3] DEBUG o.s.web.servlet.DispatcherServlet - Successfully completed request
09:33:58.657 [http-bio-9090-exec-3] DEBUG o.s.s.w.a.ExceptionTranslationFilter - Chain processed normally
09:33:58.657 [http-bio-9090-exec-3] DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed
On the second call, I can see this (differences start at 2nd line):
09:50:52.384 [http-bio-9090-exec-7] DEBUG o.s.o.jpa.EntityManagerFactoryUtils - Closing JPA EntityManager
09:50:52.385 [http-bio-9090-exec-7] DEBUG o.s.w.s.m.m.a.RequestResponseBodyMethodProcessor - Written [com.mycompany.myproject.dto.patrimoine.mobile.ligne.LigneMobile@18949ad1] as "application/json;charset=UTF-8" using [org.springframework.http.converter.json.MappingJacksonHttpMessageConverter@32a64bcd]
09:50:52.385 [http-bio-9090-exec-7] DEBUG o.s.web.servlet.DispatcherServlet - Null ModelAndView returned to DispatcherServlet with name 'springServlet': assuming HandlerAdapter completed request handling
09:50:52.385 [http-bio-9090-exec-7] DEBUG o.s.web.servlet.DispatcherServlet - Successfully completed request
09:50:52.385 [http-bio-9090-exec-7] DEBUG o.s.s.w.a.ExceptionTranslationFilter - Chain processed normally
09:50:52.385 [http-bio-9090-exec-7] DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed
So, in the first case, I get some HttpMediaTypeNotAcceptableException when trying to convert the object to JSON.
Upvotes: 2
Views: 1413
Reputation: 11315
You say, that Accept Headers contains application/json
. I would start investigation by sending request without specifying accepted content types. There should be some relevant clue in server response, when it's not constrained by specific content type. Web servers usually tend to return error page formatted as HTML if they encounter any error during processing the request. Content type is of course text/html in such case and therefore the real problem is obfuscated by 406 error.
Upvotes: 1
Reputation: 5710
Given that you see this error only after you restart your server, makes me think that maybe this is related to lazy class loading.
Try using a servlet that initializes on server start (i.e. with a load-on-startup
value of 1), that - in its init
method - refers to all the classes involved in rendering com.mycompany.myproject.dto.datagrid.LoadResult
to json?
Remember that you're trying to ensure that all the classes involved, are loaded by the ClassLoader before the request comes in.
Upvotes: 0
Reputation: 33779
Have you tried to set a breakpoint on the first line of the controller method, i.e. return lineService.getById(id);
?
I suspect that you will hit that line, but that there will be some initial error if you try to "step into" that method with the debugger. If my assumption is correct, somewhere an exception will be thrown, resulting in an html page with a stack trace. Next, you will see the 406 occur, because the html page has media type application/html
, or similar which cannot be converted to application/json
.
Upvotes: 0
Reputation: 5703
I would start by firing up something like Fiddler to see what bits are actually going over the wire.
Upvotes: 1