cxf-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Polar Humenn <phum...@iona.com>
Subject Re: [PROPOSAL] Client and Conduit changes
Date Tue, 20 Mar 2007 15:49:46 GMT
Glynn, Eoghan wrote:
>  
>
>   
>> -----Original Message-----
>> From: Dan Diephouse [mailto:dan@envoisolutions.com] 
>> Sent: 20 March 2007 00:09
>> To: cxf-dev@incubator.apache.org
>> Subject: Re: [PROPOSAL] Client and Conduit changes
>>
>> On 3/17/07, Glynn, Eoghan <eoghan.glynn@iona.com> 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
>   


Mime
View raw message