Arnaud Denoyelle
Arnaud Denoyelle

Reputation: 31235

Investigate HTTP 406 Error code only on first call

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 :

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

Answers (4)

ElmoVanKielmo
ElmoVanKielmo

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

Rajesh J Advani
Rajesh J Advani

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

matsev
matsev

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

Mark Leighton Fisher
Mark Leighton Fisher

Reputation: 5703

I would start by firing up something like Fiddler to see what bits are actually going over the wire.

Upvotes: 1

Related Questions