CXF,wsdl2java。自定义端口名称

时间:2018-05-14 20:13:06

标签: java xml soap cxf wsdl2java

简短问题: 我可以以某种方式绑定wsdl:port名称来生成服务中的自定义java字段名称吗?

长问题: 我有一个wsdl这样的部分:

<wsdl:service name="123xxx">
   <wsdl:port name="123xxxHttpSoap11Endpoint" binding="tns:123xxxSoap11Binding">
     <soap:address location="..."/>
   </wsdl:port>
</wsdl:service>

maven wsdl2java目标生成名为123xxx的服务(我已经通过调用MyService来修复绑定)并在此服务中生成一个字段:

public class MyService extends Service {
    ...
    public final static QName 123xxxHttpSoap11Endpoint = 
                 new QName("http://new.webservice.namespace", "123xxxHttpSoap11Endpoint");
    ...
}

这会导致编译错误,因为变量不能以Java中的数字开头。我无法找到一种方法以某种方式自定义生成的代码,而无需更改原始的wsdl。

那么,有没有办法通过cxf绑定绑定它,就像服务本身一样:

<bindings...>
    <bindings node="wsdl:definitions/wsdl:service">
    <class name="MyService"/>
    </bindings>
</bindings>

或者可能还有其他方法可以实现这个目标吗?

4 个答案:

答案 0 :(得分:6)

最后我找到了解决方案。 当然,这是常见的wsdl生成过程的开销,但它只是(或几乎只是)满足我的限制的方式。

首先,我检查了cxf库的来源,发现有一种生成Port元素的方法:

org.apache.cxf.tools.wsdlto.frontend.jaxws.processor.internal.ServiceProcessor#processPort

只创建名称JavaPort,从原始wsdl获取并且不使用任何绑定处理它:

JavaPort jport = new JavaPort(NameUtil.mangleNameToClassName(port.getName().getLocalPart()));

更进一步,我发现有可能注入自定义代码生成器,它负责从java模型创建cxf类。

经过一番研究后,我发现 this answer 帮助我做到了。

所以我用这样的类创建了一个单独的模块(检查注释):

//note that I've put my class inside the package, 
//which is used for other default generators in cxf
package org.apache.cxf.tools.wsdlto.frontend.jaxws.generators;

import java.util.List;
import java.util.Map;

import org.apache.cxf.tools.common.ToolContext;
import org.apache.cxf.tools.common.ToolException;
import org.apache.cxf.tools.common.model.JavaPort;
import org.apache.cxf.tools.common.model.JavaServiceClass;

public class CustomSEIGenerator extends SEIGenerator {

    @Override
    public void generate(ToolContext penv) throws ToolException {
        //no streams, because we still on java 7
        //fetch all services
        Map<String, JavaServiceClass> ss = penv.getJavaModel().getServiceClasses();
        for (Map.Entry<String, JavaServiceClass> s : ss.entrySet()) {
            //fetch all ports from each service
            for (JavaPort port : s.getValue().getPorts()) {
                //set custom name to each port
                port.setName("_" + port.getName);
            }
        }
    }
}

并将tools-plugin.xml放入META-INF文件夹:

<?xml version="1.0" encoding="utf-8"?>
<plugin xmlns="http://cxf.apache.org/tools/plugin" name="play" version="" provider="play.typesafe.com">
    <frontend name="sample" package="org.apache.cxf.tools.wsdlto.frontend.jaxws" profile="JAXWSProfile">
        <container name="JAXWSContainer" package="org.apache.cxf.tools.wsdlto.frontend.jaxws" toolspec="jaxws-toolspec.xml"/>
        <processor name="WSDLToJavaProcessor" package="org.apache.cxf.tools.wsdlto.frontend.jaxws.processor"/>
        <builder name="JAXWSDefinitionBuilder" package="org.apache.cxf.tools.wsdlto.frontend.jaxws.wsdl11"/>
        <generators package="org.apache.cxf.tools.wsdlto.frontend.jaxws.generators">
            <generator name="CustomSEIGenerator"/>
            <generator name="AntGenerator"/>
            <generator name="ClientGenerator"/>
            <generator name="FaultGenerator"/>
            <generator name="ImplGenerator"/>
            <generator name="SEIGenerator"/>
            <generator name="ServerGenerator"/>
            <generator name="ServiceGenerator"/>
        </generators>
    </frontend>
</plugin>

(请注意,我已将自定义生成器置于默认生成器之前,以使其与修改后的模型一起使用)。

接下来,我刚刚根据上面发布的答案修改了我的pom文件,很高兴看到它正在运行。

答案 1 :(得分:3)

除非你绑定到wsdl2java,否则请使用wsimport。它会在任何以数字开头的变量之前添加下划线。它也有一个maven的目标。

答案 2 :(得分:2)

我建议你改变WSDL。 WSDL中的这个字段应该具有不能以数字开头的NCName类型。 如果启用WSDL验证,我认为您将直接使用WSDL语法获得错误。因此,不确定您是否可以使用自定义绑定进行更正。

答案 3 :(得分:2)

正如Tarun Lalwani在评论中提到的那样,你应该使用像这样的jaxb绑定:

<plugin>
    <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-codegen-plugin</artifactId>
        <version>${cxf.version}</version>
        <executions>
            <execution>
                <phase>generate-sources</phase>
                <configuration>
                    <sourceRoot>
                        ${basedir}/src/main/java
                    </sourceRoot>
                    <wsdlOptions>
                        <wsdlOption>
                            <wsdl>
                                ${basedir}/xxx/yourwsdl.wsdl
                            </wsdl>
                                <extraargs>
                                <!-- you can redefine the client -->
                                <extraarg>-client</extraarg>
                                <extraarg>-b</extraarg>
                                <extraarg>${basedir}/xxx/binding.xml</extraarg>
                    </extraargs>
                    </wsdlOption>
                </wsdlOptions>
            </configuration>
            <goals>
                <goal>wsdl2java</goal>
            </goals>
        </execution>
    </executions>
</plugin>

绑定文件:

<bindings
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    wsdlLocation="yourwsdl.wsdl"
    xmlns="http://java.sun.com/xml/ns/jaxws">

    <bindings node="wsdl:definitions/wsdl:portType[@name='123xxxHttpSoap11Endpoint']">
    <class name="yourservice"/>
    </bindings>
</bindings>

请参阅JAXWS Customization