JAX-WS从jar加载WSDL

Cog*_*gsy 44 wsdl jar jax-ws wsimport

我正在编写一个胖客户端,它利用SOAP服务来实现某些功能(错误报告等)

我有JAX-WS工作正常,但默认情况下(至少在netbeans中)它每次初始化服务时从远程服务器获取WSDL.我希望这有助于提供一些版本支持等,但这不是我想要的.

我已将wsdllocationarg 添加到wsimport以将生成的类指向本地资源.以下代码段是App​​licationService.java中WSDL资源的URL加载.

baseUrl = net.example.ApplicationService.class.getResource(".");
url = new URL(baseUrl, "service.wsdl");
Run Code Online (Sandbox Code Playgroud)

我很确定在net/example/resources包中指向存储在jar中的资源应该没有问题,并且jar本身按预期构造.但是服务不会加载...具体来说,当我调用ApplicationService.getPort()时,我得到一个NullPointerException;

这可能吗?还是只是一场疯狂的追逐?

Dav*_*eri 48

是的,这绝对是可能的,因为我在通过javax.xml.ws.EndpointReference(一个与WS-A相关的类)创建客户端时已经这样做了.我已经将WSDL的类路径引用添加到WS-A EndPointReference,并且JAX-WS的Metro实现加载它就好了.无论是从WS-A EndPointReference还是从文件或http URL加载WSDL,您的JAX-WS实现应使用相同的WSDL解析代码,因为您所做的只是解析URL.

对您而言,最好的方法可能是执行以下操作:

URL wsdlUrl = MyClass.class.getResource(
            "/class/path/to/wsdl/yourWSDL.wsdl");

Service yourService= Service.create(
            wsdlUrl,
            ...);
Run Code Online (Sandbox Code Playgroud)

where ...表示WSDL内部的WSDL服务的QName.现在要记住的重要一点是,您的WSDL需要完整且有效.这意味着如果您的WSDL导入XSD文件或其他WSDL,则URL必须正确.如果将导入的WSDL和XSD包含在与WSDL文件相同的JAR中,则应使用相对URL进行导入,并将所有导入保留在同一JAR文件中.JAR URL处理程序不会将相对URL视为相对于类路径的相对URL,而是将其视为JAR文件中的相对URL,因此除非您实现自定义URL处理程序和您自己的前缀,否则您不能在WSDL中具有跨JAR运行的导入基于类路径的导入解析.如果您的WSDL导入外部资源,那就没问题,但如果这些资源移动,您就是在为自己注册维护问题.即使从类路径中使用WSDL的静态副本也违背了WSDL,Web服务和JAX-WS的精神,但有时候它是必要的.

最后,如果您嵌入了静态WSDL,我建议您至少使服务端点可配置用于测试和部署目的.重新配置Web服务客户端的端点的代码如下:

  YourClientInterface client = yourService.getPort(
            new QName("...", "..."),
            YourClientInterface.class);
  BindingProvider bp = (BindingProvider) client;
  bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
                "http://localhost:8080/yourServiceEndpoint");
Run Code Online (Sandbox Code Playgroud)


Ada*_*ent 14

如果您将WSDL放在JAR中,然后将wsimport设置为JAR中WSDL wsdlLocation的相对资源路径,则最近的JAX-WS您不需要执行任何模式目录或编程的wsdl位置设置.那就是JAX-WS使用Java的内置Class.getResource来加载WSDL.

如果你使用Maven它的东西是这样的:

  <plugin>
    <groupId>org.jvnet.jax-ws-commons</groupId>
    <artifactId>jaxws-maven-plugin</artifactId>
    <version>2.3</version>
    <executions>
      <execution>
        <goals>
          <goal>wsimport</goal>
        </goals>
        <!-- Following configuration will invoke wsimport once for each wsdl. -->
        <configuration>
            <!--- VERY IMPORTANT THAT THE PATH START WITH '/' -->
    <wsdlLocation>/com/adamgent/ws/blah.wsdl</wsdlLocation>
    <wsdlDirectory>${basedir}/src/main/resources/com/adamgent/ws</wsdlDirectory>
    <wsdlFiles><wsdlFile>blah.wsdl</wsdlFile></wsdlFiles>
       </configuration>
      </execution>
    </executions>
  </plugin>
Run Code Online (Sandbox Code Playgroud)

对于上面的示例,您将在此处使用Maven项目布局放置WSDL src/main/resources/com/adamgent/ws.

确保WSDL进入Maven的JAR,如:

<build>
      <resources>
        <resource>
          <directory>src/main/resources</directory>
        </resource>
      </resources> ....
Run Code Online (Sandbox Code Playgroud)

现在你的wsimport生成的代码和WSDL都在一个自包含的JAR中.要使用该服务,您不必设置WSDL位置,并且非常简单:

BlahService myService = new BlayService_Service().getBlahServicePort();
Run Code Online (Sandbox Code Playgroud)

将此映射到ANT的wsimport应该是微不足道的.

  • `<!---非常重要的路径开始'/' - >`部分就是这个诀窍.其他答案建议在路径前加上`classpath:`或使用没有前缀`/`的路径,但这不起作用. (4认同)

wei*_*esr 6

也许有点晚了,但我找到了一个非常简单的解决方案来解决这个问题,但这涉及到Service类生成代码的变化:

如果Service类中有以下行

baseUrl = net.example.ApplicationService.class.getResource(".");
Run Code Online (Sandbox Code Playgroud)

改为

baseUrl = net.example.ApplicationService.class.getResource("");
Run Code Online (Sandbox Code Playgroud)

即使使用JAR中打包的WSDL,它也能正常工作.在这两种情况下都不确定getResource()的确切假设行为,但到目前为止,我在多个操作系统和Java版本上没有遇到任何问题.


sle*_*ske 5

您所描述的是JAX-WS中的错误:JAX_WS-888 - 用于解析自定义wsdlLocation的URL的错误代码.

它已针对V2.2进行了修复,因此在wsdlLocation您编写时,只需进行设置即可.


Cog*_*gsy 1

这是我的 hack-y 解决方法。

我从 jar 中解压 WSDL 并将其写入 jar 附近的文件中:

File wsdl = new File("../lib/service.wsdl");
InputStream source = getClass().getResource("resources/service.wsdl").openStream();
FileOutputStream out = new FileOutputStream(wsdl);

byte[] buffer = new byte[512];
int read;
while((read = source.read(buffer)) >= 0) {
    out.write(buffer, 0, read);
}
Run Code Online (Sandbox Code Playgroud)

然后将服务类指向file:../lib/service.wsdl

这可行,但如果有人能向我展示更优雅的解决方案,我将不胜感激。