2015-06-16 4 views
5

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

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

<?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. Я хочу, чтобы не указывать 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 = [email protected] 
    [xjc] SharedSecrets.getJavaNetAccess()[email protected] 

Если я закомментируйте наследства: реализует линию и раскомментируйте XJC: суперинтерфейс линии, ошибка будет и сборка завершается успешно, но мои классы AddressType не реализуют тип ValidatableAddress.

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

Cheers.

ответ

4

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

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

Вот мой обязательный файл "шаблон" (привязок-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="@[email protected]" 
     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="@[email protected]" 
      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.

4

Автор здесь.

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

Нет, это не работает из-за проблем в XJC.

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

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

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

Вот example of binding, который адаптирует некоторый сложный тип:

<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 является existing URL, но в сборке он переписывается via catalog в ресурс внутри артефакта 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.

Использование вы можете refer to binding files inside Maven artifacts as well:

    <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, но на данный момент это самое лучшее. Я даже подумал о forking and patching XJC, но это далеко не все, что я могу себе позволить.

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

+0

Спасибо lexicore. Как насчет объединения scd и xjc: superInterface ... Должны ли это работать? Любая идея, почему этот подход не генерирует ошибки, но также, похоже, не влияет на сгенерированный источник? – 6006604

+0

... или xjc: superInterface считается настраиваемой/вендорной настройкой, аналогичной наследованию: реализует? – 6006604

+0

На самом деле это расширение поставщика, но его расширение поставщика «первого класса», которое специально известно XJC (см. Здесь [https://github.com/gf-metro/jaxb/blob/69471fb27af6a9e990ef2a7873aab64a18e87640/jaxb-ri/ xjc/src/main/resources/com/sun/tools/xjc/reader/xmlschema/bindinfo/binding.xsd # L81)) - в отличие от «наследования: реализует». Кстати, это не 'xjc: superInterface' для [только глобальных привязок] (https://jaxb.java.net/nonav/2.1.15/docs/vendorCustomizations.html#superinterface)? Объяснил бы, почему он игнорируется в классе. – lexicore