7.2. Scheduled destruction

Scheduled destruction is a more elaborate form of resource lifecycle management, as it allows us to specify exactly when we want the resource to be destroyed. The main application of scheduled destruction is to perform lease-based lifecycle management, where we initially set the destruction time of a resource some time in the future (for example, 5 minutes). This is called the lease. Our application must periodically renew the lease (setting the destruction time another 5 minutes in the future), or the resource will eventually be destroyed. This will allow our application to purge resources that for some reason (network failure, programmer errors, etc.) have become unavailable (and therefore can't receive the lease renewal).

Using scheduled destruction requires adding more code that immediate destruction because the standard WSRF portType that provides scheduled destruction not only adds a new operation (SetTerminationTime) but also two new resource properties: TerminationTime and CurrentTime. TerminationTime specifies when the resource is set to be destroyed, and the value of CurrentTime must always be the time in the machine that hosts the resource. This means that, not only will we have to modify the WSDL file, we will also have to make sure those two new resource properties are properly implemented in our resource class.

7.2.1. The WSDL file

So, let's start with the easy part. To use scheduled resource termination, our portType must extend from the ScheduledResourceTermination portType:

<portType name="MathPortType" 
    wsdlpp:extends="wsrpw:GetResourceProperty 
                    wsrlw:ScheduledResourceTermination" 
    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>
[Note]

As seen in immediate destruction, we mustn't forget to declare the WS-ResourceLifetime namespace (wsrlw), and import its WSDL file.

7.2.2. The resource implementation

Next, we have to implement the ResourceLifetime interface in our resource class. This interface requires that we provide get/set methods for the TerminationTime and CurrentTime RPs.

public class MathResource implements Resource, ResourceIdentifier,
		ResourceProperties, ResourceLifetime

So, we'll start by adding a terminationTime attribute of type Calendar to our class to represent the resource's termination time. We don't need to add a currentTime attribute because that RP's get method will always return the system's time (which, as we'll see, we can easily obtain using the Java API).

/* Resource properties */
private int value;
private String lastOp;
private Calendar terminationTime;

Now, we have to make sure we add the two RPs to our resource's RP set:

/* Initializes RPs and returns a unique identifier for this resource */
public Object initialize() throws Exception {
	this.key = new Integer(hashCode());
	this.propSet = new SimpleResourcePropertySet(
			MathQNames.RESOURCE_PROPERTIES);
		
		try {
		ResourceProperty valueRP = new ReflectionResourceProperty(
				MathQNames.RP_VALUE, "Value", this);
		this.propSet.add(valueRP);
		setValue(0);
			
		ResourceProperty lastOpRP = new ReflectionResourceProperty(
				MathQNames.RP_LASTOP, "LastOp", this);
		this.propSet.add(lastOpRP);
		setLastOp("NONE");
			
		ResourceProperty termTimeRP = new ReflectionResourceProperty(
				SimpleResourcePropertyMetaData.TERMINATION_TIME, this);
		this.propSet.add(termTimeRP);
					
		ResourceProperty currTimeRP = new ReflectionResourceProperty(
				SimpleResourcePropertyMetaData.CURRENT_TIME, this);
		this.propSet.add(currTimeRP);
		
	} catch (Exception e) {
		throw new RuntimeException(e.getMessage());
	}
	
	return key;
}

Notice we use a Globus-supplied SimpleResourcePropertyMetaData class which includes information on the TerminationTime and CurrentTime RPs. We must make sure we import this class:

import org.globus.wsrf.impl.SimpleResourcePropertyMetaData;

Finally, the last thing needed in the resource implementation is to add a get and set method for the TerminationTime RP, and a get method for the CurrentTime RP (we can't 'set' the current time). Notice how we return the current time using an instance of the Java Calendar class.

/* Required by interface ResourceLifetime */
public Calendar getCurrentTime() {
	return Calendar.getInstance();
}

public Calendar getTerminationTime() {
	return this.terminationTime;
}

public void setTerminationTime(Calendar terminationTime) {
	this.terminationTime=terminationTime;
}
[Note]

This is part of file $EXAMPLES_DIR/org/globus/examples/services/core/rl/impl/MathResource.java

7.2.3. Deployment

As we did in immediate destruction, we need to add a Globus-supplied operation provider, SetTerminationTimeProvider, to the instance service. This provider implements the setTerminationTime operation that will allow us to set the resource's termination time. Note that we cannot set the termination time by directly modifying the TerminationTime RP (using, for example, the SetResourceProperties operation). We must use the setTerminationTime operation (this operation, as implemented in the Globus-supplied operation provider, does more than just update the RP).

<parameter name="providers" value="GetRPProvider SetTerminationTimeProvider"/>
[Note]

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

We can also modify the JNDI deploy file to control how often the container will check if a resource is past its termination time. This is done with the sweeperDelay parameter, specified in milliseconds. The default value is to check every one minute (60000 milliseconds). We will change this value to one second (1000 milliseconds) so our client will be able to observe how the resource does, in fact, expire.

<parameter>
	<name>sweeperDelay</name>
	<value>1000</value>
</parameter>
[Note]

This is part of file $EXAMPLES_DIR/org/globus/examples/services/core/rl/deploy-jndi-config.xml.

Finally, build and deploy:

./globus-build-service.sh rl
globus-deploy-gar $EXAMPLES_DIR/org_globus_examples_services_core_rl.gar

7.2.4. The client

We will test our service by creating a new resource, setting its termination 10 seconds in the future, and then checking every second to see if the resource is still 'alive'. When the resource is terminated, any call to the resource will produce an exception. Like the immediate destruction client, this client is similar to the simple client seen in Chapter 5, Multiple resources. The following is the code that we will run after the resource has been created:

1
Calendar termination = Calendar.getInstance();
termination.add(Calendar.SECOND, 10); 

2
SetTerminationTime request;
SetTerminationTimeResponse response;
request = new SetTerminationTime(termination);
response = math.setTerminationTime(request);

3
System.out.println("Current time               "
		+ response.getCurrentTime().getTime());
System.out.println("Requested termination time "
		+ termination.getTime());
System.out.println("Scheduled termination time "
		+ response.getNewTerminationTime().getTime());

boolean terminated = false;
int seconds = 0;
while (!terminated) { 4
	try {
		System.out.println("Second " + seconds);
		math.add(10);
		Thread.sleep(1000);
		seconds++;
	} catch (RemoteException e) {
		System.out.println("Resource has been destroyed");
		terminated = true;
	}
}

[Note]

This is part of file $EXAMPLES_DIR/org/globus/examples/clients/FactoryService_Math_rl/Client_sched.java

1

We get an instance of the Calendar class, which contains the current time. We add 10 seconds to it. This will be the termination time of our resource.

2

We make a call to the SetTerminationTime operation, sending the new termination time.

3

The response from the SetTerminationTime operation returns interesting information: the resource's current time and the scheduled termination, which might differ from the requested termination time (in simple scenarios like the one we are trying out now, this will not happen).

4

Finally, this loop makes a call to the add operation every second. When the resource is finally destroyed, and an exception is thrown, we exit the loop.

Compile and run the client:

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

If all goes well, you should see the following:

Created instance.
Current time               Sun Apr 03 00:54:29 CST 2005
Requested termination time Sun Apr 03 00:54:39 CST 2005
Scheduled termination time Sun Apr 03 00:54:39 CST 2005
Second 0
Second 1
Second 2
Second 3
Second 4
Second 5
Second 6
Second 7
Second 8
Second 9
Second 10
Resource has been destroyed