One of the ways to manage an instance's lifecycle in GT3 is through callback methods. These methods are called at specific points during an instance lifetime (such as instance creation and destruction).
Using callback methods is very simple. Our class must implement the GridServiceCallback interface, which includes all the callback methods. The following class implements all the callback methods:
// ... import org.globus.ogsa.GridServiceCallback; // ... public class MathImpl extends GridServiceImpl implements MathPortType, GridServiceCallback { // ... // Callback methods public void preCreate(GridServiceBase base) throws GridServiceException { super.preCreate(base); logger.info("Instance is going to be created (preCreate)"); } public void postCreate(GridContext context) throws GridServiceException { super.postCreate(context); logger.info("Instance has been created (postCreate)"); } public void activate(GridContext context) throws GridServiceException { super.activate(context); logger.info("Instance has been activated (activate)"); } public void deactivate(GridContext context) throws GridServiceException { super.deactivate(context); logger.info("Instance has been deactivated (deactivate)"); } public void preDestroy(GridContext context) throws GridServiceException { super.preDestroy(context); logger.info("Instance is going to be destroyed (preDestroy)"); } }
Add these modifications to $TUTORIAL_DIR/org/globus/progtutorial/services/core/logging/impl/MathImpl.java and save it as $TUTORIAL_DIR/org/globus/progtutorial/services/core/lifecycle/impl/MathImpl.java |
First of all, notice how we need to call the base class callback methods from our own callback methods. For example, in postCreate:
public void postCreate(GridContext context) throws GridServiceException
{
super.postCreate(context);
logger.info("Instance has been created (postCreate)");
}
It is important to do this so that the callback methods in GridServiceImpl (the base class) also get called. The GridServiceImpl callback methods take care of initializing a lot of internal values (including service data), so failing to call them will probably produce unexpected results.
However, we don't need to call the base class callback methods when using operation providers. Remember that operation providers don't extend from GridServiceImpl, but that the GridServiceImpl is still present 'in the background' (we specified this in the WSDD file). The grid services container makes sure that both the GridServiceImpl and operation provider's callback methods are called when necessary. |
Now, let's take a closer look at when each callback method is called:
preCreate : This method is called when a Grid Service starts the creation process. At this stage, its configuration has not been loaded.
postCreate : This method is called when a service has been created and all of its configuration has been set up.
activate : All Grid Services are in a 'deactivated' state by default (which means they still haven't been loaded into memory). This callback method is invoked when a service is activated.
deactivate : This method is called before a service is deactivated.
preDestroy : This method is called right before a service is destroyed.
The deployment descriptor will be very similar to the transient service's descriptor. The only important change is the GSH of the service and the baseClassName of the service (which is the class we've just programmed: the logging example's class plus the callback methods)
<?xml version="1.0"?> <deployment name="defaultServerConfig" xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"> <service name="progtutorial/core/lifecycle/MathFactoryService" provider="Handler" style="wrapped"> <parameter name="name" value="MathService Factory"/> <parameter name="instance-name" value="MathService Instance"/> <parameter name="instance-schemaPath" value="schema/progtutorial/MathService/Math_service.wsdl"/> <parameter name="instance-baseClassName" value="org.globus.progtutorial.services.core.lifecycle.impl.MathImpl"/> <parameter name="instance-className" value="org.globus.progtutorial.stubs.MathService.MathPortType"/> <!-- Start common parameters --> <parameter name="allowedMethods" value="*"/> <parameter name="persistent" value="true"/> <parameter name="handlerClass" value="org.globus.ogsa.handlers.RPCURIProvider"/> <parameter name="className" value="org.gridforum.ogsi.Factory"/> <parameter name="baseClassName" value="org.globus.ogsa.impl.ogsi.GridServiceImpl"/> <parameter name="schemaPath" value="schema/ogsi/ogsi_factory_service.wsdl"/> <parameter name="operationProviders" value="org.globus.ogsa.impl.ogsi.FactoryProvider"/> <parameter name="factoryCallback" value="org.globus.ogsa.impl.ogsi.DynamicFactoryCallbackImpl"/> </service> </deployment>
This file is $TUTORIAL_DIR/org/globus/progtutorial/services/core/lifecycle/server-deploy.wsdd |
Before compiling this service, since we have a new class that produces logging information, we need to enable logging for that class:
org.globus.progtutorial.services.core.lifecycle.impl.MathImpl=console,info
Add this line at the end of $GLOBUS_LOCATION/ogsilogging.properties |
Now, let's build the service:
./tutorial_build.sh \ org/globus/progtutorial/services/core/lifecycle \ schema/progtutorial/MathService/Math.gwsdl
And deploy it:
ant deploy \ -Dgar.name=$TUTORIAL_DIR/build/lib/org_globus_progtutorial_services_core_lifecycle.gar
Since our service uses a factory/instance model, the first thing we need to do is create an instance:
ogsi-create-service \ http://127.0.0.1:8080/ogsa/services/progtutorial/core/lifecycle/MathFactoryService
If you look at the server-side logs, you'll see the following: (verbosity removed for comfort)
INFO: Instance is going to be created (preCreate) INFO: Instance has been created (postCreate)
Now, let's access the service instance using the MathService client:
java \
-classpath ./build/classes/:$CLASSPATH \
org.globus.progtutorial.clients.MathService.Client \
http://127.0.0.1:8080/ogsa/services/progtutorial/core/lifecycle/MathFactoryService/HASH \
5
Remember to use the instance GSH returned by ogsi-create-service You should now see the following in the server-side logs:
INFO: Addition invoked with parameter a=5 INFO: getValue() invoked
These are the log messages produced by the add and getValue methods, which means no callback methods have been invoked while calling add and getValue.
Now, let's destroy the instance:
ogsi-destroy-service \
http://127.0.0.1:8080/ogsa/services/progtutorial/core/lifecycle/MathFactoryService/HASH
Remember to use the instance GSH returned by ogsi-create-service You should now see the following in the server-side logs:
INFO: Instance is going to be destroyed (preDestroy)