РедактироватьКак прекратить CXF WebService вызова в отзывной на будущее отмены
Этот вопрос прошел через несколько итераций в настоящее время, так что не стесняйтесь просматривать пересмотров, чтобы увидеть некоторую справочную информацию об истории и вещи пытался.
Я использую CompletionService вместе с ExecutorService и отзывной, чтобы одновременно вызвать ряд функций на несколько различных веб-сервисов через CXF сгенерированный код .. Эти услуги вносят свой вклад различную информацию в отношении одного набора информации, которую я использую для своего проекта. Однако службы могут не отвечать в течение длительного периода времени, не вызывая исключения, продлевая ожидание комбинированного набора информации.
Чтобы противостоять этому, я выполняю все вызовы службы одновременно и через несколько минут хотел бы прекратить любой из вызовов, которые еще не были завершены, и, желательно, регистрировать, какие из них еще не выполнены ни изнутри вызываемый или путем броска подробного Исключения.
Вот некоторые весьма упрощенный код, чтобы показать, что я делаю уже:
private Callable<List<Feature>> getXXXFeatures(final WiwsPortType port,
final String accessionCode) {
return new Callable<List<Feature>>() {
@Override
public List<Feature> call() throws Exception {
List<Feature> features = new ArrayList<Feature>();
//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<Feature>>> ftList = new ArrayList<Future<List<Feature>>>();
//Counting wrapper around CompletionService,
//so I could implement ccs.hasRemaining()
CountingCompletionService<List<Feature>> ccs =
new CountingCompletionService<List<Feature>>(threadpool);
ftList.add(ccs.submit(getXXXFeatures(port, accessionCode)));
ftList.add(ccs.submit(getYYYFeatures(port accessionCode)));
ftList.add(ccs.submit(getZZZFeatures(port, accessionCode)));
List<Feature> allFeatures = new ArrayList<Feature>();
while (ccs.hasRemaining()) {
//Low for testing, eventually a little more lenient
Future<List<Feature>> 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<Feature>> job : ftList)
if (job.cancel(true))
jobsCanceled++;
log.error("Canceled {} feature jobs because they took too long",
jobsCanceled);
break;
}
}
Проблема у меня с этим код заключается в том, что Callables на самом деле не отменены при ожидании возврата port.getXXXFeatures (...), но каким-то образом продолжают работать. Как видно из операторов if (Thread.currentThread().isInterrupted()) log.error("XXX was interrupted");
, прерванный флаг - это, установленный после того, как port.getFeatures возвращается, это доступно только после того, как вызов Webservice завершился нормально, вместо того, чтобы он был прерван, когда я вызвал Отмена.
Может ли кто-нибудь сказать мне, что я делаю неправильно, и как я могу остановить запуск вызова CXF Webservice через определенный период времени и зарегистрировать эту информацию в моем приложении?
С наилучшими пожеланиями, Тим
Чтобы уловить отмену внутри, используйте метод isCancelled(). Ваш вызов отмены должен также вызвать InterruptedException внутри, если вы заблокированы в ожидании/IO. – akarnokd
isCancelled() доступен только в будущем, тогда как мой код находится в Callable, так что первая строка не будет работать. Что касается второй строки: я пробовал (но, как я сказал, плохо), чтобы поймать любые исключение в Callable, но до сих пор этого не удалось. Закрытие всех строк в call() в блоке try/catch для InterruptedException завершилось неудачно из-за недостижимого исключения блокировки, поскольку исключение никогда не выбрасывается из тела оператора try , (Или так Eclipse говорит;)) Есть ли уродливые старые вещи из опасного класса Thread, которые могли бы помочь здесь? – Tim
Должно быть, поскольку отмена вызывает операцию IntExc на * некоторые * блокировки. Однако у меня были проблемы с этим допущением: не каждый блокирующий прерывается таким образом - я думаю, что synchronized() - такой пример (часто используемый в libs). Одним из вариантов удаления является получение доступа к основной операции ввода-вывода и использование асинхронного закрытия(). Если вы расширяете FutureTask, вы получаете как Callable, так и Future, вы пробовали это? – akarnokd