There are basically 4 main possibilities to define WS-Policy in CXF projects:

  1. WSDL Policy attachment
  2. Spring configuration
  3. In code using WSPolicyFeature
  4. Dynamically via message context property

Let look into them in detail.

WSDL Policy attachment

WS-Policies can be attached and referenced in WSDL elements. Web Services Policy 1.5 - Attachment standard describes all possible alternatives. WS-Policies can be placed inside the WSDL itself or referenced as external documents. CXF will automatically recognize, read and use policies defined or referenced in WSDL. A sample of an attached policy is shown below:

<wsdl:definitions name="HelloWorld" targetNamespace="http://apache.org/hello_world_soap_http" 
    …
    <wsdl:service name="SOAPService">
        <wsdl:port binding="tns:Greeter_SOAPBinding" name="SoapPort">
            <soap:address location="http://localhost:9000/SoapContext/SoapPort"/>
            <wsp:Policy xmlns:wsp="http://www.w3.org/ns/ws-policy">
                <wsam:Addressing xmlns:wsam="http://www.w3.org/2007/02/addressing/metadata">
                    <wsp:Policy/>
                </wsam:Addressing>
            </wsp:Policy>
        </wsdl:port>
    </wsdl:service>
</wsdl:definitions>

Spring configuration

It is possible to define policies directly in the Spring configuration of the client and service as a jaxws feature. CXF will recognize and use configured WS-Policies:
Client:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:jaxws="http://cxf.apache.org/jaxws"
       xmlns:cxf="http://cxf.apache.org/core"
       xmlns:p="http://cxf.apache.org/policy"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd
http://cxf.apache.org/policy http://cxf.apache.org/schemas/policy.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">

    <jaxws:client id="CRMServiceClient" name="{http://services.talend.org/CRMService}CRMServiceProvider"
            xmlns:serviceNamespace="http://services.talend.org/CRMService"
            serviceClass="org.talend.services.crmservice.CRMService"
            serviceName="serviceNamespace:CRMServiceProvider"
            endpointName="serviceNamespace:CRMServicePort"
            address="${endpoint.prefix}/CRMServiceProvider">
            <jaxws:features>
                <p:policies>
                    <wsp:PolicyReference xmlns:wsp="http://www.w3.org/ns/ws-policy" URI="classpath:/saml.policy"/>
                </p:policies>
            </jaxws:features>
    </jaxws:client>
</beans>

Service:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:jaxws="http://cxf.apache.org/jaxws"
       xmlns:cxf="http://cxf.apache.org/core"
       xmlns:p="http://cxf.apache.org/policy"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd
http://cxf.apache.org/policy http://cxf.apache.org/schemas/policy.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
    <jaxws:endpoint id="CRMService"
            xmlns:serviceNamespace="http://services.talend.org/CRMService"
            serviceName="serviceNamespace:CRMServiceProvider"
            endpointName="serviceNamespace:CRMServicePort"
            implementor="#CRMServiceBean"
            address="/CRMServiceProvider">
            <jaxws:features>
                <p:policies>
                    <wsp:PolicyReference xmlns:wsp="http://www.w3.org/ns/ws-policy" URI="classpath:/saml.policy"/>
                </p:policies>
            </jaxws:features>
    </jaxws:endpoint>
</beans>

In code via WSPolicyFeature

Instead of loading the policies via Spring as detailed in the previous section, we can load the policies via code using the WSPolicyFeature, and then set it on a ClientFactoryBean, ServerFactoryBean or ClientProxyFactoryBean instance, for example:

WSPolicyFeature
import org.apache.cxf.staxutils.StaxUtils;
import org.apache.cxf.ws.policy.WSPolicyFeature;
...

WSPolicyFeature policyFeature = new WSPolicyFeature();
Element policyElement =
    StaxUtils.read(getClass().getResourceAsStream("saml.policy")).getDocumentElement();
policyFeature.setPolicyElements(Collections.singletonList(policyElement));

JaxWsProxyFactoryBean clientFactoryBean = new JaxWsProxyFactoryBean();
clientFactoryBean.setFeatures(Collections.singletonList(policyFeature));

 

Dynamically via message property

Sometimes policies cannot be configured statically, because they are obtained or calculated dynamically for the concrete message (for example using Policy Server or Service Registry). For such cases CXF provides a possibility to load the policy dynamically and set it into the message context property. It can be done for example in a custom interceptor that fulfills the following:

  1. Get policy from external location and build it for current message.
  2. Parse WS-Policy XML using Neethi library.
  3. Store result Policy object into PolicyConstants.POLICY_OVERRIDE message content property.
    It is important that this custom policy interceptor is called before CXF PolicyInInterceptor or PolicyOutInterceptor. Then CXF will automatically recognize Policy stored into this property and use it with the highest priority.