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: Client API, EPRs
Date Tue, 13 Mar 2007 13:50:38 GMT
 

> -----Original Message-----
> From: Dan Diephouse [mailto:dan@envoisolutions.com] 
> Sent: 12 March 2007 20:18
> To: cxf-dev@incubator.apache.org
> Subject: Re: Client API, EPRs
> 
> On 3/12/07, Glynn, Eoghan <eoghan.glynn@iona.com> wrote:
> >
> >
> >
> > > -----Original Message-----
> > > From: Dan Diephouse [mailto:dan@envoisolutions.com]
> > > Sent: 11 March 2007 21:48
> > > To: cxf-dev@incubator.apache.org
> > > Subject: Re: Client API, EPRs
> > >
> > > Hola,
> > >
> > > Apologies for the lag here. Too much traveling going on 
> and I wanted 
> > > to spend some time thinking through this some more.
> > >
> > > Some comments inline.
> > >
> > > On 3/6/07, Glynn, Eoghan <eoghan.glynn@iona.com> wrote:
> > > >
> > > >
> > > >
> > > > Hi Dan,
> > > >
> > > > Well if CXF is embedded in another product that *already*
> > > exposes an
> > > > endpoint (e.g. a HTTP listsner) from the client process space, 
> > > > then CXF could use that to receive decoupled responses.  All the
> > > app needs
> > > > to do is to provide an appropriate EPR via 
> > > > AddressingProperties.setReplyTo (), set this on the request
> > > context,
> > > > and the CXF WS-A layer won't over-write this with any decoupled 
> > > > response endpoint that may (or may not) have been
> > > configured on the Conduit.
> > > >
> > > > However, I don't think its reasonable to expect CXF to 
> *actively* 
> > > > launch a decoupled response endpoint on the basis of a 
> replyTo EPR 
> > > > provided by the application, for a number of reasons:
> > > >
> > > > 1. the replyTo EPR may not contain all the info that 
> the transport 
> > > > needs to initiate receipt of incoming messages, e.g. 
> JMS may need 
> > > > stuff like a username/password for the connection factory,
> > > maybe a JNDI provider etc.
> > > > This sort of transport-specific stuff may not be suitable for 
> > > > shoe-horning into an EPR, and would probably need to be
> > > configured in
> > > > a transport-specific way.
> > >
> > >
> > > First, thats an edge case.
> >
> >
> > JMS is an edge-case?
> 
> 
> In the sense that:
> a) Most people use HTTP
> b) Soon we should have a mechanism to stuff all this stuff into an EPR
> c) There are other transports beside just JMS and HTTP, like 
> XMPP or TCP or FTP which work just fine with URIs. JMS is the 
> odd ball in the sense that historically it has needed stuff 
> outside the EPR.


Sure JMS is different, but that doesn't make it an edge-case that we can
disregard.

Its only seems like an odd-ball because all the other transports are
connection-oriented URI-friendly protocols.

If we had more MOM-style transports in CXF, it would seem like less of
an exceptional case.

 
> > Second, people are defining
> > > standards to shoe-horn JMS info into IRIs.
> >
> >
> > Be that as it may, but as things currently stand, JMS needs 
> more than 
> > a URI.
> 
> 
> Whats your point? 


My point is as stated ... right now JMS needs more than a URI,
regardless of any as yet incomplete standardization efforts.


> As I stated in point #3 if they absolutely 
> needed to they could fall back to configuring a specific 
> destination if they wanted via XML or the API.


And as I stated, that would seem to defeat the purpose. 


> > Third, when the
> > > decoupled destination is being set up it can still pull 
> > > configuration from xml files if people need to add extra 
> > > configuration info.
> >
> >
> > Wouldn't that defeat your stated purpose? (i.e. not having to do 
> > transport-specific config)
> 
> 
> Yes, I was simply stating this is a possibility if the user 
> needed to fall back to it. Hopefully they wouldn't need to.


Seems a lot simpler to me to drive this from config, which we know works
for every transport.

Actually, let me restate that ...

It would seem simpler to drive this via policies, that may be taken from
static config files, or equivalently may be dynamically set by the
application. I believe Andrea is using the latter approach to control
the decoupled endpoint(s) used in system test she's writing.

Maybe that would be a compromise that give the best of both worlds?

I would like to maintain some cardinality restriction on the
(automatically launched) decoupled response endpoint, by keeping it
per-Conduit as opposed to per-request (for reasons of lifecycle mgmt and
non-proliferation as I explained earlier on this thread).

But apart from that, I've no problem with the URI (or whatever the
transport needs) originating from the application code as opposed to the
cxf.xml.

 
> > 2. there's no guarantee that the replyTo EPR specified by the
> > > app makes
> > > > any sense, e.g. it may be for a different transport to that
> > > used for
> > > > the outbound request (and we discussed the 
> undesirability of mixed 
> > > > transport within an MEP on this list a while back).
> > >
> > >
> > > We should add checks to ensure that this is sane & valid 
> then. Its 
> > > not that hard to ensure that the ReplyTo transport is the same as 
> > > the outgoing one.
> > > We simply need to match up the transport IDs or the 
> protocol part of 
> > > the URL.
> > >
> > > 3. its hard to see how to manage the lifecycle of a 
> listener created 
> > > on
> > > > demand by CXF on foot of an application-provided replyTo.
> > > What if the
> > > > app specifies a different replyTo URI for each 
> sucessive request, 
> > > > maybe intending that the listener is a one-shot deal 
> (i.e. is only 
> > > > intended to accept a single decoupled response). There's no way 
> > > > for the app to communicate this intended lifecycle with CXF, so 
> > > > CXF wouldn't know when to shutdown the Destination.
> > > >
> > >
> > > Lets ignore the per request case a moment: How would this differ 
> > > from how things currently are?
> >
> > Well the intention was that the decoupled endpoint is 
> ref-counted, and 
> > then shutdown when the last HTTPConduit referencing it is closed.
> >
> > However, looking at the code, this intention seems to be 
> frustrated by 
> > two factors:
> > - Conduit.close() is not being called anywhere
> > - the ref count has morphed into being non-static
> >
> > Gonna have to fix that ...
> 
> 
> I think you're oversimplifying the issue. Either you're trying to:
> a) count the number of clients which are actively invoking. 
> In which case when I stop sending and then resume a minute 
> later you're going to have to start it all over again, which 
> wouldn't make a lot of sense. Especially in a single thread 
> scenario as it would be starting & stopping a server during 
> each invocation.
> 
> b) Implement a timeout mechanism. In which case it would work 
> equally well when setting a reply-to EPR on a Client.
> 
> c) Implement a refcount & timeout mechanism. i.e. if I call 
> close on my conduit, but another client still has the same 
> decoupled server/port open we would obviously want it to stay 
> up. Which once again works equally well when setting a reply 
> to EPR on the client.
> 
> d) Trying to call Conduit.close() when the client is being 
> GC'd. But there is no sure way to do this Java. Even if you 
> could, this would once again work equally as well when 
> setting an EPR on the Client.


There's no question of what's there being an attempt to be timeout-based
or reliant on GC.

Instead the idea in the original Celtix code was to use a reference
counting scheme for the decoupled response endpoint, and to allow this
to be shared across client transport instances. This was simply not
ported over properly to CXF. 

The original scheme worked as the HTTPClientTransport was created once
per binding instance, had well-defined shutdown semantics, and reused if
possible a pre-existing listener for the decoupled endpoint, even if
this was created from another HTTPClientTransport. This reuse was easy
to do as HTTPClientTransport registered the Jetty handler directly,
instead of going thru' the DestinationFactory, and thus could easily
check if a pre-existing handler was already registered.

 
> The issue is there is no great place to call Conduit.close(). 
> You need to do it once you're done with the client, but there 
> is no way to be sure of that.
> So the next best thing is to allow the user to do it them 
> selves and possibly auto-close/reopen if necessary.


Sure, giving the user the capability to shut down the Client explicitly
wouldn't be a bad thing.


> > Lets say I define a
> > > replyTo endpoint in my cxf.xmlfile. Its not going to get 
> shut down 
> > > until I specifically shut it down myself or until I shut the 
> > > appserver down. So letting CXF create a destination automatically 
> > > would not really be any different. It just makes it 
> easier for the 
> > > user to set up the decoupled endpoint via the API. Once they are 
> > > done with the client they could call
> > > Client.getDestination().shutdown()
> > > and release any resources.
> >
> >
> > I'm not sure it would be that simple.
> >
> > The user may have specified different decoupled destinations for a 
> > series of invocations mediated by the same Client instance.
> 
> 
> So are we going let these accumulate and then have a
> > close-all-in-one-fell-swoop type API on Client, say 
> > shutdownAllDestinations()?
> 
> 
> This is an issue *regardless of how you are setting up the decoupled
> destination.*  The only way to auto-close them is to combine 
> it with a refcount/timeout mechanism like I outlined above or 
> to have the user explicitly close them (either on a per 
> request or client lifecycle basis).
> 
> But that would have the effect of the client hogging 
> transport resources
> > (e.g. HTTP ports or JMS Destinations) for much longer than 
> necessary, 
> > i.e. for the period after the client has stopped using these as the 
> > replyTo for requests, but before the corresponding JAX-WS proxy or 
> > whatever goes away.
> >
> > Also there's the issue of what WS-RM uses as its acksTo 
> address. AFAIK 
> > this is still just the decoupled endpoint associated with 
> the Conduit.
> > However, it needs to continue to be available to receive 
> ACKs for the 
> > lifetime of the RM sequence. So we don't want the application to be 
> > able pull the rug out from under RM by specifying a 
> short-lived replyTo.
> 
> 
> There are a couple ways to solve this:
> - We can ref count the decoupled server endpoint. If the 
> client closed, there would still be an outstanding reference 
> to the server. So the server endpoint wouldn't close until RM 
> terminated its sequence and it called
> close() on the decoupled destination.
> - We could add extension points via a Client.close() API so 
> that RM could terminate the sequence and shut down the 
> decoupled destination when its called.
> 
> This brings up an interesting point: Currently I can only 
> associate a decoupled destination with a client's conduit 
> AFAIK. But this makes absolutely no sense to me - there are 
> many decoupled destinations that could be associated with a 
> client. For instance it might have a different acksTo then 
> ReplyTo. Or I might have a different FaultTo.


I don't think you're correct here. If I go and explicitly set the
replyTo to a Destination that I've created (via a DestinationFactory)
then this will be used for the <wsa:ReplyTo> in the outgoing message, as
opposed to the back-channel destination overwriting the explicit
setting. 

Similarly the acksTo could be set to any Destination, but RM just
happens to be implemented to use the back-channel destination for
convenience. By convenience, I mean it avoids the RM layer having to set
up a separate in-interceptor-chain to handle incoming out-of-band
messages.

The per-Conduit restriction only applies to *automatically launched*
decoupled response endpoints. The application can go nuts explicitly
creating response endpoints all over town if it wants ...

/Eoghan

Mime
View raw message