You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 9 Next »

Retrieval of Policies

Policies are associated with policy subjects. In the web services context, there are four different subjects:

  • Service
  • Endpoint
  • Operation
  • Message

Using WSDL 1.1, the policy-subject association usually takes the form of xml element attachment: a wsp:Policy element is attached to a WSDL element such as wsdl:port Ythe wsp prefix denotes the http://www.w3.org/2006/07/ws-policy namespace). Similary, wsp:PolicyReference elements can be attached to a wsdl element. In that case, the actual wsp:policy element may reside outside of the wsdl). Note that subjects do not correspond to wsdl elements directly. Rather, they map to a set of wsdl elements (see below). For example wsdl:port, wsdl:portType and wsdl:binding elements together describe the endpoint as a subject.

Another form of associating policies with policy subjects is external attachment: wsp:PolicyAttachment elements, which can reside in arbitrary locations, explicitly specify the subject(s) they apply to in their AppliesTo child element.

In CXF, elements attached to a wsdl element are available as extensors in the service model representation of that wsdl element: wsp:Policy and wsdp:PolicyReference elements can be obtained through the service model as extensors of type UnknownExtensibilityElement with matching element names (note that these attached elements are not parsed when the service model is built).
Policies attached to their subject through xml element attachment in WSDL 1.1 can therefore be obtained through the service model associated with an endpoint/an operation.

Using PolicyAttachment Documents

The location of documents containing PolicyAttachment documents on the other hand needs to be made known to the framework. This can easily be achieved through configuration:

<bean class="org.apache.cxf.ws.policy.attachment.external.ExternalAttachmentProvider">
    <constructor-arg ref="cxf"/>
    <property name="location" value="org/apache/cxf/systest/ws/policy/addr-external.xml"/>
</bean>

The location of the document containing PolicyAttachments is specified in the form of a classpath resource or URL. Any number of external attachment providers can be specified.

Note that PolicyAttachments are extensible w.r.t. the type of domain expressions. Domain expressions are used to identify entities such as endpoints, operations or messages with which a policy can be associated:

<wsp:PolicyAttachment>
    <wsp:AppliesTo> 
        <x:DomainExpression/> +
    </wsp:AppliesTo>
    (<wsp:Policy>...</wsp:Policy> | <wsp:PolicyReference>...</wsp:PolicyReference>)
</wsp:PolicyAttachment>

Currently, CXF supports domain only domain expressions of type wsa:EndpointReferenceType: This allows to associate the policies or policy references in an attachment with an endpoint (by means of matching the endpoint's address with that in the EndpointReferenceType element).
Support for other types of domain expressions can be plugged in by implementing the DomainExpressionBuilder interface and adding a corresponding bean to your configuration file (all DomainExpressionBuilder instances loaded that way will automatically register with the DomainExpressionBuilder and thus be considered in the process of parsing PolicyAttachment elements).

Now that the framework knows where to look for wsp:Policy, it parses the elements and creates runtime presentations for them. This is where AssertionBuilders come into play: Child elements of a wsp:Policy element that are not in the wsp namespace are considered to be assertions. The framework will use its AssertionBuilderRegistry to find an AssertionBuilder registered for the element type in question and in that case proceed to build an Assertion object (or else throw a PolicyException).

Computation of Effective Policies

As mentioned above, policies are associated with policy subjects. With WSDL 1.1, the effective policy for a subject is the aggregation, or the merge, of the policies attached to the wsdl elments representing that subject:
The effective policy for a service subject is the merge of all policies applying to the wsdl:service element.
The effective policy for an endpoint subject is the merge of all policies applying to the wsdl:port, wsdl:portType and wsdl:binding elements.
The effective policy for an operation subject is the merge of all policies applying to the wsdl:portType/wsdl:operation and wsdl:binding/wsdl:operation elements.
The effective policy for a (input | output | fault) message subject is the merge of all policies applying to the wsdl:message, (wsdl:portType/wsdl:operation/wsdl:input | wsdl:portType/wsdl:operation/wsdl:output | wsdl:portType/wsdl:operation/wsdl:fault) and (wsdl:binding/wsdl:operation/wsdl:input | wsdl:binding/wsdl:operation/wsdl:output | wsdl:binding/wsdl:operation/wsdl:fault).

Additional aggregation takes place to determine the effective policy of an endpoint:
The effective policy for a service is the effective policy for the service subject.
The effective policy for an endpoint is the merge of the effective policies for the service subject and the endpoint subject.
The effective policy for an operation is the merge of the effective policies for the service subject, the endpoint subject and the operation subject.
The effective policy for a (input | output | fault) message is the merge of the effective policies for the service subject, the endpoint subject, the operation subject and the message subject.

Note

Multiple sources can be used to supply policies applying to the same subject. In the case of an endpoint subject for example, its associated wsdl:port element can have multiple wsp:Policy child elements. An additional external provider can also contain multiple wsp:PolicyAttachment elements in which the AppliesTo children identify the endpoint in question as the target subject. Both the Policies attached to the port element as well as those in the matching PolicyAttachment elements will contribute to the effective policy of the endpoint subject.

It is also important to keep in mind that the aggregation process described above makes it possible for an effective policy to have multiple assertion elements of the same type in one alternative (although this would not be considered the normal). Different assertions of the same type within the same alternative do not overwrite each other. Instead, they may contradict each other, but it is also possible that they complement each other. In any case, the framewwork will not remove such duplicates and instead leave it to the interceptors involved in the assertion process to decide if they can meaningfully interpret the existence of multiple assertions of the same type.

It is obvious that the above aggregation process can be quite resource intense. Effective policies for messages and endpoints are therefore cached by the framework for future reference. The entity that manages the cache of effective policies is the PolicyEngine.

When computing the effective policy for an endpoint or a message, the framework also chooses one of the effective policy's alternatives. Currently, it choses the first alternative in which all assertions may be supported either by interceptors (i.e. there is a PolicyInterceptorProvider for the assertion type) or by the conduit/destination (if this implements the Assertor interface and via its canAssert method expresses the fact that it can support the assertion type). Note that, even if such an alternative can be found, this does not necessarily mean that the alternative is supported: While an interceptor may in principle be able to support a specific type of assertions, it may not actually support an individual instance of that assertion type.

The choice of alternative, along with the set of interceptors (obtained from the PolicyInterceptorProviders in the PolicyInterceptorProviderRegistry), is cached along with the actual effective message or endpoint policy in the form of an EffectivePolicy or EffectiveEndpointPolicy object. In the case of an effective endpoint policy, interceptors are chosen in such a way that the assertions in the chosen alternative of the effective endpoint policy can be supported, but also any assertion in any alternative of any of the operation and message specific policies. This is necessary in situations where the underlying message is not known, for example on the server inbound path: Once an alternative has been chosen for the effective policy of the server's endpoint we know which assertions must definitely be supported, regardless the underlying message/operation. Additional interceptors that are necessary to support the assertions that only appear in specific operation or input message policies are added pre-emptively. Note that this relies on interceptors being coded defensively - good practice anyway but especially so for interceptors returned by PolicyInterceptorProviders!

On-the-fly Provision of Interceptors

The policy framework, when activated (by loading the PolicyEngine and setting its "enabled" attribute to true), installs a couple of interceptors at bus level which execute early on in their respective interceptor chains:

Role

Chain

Phase

Interceptor

Effective Subject Policies Known

Client

Out

SETUP

ClientPolicyOutInterceptor

Service, Endpoint, Operation, (Input) Message

Client

In

RECEIVE

ClientPolicyInInterceptor

Service, Endpoint

Client

InFault

RECEIVE

ClientPolicyInFaultInterceptor

Service, Endpoint

Server

In

RECEIVE

ServerPolicyInInterceptor

Service, Endpoint

Server

OutFault

SETUP

ServerPolicyOutFaultInterceptor

Service, Endpoint, Operation, (Fault) Message

Server

Out

SETUP

ServerPolicyOutInterceptor

Service, Endpoint, Operation, (Out) Message

Their main purpose is to add further interceptors that are required to support the effective policy of the underlying message - even if that policy is not yet known at the point the interceptor executes (because the operation is not yet known).
In case where the effective message policy is known, the assertions of its selected alternative are inserted into the message in the form of an AssertionInfoMap. This is a map, keyed by assertion type name, of collections of AssertionInfo objects, the latter being stateful (asserted/not asserted) representations of Assertion objects.
Where the effective message policy is not known, not only the assertions for the selected alternative in the effective endpoint policy are included in the AssertionInfoMap, but also all assertions in assertion in all alternative of all of the operation and message specific policies. Not all of these will be asserted at the end of the chain, but that is fine if it turns out the unasserted assertions apply to operation sayHi when in fact we have been processing an inbound greetMe request!

Policy Aware Interceptors

Policy-aware interceptors extract the collection of AssertionInfo objects for the assertion types they understand from the AssertionInfoMap in the message. They can then use the wrapped Assertion objects to fine tune their behaviour, possibly exhibiting message type specific behaviour, and finally express whether or not they could support these assertions. Given an assertion type that has attributes, and assuming there are two instances of assertions of this type, it is possible that the interceptor can assrt one, but not the other assertion. In any case, inability to support all assertions understood by the interceptor does not necessarily indicate a failure. As mentioned above in relation to pre-emptive interceptor installation, it is possible that the ones that cannot be supported do not in fact apply to the underlying message at all.
Typically the interceptor would strive at supporting as many of these assertions as possible however, and for that purpose it may avail of the AssertionBuilder's capability to compute a compatible policy. For example, by scheduling an acknowledgement to be sent in 3 seconds, an RM interceptor would support both of the following RMAssertions:

<wsrmp:RMAssertion xmlns:wsrmp="http://schemas.xmlsoap.org/ws/2005/02/rm/policy">
    <wsrmp:AcknowledgementInterval Milliseconds="30000"/>
</wsrmp:RMAssertion>
<wsrmp:RMAssertion xmlns:wsrmp="http://schemas.xmlsoap.org/ws/2005/02/rm/policy">
    <wsrmp:AcknowledgementInterval Milliseconds="50000"/>
</wsrmp:RMAssertion>

Verification

Another set of interceptors installed by the policy framework is responsible for verifying that one of the alternatives in the effective policy of the underlying message is indeed supported. These are:

Chain

Phase

Interceptor

Out, OutFault

POST_STREAM

PolicyVerificationOutInterceptor

In

PRE_INVOKE

PolicyVerificationInInterceptor

InFault

PRE_INVOKE

PolicyVerificationInFaultInterceptor

Their behaviour is (if applicable at all) symmetric on client and server side.
On the outbound chain the effective message policy was known by the time the policy interceptor executing in the SETUP phase had inserted the AssertionInfoMap into the message. Asthis was built exclusively from the Assertion objects that form part of the chosen alternative for the effective message policy, all of them must be supported. In other words, all of the AssertionInfo objects in the need to be in the asserted state. If one of them is not, the interceptor throws a Fault (wrapping a PolicyException).

On the inbound paths a little bit more wotk is necessary: If the message is a fault, we know by now what type of fault it is and what operation it applies to, otherwise we know the underlying operation and can, from the location of the interceptor (client or server side) infer the message subject (input or output message). Either way, all information is now available to obtain the effective message policy. To check if any of is alternative is supported, the policy verification interceptors simply verify that for each of the assertions in the alternative under test the associated AssertionInfo object is in the assrted state. If it turns out that no alternative is supported, the interceptor throws a Fault (wrapping a PolicyException).

  • No labels