7.1. Immediate destruction

Immediate destruction is the simplest type of lifecycle management. It allows us to request that a resource be destroyed immediately by invoking a destroy operation in the instance service. Notice how, even though the factory service is responsible for creating the resources, destruction must be requested to each individual resource through the instance service.

To add immediate destruction to our service, we simply need to extend from the standard WSRF ImmediateResourceTermination portType. This portType adds a destroy operation to our portType that will instruct the current resource to terminate itself immediately.

<portType name="MathPortType" 
    wsdlpp:extends="wsrpw:GetResourceProperty 
                    wsrlw:ImmediateResourceTermination" 
    wsrp:ResourceProperties="tns:MathResourceProperties">

	<operation name="add">
		<input message="tns:AddInputMessage"/>
		<output message="tns:AddOutputMessage"/>
	</operation>
        
	<operation name="subtract">
		<input message="tns:SubtractInputMessage"/>
		<output message="tns:SubtractOutputMessage"/>
	</operation>

</portType>

To be able to do this, we must remember to declare the WS-ResourceLifetime namespace, and import its WSDL file:

<definitions name="MathService"
    targetNamespace="http://www.globus.org/namespaces/examples/core/MathService_instance_rl"
    xmlns="http://schemas.xmlsoap.org/wsdl/"
    xmlns:tns="http://www.globus.org/namespaces/examples/core/MathService_instance_rl"
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    xmlns:wsrlw="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceLifetime-1.2-draft-01.wsdl"    
    xmlns:wsrp="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.xsd"
    xmlns:wsrpw="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.wsdl"
    xmlns:wsdlpp="http://www.globus.org/namespaces/2004/10/WSDLPreprocessor"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<wsdl:import 
    namespace=
    "http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceLifetime-1.2-draft-01.wsdl"
    location="../../wsrf/lifetime/WS-ResourceLifetime.wsdl" />
[Note]

This is part of file $EXAMPLES_DIR/schema/examples/MathService_instance_rl/Math.wsdl

Next, we need to add the Globus-supplied DestroyProvider operation provider to the instance service. This provider implements the destroy operation mentioned above.

<?xml version="1.0" encoding="UTF-8"?>
<deployment name="defaultServerConfig" 
    xmlns="http://xml.apache.org/axis/wsdd/" 
    xmlns:java="http://xml.apache.org/axis/wsdd/providers/java" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">

    <!-- Instance service -->
    <service name="examples/core/rl/MathService" provider="Handler" use="literal" style="document">
        <parameter name="className" value="org.globus.examples.services.core.rl.impl.MathService"/>
        <wsdlFile>share/schema/examples/MathService_instance_rl/Math_service.wsdl</wsdlFile>
        <parameter name="allowedMethods" value="*"/>
        <parameter name="handlerClass" value="org.globus.axis.providers.RPCProvider"/>
        <parameter name="scope" value="Application"/>
        <parameter name="providers" value="GetRPProvider DestroyProvider"/>
    </service>

    <!-- Factory service -->
    <service name="examples/core/rl/MathFactoryService" provider="Handler" use="literal" style="document">
        <parameter name="className" value="org.globus.examples.services.core.rl.impl.MathFactoryService"/>
        <wsdlFile>share/schema/examples/FactoryService/Factory_service.wsdl</wsdlFile>
        <parameter name="allowedMethods" value="*"/>
        <parameter name="handlerClass" value="org.globus.axis.providers.RPCProvider"/>
        <parameter name="scope" value="Application"/>
        <parameter name="instance" value="examples/core/rl/MathService"/>
    </service>

</deployment>
[Note]

This file is $EXAMPLES_DIR/org/globus/examples/services/core/rl/deploy-server.wsdd.

Now, we can compile the service:

./globus-build-service.sh rl

And deploy it:

globus-deploy-gar $EXAMPLES_DIR/org_globus_examples_services_core_rl.gar

To try out resource destruction, we will use a client that is identical to the simple client seen in Chapter 5, Multiple resources. The only difference is that, at the end of the client we will add a call to the destroy operation.

package org.globus.examples.clients.FactoryService_Math_rl;

import org.apache.axis.message.addressing.Address;
import org.apache.axis.message.addressing.EndpointReferenceType;

import org.globus.examples.stubs.MathService_instance_rl.MathPortType;
import org.globus.examples.stubs.MathService_instance_rl.service.MathServiceAddressingLocator;
import org.globus.examples.stubs.Factory.service.FactoryServiceAddressingLocator;
import org.globus.examples.stubs.Factory.FactoryPortType;
import org.globus.examples.stubs.Factory.CreateResource;
import org.globus.examples.stubs.Factory.CreateResourceResponse;

import org.oasis.wsrf.lifetime.Destroy;

/* This client creates a new MathService instance through a FactoryService. This client
 * expects one parameter: the factory URI.
 */
public class Client_immed {

	public static void main(String[] args) {
		FactoryServiceAddressingLocator factoryLocator = new FactoryServiceAddressingLocator();
		MathServiceAddressingLocator instanceLocator = new MathServiceAddressingLocator();

		try {
			String factoryURI = args[0];
			EndpointReferenceType factoryEPR, instanceEPR;
			FactoryPortType mathFactory;
			MathPortType math;

			// Get factory portType
			factoryEPR = new EndpointReferenceType();
			factoryEPR.setAddress(new Address(factoryURI));
			mathFactory = factoryLocator.getFactoryPortTypePort(factoryEPR);

			// Create resource and get endpoint reference of WS-Resource.
			// This resource is our "instance".
			CreateResourceResponse createResponse = mathFactory
					.createResource(new CreateResource());
			instanceEPR = createResponse.getEndpointReference();

			// Get instance PortType
			math = instanceLocator.getMathPortTypePort(instanceEPR);

			System.out.println("Created instance.");

			// Perform an addition
			math.add(10);

			// Perform another addition
			math.add(5);

			// Perform a subtraction
			math.subtract(5);
			
			math.destroy(new Destroy());
			System.out.println("Destroyed instance.");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
[Note]

This file is $EXAMPLES_DIR/org/globus/examples/clients/FactoryService_Math_rl/Client_immed.java

Compile the client:

javac \
-classpath ./build/stubs/classes/:$CLASSPATH \
org/globus/examples/clients/FactoryService_Math_rl/Client_immed.java

And run it:

java \
-classpath ./build/stubs/classes/:$CLASSPATH \
org.globus.examples.clients.FactoryService_Math_rl.Client_immed \
http://127.0.0.1:8080/wsrf/services/examples/core/rl/MathFactoryService

If all goes well, you should see the following:

Created instance.
Destroyed instance.

Well, that wasn't too exciting, was it? How do we really now that resource destruction is actually happening? Well, there's a simple way of testing it. Modify the last lines of the client so they will look like so:

math.destroy(new Destroy());
System.out.println("Destroyed instance.");
			
// Perform another addition
math.add(5);

As you can see, we are going to try to invoke an operation after destroying the resource that operation is supposed to use. As you can probably imagine, no good will come of this. If you recompile the client and run it again, you should again see the following:

Created instance.
Destroyed instance.

And, then, a really nasty error message where you should be able to make out the following:

java.rmi.RemoteException: ; nested exception is:
        org.globus.wsrf.NoSuchResourceException

What has just happened is that the add has been invoked as normal. However, the endpoint reference that is being passed in the call refers to a resource that no longer exists. So, when add tries to retrieve the resource, a NoSuchResourceException is thrown.