cxf-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Dan Diephouse" <...@envoisolutions.com>
Subject Re: Proposal for Decoupling and Issues with CXFServlet
Date Wed, 17 Jan 2007 20:19:24 GMT
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>

(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.)

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?

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

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?

(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.)

- 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/%3C05668670AA9BAD4695A071CED7A496D201BFDE45@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
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message