2009-07-13 10 views
1

РедактироватьКак прекратить 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 через определенный период времени и зарегистрировать эту информацию в моем приложении?

С наилучшими пожеланиями, Тим

+0

Чтобы уловить отмену внутри, используйте метод isCancelled(). Ваш вызов отмены должен также вызвать InterruptedException внутри, если вы заблокированы в ожидании/IO. – akarnokd

+0

isCancelled() доступен только в будущем, тогда как мой код находится в Callable, так что первая строка не будет работать. Что касается второй строки: я пробовал (но, как я сказал, плохо), чтобы поймать любые исключение в Callable, но до сих пор этого не удалось. Закрытие всех строк в call() в блоке try/catch для InterruptedException завершилось неудачно из-за недостижимого исключения блокировки, поскольку исключение никогда не выбрасывается из тела оператора try , (Или так Eclipse говорит;)) Есть ли уродливые старые вещи из опасного класса Thread, которые могли бы помочь здесь? – Tim

+1

Должно быть, поскольку отмена вызывает операцию IntExc на * некоторые * блокировки. Однако у меня были проблемы с этим допущением: не каждый блокирующий прерывается таким образом - я думаю, что synchronized() - такой пример (часто используемый в libs). Одним из вариантов удаления является получение доступа к основной операции ввода-вывода и использование асинхронного закрытия(). Если вы расширяете FutureTask, вы получаете как Callable, так и Future, вы пробовали это? – akarnokd

ответ

2

Редактировать 3 Новый ответ.

Я вижу следующие варианты:

  • Начать вашу проблему на Apache CXF как запрос признака
  • Fix ACXF себя и раскрыть некоторые особенности.
  • искать варианты для асинхронной поддержки WS вызова внутри Apache CXF
  • рассмотреть вопрос о переходе к другому поставщику WS (JAX-WS?)
  • ли ваши WS называть себя с помощью RESTful API, если услуга поддерживает его (например, обычные HTTP-запрос с параметрами)
  • Только для экспертов über: используйте настоящие нити/группу нитей и уничтожьте потоки неортодоксальными методами.
+0

Извините, но как это сработает? Вы не можете просто «отменить» Callable. Вы можете только отменить * Будущее *, возвращенное при отправке Callable. Я не вижу, как я смогу получить URL из Callable, как только он будет потерян после отправив его Исполнителю. – Tim

+0

О, извините, вы правы. Подумайте об этом еще раз. – akarnokd

+0

Перефразировал вопрос, поскольку ведение журнала больше не является проблемой: проблема заключается в том, что вызов webservice не отменяется в первую очередь! Спасибо за помощь до сих пор, давайте посмотрим, какие новые ответы на это перефразируют приносит .. – Tim

1

В CxF документы есть некоторые инструкции для установки тайм-аут чтения на HttpURLConnection: http://cwiki.apache.org/CXF20DOC/client-http-transport-including-ssl-support.html

Это, вероятно, отвечают вашим потребностям. Если сервер не отвечает вовремя, возникает исключение, и вызываемый может получить исключение. (за исключением того, что есть ошибка, в которой вместо этого МОЖЕТ висеть. Я не могу вспомнить, было ли это исправлено для 2.2.2, или если это просто в SNAPSHOTS прямо сейчас.)