Glynn, Eoghan wrote:
-----Original Message-----
From: Dan Diephouse [mailto:[EMAIL PROTECTED] Sent: 20 March 2007 00:09
To: [email protected]
Subject: Re: [PROPOSAL] Client and Conduit changes

On 3/17/07, Glynn, Eoghan <[EMAIL PROTECTED]> wrote:

My position is that the Conduit should continue to hold to the reference to, and manage the lifecycle of, the decoupled
response endpoint (DRE).
Without rehashing the entire thread, my reasons briefly are:

1. Separation of concerns

The DRE is an aspect of the transport and thus should be
created and
referenced from within the realm of the transport.
Then why aren't we creating other decoupled endpoints from the transport layer?


Because the DRE is the only canonical back-channel IMO. By canonical, I mean you've got to have a back-channel for decoupled request/response MEPs to occur.
The faultTo on the other hand, is an added convenience provided by WS-A, but it 
is not central to the normal decoupled request/response paradigm.

The acksTo is even less central, as its obviously used only for out-of-band RM 
messaging.

In the normal case, the degrees of freedom presented by the faultTo and acksTo are not required by applications, i.e. they're happy to allow these default to be the same as the DRE.
In the less usual case where the application wants to set the faultTo and/or 
acksTo to a different address, then it has to do a bit more work.


The fact that it is in the standard, means we should architecturally be able to support it, no?

You can conceivably set up three different Destinations for an "invocation", correct?
I'm not sure on the standard, but logically thinking:

A response message goes to either the Reply-To, or Fault-To but not both,
and an Ack-To goes regardless. Only in the cases where these headers are not present does it default to the transport the message came in on, correct?

So, that tells me that these Destinations are particular to the "invocation" and not the transport.

This assumes a 1:1 association which isn't so.


Do you mean a 1:1 association between Conduits and Destinations?

I don't think it does necessarily, rather it depends on how the 
DestinationFactory is implemented.

Currently DestinationFactory.getDestination() returns a brand new Destination each time, but it could be changed easily so that subsequent calls to getDestination() with the same EndpointInfo get back the same instance, possibly with a ref-count that's decremented in Destination.shutdown(). I think you suggested something similar yourself in the earlier thread.
I think the assumed association that's actually inappropriate is the one 
between a Client and Destination, or even between a Client and Conduit. I won't 
re-hash the reasons for this, as I'm guessing anyone reading this thread will 
soon lose the will to live if either of us repeat ourselves any further :)

On the other hand, the purpose of the Client is to set up interceptor chains
and dispatch the invocation. Such invocations may NOT
require a DRE,
or even a Conduit for that matter. Thus I think it
inappropriate for
the Client to be concerned with the creation of the DRE, and would even go one step further and move the Conduit creation to the MessageSenderInterceptor, so that a Conduit comes into
being only if it really is needed.


Then do you want to get rid of Exchange.getConduit/getDestination or Message.getConduit/getDestination as well?


I think there's a big difference here. Exchange/Message.getConduit() are just accessors. Client.getConduit() currently causes the creation of a Conduit.

Just because you want to not require the conduit doesn't mean that there shouldn't be conduit/destination properties on the Client. This is completely orthogonal to the issue.


So how would a user suppress the Client's creation of a Conduit if its only 
when the dispatch gets as far as some interceptor that the dispatch is diverted 
in such as a way as to not require a Conduit? Note the Conduit is created 
*up-front* by the Client, before InterceptorChain.doInterceptor() is called for 
the outward dispatch.


Well, such is the nature of these interceptors. Who even says you need a Message? :) I guess it really depends on how you would want to adhere to an underlying architecture.

When you are a Client, you are expecting the message to go over a particular Conduit regardless. An interceptor may divert that for good reason, but still the Client "intends" that particular Conduit, quite possibly for trust/assurance issues.

If the purpose of this diversion is for local invocation, then perhaps there should be a "local" Conduit that the message goes "over" but stays in process?

2. Avoid forcing the usage of a Client instance
In general, if A is to be responsible for maintaining a
reference to
B, then its reasonable to expect that the existence of a B
implies the
existence of an A. Otherwise, in some cases an instance of
A will have
be artificially created, solely to manage the reference to B.

But if a DRE is in use, then the *only* other thing we're
guaranteed
also exists is the corresponding Conduit.

IMO we should neither require the usage of a Client instance to mediate invocations, nor impose any undue burden on
applications that
choose to wire up the interceptor chains directly and
initiate dispatch themselves.
An example of an undue burden would be forcing such applications to either always create the DRE *programmatically* via DestinationFactory.getDestination(), or if they want the DRE to be specified declaratively, to manage this configuration themselves.
Undue burden? Where is the undue burden?


The undue burden is NOT in driving the programmatic API. I agree the amount of 
work there is roughly the same.

The problem is that there should be declarative mechanism as well as a programmatic API. The application doesn't necessarily want to hard-code the DRE address. This declarative mechanism is currently provided by the Conduit configuration. Any application can take advantage of this, regardless of how the invocation is dispatched (whether via the Client, Dispatch, direct InterceptorChain.doIntercept(), whatever) because if it's a remote invocation, there's *always* going to be a Conduit instance involved.
You're proposing moving this config to hang off the Client instead. As a result 
the application would be forced to either (a) use the Client in order to 
declaratively specify the DRE, or (b) invent and manage its own config 
mechanism. Makes sense, or?

Your approach:

Conduit conduit = conduitInitiator.getConduit(Endpoint);
ConduitPolicy policy = conduit.getConduitPolicy(); policy.setDecoupledEndpoint (replyToEPR); conduit.setMessageObserver(myObserver);

My approach:

Conduit conduit = conduitInitiator.getConduit(Endpoint);
DestinationFactory destination = destinationFactory.getDestination (replyToEPR); destination.setMessageObser(myObserver); conduit.setMessageObserver(myObserver); // if you need to listen for back channel messages

It is arguably the SAME amount of work.


Agreed. See above though why this isn't the issue.


The benefit of the latter is its consistent.

3. Suitability for JMS
In order to setup a Destination, JMS may require more
information than
can be easily shoe-horned into an EPR. Stuff like a JNDI provider, ConnectionFactory username/password etc.

Now I don't accept the JMS as odd-man-out argument, especially when most of the counter-examples wheeled out ( i.e. XMPP, TCP,
FTP) do not
currently even exist as CXF transports. I could just as
easily make up
a list of non-existent transports that suggests that the URI-friendliness of HTTP is the exceptional case, but
obviously you'd
argue my list was hypothetical and proved nothing. And
you'd be right
:)

Neither does the "most people just use HTTP" line wash with
me. One of
the design centres of CXF is to be a multi-transport stack,
and that
in my book amounts to more than just paying lip-service to
non-HTTP transports.


Even if there isn't enough information in the JMS EPR to completely set up a JMS endpoint, it doesn't mean its completely useless. It can still be a nice way to hang onto references of a JMS endpoint that I've set up earlier on. For instance, a user could enter in the jms:// EPR in a configuration screen. By calling DestinationFactory.getDestination(epr) it would then retrieve a previously configured instance of the JMS destination.


Sure that could work.

And my point along is that we would have to take some JMS-specific approach 
like this, and thus lose one of the main purported benefits of your proposal, 
i.e. that the mechanism for setting up the DRE is consistent across transports.

Also I'd like to respond quickly to a couple of specific points that Dan
makes in his proposal:

"Right now if you want to create different endpoints for receiving ReplyTos and FaultTos you have configure the ReplyTos using the Conduit API and the FaultTos using the destination API.
Creating those
endpoints in different ways is bad IMO."

So how would this be any different under your proposal? Is the implication that in addition to a Client.setAsynchronousEndpoint() API, you'd also add Client.setFaultToEndpoint() and Client.setAcksToEndpoint(), and similarly expose <faultToEndpoint> and <acksToEndpoint> elements in your proposed <client> bean?
If so, this would expose *way* too much of WS-A and WS-RM semantics directly
in the Client, which should IMO be independent of such QoS
concerns.
The CXF WS-A and WS-RM layers were specifically designed to be pluggable, so that they could slotted into the runtime
without impact
on the core APIs. I would be strongly against a move that
breaks this
... I mean, what next, Client.setSecurityPolicyToken()??
If on the other hand, if you're not suggesting polluting the Client with
those aspects of WS-A & WS-RM, can you explain how your proposal provides a consistent mechanism for specifying the faultTo & acksTo vis-à-vis the replytTo?
No, I was more referring to scenarios where someone is not using the Client.
The one you seem to be so concerned about in #1.


So regardless of whether:

(a) we hang the DRE config off the Conduit (as is currently the case) or the 
Client (as you propose),

or

(b) the application chooses to use the Client or some other mechanism to 
mediate the invocation

Would you agree that if the application wants to set the faultTo or acksTo to 
some other address than the replyTo, then they would have to do so in a way 
that's not consistent with whatever way the replyTo is set?

If so, I think the setting of the faultTo/acksTo is neutral to the argument, 
and neither bolsters your case nor mine.




Hmmm, It seems that there are default defacto types of Destinations for a particular Client. (Reply-To, Fault-To, Acks-To, whatever) These are merely defaulted to the Conduit's Destination.

Perhaps, the Client is a MessageObserver to the Conduit's 1:1 Destination. When a Message comes in on the Conduit, the Client MessageObserver dispatches that message depending on response message headers (Reply, Fault, Ack, etc) to the appropriate Destination's MessageObservers that was default/overridden on the Client.

When the Client makes the invocation, the ProtocolHeaders (Reply-To, Fault-To, Ack-To, etc) before dispatching to the interceptors?

Cheers,
-Polar

Another point which I strongly disagree with:
"If all Conduits share the same code for setting up decoupled destinations, that is a sign to me that we can take it out
of the Conduit."
I've never come across a design principle that suggests
having common
code in a common base class is a sign that such code should
be moved elsewhere.
In fact what purpose do common base classes serve, other than to factor out commonality from sub-classes?
Base classes would be another solution to that problem. I wasn't trying to say base classes are evil. I was trying to say that the concept of a decoupled endpoint isn't critical to the concept of a Conduit, and so I think it should be taken out. Sometimes you can simplify the classes and then incorporate more advanced concepts into another class. For instance, in Microsoft's WCF, you have the IDuplexChannel which extends the IInputChannel and IOutputChannel. I don't think that is so outrageous really...


Agreed, not outrageous, just another way of doing it that happens to suit WCF.

/Eoghan

Reply via email to