Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

It gets more complicated when we consider operation or even message policies. As we have determined the operation (and its parts) only after unmarshalling, we can calculate the effective policy for the operation/message also only at this point. On the other hand, at this point we must have already executed some of the policy related interceptors, i.e. all those that read headers like the addressing and RM SOAP interceptors. Another complicating factor is that in the case of multiple policy alternatives the server has no direct knowledge about which alternative was actually chosen by the client.
The first problem can be worked around by preemptively adding the interceptors for all AssertionBuilders for the policy vocabulary used by the endpoint are added to the chain: Generalizing the definitions in the WS-Policy specification we can define the vocabulary of an endpoint to be the merged vocabulary of the policies of its operations. Example: the RM interceptors would be added to the chain even if only some of the operations on the endpoint should be reliable, and these interceptors should be made robust w.r.t. to the absence of associated headers (respective changes required in the currently implemented addressing and RM interceptors are trivial) - they simply pass the message through.
We can weaken this to initially only add such interceptors if they belong to one of the pre-MARSHALLING phases, e.g. in that case the RMSoapInterceptor. Other interceptors can be added at a later stage, once the operation is known and according to policy vocabulary used for that operation or message.
Finally, we can only determine which requirements have been asserted at the end of the interceptor chain: the execution of an interceptor alone is not enough, nor is the presence of specific headers (although for well designed policies this should be enough). It is possible that we have to look at the header (or even message) content to check for a specific assertion. So, in order to decide at the end of the chain if everything that should have been asserted actually was asserted, we need to keep track of what was asserted by the individual interceptors. How can we do this?
At the begin end of the inbound chain we initialize , a map of assertion state variables (the key set is the vocabulary of the endpoint) and store this in the message. Potential states are ASSERTED, NOT_ASSERTED, MAYBE_ASSERTED. Each policy aware interceptor can retrieve the PolicyVerificationInterceptor first of all computes the effective policy for that operation/message. It then iterates backwards over all interceptors executed thus far and checks which of them implement the AssertionBuilder interface, and thus can decide if the requirement for a particular assertion has been met. The candidates get then passed the set of assertions of the types known to it, and for each assertion correspondingly promote the state to ASSERTED. E.g. the RM soap interceptor, if it finds that the underlying message is an application message and has seen that there is a sequence header, can assert the RMAssertion - provided the parameters of the RM assertion, i.e. InactivityTimeout, BaseRetransmissionInterval etc. are compatible with its behavior (the assertion should actually determine the precise behavior of the interceptor for the underlying operation/message). At the end of the inbound chain, in a PolicyVerificationInterceptor, we know the operation and can thus determine the effective policy and its vocabulary. We can now find out if there is one alternative for which all required assertions have been asserted by looking up the map. That alternative can then be identified as supported. If no alternative is supported, an exception is thrown before dispatching to the implementorthem and return the subset of these assertions that they can assert. Now, the PolicyVerificationInterceptor can decide if all required assertions for any of the effective policy's alternatives are supported. If this is not the case, the interceptor throws an Exception.
This process can be sped up by initialising a message property with an empty list of AssertionBuilders, to which each interceptor that wants to participate in the final decision process can contribute itself (avoiding the instanceof AssertionBuilder).
The transport may be included in this decision process if it also implements the AssertionBuilder interface (see discussions on cxf-dev on class #1/class #2 assertions) (here the type check cannot be avoided though).