使用 CXF 和 wsdl2java 生成代码时解决冲突

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22425306/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 15:39:08  来源:igfitidea点击:

Resolving conflicts when generating code with CXF and wsdl2java

javaweb-servicesmavenjaxbwsdl

提问by Markus Yrj?l?

I'm struggling with some conflicts during code generation from a bunch of WSDL files using wsdl2java via the cxf-codegen-plugin with Maven. The WSDLs declare different APIs of the same system, and the generated code has some amount of overlap (especially with the model classes). The external system and the WSDLs come from a third party and are therefore not controlled by us.

我在使用 wsdl2java 通过 cxf-codegen-plugin 和 Maven 从一堆 WSDL 文件生成代码的过程中遇到了一些冲突。WSDL 声明了同一系统的不同 API,并且生成的代码有一定的重叠(尤其是模型类)。外部系统和 WSDL 来自第三方,因此不受我们控制。

The first problem I have is a naming conflict in one of the resulting ObjectFactoryclasses caused by one of the WSDLs. It defines a complexType with the name Foothat contains an element with the name Status, and it also defines a element with the name FooStatus. When generating the code, JAXB throws a fit because the ObjectFactorywould have two factory methods with the name createFooStatus(...)and I end up with an exception during runtime. I've tried providing the option -autoNameResolutionto wsdl2java with no avail. I've looked at "Two declarations cause a collision in the ObjectFactory class"and "Applying external JAXB binding file to schema elements imported from WSDL", and based on those I've written an external binding file that renames one of the factory methods. I use SCD instead of XPath in the binding file as shown in the latter link, because I had the same problem with XPath as the author. This works, but only if I process the WSDL files individually and apply the binding file only to the WSDL that causes the conflict. The Maven configuration looks like this:

我遇到的第一个问题是ObjectFactory由其中一个 WSDL 引起的结果类中的一个命名冲突。它定义了一个带有名称的 complexType ,Foo其中包含一个带有名称的元素,Status它还定义了一个带有名称的元素FooStatus。在生成代码时,JAXB 会抛出一个合适的错误,因为它ObjectFactory会有两个同名的工厂方法,createFooStatus(...)而我在运行时最终会出现异常。我试过为-autoNameResolutionwsdl2java提供选项但无济于事。我看过“两个声明导致 ObjectFactory 类中的冲突”“将外部 JAXB 绑定文件应用于从 WSDL 导入的模式元素”,并基于这些,我编写了一个重命名工厂方法之一的外部绑定文件。我在绑定文件中使用 SCD 而不是 XPath,如后一个链接所示,因为我和作者在使用 XPath 时遇到了同样的问题。这有效,但前提是我单独处理 WSDL 文件并将绑定文件仅应用于导致冲突的 WSDL。Maven 配置如下所示:

<plugin>
  <groupId>org.apache.cxf</groupId>
  <artifactId>cxf-codegen-plugin</artifactId>
  <version>3.0.0-milestone1</version>
  <executions>
    <execution>
      <id>generate-proxies</id>
      <phase>generate-sources</phase>
      <configuration>
        <wsdlOptions>
          <wsdlOption>
            <wsdl>${basedir}/First.wsdl</wsdl>
            <bindingFiles>
              <bindingFile>${basedir}/bindings.xml</bindingFile>
            </bindingFiles>
          </wsdlOption>
          <wsdlOption>
            <wsdl>${basedir}/Second.wsdl</wsdl>
          </wsdlOption>
          <wsdlOption>
            <wsdl>${basedir}/Third.wsdl</wsdl>
          </wsdlOption>
          ... More wsdlOption declarations ...
        </wsdlOptions>
      </configuration>
      <goals>
        <goal>wsdl2java</goal>
      </goals>
    </execution>
  </executions>
</plugin>

Now, if I do this I end up with another problem, because the generated code from the different WSDL files uses the same package structure. What this means in practice is that the ObjectFactoryclasses get overridden when processing subsequent WSDL files, meaning that only the one generated from the last WSDL will exist after the plugin execution. I know that I could change the target package structure, but the code generated from the different WSDLs has a lot of overlap and it would feel silly to duplicate it. I've also tried using the -keepwsdl2java option, but that doesn't seem to do anything (or at least the ObjectFactoryclasses still get overridden). My understanding is that the solution to this would be to process all of the WSDLs in one go with a Maven configuration like this (showing only the configuration section, all else stays the same):

现在,如果我这样做,我最终会遇到另一个问题,因为从不同 WSDL 文件生成的代码使用相同的包结构。这在实践中意味着在ObjectFactory处理后续 WSDL 文件时这些类会被覆盖,这意味着只有从最后一个 WSDL 生成的文件才会在插件执行后存在。我知道我可以更改目标包结构,但是从不同 WSDL 生成的代码有很多重叠,复制它会感觉很愚蠢。我也试过使用-keepwsdl2java 选项,但这似乎没有做任何事情(或者至少ObjectFactory类仍然会被覆盖)。我的理解是,对此的解决方案是使用这样的 Maven 配置一次性处理所有 WSDL(仅显示配置部分,其他所有内容保持不变):

<configuration>
  <defaultOptions>
    <bindingFiles>
      <bindingFile>${basedir}/bindings.xml</bindingFile>
    </bindingFiles>
  </defaultOptions>
  <wsdlRoot>${basedir}</wsdlRoot>
  <includes>
    <include>*.wsdl</include>
  </includes>
</configuration>

However, this results in a com.sun.istack.SAXParseException2, saying that my SCD expression doesn't match any schema component (since the schema component exists only in one of the WSDLs).

但是,这会导致com.sun.istack.SAXParseException2, 表示我的 SCD 表达式不匹配任何架构组件(因为架构组件仅存在于其中一个 WSDL 中)。

I can get the result I want if I modify the WSDL file itself and use the latter Maven configuration without the binding file. By doing this, the resulting ObjectFactoryis a merge from the ones that would be created when processing the WSDLs individually with the first Maven config. However, I'd rather not do that, but instead would like to manage this with an external binding file. How should I go about solving this? Can I write/apply the binding file so that no exception is raised if the matching schema component is not found? Or can I process the WSDLs individually and not overwrite the ObjectFactoryclasses? Or do I just have to suck it up and either generate the code from different WSDLs to different packages or edit the WSDL files themselves? Just in case it matters, my current binding file looks like this (the WSDLs are located inside my project in the same directory with the binding file):

如果我修改 WSDL 文件本身并使用没有绑定文件的后一个 Maven 配置,我可以获得我想要的结果。通过这样做,结果ObjectFactory是与使用第一个 Maven 配置单独处理 WSDL 时创建的那些的合并。但是,我宁愿不这样做,而是想使用外部绑定文件来管理它。我应该如何解决这个问题?我可以编写/应用绑定文件,以便在找不到匹配的架构组件时不会引发异常吗?或者我可以单独处理 WSDL 而不是覆盖ObjectFactory课?或者我是否只需要解决它并从不同的 WSDL 生成代码到不同的包,或者自己编辑 WSDL 文件?以防万一,我当前的绑定文件如下所示(WSDL 位于我的项目中,与绑定文件位于同一目录中):

<bindings scd="x-schema::tns" xmlns:tns="NamespaceOfFoo" xmlns="http://java.sun.com/xml/ns/jaxb" version="2.1">
  <bindings scd="tns:FooStatus">
    <factoryMethod name="FooStatusType"/>
  </bindings>
</bindings>

采纳答案by Markus Yrj?l?

I eventually solved this myself after some more googling around and reading forum posts. I managed to write the external binding file using XPath (instead of SCD) in a way that only targets the node I'm interested in without giving an error when processing the other WSDL files. The main source of confusion that initially prevented me from targeting nodes in the WSDL with XPath was the similar XML schemas of the JAXB and JAXWS namespaces (both define the element 'bindings', and most tutorials I've seen used the JAXB version while here I had to use the JAXWS version). The resulting binding file looks like this:

经过更多的谷歌搜索和阅读论坛帖子后,我最终自己解决了这个问题。我设法使用 XPath(而不是 SCD)以仅针对我感兴趣的节点的方式编写外部绑定文件,而在处理其他 WSDL 文件时不会出错。最初阻止我使用 XPath 定位 WSDL 中的节点的主要混淆来源是 JAXB 和 JAXWS 命名空间的相似 XML 模式(两者都定义了元素“绑定”,并且我在这里看到的大多数教程都使用了 JAXB 版本我必须使用 JAXWS 版本)。生成的绑定文件如下所示:

<jaxws:bindings xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
                xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
                xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
                wsdlLocation="First.wsdl"
                version="2.1">
  <jaxws:bindings node="wsdl:definitions/wsdl:types/xsd:schema/xsd:element[@name='FooStatus']">
    <jaxb:factoryMethod name="FooStatusType"/>
  </jaxws:bindings>
</jaxws:bindings>