Apache CXF XSD 方案改为 Java,更改输出类和工厂名称

问题描述 投票:0回答:1

我正在使用 CXF maven 插件根据 XSD 方案定义生成 Java 类。我使用两个 xsdOptions 标签将两种不同方案的 Java 文件创建到两个不同的包中。生成的 Java 类和工厂具有相同的名称,例如“ObjectFactory.java”。如何将生成的文件的名称更改为自定义名称?

我的 POM.xml 文件中的插件条目:

<plugin>
                    <groupId>org.apache.cxf</groupId>
                    <artifactId>cxf-xjc-plugin</artifactId>
                    <version>3.3.0</version>
                    <executions>
                        <execution>
                            <id>xjc</id>
                            <phase>generate-sources</phase>
                            <goals>
                                <goal>xsdtojava</goal>
                            </goals>
                        </execution>
                    </executions>
                    <configuration>
                        <sourceRoot>${basedir}/src/main/java/</sourceRoot>
                        <xsdOptions>
                            <xsdOption>
                                <xsd>${basedir}/src/main/resources/schemes/A.xsd</xsd>
                                <packagename>com.exmaple.A</packagename>
                            </xsdOption>
                            <xsdOption>
                                <xsd>${basedir}/src/main/resources/B.xsd</xsd>
                                <packagename>com.example.B</packagename>
                            </xsdOption>
                        </xsdOptions>
                    </configuration>
                </plugin>

我尝试添加extensionArgs-tags,但没有运行。

xml maven xsd jaxb
1个回答
0
投票

download (zip) 是一个独立的 Maven 项目,用于演示来自 Apache CXF 的 Maven cxf-xjc-plugin 以及 XJC HiSrc BasicJAXB Plugins 的配置。具体来说,

注意: 将下载解压到本地文件夹后,您可以使用以下命令运行测试和/或演示:

mvn -Ptest clean test
mvn -Pexec compile exec:java

两种 XML 模式(A 和 B)都定义了类似的业务模型。每个模型都有一个

notebook
。 A 模式模拟“纸质”笔记本,而 B 模式模拟“电子”笔记本。两个模型具有相同的元素名称: 商业模式

notebook owner pageSpec 默认情况下,XJC 在单独的 Java 包中为上述每个内容生成一个 JAXB 类:

无定制:A

org.example.nb.A.Notebook org.example.nb.A.Owner org.example.nb.A.PageSpec org.example.nb.A.ObjectFactory

无定制:B

org.example.nb.B.Notebook org.example.nb.B.Owner org.example.nb.B.PageSpec org.example.nb.B.ObjectFactory 虽然类名相同,但每个类都由自己的 Java 包限定。在 XML 方面,每个文档都声明它自己的名称空间。

解组
时,JAXB 使用 XML 文档中的命名空间(
nbA.xml

nbB.xml)来确定正确的业务模型。 问题在于,在同一 Java 代码块中引用这两个模型需要使用完全限定的类名。

为了解决该问题

,每个 XML 模式都使用 JAXB 绑定文件进行自定义,调用

jaxb:class

声明来重命名生成的 Java 类。 A 模式中的类是

定制
以包含后缀:

Analog

摘自
nbA.xjb

<jaxb:bindings schemaLocation="nbA.xsd" node="/xs:schema"> <jaxb:bindings node="//xs:element[@name='notebook']/xs:complexType"> <anx:annotate>@jakarta.xml.bind.annotation.XmlRootElement(name = "notebook")</anx:annotate> <jaxb:class name="NotebookAnalog" /> </jaxb:bindings> <jaxb:bindings node="//xs:complexType[@name='Owner']"> <jaxb:class name="OwnerAnalog" /> </jaxb:bindings> <jaxb:bindings node="//xs:complexType[@name='PageSpec']"> <jaxb:class name="PageSpecAnalog" /> </jaxb:bindings> </jaxb:bindings> B 模式中的类是

定制
以包含后缀:
Digital

摘自
nbB.xjb

<jaxb:bindings schemaLocation="nbB.xsd" node="/xs:schema"> <jaxb:bindings node="//xs:element[@name='notebook']/xs:complexType"> <anx:annotate>@jakarta.xml.bind.annotation.XmlRootElement(name = "notebook")</anx:annotate> <jaxb:class name="NotebookDigital" /> </jaxb:bindings> <jaxb:bindings node="//xs:complexType[@name='Owner']"> <jaxb:class name="OwnerDigital" /> </jaxb:bindings> <jaxb:bindings node="//xs:complexType[@name='PageSpec']"> <jaxb:class name="PageSpecDigital" /> </jaxb:bindings> </jaxb:bindings>

注意:为什么
<anx:annotate ... >
元素上有
notebook

扩展?因为,当使用

@XmlRootElement
更改
jaxb:class
类名时,XJC 启发式忽略了通常存在的
Notebook
注释。
HiSrc HyperJAXB Annox
用于重新添加注释。

ObjectFactory

的 JAXB/XJC 命名约定不太灵活。 JAXB 参考实现和 API 都假设这是一个众所周知的类名,由其 Java 包名称限定。例如,JAXB RI 将名称注册为
保留类名称

好消息是,应用程序只需要每个 ObjectFactory 的一个实例;因此,每个都可以用短名称声明为静态实例。

示例:

AbstractNotebookTest

protected static final org.example.nb.A.ObjectFactory OFA = new org.example.nb.A.ObjectFactory(); protected static final org.example.nb.B.ObjectFactory OFB = new org.example.nb.B.ObjectFactory(); 然后可以在同一代码块中方便地使用

OFA
OFB

实例,如此处所示...

FluentAPI测试

final Object object = getUnmarshaller().unmarshal(sample); if ( object instanceof NotebookAnalog ) { NotebookAnalog nba1 = (NotebookAnalog) object; NotebookAnalog nba2 = OFA.createNotebookAnalog() .useTitle("PaperBook") .useOwner(OFA.createOwnerAnalog() .useFirstname("Paul") .useLastname("McCartney")) .usePageSpec(OFA.createPageSpecAnalog() .useLinesPerPage(new BigInteger("66")) .usePageCount(new BigInteger("100"))); getLogger().debug("NBA1: {}", nba1); getLogger().debug("NBA2: {}", nba2); assertEquals(nba1, nba2, "Unmarshaled and Fluent NBAs are equal."); } else if ( object instanceof NotebookDigital ) { NotebookDigital nbb1 = (NotebookDigital) object; NotebookDigital nbb2 = OFB.createNotebookDigital() .useTitle("EBook") .useOwner(OFB.createOwnerDigital() .useFirstname("John") .useLastname("Lennon")) .usePageSpec(OFB.createPageSpecDigital() .useKbPerPage(new BigInteger("512")) .usePageCount(new BigInteger("1024"))); getLogger().debug("NBB1: {}", nbb1); getLogger().debug("NBB2: {}", nbb2); assertEquals(nbb1, nbb2, "Unmarshaled and Fluent NBBs are equal."); }

POM配置

POM 配置为每个模式使用两个块:A 和 B。

pom.xml

中提取 ... <!-- mvn cxf-xjc:help -Ddetail=true --> <!-- mvn cxf-xjc::generate --> <plugin> <groupId>org.apache.cxf</groupId> <artifactId>cxf-xjc-plugin</artifactId> <version>${cxf-xjc-plugin.version}</version> <executions> <execution> <id>generate-sources</id> <phase>generate-sources</phase> <goals> <goal>xsdtojava</goal> </goals> <configuration> <fork>false</fork> <sourceRoot>${basedir}/target/generated-sources/xjc/</sourceRoot> <extensions> <extension>org.patrodyne.jvnet:hisrc-basicjaxb-plugins:2.2.1</extension> <extension>org.patrodyne.jvnet:hisrc-hyperjaxb-annox-plugin:2.2.1</extension> </extensions> <xsdOptions> <xsdOption> <bindingFiles> <bindingFile>${basedir}/src/main/resources/nb.xjb</bindingFile> <bindingFile>${basedir}/src/main/resources/nbA.xjb</bindingFile> </bindingFiles> <packagename>org.example.nb.A</packagename> <xsd>${basedir}/src/main/resources/nbA.xsd</xsd> <extension>true</extension> <extensionArgs> ... <extensionArg>-XfluentAPI</extensionArg> <extensionArg>-XfluentAPI-fluentMethodPrefix=use</extensionArg> </extensionArgs> </xsdOption> <xsdOption> <bindingFiles> <bindingFile>${basedir}/src/main/resources/nb.xjb</bindingFile> <bindingFile>${basedir}/src/main/resources/nbB.xjb</bindingFile> </bindingFiles> <packagename>org.example.nb.B</packagename> <xsd>${basedir}/src/main/resources/nbB.xsd</xsd> <extension>true</extension> <extensionArgs> ... <extensionArg>-XfluentAPI</extensionArg> <extensionArg>-XfluentAPI-fluentMethodPrefix=use</extensionArg> </extensionArgs> </xsdOption> </xsdOptions> </configuration> </execution> </executions> ... (dependencies) </plugin> ...

注意:
cxf-xjc-plugin

提供 extensionArgs 来从扩展库(如 HiSrc BasicJAXB Plugins)激活 XJC 插件。它是传递给 XJC 的附加参数列表。 (例如:

-XfluentAPI
)。
JAR 冲突

上面的
cxf-xjc-plugin

明确声明了几个依赖项(未显示)来解决CXF产品和HiSrc产品之间的JAR冲突。由于这些产品是由独立团队生产的,因此可能存在一些版本冲突。

下载 (zip)

包含一个名为

ReadJarManifest.java
的工具,用于识别和解决冲突。冲突已在 download 示例中得到解决。
生成
build.log

mvn -Dorg.slf4j.simpleLogger.log.org.apache.cxf.maven_plugin.XSDToJavaMojo=DEBUG -Ptest clean test >build.log

ReadJarManifest.java

Read JAR Manifest from a JAR file or a LOG file. Usage: javac ReadJarManifest.java java ReadJarManifest [jarfile | stdin] Example: java ReadJarManifest <build.log

注意:
ReadJarManifest.java

工具可以捕获大多数问题,但也可以报告 错误冲突。在此示例中,冲突百分比错误地高,因为两个不冲突的 jar 具有相同的版本号,但名称不同但相似。 Conflict%: 89 file:/home/rick/.m2/repository/org/glassfish/jaxb/txw2/4.0.5/txw2-4.0.5.jar file:/home/rick/.m2/repository/org/glassfish/jaxb/xsom/4.0.5/xsom-4.0.5.jar

免责声明:
我是 HiSrc 项目的维护者。

© www.soinside.com 2019 - 2024. All rights reserved.