web-dev-qa-db-ja.com

インターフェースを実装するJAXBクラスの生成

現在、JAXBを使用して、XMLをアンマーシャルするためにJavaクラスを生成しています。次に、最初と非常によく似た新しいスキーマを作成し、生成されるクラスに同じインターフェースを実装させます。 。

たとえば、XMLを同様のタグで定義する2つのスキーマファイルがあるとします。

adult.xsd

_<?xml version="1.0" encoding="UTF-8"?>
<xs:element name="Person">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="Name" type="xs:string" />
      <xs:element name="Age" type="xs:integer" />
      <xs:element name="Job" type="xs:string" />
    </xs:sequence>
  </xs:complexType>
</xs:element>
_

kid.xsd

_<?xml version="1.0" encoding="UTF-8"?>
<xs:element name="Person">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="Name" type="xs:string" />
      <xs:element name="Age" type="xs:integer" />
      <xs:element name="School" type="xs:string" />
    </xs:sequence>
  </xs:complexType>
</xs:element>
_

JAXBとXJCを使用して、2つのクラスファイルを生成します。

_public class Adult implements Person {
    ...
    public String getName() { ... }
    public int getAge() { ... }
    public String getJob { ... }
}

public class Kid implements Person {
    ...
    public String getName() { ... }
    public int getAge() { ... }
    public String getSchool { ... }
}
_

ここで、PersonインターフェースはgetName()およびgetAge()メソッドを定義します。

私は documentation のいくつかをインターフェイスのマッピングについて見てきましたが、これは、マッピングしたいクラスがすでにJava DOM。

また、私はこれを使用しようとしました 外部プラグイン が動作しないようです。これが私のxjbバインディングファイルです。

_<jxb:bindings version="1.0" 
  xmlns:jxb="http://Java.Sun.com/xml/ns/jaxb" 
  xmlns:xs="http://www.w3.org/2001/XMLSchema" 
  xmlns:xjc="http://Java.Sun.com/xml/ns/jaxb/xjc"
  xmlns:ext="http://xml.w-wins.com/xjc-plugins/interfaces"
  jxb:extensionBindingPrefixes="xjc">

    <jxb:bindings schemaLocation="xsd/adult.xsd" node="xs:schema/xs:complexType[@name='Person']">
        <ext:interface>mypackage.Hello</ext:interface> 
    </jxb:bindings>

</jxb:bindings>
_

ただし、これにより次のエラーが発生します。

_$ Java -cp "lib/activation.jar;lib/InterfacesXJCPlugin.jar;lib/jaxb1-impl.jar;lib/jaxb-api.jar;lib/jaxb-xjc.jar;lib/jsr173_1.0_api.jar" com.Sun.tools.xjc.XJCFacade -p mypackage.myxml -extension -Xinterfaces xsd/adult.xsd -b binding.xjb
parsing a schema...
[ERROR] XPath evaluation of "xs:schema/xs:complexType[@name='Person']" results in empty target node
  line 8 of file:/C:/dev/jaxb/jaxb-ri/binding.xjb

Failed to parse a schema.
_

インターフェースを実装するJAXBでクラスを生成することは可能ですか?

更新

Interface Insertion プラグインを使用しようとしましたが、何らかの理由で機能しません。これは私がxjcを呼び出す方法ですが、プラグインjarがクラスパスから選択されていないかのようです:

_$ Java -cp "lib/xjc-if-ins.jar;lib/jaxb-xjc.jar" com.Sun.tools.xjc.XJCFacade -p mypackage -extension -Xifins myschema.xsd -b binding.xjb
_

エラーが表示されます:

_unrecognized parameter -Xifins
_

何か案は?

50
Alex Spurling

残念ながら、他の回答のいくつかで言及されているインターフェイスインジェクションプラグインは、もはや十分にサポートされていないようです。実際、ダウンロード用のJARを見つけることができません。

ありがたいことに、 JAXB2 Basics Plugins は、生成されたJAXBスタブにインターフェースを追加するための同様のメカニズムを提供します( 継承プラグイン を参照)。

Inheritanceプラグインのドキュメントには、XMLスキーマファイルがどのように見えるかを示す例があります。ただし、スキーマを変更することはできないため、代わりに外部バインディングファイルを使用できます。

<?xml version="1.0"?>
<jxb:bindings version="1.0" 
  xmlns:jxb="http://Java.Sun.com/xml/ns/jaxb" 
  xmlns:xs="http://www.w3.org/2001/XMLSchema" 
  xmlns:xjc="http://Java.Sun.com/xml/ns/jaxb/xjc"
  xmlns:inheritance="http://jaxb2-commons.dev.Java.net/basic/inheritance"
  jxb:extensionBindingPrefixes="xjc">

    <jxb:bindings schemaLocation="xsd/adult.xsd">
      <jxb:bindings node="//xs:complexType[@name='Person']">
        <inheritance:implements>mypackage.Hello</inheritance:implements> 
      </jxb:bindings>
    </jxb:bindings>

</jxb:bindings>

JAXB2 Basics Pluginsのドキュメントには、AntおよびMavenでプラグインを使用するための手順が含まれています。コマンドラインから直接使用することもできますが、コマンドは少し厄介です(クラスパスに追加する必要があるjarの数のため)。

Java -jar jaxb-xjc.jar 
     -classpath jaxb2-basics-0.5.3.jar,jaxb2-basics-runtime-0.5.3.jar,
                jaxb2-basics-tools-0.5.3.jar,commons-beanutils-0.5.3.jar,
                commons-lang.jar,commons-logging.jar
     -p mypackage.myxml -extension -Xinheritance xsd/adult.xsd -b binding.xjb

JAXB2 Basics Pluginsには、他にも便利なユーティリティが多数用意されています(equals、hashCode、toStringメソッドの自動生成など)。

45
Jim Hurne

あなたの状況にとってはやり過ぎかもしれませんが、私はこれをAspectJを使用して行いました(そのプロジェクトですでにアスペクトを使用していたため、依存関係と露出が既にありました)。

次の行に沿ってアスペクトを宣言します。

public aspect MyAspect
{
    declare parents: 
        com.foo.generated.Adult
    implements com.foo.Person;

    declare parents: 
        com.foo.generated.Kid
    implements com.foo.Person;
}

インターフェースを追加しますcom.foo.Personクラスへcom.foo.generated.Adultおよびcom.foo.generated.Adult

あなたの目的にとってはやり過ぎかもしれませんが、私たちにとってはうまくいきました。

8
Chris

私のために働いた答えは、JAXB2 Basicsプラグインを使用したJim Hurneの例でした。しかし、彼がリンクしたドキュメントはもはや利用できないように見えるので、参照のために、これが私がmavenプラグインを設定した方法です:

        <plugin>
            <groupId>org.jvnet.jaxb2.maven2</groupId>
            <artifactId>maven-jaxb2-plugin</artifactId>
            <version>0.8.2</version>
            <executions>
                <execution>
                    <goals>
                        <goal>generate</goal>
                    </goals>
                    </execution>
            </executions>
            <configuration>
                <extension>true</extension>
                <args>
                    <arg>-Xinheritance</arg>
                </args>
                <bindingDirectory>src/main/resources/xjb</bindingDirectory>
                <bindingIncludes>
                    <include>**.xml</include> <!-- This Should reference the binding files you use to configure the inheritance -->
                </bindingIncludes>
                <schemaDirectory>src/main/resources/xsd</schemaDirectory>
                <generateDirectory>${project.build.directory}/generated-sources/jaxb</generateDirectory>
                <generatePackage>mypackage</generatePackage>
                <plugins>
                    <plugin>
                        <groupId>org.jvnet.jaxb2_commons</groupId>
                        <artifactId>jaxb2-basics</artifactId>
                        <version>0.5.3</version>
                    </plugin>
                </plugins>
            </configuration>
        </plugin>
3
Alex Spurling

JAXB RI Vendor Extensions xjc:superInterfaceカスタマイズを使用して、サードパーティのプラグインを使用せずに、この単純なケースでこれを達成することができます。このアプローチにより、生成されたすべてのクラスがインターフェースを実装することに注意してください。

バインディングファイルの例:

<jxb:bindings version="1.0" 
  xmlns:jxb="http://Java.Sun.com/xml/ns/jaxb" 
  xmlns:xs="http://www.w3.org/2001/XMLSchema" 
  xmlns:xjc="http://Java.Sun.com/xml/ns/jaxb/xjc" 
  jxb:extensionBindingPrefixes="xjc">
    <jxb:bindings schemaLocation="adult.xsd" node="/xs:schema">
    <jxb:globalBindings>
        <xjc:superInterface name="com.example.model.Person"/>
    </jxb:globalBindings>
    </jxb:bindings>
</jxb:bindings>

次に、 xjc を実行するだけで、バインディングファイルを指定し、-extensionフラグを設定できます。 JAXB2Basicsを取り込むよりもはるかに速く/簡単です!

私は当初、これがドキュメントに記載されているとおりに機能するのではないかと疑っていました。

カスタマイズでは、生成されるすべてのインターフェースのルートインターフェースとして使用されるJavaインターフェースの完全修飾名を指定できます。このカスタマイズは、特にインターフェースを生成しない限り効果がありません。 globalBindings generateValueClass = "false"スイッチ。

しかし、上記と同様のバインディング(generateValueClass = "false"を指定せず、インターフェースではなくクラスを生成)で試してみると、必要な出力が得られました-生成されたすべてのクラスは共通インターフェースを実装しました。

3
Malcolm Smith

私の場合、Java -jarが機能するコマンドライン呼び出し:

Java -jar $somepath/jaxb-xjc.jar -classpath $somepath/xjc-if-ins.jar my.xsd -d $destdir -b $bindingconfig -p $desiredpackage -extension -Xifins

ただし、xjc ant-taskを実行すると、エラーが残ります。私の場合の本当の理由は、クラスファイルのantがロードしようとするバージョン番号が間違っているためです(以下のスタックトレースを参照)。この正しいエラーメッセージは、ANT_OPTSに次を追加した場合にのみ表示されます。-Dcom.Sun.tools.xjc.Options.findServices=true

[xjc] Java.lang.UnsupportedClassVersionError: Bad version number in .class file
[xjc]     at Java.lang.ClassLoader.defineClass1(Native Method)
[xjc]     at Java.lang.ClassLoader.defineClass(ClassLoader.Java:620)
[xjc]     at org.Apache.tools.ant.AntClassLoader.defineClassFromData(AntClassLoader.Java:1134)
[xjc]     at org.Apache.tools.ant.AntClassLoader.getClassFromStream(AntClassLoader.Java:1320)
[xjc]     at org.Apache.tools.ant.AntClassLoader.findClassInComponents(AntClassLoader.Java:1376)
[xjc]     at org.Apache.tools.ant.AntClassLoader.findClass(AntClassLoader.Java:1336)
[xjc]     at org.Apache.tools.ant.AntClassLoader.loadClass(AntClassLoader.Java:1074)
[xjc]     at Java.lang.ClassLoader.loadClass(ClassLoader.Java:299)
[xjc]     at Java.lang.ClassLoader.loadClass(ClassLoader.Java:251)
[xjc]     at com.Sun.tools.xjc.Options.findServices(Options.Java:936)
[xjc]     at com.Sun.tools.xjc.Options.getAllPlugins(Options.Java:336)
[xjc]     at com.Sun.tools.xjc.Options.parseArgument(Options.Java:632)
[xjc]     at com.Sun.tools.xjc.Options.parseArguments(Options.Java:742)
[xjc]     at com.Sun.tools.xjc.XJC2Task._doXJC(XJC2Task.Java:444)
[xjc]     at com.Sun.tools.xjc.XJC2Task.doXJC(XJC2Task.Java:434)
[xjc]     at com.Sun.tools.xjc.XJC2Task.execute(XJC2Task.Java:369)
[xjc]     at com.Sun.istack.tools.ProtectedTask.execute(ProtectedTask.Java:55)
[xjc]     at org.Apache.tools.ant.UnknownElement.execute(UnknownElement.Java:291)
[xjc]     at Sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[xjc]     at Sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.Java:39)
[xjc]     at Sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.Java:25)
[xjc]     at Java.lang.reflect.Method.invoke(Method.Java:585)
[xjc]     at org.Apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.Java:106)
[xjc]     at org.Apache.tools.ant.Task.perform(Task.Java:348)
[xjc]     at org.Apache.tools.ant.Target.execute(Target.Java:390)
[xjc]     at org.Apache.tools.ant.Target.performTasks(Target.Java:411)
[xjc]     at org.Apache.tools.ant.Project.executeSortedTargets(Project.Java:1360)
[xjc]     at org.Apache.tools.ant.Project.executeTarget(Project.Java:1329)
[xjc]     at org.Apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.Java:41)
[xjc]     at org.Apache.tools.ant.Project.executeTargets(Project.Java:1212)
[xjc]     at org.Apache.tools.ant.Main.runBuild(Main.Java:801)
[xjc]     at org.Apache.tools.ant.Main.startAnt(Main.Java:218)
[xjc]     at org.Apache.tools.ant.launch.Launcher.run(Launcher.Java:280)
[xjc]     at org.Apache.tools.ant.launch.Launcher.main(Launcher.Java:109)
[xjc]
[xjc] failure in the XJC task. Use the Ant -verbose switch for more details
1
cfsh

インターフェース挿入プラグインのドキュメントでは、次のことが提案されています。

[コマンドラインからInterface Insertionプラグインを使用してxjcを呼び出すには、次のように記述します。

Java -cp $JAXB_HOME/share/lib/xjc-if-ins.jar -extension -Xifins schema

]

間違ったクラスのメインメソッドであるcom.Sun.tools.xjc.XJCFacadeを呼び出していると推測しています。おそらく、正確な構文で再試行する必要があります。

同様の問題を議論する別のフォーラムのリンクがあります。 http://forums.Java.net/jive/message.jspa?messageID=220686

  • これをコメントとして投稿しますが、コメントするのに十分なポイントがありません。
0
Thimmayya

より複雑なスキーマ(最新のオープンソースXMLツール)のためのJAXBデータバインディングファイルの構築を支援したい人のために、CAM Editor v2.2は現在これをサポートしています。

ステップバイステップガイドのリソースおよびダウンロードサイトにアクセスして、ツールのページ上部にダウンロードセクションを表示できます。

http://www.cameditor.org/#JAXB_Bindings

楽しい。

0
user841942