Маршал JAXB сгенерировал классы без XmlRootElement с верблюдом Apache

Чтобы упорядочить классы jaxb с помощью Apache Camel, класс jaxb должен включать аннотацию XmlRootElement.

При создании классов jaxb из XSD аннотация XmlRootElement может не генерироваться.

Это приведет к исключению во время сортировки: "Нет доступных преобразователей типов для преобразования из типа:"

Как только я добавляю @XmlRootElement вручную, все работает нормально, но, поскольку эти классы Jaxb генерируются, добавление аннотации вручную не является вариантом.

Согласно документации Camel в таком случае, JaxbDataFormat может быть установлен на 'fragement(true)

JaxbDataFormat jaxbMarshal = new JaxbDataFormat();
jaxbMarshal.setContextPath(ObjectFactory.class.getPackage().getName());
jaxbMarshal.setFragment(true);

К сожалению, я все еще получаю то же исключение.

Есть ли способ настроить JaxbDataFormat по-другому, т.е. определить JAXBElement, который является корневым элементом, как я бы сделал в Java

marshaller.marshal( new JAXBElement( new QName("uri","local"),
   MessageType.class, messageType ));

или есть другая стратегия, чтобы получить XML маршаллированный?

РЕДАКТИРОВАТЬ используемый маршрут:

 from("file://inbox").unmarshal(jaxbDataFormat)
.marshal(jaxbDataFormat).to("file://outbox");

трассировка стека:

java.io.IOException: org.apache.camel.NoTypeConversionAvailableException: нет преобразователя типов, доступного для преобразования из типа: com.xyz.AddressType в требуемый тип: java.io.InputStream со значением com.xyz.AddressType@32317e9d в org.apache.camel.converter.jaxb.JaxbDataFormat.marshal(JaxbDataFormat.java:148) ~[camel-jaxb-2.16.0.jar:2.16.0] в org.apache.camel.processor.MarshalProcessor.process(MarshalProcessor.java:83) ~[camel-core-2.16.0.jar:2.16.0] в

...

[na: 1.8.0_25] at java.lang.Thread.run (Thread.java:745) [na: 1.8.0_25] Причина: org.apache.camel.NoTypeConversionAvailableException: нет доступных преобразователей типов для преобразования из типа: com.xyz.AddressType для требуемого типа: java.io.InputStream со значением com.xyz.AddressType@32317e9d в org.apache.camel.impl.converter.BaseTypeConverterRegistry.mandatoryConvertTo(BaseTypeConverterRegistry.java:5) 2.16.0.jar: 2.16.0] в

...

3 ответа

В Camel 2.17 @XmlRootElementне требовалось. Начиная с версии 2.21 это так. Если только...

Класс org.apache.camel.converter.jaxb.FallBackTypeConverter изменил его реализацию с:

protected <T> boolean isJaxbType(Class<T> type) {
    return hasXmlRootElement(type) || JaxbHelper.getJaxbElementFactoryMethod(camelContext, type) != null;
}

Кому:

protected <T> boolean isJaxbType(Class<T> type) {
    if (isObjectFactory()) {
        return hasXmlRootElement(type) || JaxbHelper.getJaxbElementFactoryMethod(camelContext, type) != null;
    } else {
        return hasXmlRootElement(type);
    }
}

По умолчанию isObjectFactory()метод возвращает false. Если вы установите свойствоCamelJaxbObjectFactoryна ваше CamelContext к true. затемJaxbHelper.getJaxbElementFactoryMethod(camelContext, type) вернет истину, и десериализация снова будет работать, как и прежде, без необходимости @XmlRootElement. Для полноты:

<camelContext xmlns="http://camel.apache.org/schema/spring" id="camelContext">
    <properties>
        <property key="CamelJaxbObjectFactory" value="true"/>
    </properties>
</camelContext>

Я испытал эквивалентное поведение с JaxB (аннотация @XmlRootElement, отсутствующая в сгенерированном классе), и я предполагаю, что это происходит из-за способа определения корневого элемента в схеме XML.

Например:

<xsd:element name="DiffReport" type="DiffReportType" />
<xsd:complexType name="DiffReportType">
    ...
</xsd:complexType>

это сгенерирует вам DiffReportType класс без @XmlRootElement аннотаций. Но если вы прямо определите свой корневой элемент следующим образом, вы получите набор аннотаций в созданном классе (тогда имя корневого класса DiffReport в моем примере).

<xsd:element name="DiffReport">
    <xsd:complexType>
        ...

Примечание: я использовал первый способ определения сложных типов в моей схеме для согласованности имени класса.

Вы можете использовать опцию "partClass" формата данных jaxb верблюда. На ваш вопрос ответили в документах верблюда для jaxb, в которых описывается, как упорядочить фрагменты XML (или XML, сгенерированный без аннотации XmlRootElement).

Использование partClass и укажите фактическое имя класса, которому вы хотите выполнить маршал. В случае сортировки вы также должны предоставить partNamespace которое является целевым пространством имен желаемого объекта XML.

Другие вопросы по тегам