Responsebody encoding in Spring MVC 4.3.3 - spring

To set #responsebody encoding in spring-webmvc, I used to add the following lines in configuration file:
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/plain;charset=UTF-8</value>
<value>text/html;charset=UTF-8</value>
</list>
</property>
</bean>
<bean class="org.springframework.http.converter.BufferedImageHttpMessageConverter"/>
</mvc:message-converters>
This override the default charset responsebody handler use. And it worked with spring-mvc version 4.2.7 and below.
However, in the latest version of spring-webmvc(4.3.3), this method does not work. In the new version, StringHttpMessageConverter reads content-type from response header, and if content-type string includes charset information, it use this charset and ignores it's default charset.
I know I can write like this to solve this problem:
#RequestMapping(value = "/getDealers", method = RequestMethod.GET,
produces = "application/json; charset=utf-8")
#ResponseBody
public String sendMobileData() {
}
But I have to write it on every method or every controller.
Is there any way to set responsebody encoding globally like I did before?

I find that I didn't add <value>application/json;charset=UTF-8</value> in my configuration. I don't know why my old configuration works with version 4.2.7 and below, but this new configuration just works with version 4.3.3:
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/plain;charset=UTF-8</value>
<value>text/html;charset=UTF-8</value>
<value>application/json;charset=UTF-8</value>
</list>
</property>
</bean>
<bean class="org.springframework.http.converter.BufferedImageHttpMessageConverter"/>
</mvc:message-converters>

Related

Spring Controller #ResponseBody text/xml response UTF-8 encoding issue

I have annotation based Spring Rest Service running on jetty web server(also tomcat).The controller code is :
#RequestMapping(method = RequestMethod.POST, value = { "/ssrfeed/exec/",
"/query/exec" }, consumes = { "application/xml", "text/xml",
"application/x-www-form-urlencoded" }, produces = {
"application/xml;charset=UTF-8", "text/xml;charset=UTF-8",
"application/x-www-form-urlencoded;charset=UTF-8" })
#ResponseBody
protected String getXmlFeed(HttpServletRequest request,
#PathVariable String serviceName, #RequestBody String xmlReq) {
//code....
return appXMLResponse;
}
The problem is that the response xml returned by Controller contains some characters like ä ö ü (Umlaute). The response when rendered on browser gives the parsing error :
XML Parsing Error: not well-formed
Location: //localhost:8083/MySerice/ssrfeed/exec/
Line Number 18111, Column 17:
<FIRST_NAME>Tzee rfista</FIRST_NAME>
----------------^
(a small triangle appear in place of ü)
The expected is : <FIRST_NAME>Tzeeürfista</FIRST_NAME>
I have tried a below solutions but issue is still there.
Tried using filters referring to solution given on technowobble
passed the charset to StringHttpMessageConverter property
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="supportedMediaTypes" value="application/json" />
</bean>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes" value="text/xml;charset=UTF-8" />
</bean>
</list>
</property>
</bean>
ref link
Enabled the SetCharacterEncodingFilter in tomcat -web.xml
Changed the code to return ResponseEntity instead of String and removed #ResponseBody.
protected ResponseEntity<String> getXmlFeed(HttpServletRequest
request, #PathVariable String serviceName, #RequestBody String xmlReq) {
//line of code
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.add("Content-Type", "application/xml; charset=utf-8");
return new ResponseEntity<String>(appXMLResponse, responseHeaders, HttpStatus.CREATED);
}
The 4th solution works But this being existing code I can't change method signature as it might impact existing clients of this service. Any ideas/pointers to solve this ?
in your dispatcher servlet context xml, you have to add a propertie. e.g.
<bean class = "org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<array>
<bean class = "org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes" value = "text/plain;charset=UTF-8" />
</bean>
</array>
</property>
</bean>
Finally the issue is resolved. Here is what I did.
1. Used StringHttpMessageConverter's constructer for setting charset as :
<bean id="stringHttpMessageConverter"
class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg index="0" name="defaultCharset" value="UTF-8"/>
<property name="supportedMediaTypes">
<list>
<value>application/xml</value>
<value>text/xml</value>
<value>application/x-www-form-urlencoded</value>
</list>
</property>
</bean>
Also I removed the unnecessary spring3.0 and 3.1 jars from my project. These were not required but were lying there. (should have done earlier).
This solved the problem for me.
There is no such answer with what I've solved my encoding problem so I'll post it.
I've got Spring RestService running on Jetty. At response body part of data that was received from database had correct UTF-8 encoding, but data from .property file (with error and success messages) had incorrect encoding and was like äöü...
At first I checked encoding of .property file itself with File->Settings->Editor->Code Style-> File Encodings (in such way you could not only check but set encoding you need) - it was UTF-8.
Then I set response encoding #RequestMapping in my RestController:
#RequestMapping(value = "/category/{categoryId}", method = RequestMethod.DELETE, produces = { "application/json;**charset=UTF-8**" })
and set defaultCharset property for Jackson2:
<bean id="jsonConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes" value="application/json;" />
<property name="prettyPrint" value="true" />
<property name="defaultCharset" value="UTF-8"/>
</bean>
No result.
But then I found that the problem could be solved by adding UTF-8 encoding to
PropertyPlaceholderConfigurer who grabs data from my .property file:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:app.properties</value>
<value>classpath:database.properties</value>
<value>classpath:ru.error.messages.properties</value>
<value>classpath:ru.success.messages.properties</value>
</list>
</property>
<property name="fileEncoding" value="UTF-8"/>
</bean>
... and the problem has gone )))

Spring RestTemplate not loading the correct custom ObjectMapper in the MappingJackson2HttpMessageConverter

In my servlet.xml, I have the following RestTemplate configuration:
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate" >
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper" ref="jodaObjectMapper"/>
</bean>
</list>
</property>
</bean>
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper" ref="jodaObjectMapper"/>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<bean id="jodaObjectMapper" class="com.xyz.JodaObjectMapper"/>
When I deploy the app, the converter is setting up my custom mapper through the setObjectMapper method correctly. But when I use the restTemplate in my service, it is using the default ObjectMapper.
ResponseEntity responseEntity = restTemplate.exchange(url, HttpMethod.PUT, httpEntity, String.class);
Am I doing something wrong?
Thanks in advance

Spring MVC REST produces XML on default

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.
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 :)
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."

How do you force a response for a RequestMapping to use the AtomFeedHttpMessageConverter?

Our Spring 3.1 application uses message converters in the following manner:
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
....
....
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="writeAcceptCharset" value="false"/>
</bean>
<bean class="org.springframework.http.converter.ResourceHttpMessageConverter"/>
<bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"/>
<bean class="org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter"/>
<bean class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter"/>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>
<bean class="org.springframework.http.converter.feed.AtomFeedHttpMessageConverter"/>
</list>
</property>
</bean>
<bean class="org.codehaus.jackson.map.ObjectMapper" name="objectMapper"/>
In one of my controllers, I have a RequestMapping as such:
#RequestMapping(value = "pathFoo", produces = MediaType.APPLICATION_ATOM_XML_VALUE)
public #ResponseBody Feed getFooAtomXML(HttpServletRequest request, HttpServletResponse response){
but it seems that unless I specify a request header Accept=application/atom+xml, the response comes back as JSON instead of XML. How can I configure the application so that the AtomFeedHttpMessageConverter is used at this mapping, regardless of whether the request header is present?
Would I need to rely on a ViewResolver?
The problem here is that the AnnotationMethodHandlerAdapter bean goes through your list of HttpMessageConverter beans in declared order.
It first calls the canWrite(Class, MediaType) method on each HttpMessageConverter and uses the first one that returns true.
Without providing the Accept header as application/atom+xml, the MappingJacksonHttpMessageConverter will return true first before the AtomFeedHttpMessageConverter has a chance to. This happens for two reasons.
If no Accept header is provided, Spring considers all MediaTypes as acceptable.
MappingJacksonHttpMessageConverter accepts the application/json content-type
This is because MappingJacksonHttpMessageConverter is implemented as
#Override
public boolean canWrite(Class<?> clazz, MediaType mediaType) {
return (this.objectMapper.canSerialize(clazz) && canWrite(mediaType));
// ^ will pretty much always return true ^ application/json
}
So since the acceptable media types include everything, the MappingJacksonHttpMessageConverter will be able to produce a response and Spring will choose it.
To change this either change the order of beans
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="writeAcceptCharset" value="false"/>
</bean>
<bean class="org.springframework.http.converter.ResourceHttpMessageConverter"/>
<bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"/>
<bean class="org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter"/>
<bean class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter"/>
<bean class="org.springframework.http.converter.feed.AtomFeedHttpMessageConverter"/>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>
</list>
</property>
Or provide an Accept header as the HTTP specification specifies.
Or move to Spring 3.2 which uses RequestMappingHandlerAdapter instead of AnnotationMethodHandlerAdapter (which is deprecated), but also registers the AtomFeedHttpMessageConverter before the MappingJacksonHttpMessageConverter by default.

RestClientException Could not extract response spring mvc

i'm trying to connect via the restTemplate to the server side in order to retrieve xml's. But i'm taking an RestClientException and this message:"Could not extract response: no suitable HttpMessageConverter found for response type [frontend.model.Registration] and content type [application/xml]"
In the dispatcher-servlet i write this:
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="mediaTypes">
<map>
<entry key="xml" value="application/xml"/>
<entry key="atom" value="application/atom+xml"/>
<entry key="html" value="text/html"/>
</map>
</property>
<property name="viewResolvers">
<list>
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
</list>
</property>
And afterwards i add this:
<bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"/>
Also the exception appears at this line:3
ResponseEntity<Registration> result = restTemplate.exchange("http://www.../ckp/user/{id}",
HttpMethod.GET, entity, Registration.class, id);
I can't solve the problem days now..i'm thinking to add ViewResoler and MessageConverter by i don't know which resolvers and which converters. Can anyone propose something to try?
Should i add something on disptcher servlet?should i add a library?
My model classes are pojo's contains jaxb annotations.
You need to add the xml message converter bean to the RestTemplate bean definition. This is what I use:
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"/>
<bean class="org.springframework.http.converter.FormHttpMessageConverter"/>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>
</list>
</property>
</bean>
Don't forget to inject the restTemplate bean into your class (via xml or annotation).
EDIT: In your class where you call RestTemplate, add a field like this:
#Inject
private RestTemplate restTemplate;

Resources