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 Fri, 30 Mar 2007 10:31:32 GMT
 

> -----Original Message-----
> From: Dan Diephouse [mailto:dan@envoisolutions.com] 
> Sent: 30 March 2007 01:52
> To: cxf-dev@incubator.apache.org
> Subject: Re: [PROPOSAL] Client and Conduit changes
> 
> On 3/29/07, Glynn, Eoghan <eoghan.glynn@iona.com> wrote:
> >
> >
> >
> > > 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.
> 
> 
> Unnecessary dispatch overhead? By calling Conduit.open() and 
> close()? Are you just trying to avoid serialization?


Direct quote from my last mail ...

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

So clearly I'm not *just* talking about calls to Conduit.open() and
close() ... 

On an aside, an open() method doesn't exist in the Conduit API, but I
assume you mean here the ConduitInitiator.getConduit() call.

What I'm talking about is avoiding *any and all* overhead that would be
unnecessary if the message is not leaving the current process space.
That overhead includes the getting the Conduit, marshalling the message
payload & headers, and possibly applying transformations such as
encryption or compression.

Now originally you stated a strong objection to just-in-time retrieval
of the Conduit. You then asked for my use-cases. Which I described
briefly. You asked for more detail. Which I provided. 

So can we now steer the discussion onto the substantive point of whether
it's a good idea to defer the Conduit retrieval until we know its
actually needed?


> *snip*
> >
> > 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.
> 
> 
> In general? 


Yes, in general. 

In the sense that in many cases its OK to get the Conduit in
Client.invoke(), but in other cases it doesn't make sense to do so.

So in general its not the right thing to do.


> In retrieving a Conduit inside the Client creates 
> no problems.


Other than wasted effort, and possibly a premature failure (depending on
how the ConduitInitiator.getConduit() is implemented).


> If we don't ultimately use this Conduit, this shouldn't be 
> any issue. Any resource intensive operations should be 
> delayed until open() is called.


As it happens, that is the case with all our extant Conduit
implementations.

However, it may not be the case for all future Conduit implementations,
and its certainly not part of the Conduit contract as-is.

I could for example envisage a defensively-coded Conduit probing the
target upfront in its ctor so as to fail-fast if a connection would be
impossible to establish. 

I can also envisage resources to be shared across Conduit instances
being set up in the initial ConduitInitiator.getConduit() call, as
opposed to being deferred to the first Conduit.send().

Of course we could spell out a requirement that a Conduit implementation
doesn't do any heavy-lifting until the first send() occurs. But I could
see potential transport authors thinking, why doesn't the CXF runtime
just avoid making the ConduitInitiator.getConduit() call if its not sure
it needs the Conduit? 

Your arguments are often based on making life easier for potential
transport-writers. And here's a case where we can avoid imposing an
ambiguous post-condition on ConduitInitiator.getConduit(). By
"ambiguous", I meaning adding javadoc like "don't do anything resource
intensive until Conduit.send() is called". Whether the transport author
respects this is not verifiable (we're not coding in Eiffel), also it
could be open to mis-interpretation (e.g. would 'resource intensive'
include pulling in config values?).

 
> 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?
> 
> 
> My point is that a user should just be able to do 
> client.getConduit() and change some transport settings. They 
> shouldn't have to explicitly create the Conduit though, which 
> is what your proposal does.
> 
> What about just a ClientImpl.setInitializeConduit(false)?


That would be fine if the default for initializeConduit was false (as I
don't think the application should have to make an explicit API call to
get the correct, IMO, behavior).

Also I guess you'd probably want to extend your <client> config bean
with an <initializeConduit> property (and similarly, I'd advocate false
as the default value).


> > 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.
> >
> > > >
> > > > 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?
> 
> 
> Sure, but see my previous message for why this isn't really a 
> big a deal as you make it out to be.
> 
> > 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.
> 
> 
> I see what you're saying, and if you're comparing the Client 
> to the Conduit, then thats true. But I'm specifically talking 
> about the use case where people are just working with the 
> transport APIs and not the Client. At a transport level, this 
> would give a consistent way to do things. I.e. if I'm just 
> using the Conduit and Destination APIs, there would be a 
> consistent API for setting up decoupled endpoints.
>
>
> > > 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.
> 
> 
> Yeah, but they're still going to look at the Conduit 
> interface and wonder about what that method is. And on the 
> other side of things, as a user of the Conduit interface you 
> still need to understand Conduit.getBackChannel(). And then 
> if we don't go down the route of removing decoupled 
> destinations from the Conduit, they'll also have to 
> understand the ConduitPolicy interface.
> 
> Do you see my point now?


I suppose it just doesn't seem like that big an issue to me, especially
if we make it clear in the javadoc that getBackChannel() only needs to
be overridden in very specific circumstances.

Similarly, the transport-writer doesn't really have to worry about the
mechanics of the ConduitPolicy. Beyond knowing that it factors out some
commonality, and they should extend in their config schema *if* they
need transport-specific conduit config.

Cheers,
Eoghan



Mime
View raw message