4

I have a problem with Spring MVC and REST. The problem is that when i post a url without extension or whatever extension other then json or html or htm i am always getting an xml response. But i want it to default to text/html response. I was searching in many topics and cant find the answear to this.

Here is my Controller class :

@RequestMapping(value="/user/{username}", method=RequestMethod.GET)
public String showUserDetails(@PathVariable String username, Model model){
    model.addAttribute(userManager.getUser(username));
    return "userDetails";
}

@RequestMapping(value = "/user/{username}", method = RequestMethod.GET,   
        produces={"application/xml", "application/json"})  
@ResponseStatus(HttpStatus.OK)
public @ResponseBody 
    User getUser(@PathVariable String username) {
    return userManager.getUser(username);
}

Here is my mvc context config:

<mvc:resources mapping="/resources/**"
    location="/resources/"/>

<context:component-scan
    base-package="com.chodak.controller" />


    <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
    <property name="defaultContentType" value="text/html" />  
    <property name="mediaTypes">
       <map>
         <entry key="json" value="application/json"/>
         <entry key="xml" value="application/xml"/>
       </map>
     </property>

   </bean>

<bean id="viewResolver"
    class="org.springframework.web.servlet.view.UrlBasedViewResolver">
    <property name="viewClass">
        <value>
            org.springframework.web.servlet.view.tiles3.TilesView
        </value>
    </property>
</bean>
<bean id="tilesConfigurer"
    class="org.springframework.web.servlet.view.tiles3.TilesConfigurer">
    <property name="definitions">
        <list>
            <value>/WEB-INF/tiles.xml</value>
        </list>
    </property>
</bean>

Actually when I tried the built in Eclipse browser it works fine, but when I use firefox or chrome it shows xml response on a request with no extension. I tried using ignoreAcceptHeader, but no change.

Also works on IE :/

If anyone has an idea please help, Thank you.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Rhinox
  • 83
  • 1
  • 8
  • Have you tried to just change the order of produced media types in `@RequestMapping` to `{"application/json", "application/xml"}` ? I know that works in CXF. Probably it will do for Spring MVC. – Aleksandr Kravets Jan 12 '15 at 10:15

2 Answers2

1

I actually found out how to do it, i dont really understand why but it is working now, I added default views to the contentresolver like :

<property name="defaultViews">
    <list>
      <!-- JSON View -->
      <bean
        class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
      </bean>

      <!-- JAXB XML View -->
      <bean class="org.springframework.web.servlet.view.xml.MarshallingView">
        <constructor-arg>
            <bean class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
               <property name="classesToBeBound">
                <list>
                   <value>com.chodak.tx.model.User</value>
                </list>
               </property>
            </bean>
        </constructor-arg>
      </bean>
     </list>
  </property>

and removed the getUser method, the one annoted to produce xml and json. If I leave it with the added default views its still not working. If anyone can explain why it would be awesome :)

Rhinox
  • 83
  • 1
  • 8
0

You can do

import org.springframework.http.MediaType;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
// @EnableWebMvc already autoconfigured by Spring Boot
public class MvcConfiguration {

@Bean
public WebMvcConfigurer contentNegotiationConfigurer() {
    return new WebMvcConfigurerAdapter() {
        @Override
        public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
            configurer.favorPathExtension(false)
                    .favorParameter(true)
                    .parameterName("mediaType")
                    .ignoreAcceptHeader(true)
                    .useJaf(false)
                    .defaultContentType(MediaType.APPLICATION_JSON)
                    .mediaType("xml", MediaType.APPLICATION_XML)
                    .mediaType("json", MediaType.APPLICATION_JSON);
            // this line alone gave me xhtml for some reason
            // configurer.defaultContentType(MediaType.APPLICATION_JSON_UTF8);
        }
    };
}

(tried with Spring Boot 1.5.x)

see https://spring.io/blog/2013/05/11/content-negotiation-using-spring-mvc

"What we did, in both cases:

  • Disabled path extension. Note that favor does not mean use one approach in preference to another, it just enables or disables it. The order of checking is always path extension, parameter, Accept header.

  • Enable the use of the URL parameter but instead of using the default parameter, format, we will use mediaType instead.

  • Ignore the Accept header completely. This is often the best approach if most of your clients are actually web-browsers (typically making REST calls via AJAX).

  • Don't use the JAF, instead specify the media type mappings manually - we only wish to support JSON and XML."

aliopi
  • 3,682
  • 2
  • 29
  • 24