cxf-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Glynn, Eoghan" <eoghan.gl...@iona.com>
Subject RE: [PROPOSAL] Client and Conduit changes
Date Thu, 29 Mar 2007 15:11:44 GMT
 

> -----Original Message-----
> From: Dan Diephouse [mailto:dan@envoisolutions.com] 
> Sent: 28 March 2007 18:39
> To: cxf-dev@incubator.apache.org
> Subject: Re: [PROPOSAL] Client and Conduit changes
> 
> On 3/28/07, Glynn, Eoghan <eoghan.glynn@iona.com> wrote:
> 
> >
> > What do you mean by an "abstraction with boundaries of Conduits and 
> > Destinations"?
> >
> > Are the boundaries of which you speak:
> >
> > (a) the Conduit and Destination APIs
> > (b) the lifecycle of, and referers to, the Conduit and Destination 
> > instances
> > (c) something else?
> >
> > As far as I can see, we're *both* proposing changes that would fall 
> > mainly under category (b).
> >
> > Currently the Conduit lifecycle is managed by the Client. 
> And the DRE 
> > lifecycle is managed by the Conduit.
> >
> > You want to change things so that DRE is also managed by the Client.
> > Correct?
> >
> > I want to change things so that neither is managed by the Client.
> >
> > So I think it would be fair to say that we *both* see a 
> reason to go 
> > changing things. Just different things. Or?
> 
> 
> Sure, but its hard for me to know what is motivating your 
> proposal if you do come up with some specific use cases. I'm 
> glad to see that you daded a couple below.


I've expanded below on my (initially perhaps over-terse :) descriptions
of the use cases I've in mind.


> > I don't really see any reason to go changing this.
> >
> > See above.
> >
> > And here's a specific reason ...
> >
> > Having the Client create a Conduit before its actually 
> definite that a 
> > Conduit is required makes it awkward for an interceptor in the 
> > outbound chain to:
> >
> > (a) divert the message in such a way that doesn't require a 
> Conduit at 
> > all
> 
> 
> I have no idea what you're getting at here. Can you please 
> give a use case?


Yes, see below.


> That statement is kind of circular... of course if a conduit 
> is required, you won't be able to divert a message in a way 
> that doesn't require a conduit. 


Just as an aside, I don't agree that my statement was in the least
circular. I'm talking about the case where a Conduit *isn't* required.
But either way, lets not get bogged down on a tangent :)


> But where are you diverting it? 


The diversion would be driven by an interceptor, to a target within the
local process space.


> How do you want to divert?


By dynamically manipulating the trailing interceptor chain.


> Why?


To avoid unnecessary dispatch overhead where the target exists within
the client process space.


> (b) divert the message to a different endpoint, that maybe 
> necessitates
> > a different Conduit instance to the one selected up front by the 
> > Client
> 
> 
> This is where I was going with the Camel example... We could 
> send a message off to camel (or any other routing thingy - 
> synapse or mule might be options for people too). Or if we 
> want to route inside the interceptor chain we can select a 
> new Conduit in any interceptor. Then the 
> MessageSenderInterceptor can use this new Conduit. If you're 
> tyring to change the destination after the 
> messagesenderinterceptor - i.e. mid serialization, I don't 
> think thats very feasible for most bindings/messages.


Sure.

My point all along has been that MessageSenderInterceptor is the place
where we should be retrieving the Conduit. See [1], paragraph beginning:
"I'm thinking we may not even need a Conduit instance at all when
mediating an invocation ...".

I totally agree that it would be *too late* to try to switch Conduits at
a later point in the dispatch, in mid-serialization as you correctly put
it.

And conversely, setting up the Conduit in the Client.invoke() is IMO
*too early* in general. We're only 100% sure we need a Conduit when we
get to a point in outbound interceptor chain that actually needs to use
a Conduit for something. This point is the MessageSenderInterceptor. So
my proposal is to defer getting the Conduit unless and until this point
is reached. 

Call it just-in-time Conduit retrieval. And as with any just-in-time
strategy, the pay-off is in avoiding wasted effort when it turns out
that its not really needed, or something else is needed instead. 

The "its not really needed" case would occur when we detect during the
dispatch that marshalling and transport involvement are not required. 

The "something else needed instead" case could occur in your "route
inside the interceptor chain" example above.

But I wouldn't necessarily preclude upfront setting up of the Conduit in
the Client in the non-default case. For example your convenience
Client.setConduit() API to allow the application to easily over-ride the
Conduit for some reason. So retrieval of the Conduit in the
MessageSenderInterceptor could be contingent on a specific Conduit not
having being overridden via the Client. Would that make it more
acceptable to you?

 
> Once again, what are your use cases here? Please supply some 
> specific scenarios which require the removal of a Conduit.


I have two specific use-cases in my mind, which I labeled (a) and (b) in
my last mail.

I've already expanded on (a) above. Is that clear now?

Case (b) is where I want to be able to dynamically switch to a different
Conduit from within the interceptor chain. Among many other potential
uses, this would facilitate late-binding to one of a cluster of target
endpoints.

 
> > For instance, I've been talking to James Strachan about using
> > > Camel a bit.
> > > Camel can do a bit of routing of CXF messages. On the 
> Client side of 
> > > things, we should be able to send a message in and then get the 
> > > response some time later from Camel (if there is a response). The 
> > > idea is that it can work on whatever the representation - pojos, 
> > > xml, bytes, etc. The boundary into this system from the client 
> > > perspective would still be a transport. Camel can just add a 
> > > MessageObserver on a local:// destination. How the message comes 
> > > into Camel then becomes a matter of the Binding.  For the 
> POJO case, 
> > > I'd like to create an ObjectBinding which doesn't do any 
> > > serialization. It'd also be nice to have a flag so the 
> SOAP binding 
> > > produce a Source object ultimately.
> >
> >
> > Sorry I don't really see the relevance of this to the current 
> > discussion.
> >
> > Maybe I'm just being slow today :)
> >
> > Can you explain why the Camel requirement necessitates the type of 
> > changes you're proposing?
> 
> 
> I was simply talking about how mediation would be possible 
> with Camel as you had stated that one of the requirements for 
> mediation was the removal of the Conduit from the Client 
> class. The example was to show that removing the Conduit is 
> not necessariliy required.
> 
> >
> > > Lets compare the two cases of setting up a decoupled 
> endpoint from 
> > > an XML configuration perspective.
> > >
> > > Case 1: now
> > >
> > >
> > >     <http:conduit id="{
> > > http://cxf.apache.org/greeter_control}GreeterPort.http-conduit">
> > >       <http:client DecoupledEndpoint="
> > > http://localhost:9995/decoupled_endpoint"/>
> > >     </http:conduit>
> > >
> > > Case 2:My Proposal
> > > 2a) No Client: No XML configuration is needed, unless 
> you're using 
> > > JMS.
> >
> >
> > No XML configuration is needed? So you're proposing a (client-less,
> > HTTP-based) application must hard-code the DRE address?
> >
> > What happens if I reorganize by domains? Or my DHCP lease 
> expires? Or 
> > I'm assigned a new port range? Or I discover a port clash with some 
> > other piece of software? Or my firewall config is changed? 
> Or the NATS 
> > setup is changed? Or I want to provision the client app to 100s or 
> > 1000s of different hosts without recompiling for each? Or 
> the client 
> > app is migrated to a new host? Or the server app is 
> migrated off-host 
> > so that a localhost-based DRE no longer works?
> 
> 
> I see what your saying, but...
> 
> They can just put it in their application configuration. If 
> they're already working with CXF they probably have their own 
> configuration which will drive their application - whether 
> its UI or database or Spring based.


Finally, we're on the same page :)

That's been my whole "undue burden on client-less applications" point
all along.

Under your proposal we'd be giving such applications extra work to do
... work that is currently handled on its behalf via the Conduit config.

Now if the application already has a config mechanism (UI or database or
Spring based as you say), then extending this with a new DRE config item
may not be a huge task. 

On the other hand however, the application may currently work perfectly
fine without any application-specific config at all, or the
config/DB/UI/whatever may be difficult to change.

So you do see now why I think your proposal would impose an extra burden
on such applications?

 
> Also, the number of people attempting to understand the 
> transport API or write transports will be much greater than 
> those trying to write decoupled applications without the 
> Client. Sure, I have no statistics to back that up, but I do 
> have a fair amount of experience in the area. Most people 
> won't even setup a decoupled endpoint. And the majority of 
> people who do use decoupled endpoints will use the Client.
> 
> I would definitely wager a large sum of money that there are 
> more people trying to grok or write transports than those 
> writing decoupled applications without a Client. By an order 
> of magnitude at least. So I have yet to see why this argument 
> should carry that much weight.
> 
> 
> > >
> > > When you use the Client, yes, the Client adds some convenience 
> > > wrapper methods. When you don't use the Client, you 
> always use the 
> > > destination apis to set up the decoupled endpoint.
> >
> >
> > OK, can we be 100% clear here. What exactly are these convenience
> > wrapper methods?
> >
> > Are you proposing new APIs on Client such as 
> setFaultToEndpoint() and
> > setAcksTo()?
> 
> 
> No, just the 
> setAsyncrhronousDestination/setAsyncryhronousEndpoint in my
> original proposal.


Great, we've established that.

So how would your proposed mechanism be any more consistent when it
comes to setting the faultTo and/or acksTo versus the replyTo?

In *both* the current scenario and in your prospoal, a *different*
mechanism is used to set faultTo and/or acksTo versus the replyTo.

Hence, both approaches are equally inconsistent on this point.

Which is fine by me, as I've argued before that only the replyTo is
canonical.

 
> > > Is introducing an abstract ConduitPolicy really that big an issue?
> > >
> > >
> > > YES! We've already created very complex APIs for transports.
> > > Its time to simplify.
> >
> >
> > But the complexity you take away with one hand, you add 
> back with the
> > other ... i.e. you're proposing adding a bunch of complexity to the
> > Client.
> >
> > Now I'd anticipate your counter-argument as something like 
> ... yes but
> > we want developers to write their own transports, not their 
> own clients.
> > Fair enough, but I'm saying that transport-writers need not 
> be concerned
> > with handling the DRE logic if its factored out to the 
> AbstractConduit.
> 
> 
> You're completely missing the point. The point is that the 
> whole CONCEPT of
> Conduits and Destinations are overly complex. 


I suppose where I'm coming from is that there are different ways of
mitigating/hiding that complexity.


> To understand AbstractConduit you still need to understand Conduit.


Have you got that backwards, i.e. to understand Conduit you still need
to understand AbstractConduit?

If so, I don't think this is necessarily true. One purpose of an
abstract base classes is encapsulation of complexity. That is, a writer
of a sub-class doesn't have to be familiar with the implementation of
the super-class, just the contract between them (i.e. the stuff that's
protected and/or abstract in Java terms).

For example a trivial implementation of Conduit.getBackChannel()
currently lives in AbstractConduit. This allows someone writing a new
non-decoupled transport to completely ignore the decoupled backchannel
concept.

Now supposing we go a bit further and add code to the AbstractConduit
that creates the DRE (via the DestinationFactory) if a new abstract
ConduitPolicy is configured appropriately.

Then someone writing a transport that *does* have a concept of decoupled
back channel, which can set up solely on the basis of an EPR, also has
no extra work to do. That is, they also can just completely ignore the
decoupled backchannel concept.


> So AbstractConduit doesn't really helpin that regard.

Wouldn't what I've proposed above be helpful, or?

/Eoghan


[1]
http://mail-archives.apache.org/mod_mbox/incubator-cxf-dev/200703.mbox/%
3cFA1787F64A095C4090E76EBAF8B183E071FCAF@emea-ems1.IONAGLOBAL.com%3e

Mime
View raw message