Managing State
Contents
How to publish the state
GCUBEProvider
Import GCUBEProvider WSDL inside the Stateful WSDL:
<definitions name="Stateful" targetNamespace="http://acme.org/sample" .... xmlns:wsdlpp="http://www.globus.org/namespaces/2004/10/WSDLPreprocessor" xmlns:wsrp="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.xsd" xmlns:provider="http://gcube-system.org/namespaces/common/core/porttypes/GCUBEProvider" /> <import namespace=http://gcube-system.org/namespaces/common/core/porttypes/GCUBEProvider location="../gcube/common/core/providers/GCUBEProvider.wsdl"/> ... </definition>
Include the GCUBEProvider in the list of providers on service WSDD:
<parameter name="providers" value="GCUBEProvider"/>
WS-Resource Property document
Declare the WS-Resource Property document in the Stateful WSDL:
<definitions name="Stateful" targetNamespace="http://acme.org/sample" ...> <types> <xsd:schema targetNamespace="http://acme.org/sample"> <xsd:import namespace="http://gcube-system.org/namespaces/common/core/types" schemaLocation="../gcube/common/core/types/GCUBETypes.xsd"/> <xsd:element name="aboutSF" type="coretypes:VOID" /> <xsd:element name="aboutSFResponse" type="xsd:string" /> <xsd:element name="Name" type="xsd:string"/> <xsd:element name="Visits" type="xsd:int"/> <xsd:element name="StatefulResourceProperties"> <xsd:complexType> <xsd:sequence> <xsd:element ref="tns:Name" minOccurs="1" maxOccurs="1"/> <xsd:element ref="tns:Visits" minOccurs="1" maxOccurs="1"/> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:schema> </types>
Port-Type definitions
Extend the Stateful port-type with the GCUBEProvider and declare in the port-type definition the Resource Property document:
<portType name="StatefulPortType" wsrp:ResourceProperties="tns:StatefulResourceProperties" wsdlpp:extends="provider:GCUBEProvider"> ... </portType>
Publication Profile
Provide a Publication Profile:
<ServiceGroupRegistrationParameters xmlns:sgc="http://mds.globus.org/servicegroup/client" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing" xmlns:agg="http://mds.globus.org/aggregator/types" xmlns="http://mds.globus.org/servicegroup/client"> <!-- Specifies that the registration will be renewed every 30 seconds --> <RefreshIntervalSecs>60</RefreshIntervalSecs> <!-- <Content> specifies registration specific information --> <Content xsi:type="agg:AggregatorContent"> <agg:AggregatorConfig> <agg:GetMultipleResourcePropertiesPollType xmlns:tutorial="http://acme.org/sample"> <agg:PollIntervalMillis>60000</agg:PollIntervalMillis> <agg:ResourcePropertyNames>tutorial:Name</agg:ResourcePropertyNames> <agg:ResourcePropertyNames>tutorial:Visits</agg:ResourcePropertyNames> </agg:GetMultipleResourcePropertiesPollType> </agg:AggregatorConfig> <agg:AggregatorData/> </Content> </ServiceGroupRegistrationParameters>
Save the profile as registration.xml and place it in the etc folder under the service location:
|-SampleService |--etc |---profile.xml |---deploy-jndi-config.xml |---deploy-server.wsdd |---build.properties |---registration.xml | |--src |---<omissis> | |--schema |---Stateless.wsdl |---Factory.wsdl |---Stateful.wsdl | | |--build.xml | |-Dependencies |--SampleService
Include the Publication Profile resource and the RPDName (Resource Property document name) in the stateful JNDI configuration:
<jndiConfig> <omissis> <service name="acme/sample/stateful"> <environment name="RPDName" value="StatefulResourceProperties" type="java.lang.String" override="false"/> <resource name="publicationProfile" type="org.gcube.common.core.state.GCUBEPublicationProfile"> <resourceParams> <parameter> <name>factory</name> <value>org.globus.wsrf.jndi.BeanFactory</value> </parameter> <parameter> <name>mode</name> <value>pull</value> </parameter> <parameter> <name>fileName</name> <value>@config.dir@/registration.xml</value> </parameter> </resourceParams> </resource> <resource name="home" type="org.acme.sample.stateful.Home"> <resourceParams> <parameter> <name>factory</name> <value>org.globus.wsrf.jndi.BeanFactory</value> </parameter> <parameter> <name>resourceClass</name> <value>org.acme.sample.stateful.Resource</value> </parameter> <parameter> <name>persistenceDelegateClass</name> <value>org.acme.sample.stateful.ResourcePersistenceDelegate</value> </parameter> </resourceParams> </resource> <environment name="frequentUserLimit" value="3" type="java.lang.Integer" override="false" /> </service> </jndiConfig>
How to persist the state
The gCore Framework comes with a persistence mini-framework implementing GCUBEStatefulResource
serialization and deserialization from/to some form of long-term storage.
Since the most expected exploitation of the persistence is to serialise/deserialise the state of a GCUBEWSResource
, the framework provides also some ready-to-use implementations of the abstract persistence delegate for GCUBEWSResource
to perform file-based persistence.
GCUBEFilePersistenceDelegate
The root file-based persistence class (GCUBEFilePersistenceDelegate
) is an abstract extension of a persistence delegate to add persistence to any GCUBEStatefulResource
derived class.
It configures the persistence storage folder as:
$HOME/.globus/persisted/$Container.ID/$ServiceName/$Resource.class/$ResourceID.extension
It implements resource de/serialization by calling the Resource-specific onLoad/onStore
methods
It has been specialized by the following classes:
-
GCUBELocalViewFilePersistenceDelegate
-
GCUBELRFilePersistenceDelegate
-
GCUBEWSFilePersistenceDelegate
-
GCUBEWSLiteFilePersistenceDelegate
To enable the persistence of a GCUBEWSResouce, a new class extending the GCUBEWSFilePersistenceDelegate
has to be created:
package org.acme.sample.stateful; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import org.gcube.common.core.persistence.GCUBEWSFilePersistenceDelegate; public class ResourcePersistenceDelegate extends GCUBEWSFilePersistenceDelegate<Resource>{ protected void onLoad(Resource resource,ObjectInputStream ois) throws Exception { super.onLoad(resource,ois); resource.setName((String)ois.readObject()); resource.setVisits((Integer)ois.readObject()); } protected void onStore(Resource resource,ObjectOutputStream oos) throws Exception { super.onStore(resource,oos); oos.writeObject(resource.getName()); oos.writeObject(resource.getVisits()); } }
Notes:
- the class extends the
GCUBEWSFilePersistenceDelegate
class by parametrising the extension with theResource
class - the class implements the
onLoad()
andonStore()
methods - as first step, they MUST call their
super
implementation - then, they store/load the
Resource
class state, i.e. the Name and Visits properties' values
How to enable persistence
As most of gCore Framework facilities, GCUBEResource Persistence can be enabled by modifying the gCube Service JNDI file by declaring in the Home resource the persistence delegate class to use:
<jndiConfig xmlns="http://wsrf.globus.org/jndi/config"> ..... <service name="acme/sample/stateful"> <environment name="RPDName" value="StatefulResourceProperties" type="java.lang.String" override="false"/> <resource name="home" type="org.acme.sample.stateful.Home"> <resourceParams> <parameter> <name>factory</name> <value>org.globus.wsrf.jndi.BeanFactory</value> </parameter> <parameter> <name>resourceClass</name> <value>org.acme.sample.stateful.Resource</value> </parameter> <parameter> <name>persistenceDelegateClass</name> <value>org.acme.sample.stateful.ResourcePersistenceDelegate</value> </parameter> </resourceParams> </resource> </service> </jndiConfig>