Маршал 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.