JAXB: генерация классов для двух XSD, которые используют общий XSD

#java #xsd #jaxb

#java — язык #xsd #jaxb #java

Вопрос:

У меня есть 2 служебных XSD-файла AService.xsd и BService.xsd, каждый с разным пространством имен целей. Оба они используют общий XSD, называемый common.xsd. Я использую плагин JAXB Maven для генерации классов. Вот как,

 <execution>
    <id>generate-package</id>
    <goals>
        <goal>generate</goal>
    </goals>
    <configuration>
        <extension>true</extension>
        <schemaIncludes>
            <include>schema/Aservice.xsd</include>
            <include>schema/Bservice.xsd</include>                             
        </schemaIncludes>
        <bindingIncludes>                                   
            <include>schema/*.xjb</include>
        </bindingIncludes>
        <generatePackage>com.schema</generatePackage>
        <generateDirectory>src/main/java</generateDirectory>
    </configuration>
</execution>
  

Когда я пытаюсь запустить это, я получаю следующую ошибку. ValidationType определяется в common.xsd

 org.xml.sax.SAXParseException: A class/interface with the same name "com.schema.ValidationType" is already in use. Use a class customization to resolve this conflict.
..........
org.xml.sax.SAXParseException: (Relevant to above error) another "ValidationType" is generated from here.
......
com.sun.istack.SAXParseException2: Two declarations cause a collision in the ObjectFactory class.
  

Если я запускаю 2 служебных xsd в двух разных исполнениях, генерирующих в 2 разных пакетах, я получаю один и тот же ValidationType класс в 2 разных пакетах.

Есть какие-нибудь идеи о том, как заставить JAXB распознавать общие схемы?

Ответ №1:

Вы сталкиваетесь с так называемой «схемой хамелеона», которая считается плохой практикой. К сожалению, хорошего решения не существует из-за природы JAXB. Аннотация JAXB привязывает свойства компонента к элементам XML и атрибутам в определенных пространствах имен (определяется во время компиляции схемы). Итак, как только ваша схема скомпилирована, нет официального хорошего способа изменить пространства имен элементов и атрибутов, к которым привязаны ваши свойства.

Однако это именно то, чего вы хотите достичь с помощью схем «хамелеон». Классы, производные от «common.xsd», должны каким-то волшебным образом отображаться в пространство имен A, если используются в классах A, и в пространство имен B, если используются в классах B. Я могу представить эту магию, но никогда не видел в реальной жизни.

Поскольку вы, по сути, хотите, чтобы A / common и B / common были «одним и тем же», один из способов решить эту проблему — сгенерировать A и B (оба с помощью common) в двух исполнениях и заставить общие классы реализовать определенный «общий» интерфейс. Тогда ваше программное обеспечение могло бы обрабатывать A / common и B / common одним и тем же способом, независимо от того факта, что на самом деле это классы из разных пакетов.

Обновить:

Из комментария я вижу, что у вас нет схемы chameleon, а просто обычный импорт. Тогда это просто, просто скомпилируйте common, A и B отдельно. Смотрите Отдельную компиляцию схемы для maven-jaxb2-plugin.

Комментарии:

1. Common.xsd находится в своем собственном пространстве имен и импортируется в то же пространство имен в AService.xsd и BService.xsd. Нет необходимости изменять пространства имен после генерации..

2. Ваш подход тоже сработает, я сам добавил ответ, описывающий, как я пришел к решению. Спасибо за ответ.

Ответ №2:

Я настроил пакеты, как описано здесь. So common.xsd входит com.common.schema и совместно используется AService.xsd и BService.xsd , которые сами находятся в разных пакетах, поскольку они находятся в разных пространствах имен.

generatePackage Удален из конфигурации maven и выглядит следующим образом,

 <execution>
    <id>generate-package</id>
    <goals>
        <goal>generate</goal>
    </goals>
    <configuration>
        <extension>true</extension>
        <schemaIncludes>
            <include>schema/Aservice.xsd</include>
            <include>schema/Bservice.xsd</include>                            
        </schemaIncludes>
        <bindingIncludes>
            <include>schema/*.xjb</include>
        </bindingIncludes>                                
        <generateDirectory>src/main/java</generateDirectory>
    </configuration>
</execution>