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



> -----Original Message-----
> From: Dan Diephouse [mailto:[EMAIL PROTECTED]
> Sent: 30 March 2007 01:52
> To: [email protected]
> Subject: Re: [PROPOSAL] Client and Conduit changes
>
> On 3/29/07, Glynn, Eoghan <[EMAIL PROTECTED]> 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.


Yes, my bad.

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,


Overhead in getting the Conduit happens only once at Client creation.  And
in the case of a local invocation it really results in just a call to new
LocalConduit(), which I'm sure is not a bottleneck.

marshalling the message


A Conduit doesn't imply marshalling. For instance, I've outlined how we
could use an ObjectBinding (which we'd want to write for either case) with
the local transport. Currently the local transport requires you write to the
output stream, but this doesn't have to be so. I at least fixed the input
side so we can directly invoke a service, but more changes are needed.

payload & headers,


These are interceptors, and would be configured as part of the binding. And
hence in the local dispatch scenario they would not be part of the Binding,
and therefore would not be part of the interceptor chain.

and possibly applying transformations such as
encryption or compression.


These are up to the user to enable on their endpoint. I don't see why these
would be enabled if you're invoking a local endpoint.

This "overhead" that you're talking about seems completely unrelated to the
Conduit/Destination.

*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.


I don't see how that follows... In general it IS the right thing to do and
in some use cases that you outline it may not be the right thing to do. But
I'm not convinced yet that we can't just create a conduit in general and
then not use it.


> 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.


Now would be a good time to fix that.

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.


This would be bad. What if the target doesn't exist yet because the server
isn't fully intialized. We shouldn't be checking for existance until send()
is actually called.

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?


Because we want to make ClientImpl.getConduit() available to people. Seems
like a simple enough reason to me.

Your arguments are often based on making life easier for potential
transport-writers.


And transport users!

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?).


They can do some set up when the conduit is created. I don't think
transports will necessarily have that much over head providing they aren't
initializing connections. Since this only happens once when the Client is
created it shouldn't be a big deal.


>
> 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).


I'm sorry, but I can't ever be +1 on this.  We need to have the Conduit
created on the Client for the user by default.

>
> 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.


You're the one who wrote it though, so of course it makes sense :-). There
have been several other people though have noted that it is overly complex,
and I think we need to listen to them.

- Dan


--
Dan Diephouse
Envoi Solutions
http://envoisolutions.com | http://netzooid.com/blog

Reply via email to