|
Page Edited :
CXF20DOC :
Interceptors
Interceptors has been edited by willem jiang (Mar 04, 2008). Change summary: Added some comments on how to programmatically add the interceptor for the client Interceptors and PhasesInterceptors are the fundamental processing unit inside CXF. When a service is invoked, an InterceptorChain is created and invoked. Each interceptor gets a chance to do what they want with the message. This can include reading it, transforming it, processing headers, validating the message, etc. Interceptors are used with both CXF clients and CXF servers. When a CXF client invokes a CXF server, there is an outgoing interceptor chain for the client and an incoming chain for the server. When the server sends the response back to the client, there is an outgoing chain for the server and an incoming one for the client. Additionally, in the case of SOAPFaults Some examples of interceptors inside CXF include:
InterceptorChains are divided up into Phases. Each phase may contain many interceptors. On the incoming chains, you'll have the following phases:
On the outgoing chain there are the following phases:
InterceptorProvidersSeveral different components inside CXF may provide interceptors to an InterceptorChain. These implement the InterceptorProvider interface: public interface InterceptorProvider {
List<Interceptor> getInInterceptors();
List<Interceptor> getOutInterceptors();
List<Interceptor> getOutFaultInterceptors();
List<Interceptor> getInFaultInterceptors();
}
To add an interceptor to an interceptor chain, you'll want to add it to one of the Interceptor Providers. MyInterceptor interceptor = new MyInterceptor();
provider.getInInterceptors().add(interceptor);
Some InterceptorProviders inside CXF are:
Writing and configuring an InterceptorThe CXF distribution is shipped with a demo called configuration_interceptor Writing an InterceptorWriting an interceptor is relatively simple. Your interceptor needs to extend from either the AbstractPhaseInterceptor or one of its many subclasses 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 those in the Message interface. One of the sub-classes of AbstractPhaseInterceptor is AbstractSoapInterceptor 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 = "" if (action.startsWith("\"")) { action = "" 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()); } } } Note that you will need to specify the phase that the interceptor will be included in. This is done in the interceptor's constructor: public class MyInterceptor extends AbstractSoapInterceptor { public MyInterceptor() { super(Phase.USER_PROTOCOL); } ... } You can also express that you would like the interceptor to run before/after certain other interceptors defined in the same phase: public class MyInterceptor extends AbstractSoapInterceptor { public MyInterceptor() { super(Phase.USER_PROTOCOL); // MyInterceptor needs to run after SomeOtherInterceptor getAfter().add(SomeOtherInterceptor.class.getName()); // MyInterceptor needs to run before YetAnotherInterceptor getBefore().add(YetAnotherInterceptor.class.getName()); } ... } You can add your interceptors into the interceptor chain either programmatically or through configuration. Adding interceptors programmaticallyTo add this to your server, you'll want to get access to the Server object (see here for more info): import org.apache.cxf.endpoint.Server; import org.apache.cxf.frontend.ServerFactoryBean; ... MyInterceptor myInterceptor = new MyInterceptor(); Server server = serverFactoryBean.create(); server.getEndpoint().getInInterceptor().add(myInterceptor); On the Client side the process is very similar: import org.apache.cxf.endpoint.Client; import org.apache.cxf.frontend.ClientProxy; ... MyInterceptor myInterceptor = new MyInterceptor(); FooService client = ... ; // created from ClientProxyFactoryBean or generated JAX-WS client //You could also call clientProxyFactroyBean.getInInterceptor().add(myInterceptor) to add the interceptor Client cxfClient = ClientProxy.getClient(client); cxfClient.getInInterceptor().add(myInterceptor); // then you can call the service client.doSomething(); You can also use annotation to add the interceptors from the SEI or service class. When CXF create the server or client, CXF will add the interceptor according with the annotation. @org.apache.cxf.interceptor.InInterceptors (interceptors = {"com.example.Test1Interceptor" })
@org.apache.cxf.interceptor.InFaultInterceptors (interceptors = {"com.example.Test2Interceptor" })
@org.apache.cxf.interceptor.OutInterceptors (interceptors = {"com.example.Test1Interceptor" })
@org.apache.cxf.interceptor.InFaultInterceptors (interceptors = {"com.example.Test2Interceptor","com.example.Test3Intercetpor" })
@WebService(endpointInterface = "org.apache.cxf._javascript_.fortest.SimpleDocLitBare",
targetNamespace = "uri:org.apache.cxf._javascript_.fortest")
public class SayHiImplementation implements SayHi {
public long sayHi(long arg) {
return arg;
}
...
}
Adding interceptors through configurationThe configuration file Adding MyInterceptor to the bus: <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cxf="http://cxf.apache.org/core" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/core http://cxf.apache.org/schemas/core.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. --> <cxf:bus> <cxf:inInterceptors> <list> <ref bean="MyInterceptor"/> </list> </cxf:inInterceptors> <cxf:outInterceptors> <list> <ref bean="MyInterceptor"/> </list> </cxf:outInterceptors> </cxf:bus> </beans> For embedded Jetty-based web services, the configuration file can be declared by starting the service with the -Dcxf.config.file=server.xml option. See the server configuration Adding MyInterceptor to your client: <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> To specify the client-side configuration file, start your client using the -Dcxf.config.file=client.xml option. |
Unsubscribe or edit your notifications preferences
