Liu, Jervis wrote:
You are right in saying statelessness is only a sufficient condition. But I
would say it is recommended that the CXF interceptors are implemented as
statelessness unless the developer are fully aware of the implication of
writing a stateful interceptor as our current interceptor calling semantics are
not enough to guarantee thread safety in this case.
Exactly, so the call semantics have to be nailed down, documented and
adhered to. What are the intended invariants on each call?
....
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.
onFinish() was proposed to address the subchain issue, i.e., we want the
interceptor has the capability to register some sort of terminal actions with
the InterceptorChain to be executed when the chain traversal is complete, more
details on this discussion can be found from [1] [2] [3]. onFinish is not
designed to address fault handling issues.
Okay, so I read what was below. I was not yet familiar with the subChain
semantics, but now I am getting it. I see some problems with the
subChain semantics (which are below), and I almost grasp what you are
looking for, which may alleviate my concerns, so please correct me if
am totally off base.
The goal of an outbound message is to get from the application to the wire,
Application ----> Wire
is it not? Interceptor traversal happens on that arrow. An interceptor
chain is NOT *finished* until that message is out on the wire, (unless
some fault occurs). Correct?
Application ---- InterceptorChainTraversal ----> Wire
The basic requirement you are looking for is to have some backward
actions planned after the chain is traversed in one direction to do some
clean up, or write end messages, trade output streams, in the backward
direction. Correct?
I understand from your explanation of the SoapOutHandler interceptor in
[1], than on the proposed onFinish() call that the message hasn't yet
been written to the wire, but is about to be written (after adding
ending tags, etc). Finally the at the end the MessageSenderInterceptor
calls the "conduit.close(message)", which I presume actually writes the
message out on the wire.
I surmise that the interceptor chain is NOT *finished* at the last
interceptor in the chain, because the intended goal of the interceptor
chain is to get the message out on the wire, and that has not been
achieved.
I believe you really want is to describe a two phase interceptor
traversal to *complete* the chain. I realize the the execution trace
would be the same, yet the proverbial semantics are subtly different
(maybe suggesting different name for the operations).
For an interceptor chain of A,B,C,D we would get the following execution.
Application ---- A, B, C, D, D, C, B, A -> Wire
Is this the trace you intend? I suggest on the backward trace that the
interceptor is still "handling" the message. Therefore, I would suggest
different names.
interface Interceptor<T extends Message> {
void handleMessageP1(T message);
void handleMessageP2(T message);
// fault handing is another topic.
}
Where P1 and P2 distinguish the "forward" phase and the "backward"
phase of message handling, respectively. Suggestions?
Now, for my concerns about the subchain logic;
The doInterceptInSubChain and finishSubChain is a way for two
interceptors to communicate (that coordinated with each other), yet have
the unknowing possibly of being subverted by other injected interceptors
in unfortunate places that call doInterceptSubChain and finishSubChain
as well, and thereby two seemingly coordinated interceptors are
mis-coordinated.
I surmise that this approach will eliminate the need
for"doInterceptSubChain" and "finishSubChain" calls, and also will
eliminate ability to call "doIntercept" for anything but the CXF
internal processing (i.e. interceptors cannot call it).
As far as the fault handling is concerned, I agree with you that our current
fault handling logics are bit confusing. This has been raised by Eoghan couple
months ago, see [4]. Can I suggest we separate this thread into two topics? One
is the proposal of adding onFinish() into interceptor interface, which is to
address subchain and terminal actions issues. One is about the fault handling.
For the former, I would like to see if there are any objections? If there is no
different voice, at least we can start working on this and keep our discussion
for the later going until it is fully baked.
I agree. We should discuss on another thread.
Cheers,
-Polar
[1].
http://mail-archives.apache.org/mod_mbox/incubator-cxf-dev/200701.mbox/[EMAIL
PROTECTED]
[2].
http://mail-archives.apache.org/mod_mbox/incubator-cxf-dev/200701.mbox/[EMAIL
PROTECTED]
[3].
http://mail-archives.apache.org/mod_mbox/incubator-cxf-dev/200701.mbox/[EMAIL
PROTECTED]
[4]
http://mail-archives.apache.org/mod_mbox/incubator-cxf-dev/200611.mbox/[EMAIL
PROTECTED]
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]
ublin.emea.iona.com%3e
--
Dan Diephouse
Envoi Solutions
http://envoisolutions.com | http://netzooid.com/blog
---------------------------------
Access over 1 million songs - Yahoo! Music Unlimited.