Сгенерированные JAXB классы определенных типов, реализующие пользовательский интерфейс

Я работаю над приложением, которое использует XJC для создания Java POJO из XSD. Есть десятки схем, и это число будет расти. Приложение также должно иметь возможность обрабатывать разные версии одной и той же схемы, а это означает, что у меня будет несколько схем, определяющих общие типы. Я пытаюсь настроить привязки, чтобы определенные типы ядра реализовывали общий интерфейс. Плагин Inheritance JAXB2 Basics, кажется, делает то, что мне нужно, но я не могу понять правильный синтаксис.

Вот соответствующая часть моей схемы:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:my="http://example.com/core"
           targetNamespace="http://example.com/core"
           xmlns:xml="http://www.w3.org/XML/1998/namespace">

    ...

    <xs:complexType name="addressType">
        <xs:sequence>
            <xs:element name="Address" type="xs:string"/>
            <xs:element name="City" type="xs:string"/>
            <xs:element name="Province" type="xs:string"/>
            <xs:element name="Country" type="xs:string"/>
            <xs:element name="County" type="xs:string" minOccurs="0"/>
            <xs:element name="PostalCode" type="xs:string"/>
        </xs:sequence>
    </xs:complexType>

    ...

</xs:schema>

... и вот как выглядит мой пользовательский файл привязки:

    <?xml version="1.0"?>
<jaxb:bindings 
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
    xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
    xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance"
    xmlns:my="http://example.com/core"
    jaxb:extensionBindingPrefixes="inheritance"
    version="2.1">

    <jaxb:bindings scd="x-schema::my" xmlns:my="http://example.com/core">
        <jaxb:globalBindings localScoping="toplevel">
            <jaxb:serializable/>
            <xjc:simple/>
        </jaxb:globalBindings>
        <jaxb:bindings scd="/type::my:addressType">
            <inheritance:implements>com.mysite.validator.ValidatableAddress</inheritance:implements> 
            <!--<xjc:superInterface name="com.mysite.validator.ValidatableAddress"/>-->
        </jaxb:bindings>
    </jaxb:bindings>

</jaxb:bindings>

Я использую подход scd, потому что во всех "традиционных" примерах привязки, показывающих, как использовать подключаемый модуль наследования, указывается расположение схемы. Я хочу избежать необходимости указывать schemaLocation из-за большого (и растущего) количества схем. Я не хочу менять файл привязки каждый раз, когда мы добавляем новую схему. Таким образом, scd, похоже, удовлетворит этому требованию.

Однако, когда я запускаю сборку с использованием приведенной выше привязки, я получаю следующее:

  [xjc] [ERROR] cvc-elt.1: Cannot find the declaration of element 'inheritance:implements'.
  [xjc]   line 18 of file:/dev/workspace/my_app/etc/schemas/bindings-common.xml
  [xjc] failure in the XJC task. Use the Ant -verbose switch for more details
  [xjc] classLoader = java.net.URLClassLoader@ebcdbb
  [xjc] SharedSecrets.getJavaNetAccess()=java.net.URLClassLoader$7@14562c5

Если я закомментирую строку inheritance:implements и раскомментирую строку xjc:superInterface, ошибка исчезнет, ​​и сборка завершится успешно, но мой AddressType классы не реализуют тип ValidatableAddress.

Можно ли использовать подключаемый модуль наследования с scd? Можно ли ограничить xjc:superInterface только определенными элементами?

Ваше здоровье.


person 6006604    schedule 16.06.2015    source источник


Ответы (2)


Автор jaxb2-basics здесь.

См. эту проблему в XJC. Короче говоря, XJC по какой-то причине не разрешает элементы настройки пользователя/поставщика в привязках SCD.
inheritance:implements является таким элементом настройки.

Так что нет, это не работает из-за проблемы в XJC.

Я лично связываюсь через schemaLocation и XPath, но использую «виртуальный» URI местоположения схемы и переписываю его через каталоги.

SCD был бы гораздо лучшим выбором (здесь вы абсолютно правы), но он просто не работает.

Обновление местоположения виртуальной схемы и каталогов.

Вот пример привязки, которая настраивает какой-то сложный тип:

<jaxb:bindings 
    schemaLocation="http://schemas.opengis.net/wps/2.0/wpsCommon.xsd" 
    node="/xs:schema">
    <jaxb:bindings node="xs:element[@name='Data']/xs:complexType">
        <wildcard:lax/>
    </jaxb:bindings>
</jaxb:bindings>

Он связан через schemaLocation и XPath. schemaLocation — это существующий URL, но в сборке он переписан через каталог в ресурс внутри артефакта Maven:

REWRITE_SYSTEM "http://schemas.opengis.net" "maven:org.jvnet.ogc:ogc-schemas:jar::!/ogc"

Таким образом, в основном http://schemas.opengis.net/wps/2.0/wpsCommon.xsd будет загружаться из файла ogc-schema.jar!/ogc/wps/2.0/wpsCommon.xsd.

Использование maven-jaxb2-plugin вы можете сослаться на файлы привязки внутри артефактов Maven, а также:

                    <binding>
                        <dependencyResource>
                            <groupId>${project.groupId}</groupId>
                            <artifactId>ows-v_2_0</artifactId>
                            <resource>ows-v_2_0.jsonix.xjb</resource>
                            <version>${project.version}</version>
                        </dependencyResource>
                    </binding>

Таким образом, в сочетании это позволяет один раз написать файлы привязки и повторно использовать их в модулях.

Но разобраться во всем этом было огромной болью. Я сделал это для проекта ogc-schemas, который сейчас содержит около 50 сильно взаимосвязанных схем. Я сильно страдаю от недостатков и проблем XJC, но на данный момент это лучшее, что может быть. Я даже думал о разветвлении и исправлении XJC, но это далеко не предел усилий, которые я могу себе позволить.

Таким образом, я нашел несколько обходных путей для ведения блогов, которые каким-то образом работают в конце дня.

person lexicore    schedule 16.06.2015
comment
Спасибо лексикор. Как насчет объединения scd и xjc:superInterface... Должно ли это работать? Любая идея, почему этот подход не генерирует ошибок, но, похоже, не оказывает никакого влияния на сгенерированный источник? - person 6006604; 17.06.2015
comment
... или xjc:superInterface считается пользовательской настройкой/поставщиком, как и наследование: реализует? - person 6006604; 17.06.2015
comment
На самом деле это расширение поставщика, но это расширение поставщика первого класса, которое известно XJC (см. src/main/resources/com/sun/tools/xjc/reader/xmlschema/bindinfo/binding.xsd#L81" rel="nofollow noreferrer">здесь) - в отличие от inheritance:implements. Кстати, xjc:superInterface не для только для глобальных привязок? Объяснил бы, почему это игнорируется в классе. - person lexicore; 17.06.2015
comment
Я думаю, единственное, что будет работать на данный момент, это привязка к некоторым глобальным каталогам schemaLocation + XPath +. - person lexicore; 17.06.2015
comment
Все попытки использовать этот подход до сих пор терпят неудачу с этой ошибкой: [ОШИБКА] файл:/C:/dev/workspace/myapp/etc/form-schemas/common.xsd не является частью этой компиляции. Это ошибка для файла:/C:/dev/workspace/myapp/etc/form-schemas/v0001/common.xsd? - person 6006604; 18.06.2015

Спасибо lexicore за оперативные и подробные ответы. Однако этот подход не работал для меня, поэтому я пришел к следующему решению...

Поскольку я использую Ant для вызова XJC, в итоге я использовал возможности Ant <copy filtering="true"...> для динамического создания файла привязки.

Вот мой файл шаблона привязки (bindings-common.xml):

<?xml version="1.0"?>
<jaxb:bindings 
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
    xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
    xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance"
    xmlns:my="http://http://example.com/core"
    jaxb:extensionBindingPrefixes="inheritance" 
    version="2.1">
    <jaxb:bindings>
        <jaxb:globalBindings localScoping="toplevel">
            <jaxb:serializable/>
            <xjc:simple/>
        </jaxb:globalBindings>
    </jaxb:bindings>

    <jaxb:bindings
        schemaLocation="@bindingSchema@" 
        node="/xs:schema">

        <jaxb:bindings node="//xs:complexType[@name='addressType']">
            <inheritance:implements>com.example.validator.ValidatableAddress</inheritance:implements>
        </jaxb:bindings>
    </jaxb:bindings>

</jaxb:bindings>

Обратите внимание на эту строку:

<jaxb:bindings
            schemaLocation="@bindingSchema@" 
            node="/xs:schema">

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

<property name="jaxb.binding.template" value="../etc/form-schemas/bindings-common.xml"/>
<property name="jaxb.binding.file" value="${jaxb.src.dir}/bindings-common${schema.version}.xml"/>

<echo message="Filtering ${jaxb.binding.file} using template ${jaxb.binding.template}"/>

<copy file="${jaxb.binding.template}" 
      tofile="${jaxb.binding.file}"
      filtering="true">

    <filterset>
        <filter token="bindingSchema" value="../../etc/form-schemas/${schema.version}/common.xsd"/>
    </filterset>
</copy>

<xjc destdir="${jaxb.src.dir}" 
        extension="true" 
        schema="${schema.file}" 
        package="${package}" 
        binding="${jaxb.binding.file}">

    <arg value="-episode"/> 
    <arg value="${jaxb.src.dir}/common${schema.version}.episode"/> 
    <arg line="-Xinheritance"/>

        <!-- Plugins -->
        <classpath>
            <fileset dir="../build-libs/">
                <!-- JAXB2 Basics library -->
                <include name="jaxb2-basics-0.6.4.jar"/>
                <!-- JAXB2 Basics library dependencies -->
                <include name="jaxb2-basics-runtime-0.6.4.jar"/>
                <include name="jaxb2-basics-tools-0.6.4.jar"/>
                <include name="javaparser-1.0.8.jar"/>
                <include name="commons-beanutils-*.jar"/>
                <include name="commons-lang-*.jar"/>
                <include name="commons-logging-*.jar"/>
            </fileset>
        </classpath>
    </xjc>
</target>

Надеюсь, это поможет будущим поколениям жертв JAXB.

person 6006604    schedule 18.06.2015