cxf-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Daniel Kulp <daniel.k...@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 16:55:33 GMT

Just to throw out another random thought....

Interceptor chains don't need to be completely constructed up front.   
Interceptors can be added to later phases during runtime without any penalty.  
Thus, an interceptor that requires more processing can create another 
interceptor that acts as a continuation and registers it with the chain.   
That interceptor could easily be an anonymous/inner class or similar.  


public void handleMessage(Message m) {
  startSend();
  message.getChain().add( new Interceptor() {
     public void handleMessage(Message m) {
         doClose();
     } 
     .....
  });
}

To make this work more pleasantly, the PhaseInterceptorChain probably should 
have a method like:
add(Interceptor, String phase)
or similar so you can add a raw interceptor and not force it to be a 
PhaseInterceptor that has all the other methods.

Dan


On Wednesday 14 February 2007 09:39, Dan Diephouse wrote:
> Hiya,
>
> On 2/14/07, Polar Humenn <phumenn@iona.com> wrote:
> > > 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?
> >
> > But I'm confused, onTermination() isn't called at the "end" of the
> > chain. The first call to an onTermination() method is in the "middle" of
> > the chain. That's because you are still "handling" the message in
> > onTermination() calls of the interceptors. For instance, in the outgoing
> > interceptor phase chain, the message isn't guaranteed to pop-out at the
> > end of the chain, it pops out at the beginning of the chain!
> >
> > Let's take the MessageSenderInterceptor. This interceptor is placed at
> > the "PREPARE_SEND" Phase. Looking at its current implementation there is
> > a Chain.doIntercept() call. I will assume that it is the split where
> > handleMessage and onTermination() will now exist.
> >
> > handleMessage will call conduit.send(message);
> >           (which basically readies the message to get handled by other
> > interceptors,
> >            in the PRE_STREAM, etc. phases.)
> >
> > onTermination will call conduit.close(message);
> >           (which closes the OutputStream, i.e. flushes the final buffers
> > writing data to the wire, guaranteeing that the message has been sent.)
> >
> > So, my basic question is, and what is confusing to me, is why is
> > conduit.close(message) called in the PREPARE_SEND phase? Shouldn't it
> > logically be called in the "SEND" Phase, which is the *last* outgoing
> > phase?
>
> Our phases aren't very well named at the moment. Its been on my todo list
> for forever to clean them up.
>
> And what if that onTermination() call got an IOException on the
>
> > OutputStream.close(). (The message really cant be said it made it out to
> > the wire. None of the interceptors after the PREPARE_SEND phase will get
> > notified.
>
> Ahhhh, I see your point now. You're right, that does get sticky. I think
> you may be right - this may make that proposal a non starter. (Sorry it
> took me a while.)
>
> I hope no one minds if I float two more proposals that we've talked about
> earlier for the sake of completeness:
>
> The first idea that we've floated before is supporting reentrant
> interceptor chains in a slightly different manner. The idea being that
> instead of doInterceptInSubChain we would support something like this:
>
> public void handleMessage(Message m)
> startSend();
> message.getChain().doIntercept(message, endPhase)
> close();
> }
>
> This is basically just a variation on the current theme, but making it
> cleaner. The main advantage of this over the current API would be that
> databinding interceptors wouldn't need to call chain.endSubChain().
>
> The second idea would be to rework writing so that it was more
> encapsulated. In XFire we had the idea of a Serializer. One of the final
> interceptors was responsible for opening the connection, doing
> serializer.write(message), and finally closing the connection. The idea
> here is that as we move through the chain we can replace/modify the
> serializer as we feel necessary. The thing I like about this is that it
> completely removes the need for reentrant interceptorchains/onTermination. 
> Here's an example of how it might work: 1. BareOutInterceptor sets the
> serializer to something which writes the message in a doc/lit style
> 2. Outgoing SAAJ interceptor uses this serializer to write the message to a
> SAAJ tree. The serializer is then replaced with a SAAJ serializer
> 3. Attachment out interceptor wraps the current serializer with one which
> starts writing the attachments, then delegates to the SAAJ serializer, and
> then finishes writing the attachments
> 4. A MessageSenderInterceptor opens the connection, executes the current
> serializer (outputting the message to the wire), and then closes the
> connection.
>
> The thing that I don't like about this is that it introduces a new concept,
> but it does become much more straightforward how to do output IMO.
>
> And then there is the standing proposal to just completely remove
> doInterceptInSubChain() :-) Thoughts? At the moment I have a preference
> toward continuing our support for reentrant interceptors a la the first
> proposal that I floated, but I could be swayed either way yet.
>
> Thanks Polar,
>
> - Dan

-- 
J. Daniel Kulp
Principal Engineer
IONA
P: 781-902-8727    C: 508-380-7194
daniel.kulp@iona.com

Mime
View raw message