Hi Jervis,

Statelessness in interceptors is only a *sufficient* condition for thread safety. It is not a *necessary* requirement for thread safety. Thread safety may be maintained with a good specification of interceptor call semantics.

On changing the API and semantics of the interceptors, I kind of wonder if their exists a confusion between a "Fault" and a message indicating an interceptor "Fault". I am hoping somebody can clear this up for me.

From some of the recent discussion I have been privy to, it seems like the there was a misconception that the FaultOut interceptors had handleFault called, but in fact have handleMessage called. That was my initial impression when I first started looking.

However, in fact, on a particular chain, the handleMessage() works with the particular Message on its way out or in. The handleFault method merely uses the Message for correlation with a previous call to handleMessage(). This particular semantics makes perfect sense, although it maybe can use a better API (which I can formulate below) for fault indication.

There is a *different* concept of a "Fault" which is a "Fault Message" which is signified by the FaultOut or FaultIn interceptor chains.

An "Interceptor Fault" may *cause* a "Fault Message", but these things need to be explicitly differentiated and semantics nailed down.

If the case is that there really are two kinds of messages (Normal, and Fault) this should be formalized for all the protocols that CXF is going to handle.

I don't like the idea of an onFinish(Message) because it requires me to *wait* in my interceptor to make sure that my message popped out the other end. The handleFault() which is the result of an interceptor thrown Fault, gives me the "exception" to my *assumption* that the message will pop out the other end. Assuming messages make it out or in is the most abundant normal case.

Unfortunately, after a discussion with Eoghan, I find that some interceptor chains are just not completed. If that is the case, when or if would you call "onFinish()"?

I would suggest:

   void handleMessage(Message m) throws Fault;

   void handleFault(
        Message m, String phase, String interceptor, Fault f
   );

naming the phase and interceptor that threw the particular fault.
or maybe even

   class InterceptorFault {
       String phase; String interceptor; Fault fault;
   }
   void handleFault(
       Message m, List<InterceptorFault> faults
   ) throw Fault;

which allows handleMessage to throw a fault, and handleFault() to throw Faults, but is given a list of faults and the names of interceptors that throw them back along the way. The chain collects Faults and adds the faults to the list.

Cheers,
-Polar

Liu, Jervis wrote:
Hi Polar, comments in-line.

Cheers,
Jervis

-----Original Message-----
From: Polar Humenn [mailto:[EMAIL PROTECTED]
Sent: 2007?2?7? 6:05
To: [email protected]
Subject: Re: Proposal for chaning CXF Interceptor APIs. WAS: RE: When should we close the handlers in CXF?


I'm still trying to find out how this interceptor stuff works. So forgive me if I seem naive. :-[

You say CXF interceptors are stateless. Are you saying that "statelessness" is a requirement to be a CXF interceptor? Or are you saying that the processing interceptors that are currently used in CXF are stateless and that's all that need to be supported?

I can definitely see a use case for CXF interceptors maintaining state.

A simple one is an outbound message counter. The interceptor increments a counter on handleMessage() assuming the message makes out the end (has no way of knowing). So the interceptor must decrement its counter on handleFault() because that tells the interceptor that the message never made it out the end because of some interceptor downstream in the chain.

Once interceptors are created (eg, in SoapBindingFactory.java), their instances are shared across all interceptor chains and threads. Interceptors have to be stateless for the sake of thread safe. If you really have to have some states that you want to be shared among interceptors, you can put them into Message.

So, if I have this right, what you are proposing is to alter the semantics, and only call this onFinish() method on the unwind chain when the message makes finally makes it out the end of the chain.

This changes the semantics quite a bit. With the handleFault approach one can assume that the message will be successful in negotiating the chain *unless* it is told otherwise, (handleFault), which leads to optimistic processing. The latter onFinish() approach requires me to *wait* to see *if* the message was successful, which is a pessimistic, possibly more expensive approach.

It seems to me, that "fault" processing is the exceptional case, and one should be able to assume optimistic processing, unless told otherwise.


Actually what has been proposed does not change the semantics a lot. We only 
want to do two changes:

1. Remove handlerFault(). The reason for this has been presented in the previous 
discussion, just quoted again below: "However, the difference is CXF interceptors 
are not designed to hook in user logic as these JAX-WS handlers do, thus handleFault is 
not needed in CXF interceptors (correct me if I am wrong, but I believe this is the 
purpose that JAX-WS handlers's handleFault method designed for. I.e., when a known 
exception - ProtocolException occurs, handleFault() gives handler developer a hook to 
clean up sth, for example, roll back a transaction, this is different from what close() 
is supposed to do. The latter is designed to clean things up under a succeeded 
situation). For any Runtime exceptions thrown by interceptors, we just wrap it as soap 
exception then dispatch it back calling handleMessage."

2. Add a onFinish(Message) or onComplete(Message) method (using name DanD 
suggested): this method is called in a reversed direction when chain completes, 
can be used to remove the sub-chain or interceptor re-entrance. For example, 
SoapOutInterceptor can use onComplete to write the end element of SoapBody 
SoapEnvelop, this way SoapOutInterceptor does not need to wrap its following 
interceptors in a sub chain.



Thoughts?

The other thing I don't get, is what constitutes an Inbound Fault Message as opposed to an Inbound Message? Why does this make a difference in Interceptors of inbound and outbound messages?

Cheers,
-Polar


Dan Diephouse wrote:
Could I offer just once suggestion? Could we rename the postHandleMessage to
onFinish(Message) or onComplete(Message)?

- Dan

On 2/6/07, Unreal Jiang <[EMAIL PROTECTED]> wrote:
Hi,

Looks like there has no opponent for jervis' proposal, I will create a
jira task for this proposal and sign it me.

  Cheers
  Unreal

"Liu, Jervis" <[EMAIL PROTECTED]> wrote:

________________________________

From: Dan Diephouse [mailto:[EMAIL PROTECTED]
Sent: Tue 1/23/2007 1:02 AM
To: [email protected]
Subject: Re: Proposal for chaning CXF Interceptor APIs.
WAS: RE: When
should we close the handlers in CXF?



On 1/22/07, Liu, Jervis  wrote:
Hi, I would like to summarize what we have been
discussed in this
thread
(including Eoghan's proposal posted last Oct [1]) regarding
Interceptor
API
changes. Any comments would be appreciated.

Currently our Interceptor APIs look like below:

public interface Interceptor {
     void handleMessage(T message) throws Fault;
     void handleFault(T message);
}

Also in the interceptor chain, we have a notion of sub-chain or
interceptor chain reentrance by calling
message.getInterceptorChain
().doIntercept(message)
or message.getInterceptorChain().doInterceptInSubChain(message).

The main issues we have with the current implementation are:

1. Fault handling. See Eoghag's email [1]

2. Sub-chain reentrance. See previous discussion in this thread.

We propose to change Interceptor API as below:

public interface Interceptor {
     void handleMessage(T message) throws Fault;
     void handleFault(T message);
     void close(T message);
}

handleFault(T message) method is used to process fault message
(which is
done by handleMessage() in fault-chain currently).
I'm not sure I understand how you want to use this. I
guess I could
see
two
ways
1. Remove In/OutFault interceptors and call handleFault
on the In/Out
interceptors. I don't know that mapping works especially
well though.
2. Don't call handleFault on in/out interceptors, but only on the
in/outFault interceptors - this would mean, for example,
that the
logic
from
Soap11OutFaultInterceptor would be moved from the
handleMessage to
handleFault.
Can you be more specific about what you mean?
Sorry, after rethinking about this, I've changed my mind
slightly, so
here
is the idea:

CXF Interceptor API will be similiar to JAX-WS API,
section 9.3.2.1.
Throw ProtocolException or a subclass This indicates that
normal message
processing should cease.
Subsequent actions depend on whether the MEP in use requires a response to
the message currently
being processed or not:

Response: Normal message processing stops, fault message processing
starts. The message direction
is reversed, if the message is not already a fault message
then it is
replaced with a fault message4,
and the runtime invokes handleFault on the next handler or
dispatches
the
message (see
section 9.1.2.2) if there are no further handlers.

No response: Normal message processing stops, close is
called on each
previously invoked handler
in the chain, the exception is dispatched (see section 9.1.2.3).


Throw any other runtime exception This indicates that
normal message
processing should cease. Subse-
quent actions depend on whether the MEP in use includes a
response to
the
message currently being
processed or not:

Response: Normal message processing stops, close is called on each
previously invoked handler in
the chain, the message direction is reversed, and the exception is
dispatched (see section 9.1.2.3).


No response: Normal message processing stops, close is
called on each
previously invoked handler
in the chain, the exception is dispatched (see section 9.1.2.3).

However, the difference is CXF interceptors are not
designed to hook in
user logic as these JAX-WS handlers do, thus handleFault
is not needed
in CXF interceptors (correct me if I am wrong, but I
believe this is
the purpose that JAX-WS handlers's handleFault method
designed for.
I.e,  when
a known exception - ProtocolException occurs, handleFault() gives handler developer a hook to clean up sth, for example, roll back a
 transaction,
this is different from what close() is supposed to do. The
 latter is
designed to clean things up under a succeeded situation). For any Runtime exceptions thrown by interceptors, we just wrap it as soap
exception
then
dispatch it back calling handleMessage.

So here is the change we need to make:

1. Add a postHandleMessage() into Interceptor interface

2. Remove handleFault() method from Interceptor
interface. Or we can
still keep it for a while until we are absolutely sure we
wont need
this method, but I presume there is nothing we need to do in this method.

3.  We will NOT add a close() method into Interceptor interface, as
CXF interceptors are stateless, there is no resources need to be closed.

public interface Interceptor {
      void handleMessage(T message) throws Fault;
      void postHandleMessage(T message);
}

When  an interceptor chain ends normally, we need to call
postHandleMessage() on each previously traversed interceptor in a reversed
direction.

When a fault occurs on the in-bound chain, an exception
will be thrown
from  the interceptor, after catching the exception in
PhaseInterceptorChain,  we unwind the current chain by calling
postHandleMessage() on each previously traversed interceptor and then jump to the out-fault-chain, calling handleMessage() on each
interceptor
with
the fault message.

Any thoughs?




close(T message) method is called on a reverse direction
at the end of
interceptor chain or when a fault or exception occurs.
Take the fault
handling case as an example, below is how handleFault
and close work
together
+1 to close() - Although I think Eoghan has a good point
about the
ordering
not necessarily being the same. I think we need to do a
little bit
more
digging before we can know whether or not sub chains can
be removed.
when a fault occurs on the in-chain, we unwind the
current chain by
calling
close() on each previously traversed interceptor and
then jump to the
out-fault-chain, calling handleFault() on each
interceptor with the
fault
message.

Close method is also used to remove the sub-chain
reentrance. See the
SOAPHandlerInterceptor example I posted previously.

Cheers,
Jervis

[1]

http://mail-archives.apache.org/mod_mbox/incubator-cxf-dev/200
611.mbox/[EMAIL PROTECTED]
--
Dan Diephouse
Envoi Solutions
http://envoisolutions.com   | http://netzooid.com/blog





---------------------------------
Access over 1 million songs - Yahoo! Music Unlimited.




Reply via email to