RestClientException Could not extract response spring mvc - spring

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;

Related

consul properties in xml configuration

I am trying to use consul for centralised configuration for spring application. When I use annotation based configuration like Example 1 it works perfectly.
//Example 1
#Configuration
#EnableConsulPropertySource({"root/api/defaults", "root/global/defaults"})
public class ApplicationConfiguration {
#Value("httpclient.pool.maxtotal")
private int maxTotal;
#Value("httpclient.pool.defaultmaxperroute")
private int maxPerRoute;
...
}
However I could not find a way to use consul properties directly in xml.
<bean id="properties" class="org.springframework.SomeBeanToEnableConsulInXMLConfig">
<property name="locations">
<list>
<value>root/api/defaults</value>
<value>root/global/defaults</value>
</list>
</property>
</bean>
...
<bean name="http.client" class="com.xxx.HTTPClient">
<property name="maxTotal" value="${httpclient.pool.maxtotal}" />
<property name="defaultMaxPerRoute" value="${httpclient.pool.defaultmaxperroute}" />
</bean>
Does spring has something like SomeBeanToEnableConsulInXMLConfig or any hints on implementing this class?

Spring static factory with factory-method and parameter

I have a problem transfering code to Spring applicationContext.xml
The source is:
File inFile = new File ("path/to/file/", "fileName.docx")
WordprocessingMLPackage wordMLPackage = Docx4J.load(inFile);
My not working solution is:
<bean id="inFile" class="java.io.File">
<constructor-arg value="path/to/file/" />
<constructor-arg value="fileName.docx" />
</bean>
<bean id="docx4j" class="org.docx4j.Docx4J" factory-method="load">
<constructor-arg ref="inFile" />
</bean>
<bean id="wordprocessingMLPackage" class="org.docx4j.openpackaging.packages.WordprocessingMLPackage" factory-bean="docx4j" />
What I'm getting out of the bean "wordprocessingMLPackage" is indeed an instance of the Class WordprocessingMLPackage, but it seems empty although the File I'm trying to load isn't (and yes, the path is doublechecked).
When trying
MainDocumentPart mdp = wordprocessingMLPackage.getMainDocumentPart();
List<Object> content = mdp.getContent();
I'm getting a NullPointerException because mdp is null!
Has anyone an idea... or even a solution?
============================================================
I found a solution especially for my problem.
Here is the source of Docx4j.load():
public static WordprocessingMLPackage load(File inFile) throws Docx4JException {
return WordprocessingMLPackage.load(inFile);
}
That means I can create an instance of WordprocessingMLPackage by its static self!
The code which is working:
<bean id="wordprocessingMLPackage" class="org.docx4j.openpackaging.packages.WordprocessingMLPackage" factory-method="load">
<constructor-arg ref="baseDocument" />
</bean>
So I found a lucky "workaround" for the original problem.
Since this question isn't urgent any more, I'm still interested in the correct solution, especially in a solution which allows injecting the WordprocessingMLPackage in other beans.
Thank you!
Here you need to make use of MethodInvokingFactoryBean as detailed below.
<bean id="beanId"
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass" value="org.docx4j.Docx4J" />
<property name="targetMethod" value="load"/>
<property name="arguments">
<list>
<ref bean="inFile" />
</list>
</property>
</bean>
In your code get hold of applicationContext instance and invoke the below LOC
WordprocessingMLPackage ml = (WordprocessingMLPackage) applicationContext.getBean("beanId");
Let know in comments if you face any issues.
As Bond - Java Bond stated this works:
<bean id="inFile" class="java.io.File">
<constructor-arg value="path/to/file/" />
<constructor-arg value="fileName.docx" />
</bean>
<bean id="beanId" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass" value="org.docx4j.Docx4J" />
<property name="targetMethod" value="load"/>
<property name="arguments">
<list>
<ref bean="inFile" />
</list>
</property>
</bean>
You can now use the bean as
WordprocessingMLPackage ml = (WordprocessingMLPackage) applicationContext.getBean("beanId");
or you can inject the bean directly as
<bean id="service" class="app.service.Service">
<property name="wordprocessingMLPackage" ref="beanId" />
</bean>
Thank you!!!

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.

Resources