Reputation: 71
in a typical Spring MVC project, I am trying to access objects that are fetched from an external webservice source. The actual integration of this data wasn't actually - until now - my part within the project. But it's broke and I'll have to fix it. That is to say: I am not perfectly familar with the related code.
The XML Data, which is received from the external web service looks like this:
<offeredServiceTOes>
<OfferedService deleted="false">
<id>0001_01-u001/igd</id>
<title>Umschlagleistung (001)</title>
<mainType>turnover</mainType>
<services>
<service id="tos5yyeivg">
<title>Umschlag Bahn - Binnenschiff</title>
<mainType>turnover</mainType>
<systemId>RailRiver</systemId>
<meansOfTransport id="motRail">
<title>Bahn</title>
<description>Bahn</description>
<systemId>Rail</systemId>
</meansOfTransport>
<meansOfTransportRel id="motRiver">
<title>Binnenschiff</title>
<description>Binnenschiff</description>
<systemId>River</systemId>
</meansOfTransportRel>
</service>
<service id="tos5yyeiw0">
[...]
</service>
[...]
</services>
[...]
</OfferedService>
[...]
<offeredServiceTOes>
The Method using Spring Rest Templates looks like this:
@Override
public List<OfferedServiceTO> getOfferedServices() {
return restTemplate.getForObject(
dataServiceUriTemplate,
OfferedServiceTOList.class,
OFFERED_SERVICES
);
The related OfferedServiceTOList
class:
@XmlRootElement(name="OfferedService")
public class OfferedServiceTO
{
@XmlElement
@XmlID
public String id;
// [...]
@XmlElementWrapper(name="services")
@XmlElement(name="service")
public List<ServiceTO> services;
// [...]
}
The related ServiceTO
Class
@XmlRootElement(name="service")
public class ServiceTO
{
// [...]
@XmlElement
public String title;
/[...]
@XmlElementWrapper(name="mainServices")
@XmlElement(name="service")
public List<ServiceTO> mainServices;
}
The marshaller/unmarshaller xml bean configuration
<bean id="jaxbMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="classesToBeBound">
<list>
<value>a.b.beans.ServiceTO</value>
<value>a.b.OfferedServiceTO</value>
[...]
</list>
</property>
</bean>
<bean id="xmlMessageConverter"
class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
<constructor-arg ref="jaxbMarshaller" />
</bean>
<bean id="jsonHttpMessageConverter"
class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="objectMapper" ref="jaxbJacksonObjectMapper"/>
</bean>
<bean id="jaxbJacksonObjectMapper"
class="a.b.path.to.extended.jaxb.JaxbJacksonObjectMapper">
</bean>
<bean id="jsonView" class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
<property name="objectMapper" ref="jaxbJacksonObjectMapper" />
</bean>
And finally, the above mentioned path.to.extended.jaxb.JaxbJacksonObjectMapper
is:
public class JaxbJacksonObjectMapper extends ObjectMapper {
public JaxbJacksonObjectMapper() {
final AnnotationIntrospector primary = new JaxbAnnotationIntrospector();
final AnnotationIntrospector secondary = new JacksonAnnotationIntrospector();
AnnotationIntrospector introspector = new AnnotationIntrospector.Pair(primary, secondary);
DeserializationConfig deserializationConfig = super.getDeserializationConfig().withAnnotationIntrospector(introspector);
DeserializationProblemHandler errorHandler = new DeserializationProblemHandler() {
@Override
public boolean handleUnknownProperty(DeserializationContext ctxt, JsonDeserializer<?> deserializer, Object beanOrClass,
String propertyName) throws IOException, JsonProcessingException {
//TODO Logging (unbekanntes Input-JSON)
ctxt.getParser().skipChildren();
return true;
}
};
deserializationConfig.addHandler(errorHandler );
super.setDeserializationConfig(deserializationConfig);
SerializationConfig serializationConfig = super.getSerializationConfig().withAnnotationIntrospector(introspector);
serializationConfig.set(Feature.WRAP_ROOT_VALUE, true);
super.setSerializationConfig(serializationConfig);
}
}
The problem is, that the Annotations of the first listing, @XmlElementWrapper(name="services") @XmlElement(name="service")
, look fine to me regarding the xml data wrapping. But I keep getting the error:
[...] nested exception is org.springframework.web.client.ResourceAccessException: I/O error: Unrecognized field "service" (Class a.b.ServiceTO), not marked as ignorable
at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@76d697d9; line: 7, column: 18] (through reference chain: a.b.OfferedServiceTO["services"]->a.b.ServiceTO["service"]); nested exception is org.codehaus.jackson.map.exc.UnrecognizedPropertyException: Unrecognized field "service" (Class a.b.ServiceTO), not marked as ignorable
at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@76d697d9; line: 7, column: 18] (through reference chain: a.b.OfferedServiceTO["services"]->a.b.ServiceTO["service"])
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:328)
Similar related questions like this one were fixed by annotating @XmlElementWrapper(name="services")
. But this is already present.
I would appreciate any suggestions. Thank you.
-- Martin
Upvotes: 4
Views: 8297
Reputation: 71
Okay, this was easier than expected. The List field needs a wrapping layer. A closer look to the json document revealed the solution:
In OfferedServiceTO.class
the
@XmlElementWrapper(name="services")
@XmlElement(name="service")
public List<ServiceTO> services;
has to be changed to
@XmlElement(name="services")
public ServiceTOList services;
where ServiceTOList.class
has to be something like:
@XmlRootElement(name="service")
public class ServiceTOList extends ArrayList<ServiceTO> {
public List<ServiceTO> services;
}
Upvotes: 2