...
- 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 |
---|
|
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 |
---|
|
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 |
---|
|
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 |
---|
|
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 |
---|
|
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 |
---|
|
<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 |
---|
|
<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>
|