Return-Path: Delivered-To: apmail-incubator-cxf-dev-archive@locus.apache.org Received: (qmail 87200 invoked from network); 14 Feb 2007 13:25:37 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 14 Feb 2007 13:25:37 -0000 Received: (qmail 67462 invoked by uid 500); 14 Feb 2007 13:25:44 -0000 Delivered-To: apmail-incubator-cxf-dev-archive@incubator.apache.org Received: (qmail 67303 invoked by uid 500); 14 Feb 2007 13:25:43 -0000 Mailing-List: contact cxf-dev-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: cxf-dev@incubator.apache.org Delivered-To: mailing list cxf-dev@incubator.apache.org Received: (qmail 67288 invoked by uid 99); 14 Feb 2007 13:25:43 -0000 Received: from herse.apache.org (HELO herse.apache.org) (140.211.11.133) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 14 Feb 2007 05:25:43 -0800 X-ASF-Spam-Status: No, hits=-0.0 required=10.0 tests=SPF_HELO_PASS,SPF_PASS X-Spam-Check-By: apache.org Received-SPF: pass (herse.apache.org: domain of patrick.mulligan@iona.com designates 65.223.216.181 as permitted sender) Received: from [65.223.216.181] (HELO amereast-smg1.iona.com) (65.223.216.181) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 14 Feb 2007 05:25:33 -0800 Received: from amer-ems1.IONAGLOBAL.COM ([10.65.6.25]) by amereast-smg1.iona.com (Switch-3.1.7/Switch-3.1.7) with ESMTP id l1EDOxTP010660 for ; Wed, 14 Feb 2007 08:25:00 -0500 (EST) X-MimeOLE: Produced By Microsoft Exchange V6.5 Content-class: urn:content-classes:message MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Subject: RE: Proposal for chaning CXF Interceptor APIs. WAS: RE: When should we close the handlers in CXF? Date: Wed, 14 Feb 2007 08:22:34 -0500 Message-ID: In-Reply-To: <7b774c950702131947x37b27e75g108cf5b7396a9d90@mail.gmail.com> X-MS-Has-Attach: X-MS-TNEF-Correlator: Thread-Topic: Proposal for chaning CXF Interceptor APIs. WAS: RE: When should we close the handlers in CXF? Thread-Index: AcdP6wZexFGpEvcdSEGk4efH58aXQwATmr1g From: "Mulligan, Patrick" To: X-Virus-Checked: Checked by ClamAV on apache.org 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. =20 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]=20 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 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 --=20 Dan Diephouse Envoi Solutions http://envoisolutions.com | http://netzooid.com/blog