JAX-WS 从 jar 文件加载 WSDL

46

我正在编写一个厚客户端,其中使用了SOAP服务来实现一些功能(例如缺陷报告等)。

我已经成功使用JAX-WS,但默认情况下(至少在netbeans中),它每次初始化服务时都会从远程服务器获取WSDL。 我认为这有助于提供某些版本支持等,但这不是我想要的。

我已经添加了wsdllocation参数到wsimport中,以指向本地资源生成的类。 下面的代码段是从ApplicationService.java加载WSDL资源的URL。

baseUrl = net.example.ApplicationService.class.getResource(".");
url = new URL(baseUrl, "service.wsdl");

我相信这应该不会有问题,可以指向存储在 net/example/resources 包中的 jar 资源,而且 jar 文件本身也按预期构建了。但是服务将无法加载...具体来说,在调用 ApplicationService.getPort() 时,我会得到 NullPointerException 异常。

这是否可能?还是只是一场徒劳的追逐?

13个回答

1
这是我使用的一个适用于我(特别是通过httphttps)的方法。Oracle JDK 1.8.0_51的JAX-WS与Apache CXF 3.1.1创建的类一起工作。
请注意,无论如何,远程WSDL仅在第一次调用时获取。根据使用模式(长时间运行的程序),这可能完全可以接受。 基础知识:
  • 从远程主机下载WSDL并存储为文件:wget --output-document=wsdl_raw.xml $WSDL_URL
  • 您可能希望使用xmllint --format wsdl_raw.xml > wsdl.xml进行漂亮的格式化
  • 使用命令行工具生成客户端类:./cxf/bin/wsdl2java -d output/ -client -validate wsdl.xml并导入到您的项目中

请确认WSDL文件中同时存在httphttps的服务定义。在我的情况下,提供者没有为https提供一个服务定义(但接受https流量),因此我不得不手动添加。类似以下内容应该包含在WSDL中:

  <wsdl:service name="fooservice">
    <wsdl:port binding="tns:fooserviceSoapBinding" name="FooBarWebServicePort">
      <soap:address location="http://ws.example.com/a/b/FooBarWebService"/>
    </wsdl:port>
  </wsdl:service>
  <wsdl:service name="fooservice-secured">
    <wsdl:port binding="tns:fooserviceSoapBinding" name="FooBarWebServicePort">
      <soap:address location="https://ws.example.com/a/b/FooBarWebService"/>
    </wsdl:port>
  </wsdl:service>

CXF应该生成一个实现javax.xml.ws.Service接口的类,命名为Fooservice,并具有适当的构造函数:

public class Fooservice extends Service {

  public Fooservice(URL wsdlLocation) {
      super(wsdlLocation, SERVICE);
  }

  public Fooservice(URL wsdlLocation, QName serviceName) {
      super(wsdlLocation, serviceName);
  }

  public Fooservice() {
      super(WSDL_LOCATION, SERVICE);
  }

  ...etc...

在你的代码中(这里是一些易于阅读的Groovy代码),你初始化了上述的Service实例,然后调用一个端口。在这里,根据名为secure的标志,我们使用httpshttp
static final String NAMESPACE = 'com.example.ws.a.b'
static final QName SERVICE_NAME_HTTP = new QName(NAMESPACE, 'fooservice')
static final QName SERVICE_NAME_HTTPS = new QName(NAMESPACE, 'fooservice-secured')

Fooservice wsService
File wsdlfile = new File('/somewhere/on/disk/wsdl.xml')

// If the file is missing there will be an exception at connect
// time from sun.net.www.protocol.file.FileURLConnection.connect
// It should be possible to denote a resource on the classpath 
// instead of a file-on-disk. Not sure how, maybe by adding a handler
// for a 'resource:' URL scheme?

URI wsdlLocationUri = java.nio.file.Paths(wsdlfile.getCanonicalPath()).toUri()

if (secure) {
  wsService = new Fooservice(wsdlLocationUri.toURL(), SERVICE_NAME_HTTPS)
}
else {
  wsService = new Fooservice(wsdlLocationUri.toURL(), SERVICE_NAME_HTTP)
}

SomeServicePort port = wsService.getSomeServicePort()

port.doStuff()

另一种方法是在与用于服务调用的连接分开的连接上下载WSDL(使用tcpdump -n -nn -s0 -A -i eth0 'tcp port 80'观察流量),只需执行以下操作:
URI wsdlLocationUri

if (secure) {
   wsdlLocationUri = new URI('https://ws.example.com/a/b/FooBarWebService?wsdl')
}
else {
   wsdlLocationUri = new URI('http://ws.example.com/a/b/FooBarWebService?wsdl')
}

Fooservice wsService = new Fooservice(wsdlLocationUri.toURL(), SERVICE_NAME_HTTP)

SomeServicePort port = wsService.getSomeServicePort()

port.doStuff()

请注意,如果wsdlLocationUri指定了https,那么这实际上会正确使用https,尽管wsService已经使用SERVICE_NAME_HTTP进行初始化。(不确定为什么-服务是否使用检索WSDL资源所采用的方案?)

就是这样。

要调试连接,请传递:

-Dcom.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.dump=true
-Dcom.sun.xml.internal.ws.transport.http.HttpAdapter.dump=true

在命令行中向JVM传递参数,这将把http连接代码的信息写入stdout(不幸的是,不写入java.util.logging。Oracle,请注意!)。


0
我的解决方案是修改生成的服务。您需要在头注释中更改wsdlLocation,实例化块看起来像这样:
    static {
    URL url = null;
    url = com.ups.wsdl.xoltws.ship.v1.ShipService.class.getResource("Ship.wsdl");
    SHIPSERVICE_WSDL_LOCATION = url;
    }

我将wsdl文件放在与ShipService类相邻的bin目录中


0

虽然您可以通过一些调整使其正常工作,但我建议不要这样做,保持当前状态。

Web服务端点提供者应该在其合同中提供一个WSDL。生成的代码应该从服务器本身的WSDL中拉取。

在部署到WebSphere上时,您可以通过部署UI更改端点到其他端点。对于其他应用程序服务器,您可能需要查找供应商特定的绑定XML来完成它。

这仅发生在初始化时,因此对于您的整个应用程序的影响应该可以忽略不计。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接