简体   繁体   English

如何为 JAX-WS Web 服务客户端设置超时?

[英]How do I set the timeout for a JAX-WS webservice client?

I've used JAXWS-RI 2.1 to create an interface for my web service, based on a WSDL.我已经使用 JAXWS-RI 2.1 为我的 Web 服务创建了一个基于 WSDL 的接口。 I can interact with the web service no problems, but haven't been able to specify a timeout for sending requests to the web service.我可以毫无问题地与 Web 服务交互,但无法指定向 Web 服务发送请求的超时时间。 If for some reason it does not respond the client just seems to spin it's wheels forever.如果由于某种原因它没有响应,客户端似乎永远在旋转它的轮子。

Hunting around has revealed that I should probably be trying to do something like this:四处寻找表明我可能应该尝试做这样的事情:

((BindingProvider)myInterface).getRequestContext().put("com.sun.xml.ws.request.timeout", 10000);
((BindingProvider)myInterface).getRequestContext().put("com.sun.xml.ws.connect.timeout", 10000);

I also discovered that, depending on which version of JAXWS-RI you have, you may need to set these properties instead:我还发现,根据您拥有的 JAXWS-RI 版本,您可能需要设置这些属性:

((BindingProvider)myInterface).getRequestContext().put("com.sun.xml.internal.ws.request.timeout", 10000);
((BindingProvider)myInterface).getRequestContext().put("com.sun.xml.internal.ws.connect.timeout", 10000);

The problem I have is that, regardless of which of the above is correct, I don't know where I can do this.我遇到的问题是,无论以上哪一项是正确的,我都不知道在哪里可以做到这一点。 All I've got is aService subclass that implements the auto-generated interface to the webservice and at the point that this is getting instanciated, if the WSDL is non-responsive then it's already too late to set the properties:我所拥有的只是一个Service子类,它实现了 webservice 的自动生成的接口,并且在它被实例化的时候,如果 WSDL 没有响应,那么设置属性已经太晚了:

MyWebServiceSoap soap;
MyWebService service = new MyWebService("http://www.google.com");
soap = service.getMyWebServiceSoap();
soap.sendRequestToMyWebService();

Can anyone point me in the right direction?!谁能指出我正确的方向?!

I know this is old and answered elsewhere but hopefully this closes this down.我知道这是旧的并在其他地方回答,但希望这可以解决这个问题。 I'm not sure why you would want to download the WSDL dynamically but the system properties:我不确定为什么要动态下载 WSDL 但系统属性:

sun.net.client.defaultConnectTimeout (default: -1 (forever))
sun.net.client.defaultReadTimeout (default: -1 (forever))

should apply to all reads and connects using HttpURLConnection which JAX-WS uses.应该适用于使用 JAX-WS 使用的 HttpURLConnection 的所有读取和连接。 This should solve your problem if you are getting the WSDL from a remote location - but a file on your local disk is probably better!如果您从远程位置获取 WSDL,这应该可以解决您的问题 - 但本地磁盘上的文件可能更好!

Next, if you want to set timeouts for specific services, once you've created your proxy you need to cast it to a BindingProvider (which you know already), get the request context and set your properties.接下来,如果您想为特定服务设置超时,一旦您创建了代理,您需要将其转换为 BindingProvider(您已经知道),获取请求上下文并设置您的属性。 The online JAX-WS documentation is wrong, these are the correct property names (well, they work for me).在线 JAX-WS 文档是错误的,这些是正确的属性名称(好吧,它们对我有用)。

MyInterface myInterface = new MyInterfaceService().getMyInterfaceSOAP();
Map<String, Object> requestContext = ((BindingProvider)myInterface).getRequestContext();
requestContext.put(BindingProviderProperties.REQUEST_TIMEOUT, 3000); // Timeout in millis
requestContext.put(BindingProviderProperties.CONNECT_TIMEOUT, 1000); // Timeout in millis
myInterface.callMyRemoteMethodWith(myParameter);

Of course, this is a horrible way to do things, I would create a nice factory for producing these binding providers that can be injected with the timeouts you want.当然,这是一种可怕的做事方式,我会创建一个很好的工厂来生产这些绑定提供程序,这些提供程序可以注入您想要的超时。

The properties in the accepted answer did not work for me, possibly because I'm using the JBoss implementation of JAX-WS?接受的答案中的属性对我不起作用,可能是因为我使用的是 JAX-WS 的 JBoss 实现?

Using a different set of properties (found in the JBoss JAX-WS User Guide ) made it work:使用一组不同的属性(在JBoss JAX-WS 用户指南中找到)使其工作:

//Set timeout until a connection is established
((BindingProvider)port).getRequestContext().put("javax.xml.ws.client.connectionTimeout", "6000");

//Set timeout until the response is received
((BindingProvider) port).getRequestContext().put("javax.xml.ws.client.receiveTimeout", "1000");

Here is my working solution :这是我的工作解决方案:

// --------------------------
// SOAP Message creation
// --------------------------
SOAPMessage sm = MessageFactory.newInstance().createMessage();
sm.setProperty(SOAPMessage.WRITE_XML_DECLARATION, "true");
sm.setProperty(SOAPMessage.CHARACTER_SET_ENCODING, "UTF-8");

SOAPPart sp = sm.getSOAPPart();
SOAPEnvelope se = sp.getEnvelope();
se.setEncodingStyle("http://schemas.xmlsoap.org/soap/encoding/");
se.setAttribute("xmlns:SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/");
se.setAttribute("xmlns:xsd", "http://www.w3.org/2001/XMLSchema");
se.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");

SOAPBody sb = sm.getSOAPBody();
// 
// Add all input fields here ...
// 

SOAPConnection connection = SOAPConnectionFactory.newInstance().createConnection();
// -----------------------------------
// URL creation with TimeOut connexion
// -----------------------------------
URL endpoint = new URL(null,
                      "http://myDomain/myWebService.php",
                    new URLStreamHandler() { // Anonymous (inline) class
                    @Override
                    protected URLConnection openConnection(URL url) throws IOException {
                    URL clone_url = new URL(url.toString());
                    HttpURLConnection clone_urlconnection = (HttpURLConnection) clone_url.openConnection();
                    // TimeOut settings
                    clone_urlconnection.setConnectTimeout(10000);
                    clone_urlconnection.setReadTimeout(10000);
                    return(clone_urlconnection);
                    }
                });


try {
    // -----------------
    // Send SOAP message
    // -----------------
    SOAPMessage retour = connection.call(sm, endpoint);
}
catch(Exception e) {
    if ((e instanceof com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl) && (e.getCause()!=null) && (e.getCause().getCause()!=null) && (e.getCause().getCause().getCause()!=null)) {
        System.err.println("[" + e + "] Error sending SOAP message. Initial error cause = " + e.getCause().getCause().getCause());
    }
    else {
        System.err.println("[" + e + "] Error sending SOAP message.");

    }
}
ProxyWs proxy = (ProxyWs) factory.create();
Client client = ClientProxy.getClient(proxy);
HTTPConduit http = (HTTPConduit) client.getConduit();
HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
httpClientPolicy.setConnectionTimeout(0);
httpClientPolicy.setReceiveTimeout(0);
http.setClient(httpClientPolicy);

This worked for me.这对我有用。

If you are using JAX-WS on JDK6, use the following properties:如果您在 JDK6 上使用 JAX-WS,请使用以下属性:

com.sun.xml.internal.ws.connect.timeout  
com.sun.xml.internal.ws.request.timeout

In case your appserver is WebLogic (for me it was 10.3.6) then properties responsible for timeouts are:如果您的应用服务器是 WebLogic(对我来说是 10.3.6),那么负责超时的属性是:

com.sun.xml.ws.connect.timeout 
com.sun.xml.ws.request.timeout

Not sure if this will help in your context...不确定这是否对您的上下文有帮助...

Can the soap object be cast as a BindingProvider ?可以将soap 对象转换为BindingProvider 吗?

MyWebServiceSoap soap;
MyWebService service = new MyWebService("http://www.google.com");
soap = service.getMyWebServiceSoap();
// set timeouts here
((BindingProvider)soap).getRequestContext().put("com.sun.xml.internal.ws.request.timeout", 10000);
    soap.sendRequestToMyWebService();

On the other hand if you are wanting to set the timeout on the initialization of the MyWebService object then this will not help.另一方面,如果您想在 MyWebService 对象的初始化中设置超时,那么这将无济于事。

This worked for me when wanting to timeout the individual WebService calls.当想要超时单个 WebService 调用时,这对我有用。

the easiest way to avoid slow retrieval of the remote WSDL when you instantiate your SEI is to not retrieve the WSDL from the remote service endpoint at runtime.在实例化 SEI 时避免缓慢检索远程 WSDL 的最简单方法是不在运行时从远程服务端点检索 WSDL。

this means that you have to update your local WSDL copy any time the service provider makes an impacting change, but it also means that you have to update your local copy any time the service provider makes an impacting change.这意味着您必须在服务提供者进行影响性更改的任何时候更新本地 WSDL 副本,但这也意味着您必须在服务提供者进行影响性更改时更新本地副本。

When I generate my client stubs, I tell the JAX-WS runtime to annotate the SEI in such a way that it will read the WSDL from a pre-determined location on the classpath.当我生成我的客户端存根时,我告诉 JAX-WS 运行时以这样一种方式注释 SEI,它将从类路径上的预定位置读取 WSDL。 by default the location is relative to the package location of the Service SEI默认情况下,该位置相对于 Service SEI 的包位置


<wsimport
    sourcedestdir="${dao.helter.dir}/build/generated"
    destdir="${dao.helter.dir}/build/bin/generated"
    wsdl="${dao.helter.dir}/src/resources/schema/helter/helterHttpServices.wsdl"
    wsdlLocation="./wsdl/helterHttpServices.wsdl"
    package="com.helter.esp.dao.helter.jaxws"
    >
    <binding dir="${dao.helter.dir}/src/resources/schema/helter" includes="*.xsd"/>
</wsimport>
<copy todir="${dao.helter.dir}/build/bin/generated/com/helter/esp/dao/helter/jaxws/wsdl">
    <fileset dir="${dao.helter.dir}/src/resources/schema/helter" includes="*" />
</copy>

the wsldLocation attribute tells the SEI where is can find the WSDL, and the copy makes sure that the wsdl (and supporting xsd.. etc..) is in the correct location. wsldLocation 属性告诉 SEI 在哪里可以找到 WSDL,并且副本确保 wsdl(并支持 xsd.. 等)位于正确的位置。

since the location is relative to the SEI's package location, we create a new sub-package (directory) called wsdl, and copy all the wsdl artifacts there.由于该位置相对于 SEI 的包位置,我们创建了一个名为 wsdl 的新子包(目录),并将所有 wsdl 工件复制到那里。

all you have to do at this point is make sure you include all *.wsdl, *.xsd in addition to all *.class when you create your client-stub artifact jar file.此时您要做的就是确保在创建客户端存根工件 jar 文件时包含所有 *.wsdl、*.xsd 和所有 *.class。

(in case your curious, the @webserviceClient annotation is where this wsdl location is actually set in the java code (如果你好奇的话,@webserviceClient 注释是这个 wsdl 位置在 java 代码中实际设置的位置

@WebServiceClient(name = "httpServices", targetNamespace = "http://www.helter.com/schema/helter/httpServices", wsdlLocation = "./wsdl/helterHttpServices.wsdl")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM