Implementing a Policy-Aware Interceptor
This is the easiest way of providing runtime support for an Assertion. Steps 1. and 2. listed in Interaction with the Framework can usually be coded as follows:
package mycompany.com.interceptors;
import org.apache.cxf.ws.policy.AssertionInfoMap;
class MyPolicyAwareInterceptor {
static final QName assertionType = new QName("http://mycompany.com}",
"MyType"});
public void handleMessage(Message message) {
// get AssertionInfoMap
org.apache.cxf.ws.policy.AssertionInfoMap aim =
message.get(org.apache.cxf.ws.policy.AssertionInfoMap.class);
Collection<AssertionInfo ais> = aim.get(assertionType );
// extract Assertion information
for (AssertionInfo ai : ais) {
org.apache.neethi.Assertion a = ai.getAssertion();
MyAssertionType ma = (MyAssertionType)a;
// digest ....
}
// process message ...
// express support
for (AssertionInfo ai : ais) {
ai.setAsserted(...);
}
}
}
Sometimes, it may be more convenient to spead the above functionality accross several interceptors, possibly according to chain (in, in fault, out, outfault). In any case, you need to also provide a PolicyInterceptorProvider, and declare a corresponding bean. Either implement one from scratch or use the PolicyInterceptorProviderImpl in the api package and customise it as follows (assuming that one and the same interceptor is used for all paths). The main task of policy interceptor provider is to say which interceptors must be activated for specified policy assertion:
<bean name="MyPolicyAwareInterceptor"
class="mycompany.com.interceptors.MyPolicyAwareInterceptor"/>
<bean class="org.apache.cxf.ws.policy.PolicyInterceptorProviderImpl">
<constructor-arg>
<!-- the list of assertion types supported
by this PolicyInterceptorProvider -->
<list>
<bean class="javax.xml.namespace.QName">
<constructor-arg value="http://mycompany.com}"/>
<constructor-arg value="MyType"/>
</bean>
</list>
</constructor-arg>
<property name="inInterceptors">
<list>
<ref bean="MyPolicyAwareInterceptor"/>
</list>
</property>
<property name="inFaultInterceptors">
<list>
<ref bean="MyPolicyAwareInterceptor"/>
</list>
</property>
<property name="outInterceptors">
<list>
<ref bean="MyPolicyAwareInterceptor"/>
</list>
</property>
<property name="outFaultInterceptors">
<list>
<ref bean="MyPolicyAwareInterceptor"/>
</list>
</property>
</bean>
All beans of type PolicyInterceptorProvider are automatically registered with the framework's PolicyInterceptorProviderRegistry.
It is also possible to implement policy interceptor provider programmatically from scratch. It's constructor gives assertions QNames as argument of super constructor and adds corresponded interceptors using getters:
public class MyInterceptorProvider extends AbstractPolicyInterceptorProvider {
private static final long serialVersionUID = -5248428637449096540L;
private static final MyInInterceptor IN_INTERCEPTOR = new MyInInterceptor();
private static final MyOutInterceptor OUT_INTERCEPTOR = new MyOutInterceptor();
private static final MyOutFaultInterceptor OUT_FAULT_INTERCEPTOR = new MyOutFaultInterceptor();
private static final Collection<QName> ASSERTION_TYPES;
static {
ASSERTION_TYPES = new ArrayList<QName>();
ASSERTION_TYPES.add(new QName("www.mycompany.org", "myassertion"));
}
public MyInterceptorProvider() {
super(ASSERTION_TYPES);
getInInterceptors().add(IN_INTERCEPTOR);
getOutInterceptors().add(OUT_INTERCEPTOR);
getOutFaultInterceptors().add(OUT_FAULT_INTERCEPTOR);
}
}
Since version 2.5.2, Assertion builder and policy interceptor provider can be registered using CXF bus extension mechanism: just create a file META-INF/cxf/bus-extensions.txt containing the following:
org.company.MyInterceptorProvider::true
org.company.MyAssertionBuilder::true
Boolean value at the end specifies lazy loading strategy.
CXF automatically recognizes the assertion builder and policy interceptor provider and store them into registries: AssertionBuilderRegistry and PolicyInterceptorProviderRegistry.
Since CXF 2.6.0 it is possible to register multiple interceptor providers for single assertion.