Comments inline ...

> -----Original Message-----
> From: Dan Diephouse [mailto:[EMAIL PROTECTED] 
> Sent: 07 January 2007 22:05
> To: [email protected]
> Subject: Re: Proposal for Decoupling and Issues with CXFServlet
> 
> Hi Eoghan,
> 
> Comments inline...
> 
> On 1/5/07, Glynn, Eoghan <[EMAIL PROTECTED]> wrote:
> 
> > Put HTTP (or any other specific transport) out of your mind for a 
> > moment, and lets consider the fundamental question as to we 
> originally 
> > came to the conclusion that partial responses are needed by RM.
> > *snip*
> 
> 
> OK, thanks for the good summary of the issues here.
> 
> Now for an asynch transport that uses the same *long-lived* 
> destination to
> > receive *all* responses (and ACKs), and where that transport is 
> > continually listening for incoming traffic on that destination 
> > regardless of whether there's an outstanding reply 
> expected, then the 
> > requirement for partial responses shouldn't even arise (i.e. the 
> > acksTo should always be non-anonymous in this case).
> >
> > But, says you, shouldn't the above statement be true of all async 
> > transports?
> >
> > Nope, unfortunately that's not the case.
> >
> > Take for example the CXF JMS transport. For good or ill, 
> the way this 
> > currently works is that a *different* temporary queue is 
> specified as 
> > the replyTo for each request, and the client-side transport only 
> > expects to receive a *single* incoming message on that destination 
> > (i.e. in JMS parlance, instead of installing a 
> MessageListener on the 
> > response Queue to allow for a series of onMessage() 
> notifications, it 
> > makes just one call to
> > MessageConsumer.receive() to accept a single response message).
> >
> > For this style of JMS transport, we could envisage sending first a 
> > partial response, recognizable in some way as such by the receiving 
> > JMSConduit so as to cause it to make a second call to 
> > MessageConsumer.receive() in expectation of the full 
> response in the 
> > twoway case. For oneways, it would make just one (instead 
> of zero) calls to MessageConsumer.receive().
> >
> > You get the idea I hope ... Even though this transport is async, it 
> > still uses an anonymous style of response back-channel (in 
> the wider 
> > sense as defined above).
> >
> > So why not just "fix" the JMS transport so that it works in a more 
> > naturally async way? Well, that a whole other discussion, 
> but my main 
> > point is that even an async-style transport may require partial 
> > response semantics. So we should not tie our usage of 
> partial response 
> > to HTTP (by setting the 202 response code from within the 
> RM layer), 
> > as we can't be sure that the underlying transport is actually HTTP.
> 
> 
> Ok, some more thoughts.
> 
> First, if there is a transport which requires an anonymous 
> partial response, we could still support that. In my mind 
> this is analagous to the SOAP case.
> SOAP has an HTTP binding and HTTP specific semantics.We have 
> some HTTP specific code in the SOAP module to support things 
> like response codes. I wouldn't be any more keen on adding 
> SOAP specifics into the HTTP transport than I am to add 
> WS-A/RM semantics.

But is polluting RM with HTTP-specifics any better that polluting HTTP
with RM concepts?

I'm not sure that the HTTP-specifics in the SOAP binding is a good
exemplar, as IIRC you yourself argued strongly against burning
special-case handling of HTTP GET into the SOAP interceptors (i.e the
isGET() logic).

Further, explicitly setting the Message.RESPONSE_CODE to 500 in the
Soap1{1|2}OutFaultInterceptor is to my mind unnecessary. Surely the
HTTPDestination could just check whether the outgoing message is a fault
(i.e. message == message.getExchage().getOutFaultMessage()) and just set
the response code itself to 500 in that case?

Also, while the partial response idea was motivated by some RM
use-cases, exposing this concept to the HTTP level isn't IMO quite the
same thing as putting RM semantics directly into the HTTP transport,
(i.e. HTTP still knows nothing about the wsrm namespace, types,
operations etc).

> Second, what is the use case for RM over JMS? JMS is 
> inherently reliable. RM over JMS doesn't buy you anything 
> that I know of. The only case I can think of is that if we 
> were bridging transports - but in that the messages wouldn't 
> be destined to the JMS endpoints. Am I missing something here?

Nope you haven't missed anything, RM over JMS isn't that compelling ...
The only practical use-case I can think of is a router mediating between
SOAP/HTTP and SOAP/JMS where reliability is guaranteed for the HTTP leg
using RM, and we wish extend this into the JMS domain in order to
provide consistent end-to-end reliability semantics.

I was only really using JMS as a concrete example of an async transport,
that due to the nature of its response channel, would need partial
response semantics. The main point was that partial response semantics
are not necessarily only required by HTTP.
 
> Now please bear with me for just a little while longer here. 
> I want to go back to the pseudocode of the current logic 
> which gets the back channel:
> 
> public Conduit getBackChannel(inMessage, partialResponse, 
> partialResponse) {
>   if (replyToEPR == null) {
>     return backChannel;
>   else {
>     if (partialResponse != null) {
>       partialResponse.put(RESPONSE_CODE, HTTP_ACCEPTED);
>       return backChannel;
>     }
>     else return conduitInitiator.getConduit(destinationEPR, 
> replyToEPR);
>   }
> }
> 
> The main things I would want to change about this are:
> 1. Take the partial response logic out of the HTTP transport 
> 2. Remove the decoupling encapsulation. By this I mean on the 
> server side, it should not be providing a decoupled conduit 
> transparently (i.e.
> conduitInitiator.getConduit(...)). And on the client side we 
> shouldn't have a reference to the ServerEngine and provide a 
> server side Destination via
> getBackChannel()

Are you objecting just to the HTTPConduit having a reference to the
ServerEngine, or to the presence of a ServerEngine instance in the
client-side runtime?

If the latter, how would the client-side arrange to receive decoupled
responses without some sort of HTTP listener being launched in-process?
Shouldn't this client-side HTTP listener re-use the server-side logic?
Or are you thinking that the client-side should only embed a minimal
HTTP listener (like nanoHTTPD)?
 
> And let me try to give a fair recap for why I understand you 
> think things are best this way:
> A) Partial responses are best dealt with in the transport 
> layer because they have transport specific logic. Namely the 
> HTTP response code needs to be set.
> B) You can't achieve (A) without encapsulating the decoupling 
> in the transport interfaces (via the getBackChannel methods)
> C) Doing things in this way makes it easier to enforce security policy
> 
> Please let me know if I've misrepresented your position. I 
> have absolutely no desire to do so.

Yes, this pretty much sums up my core arguments.

> I completely follow your logic in B, however I think I 
> disagree with A.
> 
>    -  As I mentioned above, RM has HTTP specific semantics and those
>    should be contained inside the RM module. This is the same 
> policy we have
>    with things like the SOAP binding. This does not mean it 
> has to be hardcoded
>    into the partial response logic. The RM module could 
> discover different
>    transport specific logic. i.e. we could have an 
> RMTransport interface
>    which has something like a "void 
> setupPartialResponse(Message)" method.

Would this RMTransport be like a sub-interface of Destination, that the
RM layer would down-cast to as required?

If so, any wouldn't transport that we're likely to want to run RM over
would have to implement RMTransport as opposed to Destination, so that
we end up in effect with as much (or as little, depending on your point
of view) RM pollution of the transport as before?

That said, I could see how this idea could be useful in avoiding any
impact on transports that we're sure RM will *never* be run over in
anger, say the LocalTransport or maybe a transport for some old-school
MOM like MQ (where we sure the router use-case described above never
arises).

>    - The JMS transport doesn't seem to even have any 
> transport specific
>    logic for partial responses, so that could already be 
> handled in the RM
>    layer just fine. HTTP is the only one we're concerned 
> about here. And unless
>    I'm completely something, I'm not even sure why we're 
> worried about RM over
>    JMS.

See above. I choose JMS to illustrate the discussion because we actually
have a concrete CXF JMS transport with known semantics, as opposed to
imagining for example what semantics a SMTP transport might have. 

But you're right, our JMS transport would require some changes in order
to work fully with our RM implementation, specifically to make an
additional call to MessageConsumer.receive() for the partial response. 

> Furthermore, I'm really not a fan of B, which makes me less 
> inclined to like A.  Why?
> 
>    - Encapsulating the decoupling logic complicates transports: For
>    instance, methods we've added for encapsulation of the 
> decoupling include:
>    Conduit.getBackChannel(), Destination.getBackChannel(),
>    ConduitInitiator.getConduit(EndpointInfo, EndpointReferenceTarget).

Well, I guess we could simplify things a bit by factoring out the logic
related to partial response into a separate sub-interface of Destination
(assuming that's what you intended with the suggested RMTransport).

>    - This makes transports harder to write and maintain. 
> Writers need to
>    understand RM semantics - and this is quite confusing (I think this
>    discussion is just one example of how complex it can be ;-))
>    - In the HTTP case, it creates dependencies on specific HTTP
>    implementations. For instance, currently our HTTPConduit 
> is dependent on
>    Jetty at the moment. If we abstract both the server and client HTTP
>    implementations we end up making things even more complex. 
> I would much
>    prefer a world were I could write a commons HTTP Conduit 
> and not have to
>    worry about a decoupled Destination.

I'm not sure I understand how you'd intend to get away without worrying
about a decoupled Destination on the client-side ... how would the
client be capable of receiving decoupled responses?

Currently the client-side simply re-uses the server-side HTTP
Destination (which happens to be based on Jetty) in order to avoid
duplication. Are you suggesting a light-weight alternative client-side
listener (e.g. based on nanoHTTPD as suggested above)? Or a variant on
the HTTP transport that's not capable of receiving decoupled responses
at all?

Cheers,
Eoghan

> (BTW, I do think an abstraction that encapsulated message 
> sending/receiving over decoupled channels would be really 
> cool. Kind of like WCF's Channel concept. I just don't think 
> the low level transport layer is the place for
> it.)
> 
> Regards,
> - Dan
> 
> --
> Dan Diephouse
> Envoi Solutions
> http://envoisolutions.com | http://netzooid.com/blog
> 

Reply via email to