Page 1 of 2 12 LastLast
Results 1 to 10 of 11

Thread: Roo 1.2.2 web mvc json controller behaves differently in browsers FF and IE

  1. #1
    Join Date
    Aug 2012
    Posts
    7

    Default Roo 1.2.2 web mvc json controller behaves differently in browsers FF and IE

    Hello,

    Background:
    We've successfully upgraded our web project from Spring Framework 3.0.5 to 3.1.0 and from Roo 1.1.5 to 1.2.2.
    We tested our app in Firefox, it worked fine. Just a quick note about the web mvc controllers, we use both the standard non-Json controllers and the Json controllers (mostly AJAX calls where we will set request headers="Accept=application/json".

    Issue:
    When we tested our app in IE, we got so many problems (which used to work just fine).
    For example: when I clicked on "list objects" menu link, it supposed to call a standard non-Json controller method to list objects in a CRUD table (based on Spring Roo tag library); instead, it actually prompt me to download a file. When I downloaded the file, it is actually the Json object array. Right there, I realized that the IE is actually calling the Json controller method as opposed to the standard non-Json controller method.

    Observations:
    1. I compared the standard non-Json controller method (list) to my old version, I've noticed the old method changed from @RequestMapping(method = RequestMethod.GET) to @RequestMapping(produces = "text/html").
    Obviously in this default case, Firefox knows to call the non-Json controller method whereas IE doesn't, it just goes to call the Json controller method where the @RequestMapping(headers="Accept=application/json").

    2. I then removed the produces = "text/html" from the @RequestMapping. Guess what, IE works fine this time by listing objects into a CRUD table, whereas Firefox didn't work, it displays the object array in Json format.

    Questions:
    1. Why is produces = "text/html" introduced to @RequestMapping in Roo 1.2.2? Is this anything do to with the newly introduced "web mvc json" command?

    2. It's clear to me that IE and FF handle the "produces="text/html"" differently. Does anyone know if this is a known issue?

    3. Our web app used to work on both browsers (IE and FF), however, after upgrade, it only works on one of them depends on how I configure the @RequestMapping.

    We love Roo, however, if it cannot support both browsers out of the box for standard operations like this, then it will become a major issue for us. I hope it is either a bug or something that I can easily enable/modify on my end to fix this issue.

    Your help is much appreciated!

    Thanks!
    Last edited by 3panda; Aug 2nd, 2012 at 07:42 PM.

  2. #2
    Join Date
    Mar 2007
    Posts
    561

    Default

    Trace the calls in the browser, watch the accept and content-type headers.

    Activate Debug-log:
    log4j.logger.org.springframework.web=DEBUG, stdout
    log4j.additivity.org.springframework.web=false

    See how spring maps the calls onto controller methods.

    @RequestMapping(produces = "text/html") does not mean that the browser knows something. It just influences which method is used to serve the request. In this case the client must accept text/html.

  3. #3
    Join Date
    Aug 2012
    Posts
    7

    Default

    Hi spgmx,

    Thank you for your quick reply.

    log4j was already enabled on our end. Please see the following logs for the same <a href > link request /users?page=1&size=25 on both Firefox and IE:

    Firefox: (From the trace below, you can see Spring routes standard <a href >link request /users?page=1&size=25 to com.demo.web.DemoAppController.list() (a non-Json controller method, desired behavior)

    1. org.springframework.security.web.FilterChainProxy$ VirtualFilterChain.doFilter(FilterChainProxy.java: 318) : /users?page=1&size=25 at position 1 of 11 in additional filter chain; firing Filter: 'ConcurrentSessionFilter'

    2. org.springframework.security.web.util.AntPathReque stMatcher.matches(AntPathRequestMatcher.java:103) : Checking match of request : '/users'; against '/users/**'

    3. org.springframework.web.servlet.DispatcherServlet. doService(DispatcherServlet.java:799) : DispatcherServlet with name 'demoapp' processing GET request for [/demoapp/users]

    4. org.springframework.web.servlet.handler.AbstractHa ndlerMethodMapping.getHandlerInternal(AbstractHand lerMethodMapping.java:211) : Looking up handler method for path /users

    5. org.springframework.web.servlet.handler.AbstractHa ndlerMethodMapping.getHandlerInternal(AbstractHand lerMethodMapping.java:218) : Returning handler method [public java.lang.String com.demo.web.DemoAppController.list(java.lang.Inte ger,java.lang.Integer,org.springframework.ui.Model )]


    IE: (From the trace below, you can see the Spring routes the same standard <a href> link request /users?page=1&size=25 to com.demo.web.DemoAppController.listJson() (Json controller method, not desired behavior)

    1. org.springframework.security.web.FilterChainProxy$ VirtualFilterChain.doFilter(FilterChainProxy.java: 318) : /users?page=1&size=25 at position 1 of 11 in additional filter chain; firing Filter: 'ConcurrentSessionFilter'

    2. org.springframework.security.web.util.AntPathReque stMatcher.matches(AntPathRequestMatcher.java:103) : Checking match of request : '/users'; against '/users/**'

    3. org.springframework.web.servlet.DispatcherServlet. doService(DispatcherServlet.java:799) : DispatcherServlet with name 'demoapp' processing GET request for [/demoapp/users]

    4. org.springframework.web.servlet.handler.AbstractHa ndlerMethodMapping.getHandlerInternal(AbstractHand lerMethodMapping.java:211) : Looking up handler method for path /users

    5. org.springframework.web.servlet.handler.AbstractHa ndlerMethodMapping.getHandlerInternal(AbstractHand lerMethodMapping.java:218) : Returning handler method [public org.springframework.http.ResponseEntity<java.lang. String> com.alu.bsx.web.DemoAppController.listJson()]


    So, somehow in the upgraded Roo 1.2.2, the routing function behaves differently than Roo 1.1.5. I’ve noticed the new Annotation @RooWebJson was introduced to Java Controller class, not sure if it has something to do with the routing logic behind.

    From the above trace, I think the magic lies in org.springframework.web.servlet.handler.AbstractHa ndlerMethodMapping.getHandlerInternal(), this is where Spring decides which method to serve the request.
    I’d appreciate if you could take a look at it and see if it had any logic changes from previous version. I will also look at it from my end as well. If we can both work on it, we can probably speed up the investigation as others may experience the same issue.

    Thank you!
    3Panda

  4. #4
    Join Date
    Mar 2007
    Posts
    561

    Default

    When the app starts up if lists all request mappings. You have to look there.

    e.g.:

    org.springframework.web.servlet.mvc.method.annotat ion.RequestMappingHandlerMapping - Mapped "{[/foo/bar],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public void foobar()..

  5. #5
    Join Date
    Aug 2012
    Posts
    7

    Default

    Hi spgmx,

    Please see below. Same URI request with different produces (one for text/html and the other for application/json format). Keep in mind that our <a href> request is simply asking for html response.

    1. Mapped "{[/users],methods=[],params=[],headers=[],consumes=[],produces=[text/html],custom=[]}" onto public java.lang.String com.demo.web.DemoAppUserController.list(java.lang. Integer,java.lang.Integer,org.springframework.ui.M odel)

    2. Mapped "{[/users],methods=[],params=[],headers=[],consumes=[],produces=[application/json],custom=[]}" onto public org.springframework.http.ResponseEntity<java.lang. String> com.demo.web.DemoAppUserUserController.listJson()

    Any more thoughts?
    Thanks,
    3Panda

  6. #6
    Join Date
    Aug 2012
    Posts
    7

    Default

    Hi spgmx,

    I’ve captured the HTTP request headers for both Firefox and IE for you to review.

    I think I may know the issue. See the Accept part of the headers. Firefox's Accept has text/html, whereas IE doesn’t. Now, in Roo's standard generated non-Json controller method, it specifies produces=”text/html” in @RequestMapping. In Firefox case, Spring knows it wants to accept html, so it routes to non-Json method, good. However, in IE case, since it doesn’t has text/html in accept part of the header, Spring did its best guess and somehow route it to Json method instead. So, something got changed in the logic. I hope this helps.

    Thanks,
    3panda

    Firefox:
    Request Headers
    GET http://serverip/demoapp/users?page=1&size=25 HTTP/1.1
    Accept: text/html, application/xhtml+xml, application/xml;q=0.9,*/*;q=0.8

    IE:
    Request Headers
    GET http://serverip/demoapp/users?page=1&size=25 HTTP/1.1
    Accept: application/x-ms-application, image/jpeg, application/xaml+xml, image/gif, image/pjpeg, application/x-ms-xbap, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*

  7. #7
    Join Date
    Aug 2010
    Location
    Goteborg, Sweden
    Posts
    434

    Default

    If you still regard this a bug perhaps you should enter it into the JIRA?

  8. #8
    Join Date
    Mar 2007
    Posts
    561

    Default

    You have 2 times the same url, once with application/json and ones with text/html. IE sends */* - "I understand everything". So what shall spring do? Send json, send html? "So what! He understands everything, so I send what I want." Spring will just use the first match and serve the request.

  9. #9
    Join Date
    Aug 2012
    Posts
    7

    Default

    Thanks MiB and spgmx.

    Couple of thoughts:
    1. We will investigate a bit more before considering a JIRA;

    2. FF is a great browser, however, the reality is that IE is still supported and used by a lot of Enterprise customers. So multi browser support is a key factor. IE browser engine’s accept header is historically different from FF Gecko’s (i.e. FF gives text/html the highest priority with relative quality parameters =1). Just speaking for myself, the routing should be explicitly as much as possible. If */* (give me whatever) is specified in IE, I’d hope Spring will serve text/html over Json. As most of the time, people are generally just requesting web pages.

  10. #10
    Join Date
    Mar 2007
    Posts
    561

    Default

    Content negotiation gets tricky when the Accept-Headers are not explicit. */* means - I take everything, send what you want.
    Therefore offen a url-suffix is used: .html for html and .json for json.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •