Versions Compared

Key

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

...

  • Client
  • Endpoint
  • Service
  • Bus
  • Binding

Writing and configuring an Interceptor

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

Writing an Interceptor

Writing an interceptor is relatively simple. 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:

...

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 One of sub-classes of AbstractPhaseInterceptor is AbstractSoapInterceptor, extending from AbstractSoapInterceptor makes your interceptor being able to access the SoapMessage class which contains SOAP headers and version etc. For example, SoapActionInInterceptor in is used in CXF to parse soap 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 extends AbstractSoapInterceptor {
    
    public SoapActionInInterceptor() {
        super(Phase.READ);
        addAfter(ReadHeadersInterceptor.class.getName());
        addAfter(EndpointSelectionInterceptor.class.getName());
    }
    
    public 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)You may also want to specify what phase your interceptor is in. To do this, you can simply set the phase:

Code Block
java
java
MySoapInterceptor myInterceptor = new MySoapInterceptor();

Server server = serverFactoryBean.create();
server.getEndpoint().getInInterceptor().add(myInterceptor);
public class MyInterceptor extends AbstractSoapInterceptor {
  public MyInterceptor() {
    super(Phase.USER_PROTOCOL);
  }
  ...
}

You can also express that you would like your interceptor to run before/after certain other interceptors in the same phaseOn the Client side the process is very similar:

Code Block
java
java
FooServicepublic clientclass =MyInterceptor ...extends ;AbstractSoapInterceptor //{
 created frompublic ClientProxyFactoryBean or generated JAX-WS client
MySoapInterceptor myInterceptor = new MySoapInterceptor();

Client cxfClient = ClientProxy.getClient(client);
cxfClient .getInInterceptor().add(myInterceptor);
MyInterceptor() {
    super(Phase.USER_PROTOCOL);
    getAfter().add(SomeOtherInterceptor.class.getName());
  }
  ...
}

You can add your interceptors into the interceptor chain either programmatically or through configuration.

Adding interceptors programmatically

To add this to your server, you'll want to get access to the Server object (see here for more info):You may also want to specify what phase your interceptor is in. To do this, you can simply set the phase:

Code Block
java
java
publicMyInterceptor classmyInterceptor MySoapInterceptor= extends AbstractSoapInterceptor {
  public MySoapInterceptor() {
    super(Phase.USER_PROTOCOL);
  }
  ...
}
new MyInterceptor();

Server server = serverFactoryBean.create();
server.getEndpoint().getInInterceptor().add(myInterceptor);

On the Client side the process is very similarYou can also express that you would like your interceptor to run before/after certain other interceptors in the same phase:

Code Block
java
java
public class MySoapInterceptor extends AbstractSoapInterceptor {
  public MySoapInterceptor() {
    super(Phase.USER_PROTOCOL);
    getAfter().add(SomeOtherInterceptor.class.getName());
  }
  ...
}FooService client = ... ; // created from ClientProxyFactoryBean or generated JAX-WS client
MyInterceptor myInterceptor = new MyInterceptor();

Client cxfClient = ClientProxy.getClient(client);
cxfClient .getInInterceptor().add(myInterceptor);

Adding interceptors through configuration

Adding MyInterceptor to your server:

Code Block
java
java

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
  
    <bean id="MyInterceptor" class="demo.interceptor.MyInterceptor"/>

    <!-- We are adding the interceptors to the bus as we will have only one endpoint/service/bus. -->

    <bean id="cxf" class="org.apache.cxf.bus.CXFBusImpl">
        <property name="inInterceptors">
            <list>
                <ref bean="MyInterceptor"/>
            </list>
        </property>
        <property name="outInterceptors">
            <list>
                <ref bean="MyInterceptor"/>
            </list>
        </property>
    </bean> 
</beans>

Adding MyInterceptor to your client:

Code Block
java
java

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:http="http://cxf.apache.org/transports/http/configuration"
       xsi:schemaLocation="http://cxf.apache.org/transports/http/configuration http://cxf.apache.org/schemas/configuration/http-conf.xsd
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
  
    <http:conduit name="{http://apache.org/hello_world_soap_http}SoapPort9001.http-conduit">
      <http:client DecoupledEndpoint="http://localhost:9990/decoupled_endpoint"/>
    </http:conduit>
    
    <bean id="MyInterceptor" class="demo.interceptor.MyInterceptor"/>

    <!-- We are adding the interceptors to the bus as we will have only one endpoint/service/bus. -->

    <bean id="cxf" class="org.apache.cxf.bus.CXFBusImpl">
        <property name="inInterceptors">
            <list>
                <ref bean="MyInterceptor"/>
            </list>
        </property>
        <property name="outInterceptors">
            <list>
                <ref bean="MyInterceptor"/>
            </list>
        </property>
    </bean> 
</beans>