You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

模块化JAXB/JAX-WS Maven模块间如何共享/复用类?

Maven多模块JAXB/JAX-WS代码生成冲突解决

问题背景

有一个Maven多模块项目,结构如下:

my-project
+- xsd
   +- src
      +- main
         +- resources
            +- xsd
               +- foo.xsd    [定义foo:UUIDType等基础类型]
               +- bar.xsd    [导入foo.xsd]
               +- baz.xsd    [导入foo.xsd + bar.xsd]
         +- jaxb
            +- bindings.xml  [定义<jaxb:globalBindings>,包含<xjc:javaType name="java.util.UUID" xmlType="foo:UUIDType" adapter="...UuidXmlAdapter"/>]
+- wsdl
   +- src
      +- main
         +- resources
            +- wsdl
               +- qux.wsdl    [导入qux.xsd]
               +- qux.xsd     [导入foo.xsd + bar.xsd,定义qux.wsdl操作的请求响应类型]
         +- jaxws
            +- catalog.cat    [定义foo.xsd和bar.xsd的解析规则]
            +- bindings.xml   [定义<jaxb:globalBindings>,包含<xjc:javaType name="java.util.UUID" xmlType="foo:UUIDType" adapter="...UuidXmlAdapter"/>]
  • xsd模块使用org.jvnet.jaxb:jaxb-maven-plugin生成Java类,同时生成sun-jaxb.episode文件
  • wsdl模块依赖xsd模块,使用org.apache.cxf:cxf-codegen-plugin生成JAX-WS类,复用xsd模块的episode文件

遇到的矛盾:

  • 若wsdl模块不添加bindings.xml,qux.xsd里的foo:UUIDType无法映射为java.util.UUID,也不会使用对应的XmlAdapter
  • 若添加该bindings文件,会触发报错:

Exception in thread "main" org.apache.cxf.tools.common.ToolException: file:/.../myproject/wsdl/src/main/jaxws/bindings.xml [line,col]: compiler was unable to honor this conversion customization. It is attached to a wrong place, or its inconsistent with other bindings.
[WARNING] file:/.../myproject/xsd/src/main/resources/xsd/foo.xsd [line,col]: (the above customization is attached to the following location in the schema)

报错核心原因是全局绑定被重复应用到xsd模块已处理过的Schema上。

解决方案

方案1:限制绑定作用范围,避免全局重复

修改wsdl模块的bindings.xml,将类型绑定仅作用于qux.xsd本身,不影响已通过episode复用的xsd模块Schema:

<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
               xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
               version="2.1">
    <!-- 仅对qux.xsd应用绑定规则 -->
    <jaxb:bindings schemaLocation="../resources/wsdl/qux.xsd">
        <jaxb:globalBindings>
            <xjc:javaType name="java.util.UUID" xmlType="foo:UUIDType" adapter="...UuidXmlAdapter"/>
        </jaxb:globalBindings>
    </jaxb:bindings>
</jaxb:bindings>

此方式确保绑定规则只作用于当前模块的qux.xsd,不会覆盖或重复作用于xsd模块已处理的Schema,从根源避免冲突。

方案2:提取共享绑定配置,避免重复编写

将通用绑定规则(如UUID类型映射)提取到xsd模块的共享配置文件中(比如xsd/src/main/resources/jaxb/shared-bindings.xml),然后在两个模块中分别引用:

  1. xsd模块的bindings.xml导入共享文件:
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
               xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
               version="2.1">
    <jaxb:bindings>
        <jaxb:import namespace="http://java.sun.com/xml/ns/jaxb/xjc" schemaLocation="http://java.sun.com/xml/ns/jaxb/xjc.xsd"/>
    </jaxb:bindings>
    <!-- 引入共享绑定规则 -->
    <jaxb:bindings>
        <jaxb:import location="classpath:/jaxb/shared-bindings.xml"/>
    </jaxb:bindings>
</jaxb:bindings>
  1. wsdl模块的bindings.xml仅对qux.xsd引用共享文件:
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
               xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
               version="2.1">
    <jaxb:bindings schemaLocation="../resources/wsdl/qux.xsd">
        <jaxb:bindings>
            <jaxb:import namespace="http://java.sun.com/xml/ns/jaxb/xjc" schemaLocation="http://java.sun.com/xml/ns/jaxb/xjc.xsd"/>
        </jaxb:bindings>
        <!-- 引入xsd模块的共享绑定规则 -->
        <jaxb:bindings>
            <jaxb:import location="classpath:/jaxb/shared-bindings.xml"/>
        </jaxb:bindings>
    </jaxb:bindings>
</jaxb:bindings>

该方案既避免重复编写绑定规则,又保证作用范围精准。

方案3:优化CXF代码生成配置,确保episode生效

检查wsdl模块的cxf-codegen-plugin配置,确保正确引入xsd模块的sun-jaxb.episode文件,并启用xjc-episode参数:

<plugin>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-codegen-plugin</artifactId>
    <version>${cxf.version}</version>
    <executions>
        <execution>
            <id>generate-sources</id>
            <phase>generate-sources</phase>
            <goals>
                <goal>wsdl2java</goal>
            </goals>
            <configuration>
                <wsdlOptions>
                    <wsdlOption>
                        <wsdl>${project.basedir}/src/main/resources/wsdl/qux.wsdl</wsdl>
                        <extraargs>
                            <extraarg>-xjc-episode</extraarg>
                            <extraarg>-b</extraarg>
                            <extraarg>${project.basedir}/src/main/jaxws/bindings.xml</extraarg>
                            <!-- 引入xsd模块生成的episode文件 -->
                            <extraarg>-b</extraarg>
                            <extraarg>${project.basedir}/../xsd/target/generated-sources/jaxb/sun-jaxb.episode</extraarg>
                        </extraargs>
                    </wsdlOption>
                </wsdlOptions>
            </configuration>
        </execution>
    </executions>
    <dependencies>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-xjc</artifactId>
            <version>${jaxb.version}</version>
        </dependency>
    </dependencies>
</plugin>

episode文件会让CXF识别已生成的类,减少重复处理,但如果qux.xsd有新的类型使用场景,仍需针对性绑定。

总结

不需要为每个XSD单独重复绑定,最优方案是限制wsdl模块绑定的作用范围到qux.xsd,同时确保CXF正确复用xsd模块的episode文件,既解决类型映射问题,又避免重复绑定冲突。

内容的提问来源于stack exchange,提问作者Xavier Dury

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 19:33:23