如何在将来取消时在Callable中终止CXF Web服务调用

编辑

这个问题到目前为止已经经历了几次迭代,所以请随意查看修订版本以查看有关历史和所尝试事项的一些背景信息。


我正在使用CompletionService和ExecutorService以及Callable,通过CXF生成的代码同时调用几个不同的Web服务上的许多函数。这些服务都为我用于的一组信息提供不同的信息。我的项目。 但是,服务可能无法长时间响应而不会抛出exception,从而延长了等待组合信息的时间。

为了解决这个问题,我正在同时运行所有服务调用,并且在几分钟之后想要终止任何尚未完成的调用,并且最好记录哪些调用尚未完成,或者通过抛出一个详细的例外。

这里有一些高度简化的代码来说明我已经在做什么:

private Callable<List> getXXXFeatures(final WiwsPortType port, final String accessionCode) { return new Callable<List>() { @Override public List call() throws Exception { List features = new ArrayList(); //getXXXFeatures are methods of the WS Proxy //that can take anywhere from second to never to return for (RawFeature raw : port.getXXXFeatures(accessionCode)) { Feature ft = convertFeature(raw); features.add(ft); } if (Thread.currentThread().isInterrupted()) log.error("XXX was interrupted"); return features; } }; } 

并行启动WS调用的代码:

 WiwsPortType port = new Wiws().getWiws(); List<Future<List>> ftList = new ArrayList<Future<List>>(); //Counting wrapper around CompletionService, //so I could implement ccs.hasRemaining() CountingCompletionService<List> ccs = new CountingCompletionService<List>(threadpool); ftList.add(ccs.submit(getXXXFeatures(port, accessionCode))); ftList.add(ccs.submit(getYYYFeatures(port accessionCode))); ftList.add(ccs.submit(getZZZFeatures(port, accessionCode))); List allFeatures = new ArrayList(); while (ccs.hasRemaining()) { //Low for testing, eventually a little more lenient Future<List> polled = ccs.poll(5, TimeUnit.SECONDS); if (polled != null) allFeatures.addAll(polled.get()); else { //Still jobs remaining, but unresponsive: Cancel them all int jobsCanceled = 0; for (Future<List> job : ftList) if (job.cancel(true)) jobsCanceled++; log.error("Canceled {} feature jobs because they took too long", jobsCanceled); break; } } 

我对这段代码的问题是,在等待port.getXXXFeatures(…)返回时,Callables实际上没有被取消,但不知何故继续运行。 正如你可以从if (Thread.currentThread().isInterrupted()) log.error("XXX was interrupted"); 在port.getFeatures返回后设置中断标志的语句,这仅在Webservice调用正常完成后才可用,而不是在我调用Cancel时被中断。

任何人都可以告诉我我做错了什么以及如何在给定时间段后停止正在运行的CXF Webservice调用,并在我的应用程序中注册此信息?

最好的问候,蒂姆

编辑3新答案。

我看到这些选项:

  • 将您的问题作为function请求发布在Apache CXF上
  • 自己修复ACXF并公开一些function。
  • 在Apache CXF中查找异步WS调用支持的选项
  • 考虑切换到不同的WS提供程序(JAX-WS?)
  • 如果服务支持,您的WS是否使用RESTful API自行调用(例如,带参数的纯HTTP请求)
  • 仅限über专家:使用真正的线程/线程组并使用非正统方法终止线程。

CXF文档提供了一些在HTTPURLConnection上设置读取超时的说明: http ://cwiki.apache.org/CXF20DOC/client-http-transport-including-ssl-support.html

这可能会满足您的需求。 如果服务器没有及时响应,则会引发exception,并且可调用将获得exception。 (除了有一个可能会挂起的bug。我不记得是否修复了2.2.2或者它现在只是在SNAPSHOTS中。)