CXF,wsdl2java。自定义端口名称
CXF, wsdl2java. Custom port name
小问题:
我可以以某种方式绑定 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>
或者是否有其他一些方法可以实现此目的?
我建议您更改 WSDL。 WSDL 中的该字段应该具有不能以数字开头的 NCName 类型。
如果您启用 WSDL 验证,我认为您会直接收到 WSDL 语法错误。所以,不确定您之后是否可以使用自定义绑定更正此问题。
正如 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>
除非您依赖于 wsdl2java,否则请改用 wsimport。它会在任何以数字开头的变量前添加一个下划线。它也有一个 maven 目标。
我终于找到了解决办法。
当然,这是常见的 wsdl 生成过程的开销,但这只是(或几乎唯一)满足我的限制的方式。
首先查看了cxf
库的源码,发现有生成端口元素的方法:
org.apache.cxf.tools.wsdlto.frontend.jaxws.processor.internal.ServiceProcessor#processPort
它只是用名称创建 JavaPort
,从原始的 wsdl
中获取并且不使用任何绑定处理它:
JavaPort jport = new JavaPort(NameUtil.mangleNameToClassName(port.getName().getLocalPart()));
进一步我发现可以注入自定义代码生成器,它负责从 cxf
模型创建 java
classes。
经过一些研究,我发现 帮助我成功了。
所以我创建了一个单独的模块 class(查看评论):
//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 文件,很高兴看到它正在运行。
小问题:
我可以以某种方式绑定 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>
或者是否有其他一些方法可以实现此目的?
我建议您更改 WSDL。 WSDL 中的该字段应该具有不能以数字开头的 NCName 类型。 如果您启用 WSDL 验证,我认为您会直接收到 WSDL 语法错误。所以,不确定您之后是否可以使用自定义绑定更正此问题。
正如 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>
除非您依赖于 wsdl2java,否则请改用 wsimport。它会在任何以数字开头的变量前添加一个下划线。它也有一个 maven 目标。
我终于找到了解决办法。 当然,这是常见的 wsdl 生成过程的开销,但这只是(或几乎唯一)满足我的限制的方式。
首先查看了cxf
库的源码,发现有生成端口元素的方法:
org.apache.cxf.tools.wsdlto.frontend.jaxws.processor.internal.ServiceProcessor#processPort
它只是用名称创建 JavaPort
,从原始的 wsdl
中获取并且不使用任何绑定处理它:
JavaPort jport = new JavaPort(NameUtil.mangleNameToClassName(port.getName().getLocalPart()));
进一步我发现可以注入自定义代码生成器,它负责从 cxf
模型创建 java
classes。
经过一些研究,我发现
所以我创建了一个单独的模块 class(查看评论):
//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 文件,很高兴看到它正在运行。