You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@cxf.apache.org by Dennis Sosnoski <dm...@sosnoski.com> on 2011/01/19 11:24:58 UTC

Postponing or blocking message delivery from interceptor

I've verified that the current WS-RM code only implements transmit
handling (retry until acknowledged). A correct WS-RM implementation also
requires receive handling, to postpone the delivery of messages received
out of order when InOrder delivery assurance is used, and to block the
delivery of duplicate messages when AtMostOnce or ExactlyOnce is used.

In order to implement the receive handling, I need to be able to
short-circuit the processing of an in-bound message in an interceptor so
that no further processing is done at this time but the appropriate
transport response goes back to the sender (such as an HTTP 200 code). I
also need to be able to later resume processing of an in-bound message
from the point it left off. How can I best do this in CXF?

Thanks,

  - Dennis

-- 

Dennis M. Sosnoski
Java SOA and Web Services Consulting <http://www.sosnoski.com/consult.html>
Axis2/CXF/Metro SOA and Web Services Training
<http://www.sosnoski.com/training.html>
Web Services Jump-Start <http://www.sosnoski.com/jumpstart.html>


Re: Postponing or blocking message delivery from interceptor

Posted by Daniel Kulp <dk...@apache.org>.
On Thursday 20 January 2011 5:51:27 pm Dennis Sosnoski wrote:
> On 01/21/2011 10:57 AM, Daniel Kulp wrote:
> > On Thursday 20 January 2011 2:49:53 am Dennis Sosnoski wrote:
> > 
> > ..................
> > 
> >> The WS-RM code does implement duplicate message checks if AtMostOnce is
> >> specified (in org.apache.cxf.ws.rm.DestinationSequence), in which case
> >> it throws an exception that goes all the way up the call stack to
> >> PhaseInterceptorChain. I'd think that would result in a Fault response
> >> to the client when using two-way calls, though - so it really needs to
> >> be handled using the above type of approach instead, right?
> > 
> > Isn't that correct though?  Looking at  the RM 1.1 spec section 3.2.2 on
> > duplicate elimination, it says:
> > ------------------------------
> > When the Response RM-Reply Pattern is requested with Duplicate
> > Elimination for a Reliable Message, the Receiving RMP cannot deliver
> > that message to the Consumer again (because it is a duplicate of a
> > previously delivered message), and a Consumer response payload is
> > expected, the response of the SOAP MEP instance MUST contain one (but
> > not both) of the following:
> > • a copy of the original response payload returned for that Message (in
> > the SOAP Body) in addition to the Acknowledgment Indication (in the SOAP
> > Header)
> > 
> >  or
> > 
> > • a SOAP server Fault (in the SOAP Body) in addition to the
> > Acknowledgment Indication (in the SOAP Header). The Sending RMP and
> > Producer expect either a complete response or a SOAP Fault when using
> > the Response RM-Reply Pattern; these two allowed behaviors satisfy that
> > expectation.
> > ----------------------------------
> > 
> > Since we don't save the response to the original request, the second
> > option of the fault is, I think,  the  only option.    Right?   (this
> > could be a 1.1 change though.  I don't have the 1.0 spec handy right
> > now0
> 
> It looks like you're getting that from the WS-Reliability 1.1 spec,
> rather than WS-RM 1.1
> (http://docs.oasis-open.org/ws-rx/wsrm/200702/wsrm-1.1-spec-os-01-e1.html).
> WS-RM doesn't appear to say anything about responses to duplicates. 

DOH!

Yep.  Wrong ws* PDF file.  

 
> My own feeling is that responses should be cached and resent in response
> to duplicate request messages - otherwise, WS-RM is pretty much useless
> for request-response flows - but that does add potentially a lot of
> overhead since all responses would need to be held until the sequence
> was closed.  :-( Let me see what Metro does in this case, and also check
> with one of the WS-RM people to see why they didn't address it in the
> spec. It seems like it would have made sense to include response
> acknowledgments to handle this case.

Let us know what you find out.  If there is an issue, definitel log a bug.  
And a patch.    :-)

-- 
Daniel Kulp
dkulp@apache.org
http://dankulp.com/blog

Re: Postponing or blocking message delivery from interceptor

Posted by Dennis Sosnoski <dm...@sosnoski.com>.
Ah, I think I see how response handling is supposed to work in WS-RM.
CreateSequence can optionally offer to create a separate sequence for
the opposite direction. I'd say the offer should always be configured in
policy when using a request-response MEP, and should always be accepted
by the destination. Then there are separate-but-equal sequences for the
two directions of message flow.

It looks like the Offer handling is in place in CXF, so responses should
automatically be resent if they're missed - I'll test this to see if it
works. That leaves the issue of what should be sent in response to a
duplicate request. I'll see what Metro does in this case.

  - Dennis


On 01/21/2011 11:51 AM, Dennis Sosnoski wrote:
> On 01/21/2011 10:57 AM, Daniel Kulp wrote:
>   
>> On Thursday 20 January 2011 2:49:53 am Dennis Sosnoski wrote:
>>   
>> ..................
>>   
>>     
>>> The WS-RM code does implement duplicate message checks if AtMostOnce is
>>> specified (in org.apache.cxf.ws.rm.DestinationSequence), in which case
>>> it throws an exception that goes all the way up the call stack to
>>> PhaseInterceptorChain. I'd think that would result in a Fault response
>>> to the client when using two-way calls, though - so it really needs to
>>> be handled using the above type of approach instead, right?
>>>     
>>>       
>> Isn't that correct though?  Looking at  the RM 1.1 spec section 3.2.2 on 
>> duplicate elimination, it says:
>> ------------------------------
>> When the Response RM-Reply Pattern is requested with Duplicate Elimination for 
>> a Reliable Message, the Receiving RMP cannot deliver that message to the 
>> Consumer again (because it is a duplicate of a previously delivered message), 
>> and a Consumer response payload is expected, the response of the SOAP MEP 
>> instance MUST contain one (but not both) of the following:
>> • a copy of the original response payload returned for that Message (in the 
>> SOAP Body) in addition to the Acknowledgment Indication (in the SOAP Header)
>>
>>  or
>>
>> • a SOAP server Fault (in the SOAP Body) in addition to the Acknowledgment 
>> Indication (in the SOAP Header). The Sending RMP and Producer expect either a 
>> complete response or a SOAP Fault when using the Response RM-Reply Pattern; 
>> these two allowed behaviors satisfy that expectation.
>> ----------------------------------
>>
>> Since we don't save the response to the original request, the second option of 
>> the fault is, I think,  the  only option.    Right?   (this could be a 1.1 
>> change though.  I don't have the 1.0 spec handy right now0
>>   
>>     
> It looks like you're getting that from the WS-Reliability 1.1 spec,
> rather than WS-RM 1.1
> (http://docs.oasis-open.org/ws-rx/wsrm/200702/wsrm-1.1-spec-os-01-e1.html).
> WS-RM doesn't appear to say anything about responses to duplicates.
>
> My own feeling is that responses should be cached and resent in response
> to duplicate request messages - otherwise, WS-RM is pretty much useless
> for request-response flows - but that does add potentially a lot of
> overhead since all responses would need to be held until the sequence
> was closed.  :-( Let me see what Metro does in this case, and also check
> with one of the WS-RM people to see why they didn't address it in the
> spec. It seems like it would have made sense to include response
> acknowledgments to handle this case.
>
>   - Dennis
>
>   

Re: Postponing or blocking message delivery from interceptor

Posted by Dennis Sosnoski <dm...@sosnoski.com>.
On 01/21/2011 10:57 AM, Daniel Kulp wrote:
> On Thursday 20 January 2011 2:49:53 am Dennis Sosnoski wrote:
>   
> ..................
>   
>> The WS-RM code does implement duplicate message checks if AtMostOnce is
>> specified (in org.apache.cxf.ws.rm.DestinationSequence), in which case
>> it throws an exception that goes all the way up the call stack to
>> PhaseInterceptorChain. I'd think that would result in a Fault response
>> to the client when using two-way calls, though - so it really needs to
>> be handled using the above type of approach instead, right?
>>     
>
> Isn't that correct though?  Looking at  the RM 1.1 spec section 3.2.2 on 
> duplicate elimination, it says:
> ------------------------------
> When the Response RM-Reply Pattern is requested with Duplicate Elimination for 
> a Reliable Message, the Receiving RMP cannot deliver that message to the 
> Consumer again (because it is a duplicate of a previously delivered message), 
> and a Consumer response payload is expected, the response of the SOAP MEP 
> instance MUST contain one (but not both) of the following:
> • a copy of the original response payload returned for that Message (in the 
> SOAP Body) in addition to the Acknowledgment Indication (in the SOAP Header)
>
>  or
>
> • a SOAP server Fault (in the SOAP Body) in addition to the Acknowledgment 
> Indication (in the SOAP Header). The Sending RMP and Producer expect either a 
> complete response or a SOAP Fault when using the Response RM-Reply Pattern; 
> these two allowed behaviors satisfy that expectation.
> ----------------------------------
>
> Since we don't save the response to the original request, the second option of 
> the fault is, I think,  the  only option.    Right?   (this could be a 1.1 
> change though.  I don't have the 1.0 spec handy right now0
>   

It looks like you're getting that from the WS-Reliability 1.1 spec,
rather than WS-RM 1.1
(http://docs.oasis-open.org/ws-rx/wsrm/200702/wsrm-1.1-spec-os-01-e1.html).
WS-RM doesn't appear to say anything about responses to duplicates.

My own feeling is that responses should be cached and resent in response
to duplicate request messages - otherwise, WS-RM is pretty much useless
for request-response flows - but that does add potentially a lot of
overhead since all responses would need to be held until the sequence
was closed.  :-( Let me see what Metro does in this case, and also check
with one of the WS-RM people to see why they didn't address it in the
spec. It seems like it would have made sense to include response
acknowledgments to handle this case.

  - Dennis


Re: Postponing or blocking message delivery from interceptor

Posted by Daniel Kulp <dk...@apache.org>.
On Thursday 20 January 2011 2:49:53 am Dennis Sosnoski wrote:
> On 01/20/2011 08:19 AM, Daniel Kulp wrote:
> > On Wednesday 19 January 2011 5:24:58 am Dennis Sosnoski wrote:
> >> ...
> >> 
> >> In order to implement the receive handling, I need to be able to
> >> short-circuit the processing of an in-bound message in an interceptor so
> >> that no further processing is done at this time but the appropriate
> >> transport response goes back to the sender (such as an HTTP 200 code).
> > 
> > Take a look at the OneWayInInterceptor for this.   Basically, it calls
> > back into the destination with basically and empty message to notify the
> > destination that we're "done" with this.
> 
> Do you mean org.apache.cxf.interceptor.OneWayProcessorInterceptor? 

Yea.  That's it.  :-)

..................
> The WS-RM code does implement duplicate message checks if AtMostOnce is
> specified (in org.apache.cxf.ws.rm.DestinationSequence), in which case
> it throws an exception that goes all the way up the call stack to
> PhaseInterceptorChain. I'd think that would result in a Fault response
> to the client when using two-way calls, though - so it really needs to
> be handled using the above type of approach instead, right?


Isn't that correct though?  Looking at  the RM 1.1 spec section 3.2.2 on 
duplicate elimination, it says:
------------------------------
When the Response RM-Reply Pattern is requested with Duplicate Elimination for 
a Reliable Message, the Receiving RMP cannot deliver that message to the 
Consumer again (because it is a duplicate of a previously delivered message), 
and a Consumer response payload is expected, the response of the SOAP MEP 
instance MUST contain one (but not both) of the following:
• a copy of the original response payload returned for that Message (in the 
SOAP Body) in addition to the Acknowledgment Indication (in the SOAP Header)

 or

• a SOAP server Fault (in the SOAP Body) in addition to the Acknowledgment 
Indication (in the SOAP Header). The Sending RMP and Producer expect either a 
complete response or a SOAP Fault when using the Response RM-Reply Pattern; 
these two allowed behaviors satisfy that expectation.
----------------------------------

Since we don't save the response to the original request, the second option of 
the fault is, I think,  the  only option.    Right?   (this could be a 1.1 
change though.  I don't have the 1.0 spec handy right now0
 
> Incidentally, the DestinationSequence code logs a duplicate message at
> SEVERE level. Shouldn't this really be INFO level, for an event which is
> interesting but not really any kind of error?

Likely yes.



-- 
Daniel Kulp
dkulp@apache.org
http://dankulp.com/blog

Re: Postponing or blocking message delivery from interceptor

Posted by Dennis Sosnoski <dm...@sosnoski.com>.
On 01/20/2011 08:19 AM, Daniel Kulp wrote:
> On Wednesday 19 January 2011 5:24:58 am Dennis Sosnoski wrote:
>   
>> ...
>>
>> In order to implement the receive handling, I need to be able to
>> short-circuit the processing of an in-bound message in an interceptor so
>> that no further processing is done at this time but the appropriate
>> transport response goes back to the sender (such as an HTTP 200 code). 
>>     
> Take a look at the OneWayInInterceptor for this.   Basically, it calls back 
> into the destination with basically and empty message to notify the 
> destination that we're "done" with this.
>   

Do you mean org.apache.cxf.interceptor.OneWayProcessorInterceptor? That
was the closest I could find to OneWayInInterceptor, which uses this
code to send the empty message back:

    Message partial = createMessage(message.getExchange());
    partial.remove(Message.CONTENT_TYPE);
    partial.setExchange(message.getExchange());
    Conduit conduit = message.getExchange().getDestination()
        .getBackChannel(message, null, null);
    if (conduit != null) {
        //for a one-way, the back channel could be
        //null if it knows it cannot send anything.
        conduit.prepare(partial);
        conduit.close(partial);
    }

The WS-RM code does implement duplicate message checks if AtMostOnce is
specified (in org.apache.cxf.ws.rm.DestinationSequence), in which case
it throws an exception that goes all the way up the call stack to
PhaseInterceptorChain. I'd think that would result in a Fault response
to the client when using two-way calls, though - so it really needs to
be handled using the above type of approach instead, right?

Incidentally, the DestinationSequence code logs a duplicate message at
SEVERE level. Shouldn't this really be INFO level, for an event which is
interesting but not really any kind of error?


>> I
>> also need to be able to later resume processing of an in-bound message
>> from the point it left off. How can I best do this in CXF?
>>     
> Also look at the OneWayInInterceptor.  :-)    You can just pause the chain and 
> store the chain someplace.  When ready, restart it.   
>   

Yes, I see. Thanks for the pointer!

  - Dennis

Re: Postponing or blocking message delivery from interceptor

Posted by Daniel Kulp <dk...@apache.org>.
On Wednesday 19 January 2011 5:24:58 am Dennis Sosnoski wrote:
> I've verified that the current WS-RM code only implements transmit
> handling (retry until acknowledged). A correct WS-RM implementation also
> requires receive handling, to postpone the delivery of messages received
> out of order when InOrder delivery assurance is used, and to block the
> delivery of duplicate messages when AtMostOnce or ExactlyOnce is used.
> 
> In order to implement the receive handling, I need to be able to
> short-circuit the processing of an in-bound message in an interceptor so
> that no further processing is done at this time but the appropriate
> transport response goes back to the sender (such as an HTTP 200 code). 

Take a look at the OneWayInInterceptor for this.   Basically, it calls back 
into the destination with basically and empty message to notify the 
destination that we're "done" with this.

> I
> also need to be able to later resume processing of an in-bound message
> from the point it left off. How can I best do this in CXF?

Also look at the OneWayInInterceptor.  :-)    You can just pause the chain and 
store the chain someplace.  When ready, restart it.   

-- 
Daniel Kulp
dkulp@apache.org
http://dankulp.com/blog