Announcement Announcement Module
Collapse
No announcement yet.
@RequestMapping produces= not matching Accept: application/vnd.xxx+json Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • @RequestMapping produces= not matching Accept: application/vnd.xxx+json

    I have a Spring 3.1.0 web @Controller :

    Code:
        @RequestMapping("/projects")
        @Controller
        public class ProjectController {
            ...
    and I want to handle multiple Accept headers in different ways using different methods with different @RequestMapping(produces=) :

    This works for XML/JAXB2 and Jackson:

    Code:
    // the following three @RequestMapping bindings work:
        @RequestMapping(value = "", method = RequestMethod.GET, produces = "application/xml")
        @ResponseBody
        public ResponseEntity<Links> getProjectsXML(HttpServletRequest request) { ... }
    
        @RequestMapping(value = "", method = RequestMethod.GET, produces = "application/vnd.sas.collection+xml")
        @ResponseBody
        public ResponseEntity<Links> getProjectsCollectionXML(HttpServletRequest request) { ... }
    
        @RequestMapping(value = "", method = RequestMethod.GET, produces = "application/json")
        @ResponseBody
        public ResponseEntity<Links> getProjectsJSON(HttpServletRequest request) { ... }
    
    // but this one is not matched:
        @RequestMapping(value = "", method = RequestMethod.GET, produces = "application/vnd.sas.collection+json")
        @ResponseBody
        public ResponseEntity<Links> getProjectsCollectionJSON(HttpServletRequest request) { ... }
    The first three tests work, but the fourth fails:

    Code:
       
       curl -H 'Accept: application/xml' http://localhost:8080/AppGen/projects
       curl -H 'Accept: application/json' http://localhost:8080/AppGen/projects
       curl -H 'Accept: application/vnd.sas.collection+xml' http://localhost:8080/AppGen/projects
    
       curl -H 'Accept: application/vnd.sas.collection+json' http://localhost:8080/AppGen/projects
    The last test fails with a HttpMediaTypeNotAcceptableException. Debugging through org.springframework.http.converter.json.MappingJac ksonHttpMessageConverter, I see in MediaType.isCompatibleWith(MediaType) line: 495

    Code:
       mediaType = application/vnd.sas.collection+json
       this.supportedMediaTyoes = [application/json;charset=UTF-8]
    and isCompatibleWith returns false.

    Comparing this with org.springframework.http.converter.xml.Jaxb2RootEl ementHttpMessageConverter when I step into MediaType.isCompatibleWith(MediaType) I see the

    Code:
       this.supportedMediaTyoes = [application/xml, text/xml, application/*+xml]
    Seems to me MappingJacksonHttpMessageConverter should work more like Jaxb2RootElementHttpMessageConverter and have a

    Code:
       this.supportedMediaTyoes = [application/json, text/json, application/*+json]
    and not just

    Code:
       this.supportedMediaTyoes = [application/json;charset=UTF-8]
    (I'm not certain about the charset constraint.)

    Is this a bug, or intentional? If intentional, is there a workaround? (I'd prefer to not have to write my own MessageConverter.

    Thanks,
    djb

  • #2
    SPR-6386 appears to be this issue; it is marked Fixed in 3.0 RC3 but I still see it in 3.1.0.RELEASE

    SPR-7905 is Open, waiting-for-triage (and may have a kluge/workaround)

    Comment


    • #3
      However, the workaround listed in SPR-7905 does not work for me when I remove <annotation-driven>.

      I get

      Code:
      Ambiguous handler methods mapped for HTTP path '/projects': 
      { public org.springframework.http.ResponseEntity ...ProjectController.getProjectsCollectionXML(javax.servlet.http.HttpServletRequest), 
        public org.springframework.http.ResponseEntity ...ProjectController.getProjectsXML(javax.servlet.http.HttpServletRequest)}.
      
      If you intend to handle the same path in multiple methods, then factor them out into a dedicated handler
      class with that path mapped at the type level!
      so I'm still looking for a solution. (The message hint does not apply here because my controller
      already maps "/projects" at the type level - Spring does not seem to recognize the produces=
      mapping matcher)

      Comment


      • #4
        David Melia posted a working solution in SPR-7905,
        namely, how to configure the MediaTypes for org.springframework.http.converter.json.MappingJac ksonHttpMessageConverter
        from within <annotation-driven>. This works for me, at least until Spring fixes MappingJacksonHttpMessageConverter
        to work like JAXB.

        Comment

        Working...
        X