cxf-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Mulligan, Patrick" <Patrick.Mulli...@iona.com>
Subject RE: Proposal for chaning CXF Interceptor APIs. WAS: RE: When should we close the handlers in CXF?
Date Wed, 14 Feb 2007 13:22:34 GMT
After watching this thread for a few days, all I can say is keep it as
simple as possible, and remember the 80/20 rule.  The phases are fine
(only saw that in hell2days for first time), and it sounds like this
onTermination has merit.  

I think Dan's comment of " I'm worried about phase bloat, interceptor
bloat, and what it takes to understand how CXF works.." is a reasonable
concern.  Although the model may be infinitely powerful, if it gets too
crazy for the average layman, they will beg off and go use something
else.

-----Original Message-----
From: Dan Diephouse [mailto:dan@envoisolutions.com] 
Sent: Tuesday, February 13, 2007 10:48 PM
To: cxf-dev@incubator.apache.org
Subject: Re: Proposal for chaning CXF Interceptor APIs. WAS: RE: When
should we close the handlers in CXF?

Comments inline...

On 2/12/07, Polar Humenn <phumenn@iona.com> wrote:

> >
> > I agree that it would be a simpler semantic if we can have a chain
that
> only contains the calling of handleMessage(message) and only traverses
on
> one direction. But a second thought makes me to think about the trade
off we
> have to make in order to achieve this: First we have to write
corresponding
> ending interceptors for these need a terminal action, agreed it is not
a bit
> deal to write more interceptors and more phases. Secondly and more
> importantly, we have to make sure the ending interceptors are put in a
> proper place, this is where trick plays. Its not that straightforward
and
> easy to make mistakes to find a proper place in the chain for ending
> interceptors.



Actually, this is where the phases come into play. Surprisingly I like
> this architecture. I like this architecture especially over the CORBA
> interceptor architecture, as that had no idea of ordering at all.
>
> The phase thing is somebody's shear brilliance. I wish I had thought
of
> it. It actually sections out ordering semantics for interceptor
> execution. CORBA couldn't figure this out, so they PUNTED.
>
> I say Fantastic! So, bloody-well use it! Don't pretend it doesn't
exist.
> The only slight complication you speak of comes with interceptors that
> are placed in the same phase. However,  there is some notable, if not
> great mitigation strategy.


Thats bollocks. If people need more sophisticated ordering of their
"terminal actions" then they can write a separate interceptor. But a
large
number of outgoing interceptors need this type of support and I'd rather
not
see a plethora of interceptors there. This is too common of a case.
Phases
are meant to be more coarse coarse grained then UNMARSHAL_START and
UMARHSAL_END or SEND_START and SEND_END. We're dealing with multiple
protocols, bindings, and frontends here - I'd rather not see them become
too
centered around the JAX-WS SOAP case.


> Things can get even worse if we have too many interceptors in a same
> phase, I dont think addBefore and addAfter can handle complicate
ordering
> cases.
> I think if you lay out the phases with forethought, and state
> requirements for each, I doubt that you'll really get more than one
> interceptor per phase. However, the capability remains for those who
> require it, and there is some mitigation for ordering among them.


If certain internal interceptors are required to be in special places,
> then make the phases they reside on "protected" so that none, but the
> designated "system" interceptors can be on that certain phase.


The point isn't to have only one interceptor per phase. Right now I
think
its too fine grained already with the pre and post phases. The idea of
phases was to just have distinct points where we can apply policy,
security,
users interceptors, etc.

> As a side note, currently the way how interceptors order themselves is
not
> ideal, as you already noticed:  "As far as the phases go, as far as I
can
> tell so far, that the amount of phases and names of the phases are
> configurable to the particular interceptor chain, and don't really
have much
> "meaning" associated with them at the moment, except for the implicit
> ordering and where some of the CXF internal interceptors are actually
> placed." Someone wants to refactor this? ;-) Anyway, that will be
another
> story.
> Well, yes. The semantics for each phase are only suggestive by name,
but
> you may lay down by documentation certain semantics or invariants on
> phases to give developers a guide line of where they think they should
> place their interceptors. And you can "protect" certain phases only to
> hold certain known "system" interceptors.
> > To summarize, without onComplete(or onTerminate) the semantics does
look
> simpler as the chain only flows on one direction,
> I am glad you agree on that point.


It may be more simple theoretically, but not more simple practically.

> but it leaves the burden of choosing a proper phase for ending
> interceptors to developers,
> Yes, they are developers, they are burdened. (Not as burdened as the
> designers :))
> > thus subjects to human errors and obviously more work to do for
> developers.
> I see no problem with developers having to understanding the system.
And
> if human errors are what you are worried about, I doubt that you are
> going to stop those even in the other scenario.


I'm worried about phase bloat, interceptor bloat, and what it takes to
undestand how CXF works. If we go down the route of adding new phases, I
think that it complicates each one of those things.

> The semantic itself can not guarantee the terminal action in an ending
> interceptors is called in a place that is symmetric to its
corresponding
> starting interceptors. E.g., the chain below
> >
> > Interceptor A -> Interceptor B.Staring -> Interceptor C.Staring ->
> Interceptor C.Ending -> Interceptor B.Ending
> >
> > Developers are free to put interceptor C.Ending and Interceptor
B.Endinganywhere, the semantic does not enforce the ending interceptors
are called
> in a symmetric position in the chain corresponding to their starting
> interceptors.
> Exactly! "Developers" are free to put the interceptors anywhere,
> presumably they know what they are doing. You have to rely on that.
The
> straight forward line through the interceptor chain is simple to
> understand.


And the idea that onTermination() is called after the chain has been
invoked
is just as simple to understand. Are you telling me that a developer
can't
understand that a method is executed at the end of the chain?

> For example, they can end up of having a chain:
> >
> > Interceptor A -> Interceptor B.Staring -> Interceptor C.Staring ->
> Interceptor B.Ending -> Interceptor C.Ending
> >
> > This can be very wrong. Using onComplete released this burden, and I
> don't see a chain with a traverse back phase on complete is that
complicate
> in terms of semantics.
> But this could also be very right, if it was the developer's
intention.
> There are reasons for this seemingly "unsymmetrical" approach. Take
this
> scenario:
>
> Interceptor A starts ready a message header
> Interceptor B.starting places a collection object on the message.
> Interceptor C.starting handles replaces B's object with a wrapper
> collection object
>
> Other interceptors add to the collection object, which in turn
modifies
> both B and C
> objects simultaneously, of which C has an ongoing efficient
encryption.
>
> Interceptor B.ending closes its collection object, produces a
integrity
> hash on the original added objects.
>
> Interceptor C.ending closes its collection object using the hash
> produced by B creates a signature.
>
> Interceptor D gets the collection object (which it assumes it knows
> exists after B.ending, but doesn't really know about C at all) and
> request that it be marshaled it into a message body
>
> Interceptor A.ending writes the marshaled header and the marshaled
> message body to the wire.
>
> You can see that C.starting needs to come after B.starting because the
> object wouldn't exist otherwise. You can also, C.ending needs to come
> after B.ending, because B's object needs to get the close before
> C.ending. Then and only then can C.ending assume it can close its
object
> get the hash for the signature.
>
> Now if B.ending threw a handling Fault, C.ending wont do anything
> because it never got called. Then on handleFault, B.ending can clean
up
> its object. Interceptor C.starting can relinquish copy object.
> Interceptor B.starting can relinquish its object, Interceptor A, can
> note that its intended message never went out. etc.
>
> This is all pretty straight forward, the fault handing works as it
should
>
> The only thing that has to be done is to be definitive with the
Phases,
> and placing certain internal interceptors in certain phases.


First, there is no handleFault, it needs to be removed.  If there is a
fault, an interceptor can detect it in onTermination and correct for it
there.

Second, I think your example is more theoretical than real. If someone
needs
more control over the termination actions, they can always write a
second
interceptor. There is nothing about onTermination() that prevents that.

Regards,
Dan

-- 
Dan Diephouse
Envoi Solutions
http://envoisolutions.com | http://netzooid.com/blog

Mime
View raw message