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

У меня есть 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 службы xsds в 2 разных исполнениях, генерирующих в 2 разных пакета, я получаю тот же класс ValidationType в двух разных пакетах.

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

Ответы

Ответ 1

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

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

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

UPDATE:

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

Ответ 2

Я настроил пакеты, как описано здесь, http://jaxb.java.net/guide/Customizing_Java_packages.html. Итак, 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>