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: Proposal for Decoupling and Issues with CXFServlet
Date Thu, 18 Jan 2007 14:08:28 GMT
 

> -----Original Message-----
> From: Dan Diephouse [mailto:dan@envoisolutions.com] 
> Sent: 17 January 2007 20:19
> To: cxf-dev@incubator.apache.org
> Subject: Re: Proposal for Decoupling and Issues with CXFServlet
> 
> OK, still thinking about #1 here and the ramifications of 
> what that would mean. Question: do you really only need one 
> config for the scenario you raised? I think it might be two. 
> First your client http-conduit config:
> 
>     <bean name="{
> http://apache.org/hello_world_soap_http}SoapPort.http-conduit"
> abstract="true">
>         <property name="client">
>             <value>
>                 <http-conf:client DecoupledEndpoint="
> http://localhost:9000/decoupled_endpoint"/>
>             </value>
>         </property>
>     </bean>
> 
> Second your Jetty Destination config:
> 
> <bean name="org.apache.cxf.transport.http.JettyServerEngine.9000"
> abstract="true">
>    <property name="listener">
>        <value>
>            <http-conf:listener>
>                <MaxThreads>5</MaxThreads>
>            </http-conf:listener>
>        <value>
>    </property>
> </bean>

Sure there are two config beans required (which is just an artefact of
how the HTTP config schema was organized) ... but the point is that they
are both transport-level config, and are thus more likely to be
considered by the user as a group, and modified as such.
 
> (Upon further looking at the code though I don't think its 
> even possible to supply configuration to your decoupled 
> destination right now.
> setupDestination operates directly on the JettyServerEngine 
> and doesn't supply any configuration.)

Well, HTTPConduit.setupDecoupledDestination() calls the static
JettyHTTPServerEngine.getForPort() factory method, which then applies
Configurer.configure() to the newly created JettyHTTPServerEngine. So
the HTTPListenerConfigBean stuff will have been injected, and the
MaxThreads setting should apply.

So I think this is actually OK.

What is missing though is the SSLServerPolicy. Normally this is injected
into the JettyHTTPDestination in the first instance and then passed onto
JettyHTTPServerEngine.getForPort(). We're going to have to figure some
other way of getting a handle on this in the decoupled case (which has a
listener but not a destination from the point of view of HTTP config).
Maybe in this case, it's the SSLClientPolicy that should be applied to
the decoupled listener ... or more properly, we come up with a generic
SSLPolicy that can apply to both the HTTPconduit and
JettyHTTPServerEngine in the decoupled case.
 
> While one could specify a listener in the 
> SoapPort.http-conduit config, I don't think that would make 
> very much sense. You don't want to configure your MaxThreads 
> for the particular URL path, you want to configure it for the 
> whole Jetty instance on one particular port. So lets say I 
> want to listen for decoupled responses on the same port as 
> I'm listening for service requests on - port 80 (for firewall 
> reasons?). I want my MaxThreads to apply to all destinations 
> on that port, not just my one particular decoupled endpoint.  
> Hence you'll need two configurations.  I don't really see how 
> you could combine the two either. Am I missing something?

Nope, that's exactly why the HTTP destination and listener
configurations are specified separately.

The JettyHTTPServerEngines (which encapsulate a Jetty SocketListener)
are keyed on port, not on the particular URL path of an individual
destination.

Multiple URL paths with the same port also share the same listener, so
in this case the same max threads would be shared across the multiple
target URLs (whether decoupled response endpoints in the decoupled case,
or full-on Destinations). 

So I think this is covered.

> I'll concur on #2, replyTos on alternate transports are a bit 
> contrived.

Cool.
 
> For #3, I think its really just a matter of naming. You're 
> right, my proposed name of RMDestination gives the wrong 
> impression. But RMSupport, RMDestinationSupport, or 
> RMProtocolSupport or something similar wouldn't be bad. I 
> think it would be pretty clear that this isn't needed though 
> as it would be in an WS0RM package in the api module and 
> would be clearly documented as optional. Does that address 
> your concerns?

I'd be less against this if the RM association was dropped from the
name. 

So if we must have a sub-interface of Destination, how about something
generic like PartialResponder? 
 
> (FWIW, I don't think it would be all that worthwhile to add a 
> special interface at this point as the only case we would 
> need it is the two way partial response. Seems much simpler 
> to just put in a message.put(RESPONSE_CODE,
> 202) in RM like we do in SOAP for the time being. If we had 
> another transport which required special syntax we could add 
> extension points at that time.)

Ok we're just going to have to agree to disagree on this.

I really don't like setting the response code from outside the
transport.

There's also the issue that I pointed out before that its easier for the
JettyHTTPDestination to know that it's the HTTPTransportFactory it needs
to use as ConduitInitiator for the outgoing decoupled connection, wheras
obviously the WS-A layer would have to work this out for itself (maybe
requiring a getTransportId() or some-such on Destination).

/Eoghan

 
> - Dan
> 
> On 1/16/07, Glynn, Eoghan <eoghan.glynn@iona.com> wrote:
> >
> >
> > > -----Original Message-----
> > > From: Dan Diephouse [mailto:dan@envoisolutions.com]
> > > Sent: 15 January 2007 23:17
> > > To: cxf-dev@incubator.apache.org
> > > Subject: Re: Proposal for Decoupling and Issues with CXFServlet
> > >
> > > Hi Eoghan,
> > >
> > > I would say your characterizations about me desiring the 
> WS-A layer 
> > > to manage the transports correct. I'm not sure that I see 
> what the 
> > > big problem with this is though from your message. So I 
> want to take 
> > > a look at your objections to moving the decoupling out of the 
> > > transport layer:
> >
> > OK, let me explain further where the problems lie as I see it ...
> >
> > > 1. This would require configuration to be in the WS-A 
> layer instead 
> > > of the transport layer
> > >
> > > Putting this in the WS-A layer would be overly complex as 
> you imply. 
> > > But that isn't our only option. Most likely we would want this 
> > > configured as part of the Client/Server. Which is how most 
> > > frameworks do this actually.
> > > For example, I would create a Client with a ReplyTo EPR of 
> > > http://some/url.
> > > Most frameworks even make this part of the Client interface - 
> > > client.setReplyTo(new EPR(...));
> > >
> > > This really doesn't add any complexity - if anything it 
> simplifies. 
> > > Right now people need to create a separate configuration snippet 
> > > which is not only specific to the transport, but also to 
> the client. 
> > > For example:
> > >
> > > <bean
> > > 
> name="{http://apache.org/hello_world_soap_http}SoapPort.http-conduit"
> > > abstract="true">
> > >
> > > This bean is specific to both HTTP and a specific client 
> port. To me 
> > > it would be more intuitive to just embed their ReplyTo in an 
> > > existing client configuration, rather than require a 
> separate bean.
> > >
> > > <bean name="{http://apache.org/hello_world_soap_http}SoapPort"
> > > abstract="true">
> > >   <replyTo>htp://localhost/some/url</replyTo>
> > >    ... other configuration values which already exist are here 
> > > </bean>
> > >
> > > Not saying that should be the exact syntax, but I think 
> it makes my 
> > > point.
> >
> > My argument isn't based on complexity versus simplicity, rather on 
> > proper separation of concerns.
> >
> > My position is that the decoupled response endpoint is an aspect of 
> > the transport, not an aspect of the Client or the WS-A 
> layer. Hence it 
> > should be configured as such.
> >
> > Lets do a quick gedanken experiment, and consider what your 
> proposal 
> > would look like in a non-trivial case.
> >
> > Say I want to configure a decoupled replyTo, but my client 
> is running 
> > on a resource-poor platform so I need to ensure that the 
> embedded HTTP 
> > listener consumes no more than 5 threads when servicing the 
> incoming 
> > decoupled responses. Here's the sort of thing we'd end up with ... 
> > (Don't worry about the precise config syntax, its off the top of my 
> > head, so may be slightly off base)
> >
> > <bean name="{http://apache.org/hello_world_soap_http}SoapPort"
> > abstract="true">
> >    <replyTo>http://localhost:9000/some/url</replyTo>
> > </bean>
> >
> > <!-- a bunch of other config stuff -->
> >
> > <bean name="org.apache.cxf.transport.http.JettyServerEngine.9000"
> > abstract="true">
> >    <property name="listener">
> >        <value>
> >            <http-conf:listener>
> >                <MaxThreads>5</MaxThreads>
> >            </http-conf:listener>
> >        <value>
> >    </property>
> > </bean>
> >
> > Lets concentrate on what we've got here essentially ... two 
> displaced, 
> > yet intimately related, elements of config. This will end up being 
> > error-prone in practice.
> >
> > For example, consider what happens when I hit a port clash 
> with some 
> > other developer also running CXF demos against port 9000 on 
> the same 
> > host? I need to change my decoupled response endpoint to 
> listen on say 
> > 9001 instead. In order to do so, I need to remember to change two 
> > displaced elements of config (the client-level replyTo and the 
> > transport-level listener). Chances are I forget to change 
> the latter, 
> > and my 5 thread restriction is no longer honored.
> >
> > A contrived example? Well maybe so, but it demonstrates a general 
> > point ... related stuff should be 
> instantiated/managed/configured together.
> >
> 
> > > 2. WS-A wouldn't be knowledgable about whether or not a 
> ReplyTo EPR 
> > > is cabable of being used
> > >
> > > "From the physical contract (e.g. the target portType in 
> the WSDL), 
> > > WS-A would have no way of knowing that the server-side 
> would even be 
> > > capable of responing using such a replyTo EPR."
> > >
> > > Just because there is not currently a WSDL extension that enables 
> > > this scenario, doesn't mean that it shouldn't be 
> supported. What if 
> > > I want to receive a message via HTTP and respond via SMTP? So I 
> > > would consider not being able to have a ReplyTo with a different 
> > > transport a problem with the current code.
> > >
> > > Second, if we do move decoupling support out of the 
> transport layer, 
> > > this certainly doesn't change any functionality we have 
> now. It only 
> > > expands our functionality!
> > >
> > > (The only thing I can think of that this would make hard is a 
> > > scenario where a user doesn't create a ReplyTo EPR and we're 
> > > supposed to create a non-anonymous one for them. I'm not 
> sure that 
> > > we even support this now - do we? If we wanted to support this we 
> > > could add a Destination.getDestination() method to automatically 
> > > create a destination on a EPR of its choice.)
> >
> > Ouch, hoist by my own petard :)
> >
> > I intended the different-transport-in-replyTo argument to 
> demonstrate 
> > the fragility of your scheme, whereas you're probably thinking ... 
> > wow, this would give us extra flexibility!
> >
> > But is it worth having a 'feature' that just *might* work 
> if all the 
> > ducks line up?
> >
> > Remember we'd have *no way of knowing* that the server-side 
> is capable 
> > of understanding and/or acting upon a replyTo EPR for any other 
> > transport apart from that advertized in the target EPR or 
> WSDL portType or whatever.
> >
> > Even if we had an inkling that the server-side stack might 
> support say 
> > JMS as well as HTTP (regardless of fact that the target portType 
> > specifies only a HTTP URI), there's no standard JMS URI 
> scheme as yet 
> > ... so even if our suspicion that the server-side is 
> JMS-aware turns 
> > out to be correct, we still don't know if it understands whatever 
> > non-standard JMS URI we cook up for the replyTo.
> >
> > Even if we thought we were certain that the stack used on the 
> > server-side supports the different replyTo transport and definitely 
> > understands the URI scheme, we still can't be sure if this 
> particular 
> > instance of the server-side stack is configured/deployed in 
> such a way 
> > as to be capable of doing anything with the replyTo. For example it 
> > may have a pluggable architecture, and we'd have no way of 
> knowing if 
> > the required transport plugin was available. It could instead be a 
> > minimal deployment hosted by say a servlet container, 
> without support 
> > for any non-essential features or transports.
> >
> > The point is that all we have to go on is the physical contract 
> > exposed by the server-side, e.g. the WSDL. If we jump to any 
> > conclusions not directly supported by this contract, we're acting 
> > ultra vires ... and while it *may* work, its just as likely 
> to blow up in our face.
> >
> > Now the WS-A spec doesn't explicitly require that the outbound and 
> > inbound transports match. But I would argue that practical 
> > considerations support such a de facto restriction.
> >
> > And CXF isn't the only WS engine to take this position ... 
> Axis2 does 
> > also (see 
> > 
> http://mail-archives.apache.org/mod_mbox/ws-axis-user/200605.mbox/%3C0
> > 5668670AA9BAD4695A071CED7A496D201BFDE45@mclean.sra.com%3E
> > )
> >
> > > 3. Partial responses require transport specific semantics 
> (from an 
> > > earlier
> > > message)
> > >
> > > As we've already discovered on the other thread, this 
> isn't actually 
> > > true.
> > > We can just return with the default one way response code - 200.
> >
> > I'm sounding like a broken record now, but yet again, I 
> must point out 
> > that partial responses may be required for twoways as well 
> as oneways 
> > (I spelt out the reasons for this at length, and then some, in the 
> > thread "Identification of Partial Responses").
> >
> > So just because Systinet uses the 200 response code for partial 
> > response to oneways, it doesn't mean we can just fall back 
> to 200 for 
> > all partial responses, specifically it would make no sense for the 
> > partial response to a twoway. Again, I explained this before.
> >
> > > Even if we desired a special transport semantics this 
> could be done 
> > > more cleanly via an RMDestination interface which allowed 
> > > customization in a well contained method. It doesn't 
> follow that we 
> > > need partial responses in the transport layer because we 
> would need 
> > > to add transport specific semantics just as we wouldn't 
> put SOAP in 
> > > the transport layer.
> >
> > Again I don't see this as being any cleaner, in fact the 
> opposite. I 
> > feel sure that calling the separate interface "RMDestination" will 
> > cause a LOT more confusion.
> >
> > Why? Because it gives the false impression that the 
> reliability logic 
> > is hosted in the transport. Remember "RMDestination" is 
> label given by 
> > the RM spec to the endpoint that receives & ACKs incoming reliable 
> > messages. The receiver-side "reliability envelope" extends up and 
> > including the RMD, but no further ... once the message has 
> been ACKed 
> > by the RMD, its no longer within the domain of WS-RM and 
> may in fact 
> > be lost before the implementor up-call occurs. Giving the 
> impression 
> > that this window for message loss extends from the 
> transport upwards 
> > on the server-side would be completely wrong.
> >
> > OK, you say, lets call it RMTransport instead. But again 
> I'd consider 
> > this to be misleading. The transport isn't tied to RM, 
> instead it just 
> > happens to provide a generic service, the sending of partial 
> > responses. The only user of this service currently happens 
> to be RM, 
> > but that's the extent of the relationship between 
> RMTransport/Destination and RM.
> >
> > /Eoghan
> >
> > > --
> > >
> > > In summary, I'm not sure that I see any reasons why we 
> should keep 
> > > decoupling in the transport layer. And as I've said there 
> are many 
> > > reasons to move it out
> > > - It simplifies transport writing
> > > - It follows the principle of least astonishment [1]. I would not 
> > > expect as a transport writer to have to worry about WS-A/RM while 
> > > writing a transport
> > > - RM semantics should be in the RM module. This is the 
> same policy 
> > > we have for everything else - i.e. SOAP
> > > - Our HTTP decoupling is dependent on specific 
> implementations (i.e. 
> > > the client is dependent on Jetty)
> > > - ReplyTo on alternate transports aren't supported
> > >
> > > Regards,
> > > - Dan
> > >
> > > 1. http://en.wikipedia.org/wiki/Principle_of_least_astonishment
> > >
> > > On 1/15/07, Glynn, Eoghan <eoghan.glynn@iona.com> wrote:
> > > >
> > > >
> > > > > > Are you objecting just to the HTTPConduit having a 
> reference 
> > > > > > to the ServerEngine, or to the presence of a ServerEngine
> > > instance in
> > > > > > the client-side runtime?
> > > > > >
> > > > > > If the latter, how would the client-side arrange to receive
> > > > > decoupled
> > > > > > responses without some sort of HTTP listener being launched
> > > > > in-process?
> > > > > > Shouldn't this client-side HTTP listener re-use the
> > > > > server-side logic?
> > > > > > Or are you thinking that the client-side should only embed
> > > > > a minimal
> > > > > > HTTP listener (like nanoHTTPD)?
> > > > >
> > > > > Sorry if I wasn't clear. I'm objecting to maintaining 
> the server 
> > > > > side connection in the client code. And vis a versa.
> > > > > Instead of registering the Client MessageObserver like this:
> > > > >
> > > > > Destination d = conduit.getBackChannel(); // this 
> sets up a back 
> > > > > channel via the JettyHTTPServerEngine.getForPort(...)
> > > > > method d.setMessageObserver(client);
> > > >
> > > > Well that's not the way things work currently on the 
> client-side.
> > > >
> > > > We do not set a separate MessageObserver on the back-channel 
> > > > destination, whether decoupled or not.
> > > >
> > > > Instead, the MessageObserver already set for the Conduit is
> > > implicitly
> > > > also used for the back-channel. The ClientImpl just provides a
> > > > *single* MessageObserver, and the response messages are
> > > delivered to
> > > > this regardless of whether they arrived on the 
> back-channel of the 
> > > > outgoing client->server connection or on a separate
> > > server->client connection.
> > > >
> > > > The idea is that only the transport needs to be aware that it's 
> > > > configured in decoupled mode.
> > > >
> > > > The WS-A layer just asks the transport for a 
> back-channel URI. If 
> > > > something non-null is returned, this is encoded as the
> > > wsa:replyTo in
> > > > the outgoing message. Otherwise the fallback is the 
> anonymous URI.
> > > >
> > > > I think we've a different understanding of what the 
> primary task 
> > > > of the WS-A layer is, and where the division of 
> responsibilities 
> > > > vis- -vis the transport lies.
> > > >
> > > > My understanding is that job of the WS-A layer is to gather
> > > together
> > > > the information relating to addressing, and to encode 
> this in the 
> > > > out-going message. Some of this information is in the domain of 
> > > > the transport, such as the backchannel address, and the
> > > transport should
> > > > drive the creation of this. WS-A in my view simply provides
> > > a standard
> > > > transport-independent way of encoding transport-specific
> > > information.
> > > > In my view, the WS-A layer is is the aggregator, not 
> the instigator.
> > > >
> > > > You on the other hand, I think, see the WS-A layer in 
> the driving 
> > > > seat, causing the transport to create a particular 
> back-channel. 
> > > > Is that a fair characterization?
> > > >
> > > > > Just doing this instead:
> > > > >
> > > > > Destination d = destinationFactory.getDestination(replyToEPR);
> > > > > d.setMessageObserver(client);
> > > > >
> > > > > This would mean that any HTTP Destination could be 
> used with any 
> > > > > HTTP Conduit. It also simplifies the code as the http 
> > > > > conduits/destinations don't need to worry about each other.
> > > > > Is there a reason this wouldn't be possible?
> > > >
> > > > Not impossible, just not the best way of doing it IMO.
> > > >
> > > > For a start it would probably involve the WS-A layer being
> > > configured
> > > > with the replyTo EPR (instead of the transport, as is
> > > currently the case).
> > > >
> > > > In such a scenario, how would WS-A validate that the
> > > replyTo EPR even
> > > > makes any sense vis- -vis the outgoing transport? Supposing for 
> > > > example WS-A is configured with a JMS replyTo EPR, when 
> the target 
> > > > endpoint is HTTP-based. From the physical contract (e.g. the 
> > > > target portType in the WSDL), WS-A would have no way of knowing 
> > > > that the server-side would even be capable of responing 
> using such 
> > > > a
> > > replyTo EPR.
> > > >
> > > > > > >    -  As I mentioned above, RM has HTTP specific
> > > > > semantics and those
> > > > > > >    should be contained inside the RM module. This is the
> > > > > same policy
> > > > > > > we have
> > > > > > >    with things like the SOAP binding. This does not mean
> > > > > it has to
> > > > > > > be hardcoded
> > > > > > >    into the partial response logic. The RM module
> > > could discover
> > > > > > > different
> > > > > > >    transport specific logic. i.e. we could have an
> > > RMTransport
> > > > > > > interface
> > > > > > >    which has something like a "void 
> > > > > > > setupPartialResponse(Message)" method.
> > > > > >
> > > > > > Would this RMTransport be like a sub-interface of 
> Destination, 
> > > > > > that the RM layer would down-cast to as required?
> > > > > >
> > > > > > If so, any wouldn't transport that we're likely to want to
> > > > > run RM over
> > > > > > would have to implement RMTransport as opposed to
> > > > > Destination, so that
> > > > > > we end up in effect with as much (or as little,
> > > depending on your
> > > > > > point of view) RM pollution of the transport as before?
> > > > > >
> > > > >
> > > > > I think it could be done one of two ways. The first is as you 
> > > > > mention. I would imagine in this case the RMTransport 
> interface 
> > > > > would become part of the API module. The second would be
> > > to make it
> > > > > its own independent interface which is discovered like the 
> > > > > transports currently are. The first is probably easier.
> > > > >
> > > > > I don't think it would be equivalent to the current code.
> > > It would
> > > > > be in one well contained method, and isn't run unless we
> > > are doing a
> > > > > partial response in RM. It would also not need to be 
> implemented 
> > > > > unless a transport needed to support customizing a
> > > partial response
> > > > > - i.e. an HTTP 202 accepted response status. JMS 
> wouldn't need 
> > > > > to implement anything.
> > > > > Completely optional. Also my motivation for doing so would be 
> > > > > not only to remove the partial response handling, but 
> also the 
> > > > > decoupling support built into the HTTP transport as well (for 
> > > > > reasons I won't repeat...)
> > > >
> > > > Yep, there's an argument alright for allowing a transport
> > > opt out of
> > > > the whole partial response mechanism if its incapable 
> of providing 
> > > > those semantics.
> > > >
> > > > But this could be achieved more simply via some
> > > distinguished return
> > > > from Destination.backChannel(), e.g. just return null if the 
> > > > partialResponse parameter is non-null. As things currently
> > > stand, WS-A
> > > > would be tolerant to this and will simply avoid sending the
> > > partial response in this case.
> > > >
> > > > > > > Furthermore, I'm really not a fan of B, which makes me
> > > > > less inclined
> > > > > > > to like A.  Why?
> > > > > > >
> > > > > > >    - Encapsulating the decoupling logic complicates
> > > > > transports: For
> > > > > > >    instance, methods we've added for encapsulation of the
> > > > > decoupling
> > > > > > > include:
> > > > > > >    Conduit.getBackChannel(), Destination.getBackChannel(),
> > > > > > >    ConduitInitiator.getConduit(EndpointInfo,
> > > > > EndpointReferenceTarget).
> > > > > >
> > > > > > Well, I guess we could simplify things a bit by
> > > factoring out the
> > > > > > logic related to partial response into a separate
> > > sub-interface of
> > > > > > Destination (assuming that's what you intended with the
> > > > > suggested RMTransport).
> > > > > >
> > > > >
> > > > > I'm suggesting we
> > > > > - remove the Conduit.getBackChannel()
> > > > > - make Destination.getBackChannel() have no arguments 
> and only 
> > > > > return the anonymous back channel
> > > > > - remove the Conduit.getConduit(EndpointInfo,
> > > > > EndpointReferenceTarget) method
> > > > >
> > > > > This would move the decoupling support out of the 
> HTTP layer and 
> > > > > into the WS-A layer. That is the WS-A layer would be
> > > responsible for
> > > > > creating a non anonymous ReplyTo conduit, setting up 
> a decoupled 
> > > > > Client destination, etc.
> > > >
> > > > I disagree with this division of responsibility between 
> WS-A and 
> > > > transport. See above for reasoning.
> > > >
> > > > > > I'm not sure I understand how you'd intend to get 
> away without 
> > > > > > worrying about a decoupled Destination on the
> > > client-side ... how
> > > > > > would the client be capable of receiving decoupled 
> responses?
> > > > > >
> > > > >
> > > > > I'm not trying to get rid of the decoupled Destination.
> > > > > Simply trying to move the decoupling logic elsewhere.
> > > Does the above
> > > > > help explain what I mean better?
> > > >
> > > > Yep, I see where you're going, but don't agree :)
> > > >
> > > > Cheers,
> > > > Eoghan
> > > >
> > >
> > >
> > >
> > > --
> > > Dan Diephouse
> > > Envoi Solutions
> > > http://envoisolutions.com | http://netzooid.com/blog
> > >
> >
> 
> 
> 
> --
> Dan Diephouse
> Envoi Solutions
> http://envoisolutions.com | http://netzooid.com/blog
> 

Mime
View raw message