我需要调用一个响应时间非常长(几秒钟)的WS--没有实现任何轮询/回调机制。
我认为最有效的方法是在收到响应时使用非阻塞io和某种回调机制。由于我们主要使用Spring和CXF,因此我开始了一个概念验证项目来测试我的概念和配置本身。
幸运的是,有一个用于cxf的HttpAsyncClient,并且有很好的教程如何配置它。但是在某些时候我坚持了:使用同步模式它没关系,但是当我想使用回调时,它会引发以下异常:
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 interface:
@WebService
public interface SampleWebService {
public Person getDataFromWebService(@WebParam String id);
public Future<?> getDataFromWebServiceAsync(@WebParam String id, @WebParam(name = "asyncHandler", targetNamespace = "") AsyncHandler<Person> asyncHandler);
}
客户端测试(作为TestNG测试实现):
@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/
此时有人可以向我提供澄清吗? 有没有实现这个目标? 或者以合理的方式处理长时间运行的WS调用的任何解决方案?
答案 0 :(得分:4)
如果我使用'-asyncMethods'参数从wsdl生成接口,一切都很好! 主要区别在于它在我的Person对象周围生成一个名为GetDataFromWebServiceResponse的包装器对象。现在一切都很好:通过普通接口调用服务器(没有实现轮询/回调),但在客户端,响应时调用回调方法。
使用pom.xml粒子:
<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。
现在我想知道如何从客户端强制调用poll / callback样式服务方法....但那将是另一个故事: - )