简体   繁体   中英

How can I prevent Apache CXF from sending a response message?

In cases where a given SOAP header element has a given value (for example, if the value of the header tag "response" is "0"), I don't want Apache CXF to return a response at all.

How can I do this? It appears that CXF makes the assumption that all calls will receive a response.

(I know this seems strange in a web services context, but if your transport is JMS, it seems less strange).

I've been able to do this with an interceptor that aborts the interceptor chain.

I've tested this with an HTTP config (WebSphere returns an empty 200) and an ActiveMQ config (no response comes back to the response queue).

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;
     }
   }

and your applicationContext.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>

Long explanation : think about SOAP web services in terms of SOAP protocol specification. Web services is not just a fancy layer on top of HTTP, it is actually a way to describe two-way communication with various message exchange patterns implemented. The following patterns are most common ones:

  • request-response ( In-Out ): in HTTP environment this is a typical HTTP request/response call with some request message being sent from client to server and some response message is sent back. In JMS environment you would get two separate and independent messages.

  • one-way ( In-Only ): in this model the client send a request but does not expect nor care about the response. In JMS it is equivalent to a simple message sent to the broker. In HTTP on the other hand (at least this is how one-way methods are implemented in Apache CXF) you will get a void method on SEI. Moreover, CXF by default will use a separate thread pool to handle this request, so the client doesn't even wait for the response and the server is not even able to send that response (because the client might have already disconnected).

Now the important part: in WSDL you either define a method as request/response (by defining in/out messages) or as one-way (by only providing in message). This is fixed in service contract. You cannot make a method that once returns response ( out message to be precise) while other times it does not.

Obviously you can define an out message that can be empty or contain some content, but you still have to return something.

Short explanation : SOAP protocol is not flexible enough to fulfil your requirement. You either return a response or not. Create two methods and choose which one to call on the client side rather than adding custom headers.

Another tip: you might use ESB to perform some sort of transformation so that the response is discarded in presence of some SOAP header.

@Jared: I am mostly agreed with Tomasz's explanation. One workaround I can think of lets say if use ws-addressing. Ws-addressing allows you to specify <ReplyTo> and <To> . So basically, in scenario you don't want response to be sent to client who has requested, server side code can alter the value of replyTo field and can send response to dummy URI.

For your particular scenario I think the correct way to implement is to use two operations. One for in-only and other for in-out.

The way you try to implement it may cause problems in client side as well. now client has to decide whether to look for a response or not depending on the request. On the other hand since the decision is taken from a value send by the client at the client side it can decide to invoke the in-only or in-out operation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM