2015-06-16 7 views
5

Ich arbeite an einer Anwendung, die XJC verwendet, um Java POJOs von XSDs zu generieren. Es gibt Dutzende von Schemas, und diese Zahl wird wachsen. Die Anwendung muss auch in der Lage sein, verschiedene Versionen desselben Schemas zu handhaben, was bedeutet, dass ich mehrere Schemata haben werde, die gängige Typen definieren. Ich versuche, die Bindungen so anzupassen, dass bestimmte Kerntypen eine gemeinsame Schnittstelle implementieren. Das Vererbungs-Plugin von JAXB2 Basics scheint zu tun, was ich brauche, aber ich kann nicht die richtige Syntax finden.JAXB generierte Klassen bestimmter Typen, die eine benutzerdefinierte Schnittstelle implementieren

Hier ist der relevante Teil meines Schema:

<?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> 

... und das ist, was Datei meine benutzerdefinierte Bindung wie folgt aussieht:

<?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> 

ich die scd bin mit Ansatz , da in allen "traditionellen" Bindungsbeispielen, die zeigen, wie das inheritenz-plugin verwendet wird, schemaLocation angegeben wird. Ich möchte vermeiden, schemaLocation aufgrund unserer großen (und wachsenden) Anzahl von Schemas anzugeben. Ich möchte die Bindungsdatei nicht jedes Mal ändern müssen, wenn wir ein neues Schema hinzufügen. Also, scd scheint wie es diese Anforderung erfüllen wird.

Allerdings, wenn ich die Build unter Verwendung der oben Bindung laufen, bekomme ich diese:

[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] 

Wenn ich das Erbe Kommentar aus: implementiert Linie und Kommentar- der xjc: Superschnitt Linie, der Fehler geht entfernt und der Build wird erfolgreich abgeschlossen, aber meine AddressType Klassen implementieren nicht den Typ ValidatableAddress.

Kann das inheritence-Plugin mit scd verwendet werden? Kann xjc: superInterface auf bestimmte Elemente beschränkt sein?

Prost.

Antwort

4

Danke an Lexicore für die schnelle und detaillierte Antworten. Allerdings wurde dieser Ansatz nicht für mich arbeiten, so landete ich mit folgenden Lösung bis ...

Weil ich Ant bin mit XJC aufzurufen, landete ich den Ant <copy filtering="true"...> Fähigkeiten nutzte bis zu dynamisch die Bindungsdatei zu erzeugen.

Hier ist meine Bindung "Template" Datei (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="@[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> 

Hinweis diese Zeile:

<jaxb:bindings 
      schemaLocation="@[email protected]" 
      node="/xs:schema"> 

Diese Variable wird von Ant für jede der Schemata bevölkert erhalten dass ich verarbeite:

<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> 

Hoffentlich wird dies zukünftigen Generationen von JAXB Opfern helfen.

4

Autor von hier.

Siehe this issue in XJC. Kurz gesagt, XJC erlaubt aus irgendeinem Grund keine Custom/Vendor-Anpassungselemente in SCD-Bindungen.
inheritance:implements ist solch ein Anpassungselement.

Also nein, das funktioniert nicht wegen eines Problems in XJC.

Ich persönlich binden über schemaLocation und XPath aber verwenden Sie eine "virtuelle" Schema-Speicherort-URI und überschreiben Sie es über Kataloge.

SCD wäre eine viel bessere Wahl gewesen (Sie haben hier absolut Recht), aber es funktioniert einfach nicht.

Aktualisieren Sie auf virtuellen Schemastandort und Katalogen.

Hier ist ein example of binding, die etwas komplexer Typ passt:

<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> 

Es über schemaLocation und XPath gebunden ist. Die schemaLocation ist ein existing URL, aber in der Build ist es via catalog in die Ressource in einem Maven Artefakt neu geschrieben:

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

Also im Grunde wird http://schemas.opengis.net/wps/2.0/wpsCommon.xsd vom ogc-schema.jar!/ogc/wps/2.0/wpsCommon.xsd geladen werden.

verwenden Sie können 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> 

Also, in Kombination, sie verbindlich Dateien einmal und wiederverwenden sie über Module ermöglicht das Schreiben.

Aber das war alles ein großer Schmerz, um herauszufinden. Ich habe es für das ogc-schemas Projekt gemacht, das jetzt ungefähr 50 stark miteinander verbundene Schemas ist. Ich leide stark unter XJC-Problemen und Problemen, aber das ist momentan das Beste. Ich dachte sogar über forking and patching XJC, aber das ist weit von Aufwand Grenzen, die ich mir leisten kann.

Also habe ich am Ende mit einer Reihe von Workarounds zum Durchdenken fertig, die irgendwie den Job am Ende des Tages erledigen.

+0

Dank lexicore. Was ist mit der Kombination von scd und xjc: superInterface ... Sollte das funktionieren? Irgendeine Idee, warum dieser Ansatz keinen Fehler erzeugt, aber auch keine Auswirkung auf die generierte Quelle hat? – 6006604

+0

... oder wird xjc: superInterface als benutzerdefinierte Anpassung/Anbieter-Anpassung betrachtet, genau wie inheritence: implements? – 6006604

+0

Es ist eigentlich eine Erweiterung des Anbieters, aber es ist eine "erste Klasse" Vendor-Erweiterung, die speziell XJC bekannt ist (siehe [hier] (https://github.com/gf-metro/jaxb/blob/69471fb27af6a9e990ef2a7873aab64a18e87640/jaxb-ri/ xjc/src/main/resources/com/sun/tools/xjc/Leser/XmlSchema/bindinfo/binding.xsd # L81)) - im Gegensatz zu 'Vererbung: implements'. By the way, ist nicht 'xjc: superInterface' für [nur globale Bindungen] (https://jaxb.java.net/nonav/2.1.15/docs/vendorCustomisations.html#superinterface)? Würde erklären, warum es in der Klasse ignoriert wird. – lexicore

Verwandte Themen