Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
java
java
MyInterceptor interceptor = new MyInterceptor();
provider.getInInterceptors().add(interceptor);

There are main Some InterceptorProviders inside CXF are:

  • Client
  • Endpoint
  • Service
  • Bus
  • Binding

Writing an Interceptor

A CXF distribution is shipped with a demo called configuration_interceptor is shipped with CXF distribution, this demo shows you how to develope an user interceptor and add the interceptor into the interceptor chain through configuration.

Writing an interceptor is relatively simple. The best way to do this is to extend from an abstract class.

Practically speaking, there are two base classes you will be concerned with. The first is the AbstractPhaseInterceptor. The second is AbstractSoapInterceptor. The only difference between the two is that the latter will give you a SoapMessage instead of just a Message class. This allows you to access the SOAP headers and version.

Here is a small example of how to write a Soap interceptor:

Your interceptor needs to extend from either the AbstractPhaseInterceptor or some of its sub-classes such as AbstractSoapInterceptor. Extending from AbstractPhaseInterceptor allows your interceptor to access the Message class. For example, AttachmentInInterceptor is used in CXF to turn a multipart/related message into a series of attachments. It looks like below:

Code Block
java
java

import java.io.IOException;

import org.apache.cxf.attachment.AttachmentDeserializer;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;

public class AttachmentInInterceptor extends AbstractPhaseInterceptor<Message> {    
    public AttachmentInInterceptor() {
        super(Phase.RECEIVE);
    }
    
    public void handleMessage(Message message) {
        String contentType = (String) message.get(Message.CONTENT_TYPE);
        if (contentType != null && contentType.toLowerCase().indexOf("multipart/related") != -1) {
            AttachmentDeserializer ad = new AttachmentDeserializer(message);
            try {
                ad.initializeAttachments();
            } catch (IOException e) {
                throw new Fault(e);
            }
        }
    }

    public void handleFault(Message messageParam) {
    }
}

Extending from sub-classes of AbstractPhaseInterceptor allows your interceptor to access more specific information than Message class. For example, if your interceptor extends from AbstractSoapInterceptor, you will be able to access the SoapMessage class which contains SOAP headers and version etc. SoapActionInInterceptor in used in CXF to parse soap action, a simplified version looks like below:

Code Block
java
java

import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.apache.cxf.binding.soap.Soap11;
import org.apache.cxf.binding.soap.Soap12;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.binding.soap.model.SoapOperationInfo;
import org.apache.cxf.endpoint.Endpoint;
import org.apache.cxf.helpers.CastUtils;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.message.Exchange;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.Phase;
import org.apache.cxf.service.model.BindingOperationInfo;
import org.apache.cxf.service.model.OperationInfo;

public class SoapActionInInterceptor
Code Block
javajava

public class MySoapInterceptor extends AbstractSoapInterceptor {
    
    public MySoapInterceptor SoapActionInInterceptor() {
        super(Phase.PRE_PROTOCOL.READ);
        addAfter(ReadHeadersInterceptor.class.getName());
        addAfter(EndpointSelectionInterceptor.class.getName());
    }
    
    public MySoapInterceptor (String phase) {
    super(phase);
  }

  public void handleMessage(SoapMessage msg) throws SoapFault {
    System.out.println("Hello World!");
  }
} void handleMessage(SoapMessage message) throws Fault {
        if (message.getVersion() instanceof Soap11) {
            Map<String, List<String>> headers = CastUtils.cast((Map)message.get(Message.PROTOCOL_HEADERS));
            if (headers != null) {
                List<String> sa = headers.get("SOAPAction");
                if (sa != null && sa.size() > 0) {
                    String action = sa.get(0);
                    if (action.startsWith("\"")) {
                        action = action.substring(1, action.length() - 1);
                    }
                    getAndSetOperation(message, action);
                }
            }
        } else if (message.getVersion() instanceof Soap12) {
          ...........
        }
    }

    private void getAndSetOperation(SoapMessage message, String action) {
        if ("".equals(action)) {
            return;
        }
        
        Exchange ex = message.getExchange();
        Endpoint ep = ex.get(Endpoint.class);
        
        BindingOperationInfo bindingOp = null;
        
        Collection<BindingOperationInfo> bops = ep.getBinding().getBindingInfo().getOperations();
        for (BindingOperationInfo boi : bops) {
            SoapOperationInfo soi = (SoapOperationInfo) boi.getExtensor(SoapOperationInfo.class);
            if (soi != null && soi.getAction().equals(action)) {
                if (bindingOp != null) {
                    //more than one op with the same action, will need to parse normally
                    return;
                }
                bindingOp = boi;
            }
        }
        if (bindingOp != null) {
            ex.put(BindingOperationInfo.class, bindingOp);
            ex.put(OperationInfo.class, bindingOp.getOperationInfo());
        }
    }

}

To add this to your server, you'll want to get access to the Server object (see here for more info):

...