cxf-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Polar Humenn <phum...@iona.com>
Subject Re: [PROPOSAL] Client and Conduit changes
Date Mon, 19 Mar 2007 14:24:32 GMT
I've got a couple of CXF architectural questions.

Must be a Client in order for there to be an invocation 
request/response/fault/ack protocol? Does the client that send the 
invocation request get notified of the response, fault, or ack? How are 
the responses (many?) are correlated to the client invocation.

Is there actually an object called a "Request" that does this 
correlation? Should there be?

When I send a "reply-To" or "fault-To" or "ack-To" property is that on 
single message? Or is it on a single connection (for many messages)? 
What is the request/response correction based on? Is there an object in 
CXF that represents it, or is that done by the Client, the Conduit, or 
something else?

Cheers,
-Polar

Glynn, Eoghan wrote:
> My position is that the Conduit should continue to hold to the reference to, and manage
the lifecycle of, the decoupled response endpoint (DRE).
>
> Without rehashing the entire thread, my reasons briefly are:
>
> 1. Separation of concernsApache CXF - logged to http://dev.rectang.com/logs/codehaus/%23cxf/
>
> The DRE is an aspect of the transport and thus should be created and referenced from
within the realm of the transport.
>
> On the other hand, the purpose of the Client is to set up interceptor chains and dispatch
the invocation. Such invocations may NOT require a DRE, or even a Conduit for that matter.
Thus I think it inappropriate for the Client to be concerned with the creation of the DRE,
and would even go one step further and move the Conduit creation to the MessageSenderInterceptor,
so that a Conduit comes into being only if it really is needed.    
>
>
> 2. Avoid forcing the usage of a Client instance
>
> In general, if A is to be responsible for maintaining a reference to B, then its reasonable
to expect that the existence of a B implies the existence of an A. Otherwise, in some cases
an instance of A will have be artificially created, solely to manage the reference to B. 

>
> But if a DRE is in use, then the *only* other thing we're guaranteed also exists is the
corresponding Conduit.
>
> IMO we should neither require the usage of a Client instance to mediate invocations,
nor impose any undue burden on applications that choose to wire up the interceptor chains
directly and initiate dispatch themselves.
>
> An example of an undue burden would be forcing such applications to either always create
the DRE *programmatically* via DestinationFactory.getDestination(), or if they want the DRE
to be specified declaratively, to manage this configuration themselves.  
>
>
> 3. Suitability for JMS
>
> In order to setup a Destination, JMS may require more information than can be easily
shoe-horned into an EPR. Stuff like a JNDI provider, ConnectionFactory username/password etc.

>
> Now I don't accept the JMS as odd-man-out argument, especially when most of the counter-examples
wheeled out (i.e. XMPP, TCP, FTP) do not currently even exist as CXF transports. I could just
as easily make up a list of non-existent transports that suggests that the URI-friendliness
of HTTP is the exceptional case, but obviously you'd argue my list was hypothetical and proved
nothing. And you'd be right :) 
>
> Neither does the "most people just use HTTP" line wash with me. One of the design centres
of CXF is to be a multi-transport stack, and that in my book amounts to more than just paying
lip-service to non-HTTP transports.  
>
>
> Also I'd like to respond quickly to a couple of specific points that Dan makes in his
proposal:
>
> "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."
>
> So how would this be any different under your proposal? Is the implication that in addition
to a Client.setAsynchronousEndpoint() API, you'd also add Client.setFaultToEndpoint() and
Client.setAcksToEndpoint(), and similarly expose <faultToEndpoint> and <acksToEndpoint>
elements in your proposed <client> bean?
>
> If so, this would expose *way* too much of WS-A and WS-RM semantics directly in the Client,
which should IMO be independent of such QoS concerns. The CXF WS-A and WS-RM layers were specifically
designed to be pluggable, so that they could slotted into the runtime without impact on the
core APIs. I would be strongly against a move that breaks this ... I mean, what next, Client.setSecurityPolicyToken()??
>
> If on the other hand, if you're not suggesting polluting the Client with those aspects
of WS-A & WS-RM, can you explain how your proposal provides a consistent mechanism for
specifying the faultTo & acksTo vis-à-vis the replytTo?
>
> Another point which I strongly disagree with:
>
> "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've never come across a design principle that suggests having common code in a common
base class is a sign that such code should be moved elsewhere. In fact what purpose do common
base classes serve, other than to factor out commonality from sub-classes?
>
> Cheers,
> Eoghan
>
>   
>> -----Original Message-----
>> From: Dan Diephouse [mailto:dan@envoisolutions.com] 
>> Sent: 16 March 2007 22:20
>> To: cxf-dev@incubator.apache.org
>> Subject: [PROPOSAL] Client and Conduit changes
>>
>> 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:as
>> ynchronousDestination>
>> </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
View raw message