Как я могу запретить Apache CXF отправлять ответные сообщения? - PullRequest
3 голосов
/ 28 сентября 2011

В тех случаях, когда заданный элемент заголовка SOAP имеет заданное значение (например, если значение тега заголовка "response" равно "0"), я не хочу, чтобы Apache CXF вообще возвращал ответ.

Как я могу это сделать? Похоже, что CXF предполагает, что на все вызовы будет получен ответ.

(я знаю, что это кажется странным в контексте веб-сервисов, но если ваш транспорт - JMS, это кажется менее странным).

Ответы [ 4 ]

3 голосов
/ 13 октября 2011

Я смог сделать это с помощью перехватчика, который прерывает цепочку перехватчиков.

Я проверил это с помощью конфигурации HTTP (WebSphere возвращает пустые 200) и конфигурации ActiveMQ (в очередь ответов не возвращается).

package my.super.interceptor;

public final class Suppressor extends AbstractSoapInterceptor {

   public Suppressor() { super(Phase.SETUP); }

   @Override
   public void handleMessage(final SoapMessage message) throws Fault        
   {                       

     final boolean suppressResponse = this.suppressResponse(message);

     if(suppressResponse) {
         log.debug("-> Suppressing response");
         message.getInterceptorChain().abort();
     }

   //if you want to suppress both responses and faults, you need
   //to check them separately. 
   //Change this code to check headers for whatever criteria you want
   //(Note you may need to change the super(Phase...) )
   //The code's a bit messy here - just sketching out the idea for the answer
   private boolean suppressResponse(final Message message) {            
     final Fault fault = (Fault)message.getContent(Exception.class);

     if(fault != null) {
        final String faultMessage = fault.getMessage();

         return faultMessage.indexOf("Something-you-want-to-match") > 0;

     } else {
        final MessageInfo messageInfo = (MessageInfo)message.get("org.apache.cxf.service.model.MessageInfo");            
        final String operation = messageInfo.getOperation().getOutputName();            

        return operation.indexOf("Something-you-want-to-match") > 0;
     }
   }

и ваше приложениеContext.xml:

<jaxws:endpoint ...>
  <jaxws:outInterceptors>
     <bean class="my.super.interceptor.Suppressor"/>
   </jaxws:outInterceptors>
   <jaxws:outFaultInterceptors>
     <bean class="my.super.interceptor.Suppressor"/>
   </jaxws:outFaultInterceptors>
</jaxws:endpoint>
1 голос
/ 28 сентября 2011

Длинное объяснение : рассмотрите веб-сервисы SOAP с точки зрения спецификации протокола SOAP. Веб-сервисы - это не просто причудливый слой поверх HTTP, это фактически способ описания двусторонней связи с различными реализованными шаблонами обмена сообщениями . Следующие шаблоны являются наиболее распространенными:

  • запрос-ответ ( Вход-выход ): в среде HTTP это типичный HTTP-запрос / ответный вызов с некоторым запросом сообщение , отправляемым с клиента на сервер и некоторый ответ сообщение отправляется обратно. В среде JMS вы получите два отдельных и независимых сообщения.

  • в одну сторону ( In-Only ): в этой модели клиент отправляет запрос, но не ожидает и не заботится об ответе. В JMS это эквивалентно простому сообщению, отправляемому брокеру. С другой стороны, в HTTP (по крайней мере, так реализованы односторонние методы в Apache CXF) вы получите метод void в SEI. Более того, CXF по умолчанию будет использовать отдельный пул потоков для обработки этого запроса, поэтому клиент даже не ждет ответа, а сервер даже не может отправить этот ответ (поскольку клиент, возможно, уже отключился).

Теперь важная часть: в WSDL вы определяете метод как запрос / ответ (путем определения входящих / исходящих сообщений) или как односторонний (путем предоставления только в сообщении). Это зафиксировано в сервисном контракте. Вы не можете создать метод, который однажды возвращает ответ ( из сообщения , если быть точным), тогда как в других случаях это не так.

Очевидно, что вы можете определить исходящее сообщение, которое может быть пустым или содержать некоторый контент, но вам все равно придется что-то возвращать.

Краткое объяснение : протокол SOAP недостаточно гибок, чтобы удовлетворить ваши требования. Вы либо возвращаете ответ, либо нет. Создайте два метода и выберите, какой из них вызывать на стороне клиента, вместо добавления пользовательских заголовков.

Еще один совет: вы можете использовать ESB для выполнения какого-либо преобразования, так что ответ отбрасывается при наличии некоторого заголовка SOAP.

0 голосов
/ 28 сентября 2011

Я думаю, что для вашего конкретного сценария правильный способ реализации - использовать две операции. Один для входа и другой для выхода.

То, как вы пытаетесь это реализовать, может вызвать проблемы и на стороне клиента. Теперь клиент должен решить, искать ответ или нет в зависимости от запроса. С другой стороны, поскольку решение принимается из значения, отправляемого клиентом на стороне клиента, он может принять решение о вызове операции in-only или in-out.

0 голосов
/ 28 сентября 2011

@ Джаред: я в основном согласен с объяснением Томаша. Один из обходных путей, который я могу придумать, скажем, если использовать ws-адресацию. Ws-адресация позволяет указать <ReplyTo> and <To>. Таким образом, в основном, в сценарии вы не хотите, чтобы ответ отправлялся клиенту, который запросил, код на стороне сервера может изменить значение поля replyTo и может отправить ответ на фиктивный URI.

...