We develop a standard Java web application using Spring MVC, and have recently tried to upgrade from 3.0.6 to 3.2.0. Nearly of all our servlet responses are JSP or Json views, but there are some that are pdf requests, with extension 'pdf'.
In Spring 3.0.6 we had this set up, taken from the Spring MVC documentation.
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="mediaTypes">
<map>
<entry key="pdf" value="application/pdf"/>
<entry key="html" value="text/html"/>
<entry key="json" value="application/json"/>
</map>
which worked fine, in combination with an XMLViewResolver.
After updating to 3.2.0, there is a failure :
Error creating bean with name' org.springframework.web.servlet.view.ContentNegotiatingViewResolver#0' defined in class path resource [dispatcher-test-servlet.xml]: Invocation of init method failed; nested exception is
java.lang.ClassCastException: java.lang.String cannot be cast to org.springframework.http.MediaType'
After investigating the docs and some blogs, this configuration seems to work:
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="contentNegotiationManager">
<bean class="org.springframework.web.accept.ContentNegotiationManager">
<constructor-arg>
<list>
<!-- These are evaluated in order -->
<!-- Is there a media type based on suffix? -->
<bean class="org.springframework.web.accept.PathExtensionContentNegotiationStrategy">
<constructor-arg>
<map>
<entry key="html" value="text/html" />
<entry key="json" value="application/json" />
<entry key="pdf" value="application/pdf" />
</map>
</constructor-arg>
</bean>
<!-- Else use request header -->
<bean
class="org.springframework.web.accept.HeaderContentNegotiationStrategy">
</bean>
</list>
</constructor-arg>
</bean>
</property>
But, we have tried running the new Spring MVC test framework using this configuration, and get the ClassCast exception again, so it seems the test framework is not initialising the beans in the same way as when the application runs... Does anyone have a clear explanation of how to configure the ContentNegotiatingViewResolver in Spring 3,2 in a robust fashion? Thanks
Richard
I fixed the problem by removing duplicated
<mvc:annotation-driven/>
from xml-configuration or@EnableWebMVC
annotation from the class because spring documentation warns about that and allowed only once by contract.With spring 3.2 it is better resolved using
ContentNegotiationManager
. It is working for me. You could use the static field likeorg.springframework.http.MediaType.APPLICATION_JSON_VALUE
to mention the mediatype. check the following code:For this you have to use util schema in your dispatcher-servlet.xml file, i.e.
xmlns:util="http://www.springframework.org/schema/util"
and schema location http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsdWell, the error you posted is basically saying that Spring doesn't have a way to convert the string you provided, for example "application/pdf", to the MediaType objects. I am guessing the ContentNegotiatingViewResolver changed it's mediaTypes map to be a Map to a Map. You could try something like this:
Note: I did this from memory, so I may have typo'd this. Basically, you need the entry values to be MediaTypes, not strings.
I think you can achieve the same thing more easily using the ContentNegotiationManagerFactoryBean. By default it checks the URL path extension first, then a format property in the URL (such as ..../accounts?format=pdf) and then the standard HTTP Accept header property. The use of the format parameter is off by default.
If you use the JavaBeans Activation Framework, JAF, you shouldn't need the mediaTypes section. Just put activation.jar on the classpath.
Did you try this and did you also get class-cast exceptions?