Uploaded image for project: 'Spring Framework'
  1. Spring Framework
  2. SPR-9807

ContentNegotiatingViewResolver does not support wildcards in contentType

    Details

      Description

      The following configuration won't work for accept headers containing e.g. application/vnd.foo.user+json (see also http://stackoverflow.com/questions/11880359/spring-mvc-3-1-1-contentnegotiatingviewresolver-how-to-use-wildcard-characters):

          <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
              <property name="order" value="1"/>
              <property name="favorPathExtension" value="false"/>
              <property name="defaultViews">
                  <list>
                      <!-- JSON View -->
                      <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
                          <property name="contentType" value="application/*+json"/>
                      </bean>                 
                  </list>
              </property>
          </bean>

      The reason is a wrong comparison in ContentNegotiatingViewResolver#getBestView:

      Current:

              for (MediaType mediaType : requestedMediaTypes) {
                  for (View candidateView : candidateViews) {
                      if (StringUtils.hasText(candidateView.getContentType())) {
                          MediaType candidateContentType = MediaType.parseMediaType(candidateView.getContentType());
                          if (mediaType.includes(candidateContentType)) {
                              if (logger.isDebugEnabled()) {
                                  logger.debug("Returning [" + candidateView + "] based on requested media type '"
                                          + mediaType + "'");
                              }
                              return candidateView;
                          }
                      }
                  }
              }

      The problem is application/vnd.foo.user+json does not include application/*+json, the opposite is true.

      Expected:

      if (candidateContentType.includes(mediaType)) {

        Issue Links

          Activity

          Hide
          axe-felix Felix Barnsteiner added a comment -

          I've just realized, that there is a problem with that solution: If the client requests application/vnd.foo.user+json, it gets json, but the content-type header is set to application/*+json. So there is more to do:

          response.setContentType(getContentType()); 

          Is not valid then. The requested content type must be computed in the views and set:

          response.setContentType(getRequestedContentType()); 

          Generally, I feel the behaviour of @ResponseBody and ContentNegotiatingViewResolver is a bit inconsistent.

          Show
          axe-felix Felix Barnsteiner added a comment - I've just realized, that there is a problem with that solution: If the client requests application/vnd.foo.user+json, it gets json, but the content-type header is set to application/*+json. So there is more to do: response.setContentType(getContentType()); Is not valid then. The requested content type must be computed in the views and set: response.setContentType(getRequestedContentType()); Generally, I feel the behaviour of @ResponseBody and ContentNegotiatingViewResolver is a bit inconsistent.
          Hide
          rstoya05-aop Rossen Stoyanchev added a comment -

          This should now be supported as of commit c7e7e80a3ae9f6b4ed7f2d99fe321c2e12550d7b.

          Show
          rstoya05-aop Rossen Stoyanchev added a comment - This should now be supported as of commit c7e7e80a3ae9f6b4ed7f2d99fe321c2e12550d7b .

            People

            • Assignee:
              rstoya05-aop Rossen Stoyanchev
              Reporter:
              axe-felix Felix Barnsteiner
              Last updater:
              Chris Beams
            • Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:
                Days since last comment:
                5 years, 5 weeks, 4 days ago