【问题标题】:CXF, wsdl2java. Custom port nameCXF,wsdl2java。自定义端口名称
【发布时间】:2018-10-24 14:03:50
【问题描述】:

小问题: 我可以以某种方式绑定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>

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

【问题讨论】:

标签: java xml soap cxf wsdl2java


【解决方案1】:

我终于找到了解决方案。 当然,这对于常见的 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()));

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

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

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

//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 文件,很高兴看到它正在工作。

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 感谢您的提示。我找到了wsdl2java 目标的解决方案,但您的建议是我列表中的下一个检查。
    【解决方案3】:

    我建议您更改 WSDL。 WSDL 中的该字段应该具有不能以数字开头的 NCName 类型。 如果您启用 WSDL 验证,我认为您会直接收到 WSDL 语法错误。因此,不确定以后是否可以通过自定义绑定更正此问题。

    【讨论】:

    • 感谢您的回答!我无法更改命名,因为它是来自外部服务的 wsdl。他们也无法更改它,因为其他一些外部服务使用此 wsdl。但是,是的,你说得对,现在 NCName 验证失败了。
    【解决方案4】:

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

    【讨论】:

    • 抱歉,您的绑定不适用于服务类中的端口字段名称。这与 PortType 类名无关。
    猜你喜欢
    • 1970-01-01
    • 2012-09-18
    • 2013-05-18
    • 2020-06-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-16
    • 1970-01-01
    • 2012-09-09
    相关资源
    最近更新 更多