Exception while exposing a bean in webservice using spring mvc
I am using Spring 3.0.5.Release MVC for exposing a webservice and below is my servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- To enable @RequestMapping process on type level and method level -->
<context:component-scan base-package="com.pyramid.qls.progressReporter.service" />
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="marshallingConverter" />
<ref bean="atomConverter" />
<ref bean="jsonConverter" />
</list>
</property>
</bean>
<bean id="marshallingConverter" class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
<constructor-arg ref="jaxbMarshaller" />
<property name="supportedMediaTypes" value="application/xml"/>
</bean>
<bean id="atomConverter" class="org.springframework.http.converter.feed.AtomFeedHttpMessageConverter">
<property name="supportedMediaTypes" value="application/atom+xml" />
</bean>
<bean id="jsonConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="supportedMediaTypes" value="application/json" />
</bean>
<!-- Client -->
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
<property name="messageConverters">
<list>
<ref bean="marshallingConverter" />
<ref bean="atomConverter" />
<ref bean="jsonConverter" />
</list>
</property>
</bean>
<bean id="jaxbMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="classesToBeBound">
<list>
<value>com.pyramid.qls.progressReporter.impl.BatchProgressMetricsImpl</value>
<value>com.pyramid.qls.progressReporter.datatype.InstrumentStats</value>
<value>com.pyramid.qls.progressReporter.datatype.InstrumentInfo</value>
<value>com.pyramid.qls.progressReporter.datatype.BatchProgressMetricsList</value>
<value>com.pyramid.qls.progressReporter.datatype.LoadOnConsumer</value>
<value>com.pyramid.qls.progressReporter.datatype.HighLevelTaskStats</value>
<value>com.pyramid.qls.progressReporter.datatype.SessionStats</value>
<value>com.pyramid.qls.progressReporter.datatype.TaskStats</value>
<value>com.pyramid.qls.progressReporter.datatype.ComputeStats</value>
<value>com.pyramid.qls.progressReporter.datatype.DetailedInstrumentStats</value>
<value>com.pyramid.qls.progressReporter.datatype.ImntHistoricalStats</value>
</list>
</property>
</bean>
<bean id="QPRXmlView" class="org.springframework.web.servlet.view.xml.MarshallingView">
<constructor-arg ref="jaxbMarshaller" />
</bean>
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="mediaTypes">
<map>
<entry key="xml" value="application/xml"/>
<entry key="html" value="text/html"/>
</map>
</property>
<property name="viewResolvers">
<list>
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
<bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</list>
</property>
</bean>
<bean id="QPRController" class="com.pyramid.qls.progressReporter.service.QPRController">
<property name="jaxb2Mashaller" ref="jaxbMarshaller" />
</bean>
</beans>
Following is what i am doing in controller (QPRController)
@RequestMapping(value = "/clientMetrics/{clientId}", method = RequestMethod.GET)
public ModelAndView getBatchProgressMetrics(@PathVariable String clientId) {
List<BatchProgressMetrics> batchProgressMetricsList = null;
batchProgressMetricsList = batchProgressReporter.getBatchProgressMetricsForClient(clientId);
BatchProgressMetricsList batchList = new BatchProgressMetricsList(batchProgressMetricsList);
ModelAndView mav = new ModelAndView("QPRXmlView", BindingResult.MODEL_KEY_PREFIX + "batchProgressMetrics", batchList);
return mav;
}
This is what my batchprogressmetricsList looks like:
@XmlRootElement(name = "batchProgressMetrics")
public class B开发者_JS百科atchProgressMetricsList implements Serializable{
private int count;
private List<BatchProgressMetrics> batchProgressMetricsList;
public BatchProgressMetricsList() {
}
public BatchProgressMetricsList(List<BatchProgressMetrics> batchProgressMetricsList) {
this.batchProgressMetricsList = batchProgressMetricsList;
this.count = batchProgressMetricsList.size();
}
public int getCount() {
return count;
}
@XmlElement(name = "batchProgressMetrics1")
public List<BatchProgressMetrics> getBatchProgressMetrics() {
return batchProgressMetricsList;
}
Now i get the following:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'QPRController' defined in ServletContext resource [/WEB-INF/rest-servlet.xml]: Cannot resolve reference to bean 'jaxbMarshaller' while setting bean property 'jaxb2Mashaller'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jaxbMarshaller' defined in ServletContext resource [/WEB-INF/rest-servlet.xml]: Invocation of init method failed; nested exception is org.springframework.oxm.UncategorizedMappingException: Unknown JAXB exception; nested exception is com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 2 counts of IllegalAnnotationExceptions
com.pyramid.qls.progressReporter.iface.BatchProgressMetrics is an interface, and JAXB can't handle interfaces.
this problem is related to the following location:
at com.pyramid.qls.progressReporter.iface.BatchProgressMetrics
at public java.util.List com.pyramid.qls.progressReporter.datatype.BatchProgressMetricsList.getBatchProgressMetrics()
at com.pyramid.qls.progressReporter.datatype.BatchProgressMetricsList
com.pyramid.qls.progressReporter.iface.BatchProgressMetrics does not have a no-arg default constructor.
this problem is related to the following location:
at com.pyramid.qls.progressReporter.iface.BatchProgressMetrics
at public java.util.List com.pyramid.qls.progressReporter.datatype.BatchProgressMetricsList.getBatchProgressMetrics()
at com.pyramid.qls.progressReporter.datatype.BatchProgressMetricsList
org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:328)
Previously i got this without the change.
SEVERE: Servlet.service() for servlet rest threw exception
javax.servlet.ServletException: Unable to locate object to be marshalled in model: {org.springframework.validation.BindingResult.batchProgressMetrics=
Note that BatchProgressMetrics is an interface so my MAV is returning list of BatchProgressMetrics
objects and i have entry for its impl in classes to be bound in servlet.xml
.
Can you please help me as to what i am doing wrong. And yes if i send just batchProgressMetricsList.get(0)
in MAV it just works fine.
This because the JAXB context doesn't know how to handle lists of objects, only the objects themselves. It makes sense when you think about it - the only way to represent a list in XML is to wrap it in a container element, and it has no information as to how to do that.
So you need to define a class which is the container for the list of BatchProgressMetrics
, and return that in the model instead.
精彩评论