本文介绍了使用CXF和wsdl2java生成代码时解决冲突的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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.

我遇到的第一个问题是结果<$之一的命名冲突c $ c> ObjectFactory 由一个WSDL引起的类。它定义了一个名为 Foo 的complexType,它包含一个名为 Status 的元素,它还定义了一个元素名称 FooStatus 。生成代码时,JAXB抛出一个拟合,因为 ObjectFactory 将有两个工厂方法,名称为 createFooStatus(...)我在运行时期间遇到异常。我已经尝试向wsdl2java提供 -autoNameResolution 选项但没有用。我查看了和,并根据我编写的外部绑定文件重命名其中一个工厂方法。我在绑定文件中使用SCD而不是XPath,如后一个链接所示,因为我和XPath的问题与作者有同样的问题。这是有效的,但前提是我单独处理WSDL文件并仅将绑定文件应用于导致冲突的WSDL。 Maven配置如下所示:

The first problem I have is a naming conflict in one of the resulting ObjectFactory classes caused by one of the WSDLs. It defines a complexType with the name Foo that 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 ObjectFactory would have two factory methods with the name createFooStatus(...) and I end up with an exception during runtime. I've tried providing the option -autoNameResolution to 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:

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

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

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 ObjectFactory classes 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 -keep wsdl2java option, but that doesn't seem to do anything (or at least the ObjectFactory classes 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):

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

然而,这导致 com.sun.istack.SAXParseException2 ,说我的SCD表达式与任何架构组件都不匹配(因为架构组件只存在于其中一个WSDL中)。

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).

我可以得到如果我修改WSDL文件本身并使用后一个没有绑定文件的Maven配置,我想要的结果。通过执行此操作,生成的 ObjectFactory 是在使用第一个Maven配置单独处理WSDL时创建的合并。但是,我宁愿不这样做,而是想用外部绑定文件来管理它。我该如何解决这个问题?我可以编写/应用绑定文件,以便在找不到匹配的模式组件时不会引发异常吗?或者我可以单独处理WSDL而不是覆盖 ObjectFactory 类吗?或者,我是否只需要将其填充并从不同的WSDL生成代码到不同的包或自己编辑WSDL文件?如果它很重要,我当前的绑定文件看起来像这样(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 ObjectFactory is 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 ObjectFactory classes? 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):

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


推荐答案

我最终在搜索了一些谷歌阅读论坛帖子。我设法使用XPath(而不是SCD)编写外部绑定文件,其方式仅针对我感兴趣的节点,而不会在处理其他WSDL文件时出错。最初阻止我使用XPath定位WSDL中的节点的主要混淆源是JAXB和JAXWS命名空间的类似XML模式(两者都定义了元素'绑定',我见过的大多数教程都使用了JAXB版本)我不得不使用JAXWS版本)。生成的绑定文件如下所示:

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:

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

这篇关于使用CXF和wsdl2java生成代码时解决冲突的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-20 18:53