cxf-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Tully, Gary" <Gary.Tu...@iona.com>
Subject RE: Support for stateful services in CXF
Date Wed, 04 Apr 2007 16:40:17 GMT
Hi Bernd, all,

I have been toying around with my default servant test cases and
implementing as I go. My test case determines if Numbers are even by
accessing a particular Number instance from a NumberFactory (via create)
and using the returned reference to invoke the isEven() operation.
Trivial but illustrative I hope. 
To make the implementation work/scale on the Server, a single stateless
servant represents all possible numbers and determines its current
identity based on the details of its current/target Endpoint Reference.

My client code does the following:

        NumberFactoryService service = new NumberFactoryService();
        NumberFactory factory = service.getNumberFactoryPort();


	  EndpointReferenceType numberTwoRef = factory.create("2");    
        
        NumberService numService = new NumberService();
A.      ServiceImpl serviceImpl =
ServiceDelegateAccessor.get(numService);
        
B.      Number num =  (Number)serviceImpl.getPort(numberTwoRef,
Number.class);
        assertTrue("2 is even", num.isEven().isEven());
   
Of interest here is:
A: JAX-WS is correctly particular about denying access to the underlying
implementation and with 2.1, EndpointReferences are first class citizens
so the need will no longer arise. Long term we probably need to start a
jax-ws-2.1-frontend. Short term, implementing the functionality in the
CXF implementation objects and providing this accessor is a fast win.
B: the ServiceImpl.getPort(EndpointReferenceType epr,..) simply uses the
address info of the epr to override the address of the EndpointInfo.
There is an issue with duplication of information between EndpointInfo
and EPRs in the Conduit that I will address in another post.


The Server side is more interesting.
NumberFactoryServiceImpl.create() needs to produce
EndpointReferenceTypes (EPRs) for the NumberService that identity a
particular number. First it inits and publishes a NumerServiceImpl
servant. On the trunk this requires working with EndpointReferenceUtils
to flesh out a valid EPR. My default implementation uses EPR
referenceParameters to contain the unique Id and WS-A to propagate the
target address. This has the advantage of being transport neutral but it
is over kill for some transports. For example, for a transport like http
or Yoko, it is possible to embed the unique Id into the endpoint
address, append it to the context in http (context match based on
startsWith) or for Yoko, burn it into a default servant object key. Then
the need for WS-A disappears. This pushes the detail of EPR creation
with a unique Id onto the transport/Destination.

I am thinking along the lines of an extension to Destination that
transports can optionally support.

/**
 * A MultiplexDestination is a transport-level endpoint capable of
receiving
 * unsolicited incoming messages from different peers for multiple
targets 
 * identified by a unique id.
 * The disambiguation of targets is handled by higher layers as the
target
 * address is made available as a context property or as a WS-A-To
header
 */

public interface MultiplexDestination extends Destination {
    
    /**
     * @return the a reference containing the id that is 
     * associated with this Destination
     */
    EndpointReferenceType getAddressWithId(String id);
    
   /**
     * @param contextMap for this invocation, for example from 
     * JAX-WS WebServiceContext.getMessageContext(). The context will
     * either contain the WS-A To content and/or some property that 
     * identifies the target address, eg MessageContext.PATH_INFO for
     * the current invocation
     * @return the id associated with the current invocation
     */
    String getId(Map contextMap);
}

The default implementation in AbstractMultiplexDestination can map the
uniqueId to an EPR referenceParameter and propagate via WSA in a
transport neutral way. AbstractHttpDestination can optionally override
the default to make use of the address context for a more efficient and
natural http implementation.

>From a users perspective, a unique server side epr would be
resolved/created from a existing published service using

   EndpointRefernceType epr = 
	
EndpointReferenceUtils.getEndpointReferenceWithId(NUMBER_SERVICE_QNAME,
         null, // portName
         uniqueId, 
         BusFactory.getDefaultBus());

Note: The portName should allow a particular port among many in a
service, to be identified.

Where EndpointReferenceUtils goes as follows:

public static EndpointReferenceType getEndpointReferenceWithId(QName
serviceQName, String portMame, String id, Bus bus) {
        EndpointReferenceType epr = null;
        ServerRegistry serverRegistry = (ServerRegistry)
bus.getExtension(ServerRegistry.class);
        List<Server> servers = serverRegistry.getServers();
        for (Server s : servers) {
            QName targetServiceQName =
s.getEndpoint().getEndpointInfo().getService().getName();
            if (serviceQName.equals(targetServiceQName)) {
                Destination dest = s.getDestination();
                if (dest instanceof MultiplexDestination) {
                    epr =
((MultiplexDestination)dest).getEndpointReferenceWithId(id);
                break;
            }
        }
        return epr;

Also
 public static String getCurrentEndpointReferenceId(Map context, Bus
bus) {
    ...
 }

During an invocation (server dispatch) accessing the current target
EndpointReference needs a little work however. The JAX-WS MessageContext
Map contains all the required information as properties. The
MultiplexedDestination can use this information to locate and extract
the uniqueId for this current request. The use of Map in the api keeps
the EndpointReferenceUtils front-end neutral and the
MultiplexedDestination transport neutral.


Having to traverse the list of registered services in is a bit
cumbersome, would it be possible to have services registered by Service
QName? Or would that restrict us to single instance services. It could
be map<QName, List<Service>>.


Bernd, does this nail your use case? 

All, Does it make sense? 

Comments appreciated, I would like to further this into a proposal in
the near future.

Thanks,
Gary.



> -----Original Message-----
> From: Bernd Schuller [mailto:b.schuller@fz-juelich.de] 
> Sent: 23 March 2007 13:13
> To: cxf-dev@incubator.apache.org
> Subject: Re: Support for stateful services in CXF
> 
> Hi Gary,
> 
> thanks a lot for your reply.
> 
> Tully, Gary wrote:
> > 
> > Only yesterday I started to investigate providing simple 
> support for a 
> > single instance service that can represent many WS-addressing 
> > identities.
> > 
> > What I am after at the moment is a simpler version of what is 
> > supported by @Stateful in the JAX-WS RI. The only state is 
> a unique-id 
> > that is encapsulated in the WS-Address.
> 
> That looks like a starting point...
> 
> [...]
> 
> > At the moment I am capturing the FactoryPattern use-case as 
> a system 
> > test in order to provide a starting proof-point for an 
> implementation.
> > 
> > The use of WS-Context (thanks Sergey) or HTTP session 
> information as a 
> > means of determining unique id would be neat but I think this is 
> > orthogonal.
> 
> agreed.
> 
> > From a WS-RF point of view, what are the usage scenarios 
> that you will 
> > need? Do they lend them selves to capture as system tests?
> 
> The basic scenario is approximately
>   - allow for instance creation on a stateful service, for 
> example using a
>     Factory service
>   - deal with state, e.g. persist instances to some permanent storage
>   - manage instance lifecycle, manage their lifetime, destroy them
>   - allow clients to access instances by EPR / WS-Addressing 
> This can be captured by system tests, I guess.
> 
> > Like you, I am learning as I go here, so any input is appreciated, 
> > especially your ideas on improving @Stateful and your experiences 
> > doing something similar with Xfire.
> 
> My main improvements on the JAX-WS RI @Stateful would be to 
> try and make the whole instance resolving process, instance 
> lifecycle management and EPR creation much more flexible, and 
> give more control to the application programmer.
> Of course all this should fit in as nicely as possible in the 
> CXF environment, which I unfortunately don't know much about yet...
> 
> In my XFire implementation, things were fairly easy, because 
> I could hook into the mechanism that XFire uses to get the 
> service object (the Invoker). Figure out the unique id from 
> the message context, re-create the requested service instance 
> from permanent storage, restore its state, and invoke the operation.
> 
> Maybe something similar can be done in CXF.
> 
> > As I am only starting on my quest for a design, you may as 
> well give 
> > it a try from your perspective. We can swap ideas or experiences to 
> > come up with a working solution. It need not be a race :-)
> 
> Perfect!
> 
> Thanks, and best regards,
> Bernd.
> 
> 
> >> -----Original Message-----
> >> From: Bernd Schuller [mailto:b.schuller@fz-juelich.de]
> >> Sent: 23 March 2007 07:36
> >> To: CXF devel
> >> Subject: Support for stateful services in CXF [...] I was 
> wondering 
> >> about whether you think it is a good idea to add support 
> for stateful 
> >> services to CXF.
> [...]
> 
> --
> Dr. Bernd Schuller
> 
> Central Institute for Applied Mathematics Forschungszentrum 
> Juelich GmbH
> 
> mail  b.schuller@fz-juelich.de
> phone +49 2461 61 8736
> fax   +49 2461 61 6656
> blog  http://www.jroller.com/page/gridhaus
> 
> 

Mime
View raw message