«Нераспознанное поле (..), не помечено как игнорируемое» при jaxb unmarshalling ввод XML - PullRequest
4 голосов
/ 09 августа 2011

в типичном проекте Spring MVC я пытаюсь получить доступ к объектам, которые извлекаются из внешнего источника веб-сервиса. Фактическая интеграция этих данных не была - до сих пор - моей частью в проекте. Но он сломался, и мне придется это исправить. То есть: я не совсем знаком с соответствующим кодом.

обои

Данные

Данные XML, полученные от внешнего веб-сервиса, выглядят так:

<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>

Неуязвимый

  • Метод с использованием шаблонов Spring Rest выглядит следующим образом:

    @Override
    public List<OfferedServiceTO> getOfferedServices() {
        return restTemplate.getForObject(
                dataServiceUriTemplate, 
                OfferedServiceTOList.class,
                OFFERED_SERVICES
        );
    
  • Связанный OfferedServiceTOList класс:

    @XmlRootElement(name="OfferedService")
    public class OfferedServiceTO
    {
    
        @XmlElement
        @XmlID
        public String id;
    
        // [...]
    
        @XmlElementWrapper(name="services")
        @XmlElement(name="service")
        public List<ServiceTO> services; 
    
        // [...]
    }
    
  • Связанные ServiceTO Класс

    @XmlRootElement(name="service")
    public class ServiceTO
    {
        // [...]
        @XmlElement
        public String title;
    
        /[...]
        @XmlElementWrapper(name="mainServices")
        @XmlElement(name="service")
        public List<ServiceTO> mainServices;
    }
    
  • Конфигурация маршаллера / демаршаллера xml bean

    <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>
    
  • И, наконец, вышеупомянутое path.to.extended.jaxb.JaxbJacksonObjectMapper:

        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);
            }
    
        }
    

Проблема

Проблема в том, что аннотации первого списка, @XmlElementWrapper(name="services") @XmlElement(name="service"), выглядят хорошо для меня в отношении переноса данных в xml. Но я продолжаю получать ошибку:

[...] 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)

Похожие похожие вопросы, такие как , этот был исправлен с помощью аннотации @XmlElementWrapper(name="services"). Но это уже присутствует.

Буду признателен за любые предложения. Спасибо.

- Мартин

1 Ответ

2 голосов
/ 12 августа 2011

Хорошо, это было проще, чем ожидалось.Поле List нуждается в оберточном слое.Более внимательный взгляд на документ json показал решение:

В OfferedServiceTO.class

@XmlElementWrapper(name="services")
@XmlElement(name="service")
public List<ServiceTO> services;

необходимо изменить на

@XmlElement(name="services")
public ServiceTOList services;

, где ServiceTOList.class имеетбыть что-то вроде:

@XmlRootElement(name="service")
public class ServiceTOList extends ArrayList<ServiceTO> {

    public List<ServiceTO> services;
}
...