使用CXF的非阻塞WS调用 [英] Non-blocking WS call with CXF

查看:149
本文介绍了使用CXF的非阻塞WS调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要调用一个响应时间非常长(秒)的WS-无需在其端实施任何轮询/回调机制。

I need to call a WS that has very large response times (seconds) - without any polling/callback mechanism implemented on their side.

我认为最有效做到这一点的方法是在收到响应时使用非阻塞io和某种回调机制。由于我们主要使用Spring和CXF,因此我启动了概念验证项目来测试我的概念和配置本身。

I think the most effective way of doing this is using non-blocking io and some kind of callback mechanism when the response received. Since we mostly use Spring and CXF I started a proof-of concept project to test my concept and the configuration itself.

幸运的是,有一个用于cxf的HttpAsyncClient,并且有很好的教程介绍如何配置它。但是在某些时候,我坚持了下来:使用同步模式可以,但是当我想使用回调时,它会抛出以下异常:

Fortunately there is an HttpAsyncClient for cxf and there are good tutorials how to configure it. But at some point I stucked: with sync mode it is ok, but when I want to use the callback, it thorows the following exception:

javax.xml.ws.WebServiceException: Could not find wsdl:binding operation info for web method getDataFromWebServiceAsync.
    at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:126)
    at com.sun.proxy.$Proxy46.getDataFromWebServiceAsync(Unknown Source)

ws接口:

@WebService
public interface SampleWebService {
    public Person getDataFromWebService(@WebParam String id);
    public Future<?> getDataFromWebServiceAsync(@WebParam String id, @WebParam(name = "asyncHandler", targetNamespace = "") AsyncHandler<Person> asyncHandler);
}

客户端测试(作为TestNG测试实现):

client side test (implemented as a TestNG test):

@Test(threadPoolSize = 5, invocationCount = 100)
public void testMultithreadedNonBlockingSampleWs()
        throws InterruptedException, ExecutionException {

    client.getDataFromWebServiceAsync("" + id.getAndIncrement(),
            new AsyncHandler<Person>() {
                @Override
                public void handleResponse(Response<Person> resp) {
                    Person person;
                    try {
                        person = resp.get();
                        log.info(person.getName() + " | " + person.getAge()
                                + " | " + person.getDescription());
                        Assert.assertNotNull(person);
                        Assert.assertNotNull(person.getName());
                    } catch (InterruptedException | ExecutionException e) {
                        log.error("EXCEPTION WHILE PROCESSING RESPONSE CALLBACK");
                        e.printStackTrace();
                    }
                }
            });
}

服务器端春季配置:

<jaxws:endpoint id="sampleService"
    implementor="my.sample.SampleWebServiceImpl" address="/SampleWebService" />

客户端春季配置:

<jaxws:client id="client"
    serviceClass="my.sample.SampleWebService"
    address="http://localhost:8080/sample-ws-cxf/SampleWebService">
    <jaxws:properties>
        <entry key="javax.xml.ws.client.connectionTimeout" value="10" />
        <entry key="javax.xml.ws.client.receiveTimeout" value="11000" />
        <entry key="org.apache.cxf.transport.http.async.usePolicy" value="ALWAYS" />
        <entry key="org.apache.cxf.transport.http.async.ioThreadCount" value="2" /> 
    </jaxws:properties>
</jaxws:client>

从文章中我还不清楚这种(非阻塞回调)是否真的可能只有轮询/回调机制才能起作用。只有这篇文章指出:
http://czechscala.wordpress.com/2013/05/13/non-blocking-soap-web-services-invocation/

From the articles I found it is not clear whether this (non-blocking callback) is really possible or only the polling/callback mechanism should work. Only this article states that: http://czechscala.wordpress.com/2013/05/13/non-blocking-soap-web-services-invocation/

任何人都可以提供我现在要澄清吗?
有什么办法做到这一点?
还是以合理的方式处理长时间运行的WS调用的任何解决方案?

Could anybody provide me clarification at this point? Any way of achieving this? Or any solution to handle long-running WS calls in a reasonable way?

推荐答案

如果我生成接口,使用'-asyncMethods'参数设置wsdl,一切都很好!
的主要区别是它围绕我的Person对象(称为GetDataFromWebServiceResponse)生成了一个包装对象。现在一切都很好:通过普通接口调用服务器(未实现轮询/回调),但是在客户端,响应时将调用回调方法。

If I generate the interfaces out of wsdl using the '-asyncMethods' parameter, everything is fine! The main difference is that it generates a wrapper object around my Person object called GetDataFromWebServiceResponse. Now everything is fine: the server is called through the normal interface (no polling/callback implemented), but on client side the callback method is called upon response.

工作pom .xml粒子:

Working pom.xml particle:

<execution>
    <id>generate-sources</id>
    <phase>generate-sources</phase>
    <configuration>
        <sourceRoot>${full.path.to.generate.classes}</sourceRoot>
        <wsdlOptions>
            <wsdlOption>
                <wsdl>${full.path.to.wsdl}</wsdl>
                <extraargs>
                    <extraarg>-p</extraarg>
                    <extraarg>${package.name}</extraarg>
                    <extraarg>-asyncMethods</extraarg>
                </extraargs>
            </wsdlOption>
        </wsdlOptions>
    </configuration>
</execution>

我建议使用2.7以上的cxf。

I would suggest using cxf above 2.7.

现在,我想知道有人会如何从客户端强制调用轮询/回调样式服务方法....但这将是另一回事了:-)

Now I'm wondering how could anybody force calling the poll/callback style service methods from client side.... but that would be another story :-)

这篇关于使用CXF的非阻塞WS调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆