cxf-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Dan Diephouse" <...@envoisolutions.com>
Subject In Process Dispatch [was Re: [PROPOSAL] Client and Conduit changes]
Date Mon, 02 Apr 2007 03:45:15 GMT
On 4/1/07, Glynn, Eoghan <eoghan.glynn@iona.com > wrote:

> >
> > 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.
>
>
> Sure, I get what the local transport does.
>
> I'm talking about taking a different approach. That's allowed, right?


OK, let's reset here a moment. A different approach is definitely allowed.
Maybe you're right and we need to rearchitect some things. While the idea
may be crystalline clear in your head, I don't think there has been enough
information up to this point to really show that different mechanisms are
needed or how such alternate mechanisms would work. Depending on which
solution we go with, this could require significant changes to CXF, so I
think its good to be careful about this.

The local transport implies, as I understand it, a "static replacement"
> style of approach. So I specify a "local://" URI as the endpoint
> address, or my application explicitly sets a LocalConduit instance on
> the Client. Also I statically change my config or asserted polices to
> exclude interceptors that apply transformations unecessary in the local
> case, or change the interceptor impls to detect this case themselves.
> Also I engage an ObjectBinding in some way.
>
> Now that's all very well. But a different idea would be to go more for
> "adaptive diversion".
>
> Here the binding and interceptor chain would be set up exactly the same
> way, regardless of whether the target is local or remote. Where the
> target really is remote, then everything just works. If the target
> happens to be instantiated within the local process space, then I want
> to detect this and adapt accordingly, *without any static changes* (to
> config, WSDL, policies, code, whatever). Then maybe the target migrates
> to another container instance and everything reverts to work as before.


OK, this clarifies what you're looking to do for me quite a bit. If you're
looking to do an in process dispatch with an existing endpoint that has been
created (i.e. an HTTP endpoint) that is a completely different story. It
isn't very clear to me how the mechanics of such a thing would work. Could
you maybe supply a little more information about how you would see the
following working:

How would we determine if the endpoint is in the local process space? For
instance, if I have a Client talking to an HTTP Server endpoint, how does it
know to shortcut and talk to the server directly?

Would the Binding interceptors would be run?

Would your solution require the modification of the current binding
interceptors to support auto-detection of in process dispatch?

How do we determine which user level interceptors to run? Say I enable
WS-Security - what mechanisms would there be to determine that it should not
be run for the local invocation case?  Or what if a user writes a
transformation interceptor. How would the transformation be performed or
would it not be?

If a server requires HTTP security, will we just bypass it? For instance,
lets say that we have a website which communicates with its backend via a
soap service. The client uses the website's username/password to
authenticate against the server. If we just bypass that authentication, that
would be a security hole.

What if the server & the client use different databindings?

On the client side, when do we make the decision about whether or not the
endpoint is "in process"? During a client creation? Or during each
invocation? Can the decision happen mid invocation?

[First Impressions]
My first impression (based on what I understand you're trying to achieve at
this point) is that any solution:
a) Will require the use of different binding interceptors. Obviously we
don't want to go invoking soap interceptors for a local dispatch.
b) Will have some major affects on how their service is invoked and possibly
some security issues. It sounds like the user should make a conscious
decision about whether or not to use it.
c) Will have to make the decision about whether or not the Client is
invoking a local service or a remote service before the interceptor chain is
invoked. In other words, we will have to add logic to the Client to detect
this. If this is done during the interceptor chain we may already have
invoked binding interceptors.
d) Does not implicitly require that we ditch Conduits/Destinations for in
this type of in process dispatching (if you agree to b, I think this follows
relatively easily. Proposed solution below.)

[A proposed solution]
The client side is trickier. Its not clear to me that "detecting" that we
can use in process invocation is feasible or ultimately a good thing. Such a
thing makes me highly nervous. If we try to find a candidate for local
invocation based on the endpoint name, this could fail because there are
often multiple endpoints with the same name around. If we use the URL, this
may not work because we might be doing service routing and the URL may be
different. If we let the user do it, then this violates one of your stated
goals. There are also the tricky of issues as to whether or not the various
interceptors on the Client should be invoked (for instance ws-security) and
whether or not it was the user wants or intended. Are these all things we
want to occur by default? I will try to reserve judgment until I know more
about how you envision this selection logic working.

I like James's proposal of using a URI to invoke a service. This would imply
the creation of a ServiceConduit/ServiceDestination which understood URIs
such as started with endpoint:, interface:, etc. When the ServiceConduit
sends a message it would
- Find the appropriate service based on the URI (this has the limitation
that I mentioned above, namely you need to be careful about having services
with the same endpoint/service/interface name)
- Add the necessary interceptors to a chain (these would include the object
binding, endpoint, service, and bus interceptors)
- Set a ServiceDestination on the Exchange so the service can find the back
channel
- invoke the chain

These is completely transparent for the server side. However it does imply
that the user selects a different URI on the Client side. This seems like a
good thing so the user is conscious of there being an in process dispatch.
If this is ok, then it is just a hop-skip & jump since the user can just
select a different port or request a different URI.

So how could this work? I think we have two primary cases in which clients
are built: *ClientFactoryBeans and JAX-WS generated clients. The
ClientFactoryBean can auto-select the appropriate transport based on the
URI, so that is simple enough. Or in code form:
cf = new ClientFactoryBean()
cf.setAddress("endpoint:{namespace}FooService");
cf.setServiceClass(MyServiceInterface.class);
cf.create();

Inside ClientFactoryBean there would need to be detection logic for these
types of URLs to automatically load the appropriate binding or the user
would need to specify the binding.

With JAX-WS it is easier, we can just hide this logic and auto create a
local port for clients to talk to. The user could call
clientService.getPort(new
QName("MyServiceLocal"), MyServiceInterface.class); Generated stubs could
also include a handy clientService.getLocalPort() method (if this isn't
allowed by the TCK by default, this could be a flag in the wsdl2java).

CXF is intended to be a flexible framework. The user community is, or
> hopefully will be, a broad church. So CXF will accommodate a diversity
> of user-level approaches. Right?


User level approaches, yes. However, these are core architecture changes
which would potentially have a large affect on our code, so I think there
deserve a fair amount of scrutiny.

Regards,
- Dan

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

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message