簡體   English   中英

生成實現接口的JAXB類

[英]Generating a JAXB class that implements an interface

我當前正在使用JAXB生成Java類,以解組XML。 現在,我想創建一個與第一個非常相似的新模式,並讓生成的類實現相同的接口。

舉例來說,我有兩個模式文件,它們定義帶有類似標簽的XML:

成人版

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

小子

<?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生成兩個類文件:

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()方法。

我看過一些映射接口的文檔 ,但這似乎僅適用於已經具有要映射到DOM的Java類的情況。

另外,我嘗試使用此外部插件,但似乎不起作用。 這是我的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生成一個實現接口的類?

更新資料

我嘗試使用接口插入插件,但由於某種原因無法使其正常工作。 這就是我調用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

有任何想法嗎?

不幸的是,其他答案中提到的接口注入插件似乎不再受支持。 實際上,我很難找到要下載的JAR。

幸運的是, JAXB2 Basics插件提供了一種類似的機制,用於將接口添加到生成的JAXB存根(請參閱Inheritance plugin )。

繼承插件文檔中有一個示例,顯示了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插件文檔包括將插件與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插件提供了許多其他實用程序,您可能還會發現它們有用(例如,自動生成equals,hashCode和toString方法)。

對於您的情況,這可能有些過分,但是我已經使用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.Adultcom.foo.generated.Kid類中

可能出於您的目的而過度使用,但這對我們有用。

對我有用的答案是Jim Hurne的使用JAXB2 Basics插件的示例。 但是他鏈接的文檔似乎不再可用,因此僅供參考,這是我配置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>

對於這種簡單情況,無需使用JAXB RI供應商擴展 xjc:superInterface定制即可使用第3方插件即可實現。 應當注意,這種方法將導致所有生成的類都實現該接口。

綁定文件示例:

<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”並生成類而不是接口)時,它給了我所需的輸出-我所有生成的類都實現了公共接口。

在我的情況下,通過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試圖加載的類文件中的版本號錯誤(請參見下面的stacktrace)。 僅當您將以下內容添加到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

對於那些希望為更復雜的架構構建JAXB數據綁定文件的人-最新的開源XML工具-CAM Editor v2.2現在支持此功能。

您可以訪問資源和下載站點,以獲取逐步指南,並查看該工具頁面頂部的下載部分。

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

請享用。

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

  • 我本來可以將其發布為評論,但是我沒有足夠的觀點發表評論。

某種描述的XJC插件可以解決您的問題,這只是找到一個可行的問題。 對於他們來說,最好的來源是:

https://jaxb2-commons.dev.java.net/

特別是,這一個:

https://jaxb2-commons.dev.java.net/interface-insertion/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM