cxf-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Dan Diephouse" <...@envoisolutions.com>
Subject [PROPOSAL] Client and Conduit changes
Date Fri, 16 Mar 2007 22:19:49 GMT
For those of you who haven't been following the long discussion Eoghan and I
have been having, I'm going to take a moment to summarize my proposal here.
I consider it rather important. If we don't reach any consensus on the
proposal (it sucks/doesn't suck) or if Eoghan & I are the only ones who
participate, I'll probably start a vote. So do your communal duty and
participate so I don't have to do that! :-)

I propose the following:

1. API to set an Asynchronous EndpointReference
I believe we should create a simple method on the Client which allows the
user to specify the asynchronous endpoint that they wish to have used for
decoupled responses:

Client.getAsynchronousEndpoint(EndpointReferenceType epr);

The Client would check to see if this EPR was set. If so, it would call
DestinationFactory.getDestination(epr) for the EPR and use that as the
asynchronous destination. This would result in a standard way to
automatically set up the decoupled destination when using the API.

While it has been said that this isn't generic enough for JMS, I don't
agree. First, I believe that JMS will eventually get a self contained IRI
format which can be stuck in an EPR. We could even create our own
proprietary format. Second, JMS is an edge case. 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.

2. Access to the Conduits and Destinations
I would like to add the following methods to the Client:

void setConduit(Conduit) - this allows a user to easily specify an alternate
Conduit.
void setAsynchronousDestination(Destination) - this allows a user to easily
specify a decoupled endpoint. It's address would be used for WS-Addressing
interactions. If no Async destination exists, then the Client will only
listen on the Conduit.
Destination getAsynchronousDestination() - utility method to easily get the
asynchronous destination

3. Client.close();
We need a way to shutdown the decouled endpoints (regardless of whether or
not #1 & #2 are adopted). I think there is pretty good conensus we need a
Client.close() method which will do this. It will call getConduit().close()
and getAsynchronousDestination().shutdown().

(Ideally we'd like to be able to shut down RM at this same time. I'm going
to guess that this would require the addition of a client lifecycle
interface which allows RM to listen for Client.close(). This is an issue no
matter which route we go though, so I'll defer this conversation for another
thread)

4. Remove the setup of decoupled destinations from inside the Conduit
Currently, the Conduits are responsible for setting up the decoupled
destinations. We've already got a perfectly good API for creating
destinations, lets use it! Creating another API to create decoupled
destinations introduces inconsistencies into our APIs. Right now if you want
to create different endpoints for receiving ReplyTos and FaultTos you have
configure the ReplyTos using the Conduit API and the FaultTos using the
destination API. Creating those endpoints in different ways is bad IMO.

Putting in decoupled destinations inside the Conduit also makes it more
complex for transport writers or people trying to understand the API. IMO,
people intuitively expect this to be outside the Conduit class.

5. Client Configuration
I would propose that we make the decoupled destination configuration part of
the Client

<jaxws:client id="...SomePort">
  <jaxws:asynchronousEndpoint>
    <wsa:Address>http://my.decoupled/endpoint</wsa:Address>
  </jaxws:asynchronousEndpoint>
</jaxws:client>

<jaxws:client id="...SomePort">

<jaxws:asynchronousDestination><http:destination...></jaxws:asynchronousDestination>
</jaxws:client>

As an added bonus, we can now wire together clients and destinations however
we want. I wouldn't *have* to create a <conduit> config element with the
port name inside it. Instead I could simply do:

<jaxws:client id="...SomePort">
   <jaxws:conduit> <http:conduit... /> </jaxws:conduit>
</jaxws:client>

It also creates a central place to embed Client configuration - such as
enabling MTOM or configuring WS-*:
<jaxws:client id="...SomePort">
   <jaxws:conduit>...</jaxws:conduit>
   <jaxws:binding mtomEnabled="true">
     <jaxws:requestContext>
       <map><entry key="javax.xml.ws.session.maintain" value="true"/></map>
     </jaxws:requestContext>
   </jaxws:binding>
   <jaxws:features>
     <wsrm:reliability timeout="10000" .../>
   </jaxws:features>
</jaxws:client>

Users could still use the <http:conduit id="PORT"/> syntax if they wanted to
though.

(Note: I haven't written the jaxws:client Spring schema yet, but its on my
todo list. The feature stuff will hopefully be part of my commit with
WS-Security)

6. Bring back Destination.getDestination(EndpointReferenceType)
This method would be needed for the API that I propose in #1.

7. Make the JAX-WS dispatch use the client.

----

In summary:
a) This simplifies the API. We've created an API to set up decoupled
endpoints easily. We've reduced the complexity inside Conduits and have
avoided introducing new complexity onto the Conduit interface to specify a
decoupled destination.

b) It creates a consistent API for working with decoupled endpoints. There
is no reason to go writing a new API for setting up decoupled endpoints -
which is only used sometimes.

c) Dependency Injenction: By putting the Conduit & Destination on the Client
we've made it much friendlier to people using Spring or other DI containers.

d) Improved configuration: I think the jaxws:client is a more natural place
to setup the conduit and destination configuration as opposed to nesting the
destination configuration inside the conduit.

e) Setting up decoupled destinations is not the job of the conduit IMO.
We're giving Conduits a dual task unnecessarily. If all Conduits share the
same code for setting up decoupled destinations, that is a sign to me that
we can take it out of the Conduit.

I of course would be volunteering to do all this work.
--

Alternatives: While Eoghan can elaborate, I believe he would rather see
1. The decoupled endpoint remain part of the conduit. He views a decoupled
endpoint as part of the Conduit contract.
2. An API on the Conduit to set up the decoupled endpoint like so:
Client.get(Conduit.class
).getClientPolicy().setDecoupledEndpoint(EndpointReferenceType)
3. The Client.getConduit/setConduit methods go away and have the Conduit be
an optional part of the Client
4. No Client.setAsynchronousDestination method.
5. Keep the decoupled endpoint configuration as part of the conduit instead
of the client.

Regards,
- Dan

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

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