University of Surrey / Date: 30/01/2006
Department of Computing
Introductory Grid Computing Tutorial Notes #3

Objectives:

This tutorial aims to teach:

  • Service Data in Grid Services

References:

For all the tutorial notes, you are expected to know the basics in Unix and Java. Please refer to the following tutorials for more information:

  • Unix Tutorial for Beginners:
  • Java Tutorials and Code Camps:
  • The Globus Toolkit 3 Programmer’s Tutorial:

You can download the tutorials from the course web page, which is:

You can download the tutorial files from:

Instead of writing the commands manually, you can refer to the online version of the tutorials. Please do not forget to change the host ip and port name accordingly in the commands, when it is necessary.

The implementations and the explanations were taken from The Globus Toolkit 3 programmer’s tutorial, which was written by Borjo Sotomayor.

Section I: Service Data in Grid Services

Service Data is a structured collection of information that is associated to a Grid Service. This information must be easy to query, so Grid services can be classified and indexed according to their characteristics. Service data is much less technical than WSDL and is easier to classify and index.

The client can choose thanks to the Service Data associated to each MathService. If the client needs the most powerful service, without any consideration to how much it will cost, then it will probably choose the mainframe. If the decisive factor is cost, then Server A will probably be the best choice. However, if the client wants to do some sort of statistic analysis, then Server C is the best bet. Of course, this is an over-simplification: usually the client won’t implement some complicated algorithm to query Service Data and choose a service. It will probably delegate that task on an index service, which will make the decision based on multiple criteria: speed, cost, availability, etc. The criteria are usually specific to each particular problem; in the ‘US city temperature’ example, the criteria might be ‘number of cities available’, ‘availability of temperature, humidity, pressure, etc.’, ‘frequency of updates’, etc.

Summing up, Service Data is an essential part of service discovery.

We will define one Service Data Element (SDE):

  1. Undeploy your previous project: (Directory: $HOME/gt3)

ant undeploy -Dgar.id=mathtutorial

Remove the schema files.

rm –r $HOME/gt3/schema/mathtutorial.core.factory

  1. Create a new directory called “servicedata” under $HOME/gt3/samples/.

cd $HOME/gt3/samples

mkdir servicedata

  1. Create the following directory structure (Directory: $HOME/gt3/samples/servicedata)

mkdir mathtutorial

cd mathtutorial

mkdir core

cd core

mkdir factory

cd factory

mkdir client

mkdir impl

mkdir schema

  1. Set the TUTORIAL_DIR environment variable to $HOME/gt3/samples/servicedata

setenv TUTORIAL_DIR $HOME/gt3/samples/servicedata

  1. Copy “MathImpl.java” to $TUTORIAL_DIR/mathtutorial/code/factory/impl.
  2. Copy Math.gwsdl to $TUTORIAL_DIR/mathtutorial/core/factory/schema.
  3. Copy MathSDE.xsd to $TUTORIAL_DIR/mathtutorial/code/factory/schema.
  4. Copy Math.wsdd to $TUTORIAL_DIR/mathtutorial/code/factory.
  5. Copy namespace2package.mappings to $TUTORIAL_DIR.
  6. Copy Client.java to $TUTORIAL_DIR/mathtutorial/core/factory/client.
  7. Deploy your service (Directory = $TUTORIAL_DIR)

ant -Dgwsdl.interface=true -Dpackage=mathtutorial.core.factory -Dinterface.name=Math -Dpackage.dir=mathtutorial/core/factory/ -Dgwsdl.interface=Math.gwsdl -Dsde.schema.file=MathSDE.xsd

You should change the WSDL file name in build/classes/

  1. Then, deploy your service into Globus container (Directory = $HOME/gt3).

ant deploy -Dgar.name=$TUTORIAL_DIR/build/lib/mathtutorial.core.factory.Math.gar

  1. Run your globus container and check whether your service is displayed.

globus-start-container –p $MYPORT

  1. Open another terminal. Then, compile and run your client (Directory = $TUTORIAL_DIR).

javac -classpath ./build/classes/:$CLASSPATH mathtutorial/core/factory/client/Client.java

  1. Create an instance from your service.

ogsi-create-service math1

  1. Run your client.

java -classpath ./build/classes/:$CLASSPATH mathtutorial/core/factory/client/Client ogsa/services/mathtutorial/core/factory/MathFactoryService/math1 5

If everything goes successful, you will see the following information:

·Logging is working

·Date: Sun Feb 06 20:45:36 GMT 2005

·Version: Apache-XML-Security-J 1.0.4

Value: 5

Previous operation: Addition

# of operations: 1

EXERCISE:

Add a service data element, called “subtractnum”, which will display the total number of called “subtract” operations.

CODES:

MathImpl.java

package mathtutorial.core.factory.impl;

import org.globus.ogsa.ServiceData;

import org.globus.ogsa.impl.ogsi.GridServiceImpl;

import org.globus.ogsa.GridContext;

import org.globus.ogsa.GridServiceException;

import mathtutorial.core.factory.Math.MathPortType;

import mathtutorial.core.factory.MathDataType;

import mathtutorial.core.factory.Math.*;

import mathtutorial.core.factory.bindings.*;

import mathtutorial.core.factory.service.*;

import java.rmi.RemoteException;

public class MathImpl extends GridServiceImpl implements MathPortType

{

private ServiceData mathDataSDE;

private MathDataType mathDataValue;

public MathImpl()

{

super(“Simple MathService with Service Data”);

}

public void postCreate(GridContext context) throws GridServiceException

{

// Call base class’s postCreate

super.postCreate(context);

// Create Service Data Element

mathDataSDE = this.getServiceDataSet().create(“MathData”);

// Create a MathDataType instance and set intial values mathDataValue = new MathDataType();

mathDataValue.setLastOp(“NONE”);

mathDataValue.setNumOps(0);

mathDataValue.setValue(0);

// Set the value of the SDE to the MathDataType instance

mathDataSDE.setValue(mathDataValue);

// Add SDE to Service Data Set

this.getServiceDataSet().add(mathDataSDE);

}

// This method updates the MathData SDE increasing the

// number of operations by one

private void incrementOps()

{

int numOps = mathDataValue.getNumOps();

mathDataValue.setNumOps(numOps + 1);

}

public void add(int a) throws RemoteException

{

mathDataValue.setLastOp(“Addition”);

incrementOps();

mathDataValue.setValue(mathDataValue.getValue() + a);

}

public void subtract(int a) throws RemoteException

{

mathDataValue.setLastOp(“Subtraction”);

incrementOps();

mathDataValue.setValue(mathDataValue.getValue() - a);

}

}

Math.gwsdl

<?xml version=”1.0” encoding=”UTF-8”?>

<definitions name=”MathService”

targetNamespace=”

xmlns:tns=”

xmlns:data=”

xmlns:ogsi=”

xmlns:gwsdl=”

xmlns:sd=”

xmlns:xsd=”

xmlns=”

<import location=”../../ogsi/ogsi.gwsdl”

namespace=”

<import location=”MathSDE.xsd”

namespace=”

<types>

<xsd:schema targetNamespace=”

attributeFormDefault=”qualified”

elementFormDefault=”qualified”

xmlns=”

<!--======-->

<!-- Addition -->

<!--======-->

<xsd:element name=”add” type=”tns:add”>

<xsd:complexType name=”add”>

<xsd:sequence>

<xsd:element name=”a” type=”xsd:int”/>

</xsd:sequence>

</xsd:complexType>

</xsd:element>

<xsd:element name=”addResponse” type=”tns:addResponse”>

<xsd:complexType name=”addResponse”/>

</xsd:element>

<!--======-->

<!-- Subtraction -->

<!--======-->

<xsd:element name=”subtract” type=”tns:subtract”>

<xsd:complexType name=”subtract”>

<xsd:sequence>

<xsd:element name=”a” type=”xsd:int”/>

</xsd:sequence>

</xsd:complexType>

</xsd:element>

<xsd:element name=”subtractResponse” type=”tns:subtractResponse”>

<xsd:complexType name=”subtractResponse”/>

</xsd:element>

</xsd:schema>

</types>

<message name=”AddInputMessage”>

<part name=”parameters” element=”tns:add”/>

</message>

<message name=”AddOutputMessage”>

<part name=”parameters” element=”tns:addResponse”/>

</message>

<message name=”SubtractInputMessage”>

<part name=”parameters” element=”tns:subtract”/>

</message>

<message name=”SubtractOutputMessage”>

<part name=”parameters” element=”tns:subtractResponse”/>

</message>

<gwsdl:portType name=”MathPortType” extends=”ogsi:GridService”>

<operation name=”add”>

<input message=”tns:AddInputMessage”/>

<output message=”tns:AddOutputMessage”/>

<fault name=”Fault” message=”ogsi:FaultMessage”/>

</operation>

<operation name=”subtract”>

<input message=”tns:SubtractInputMessage”/>

<output message=”tns:SubtractOutputMessage”/>

<fault name=”Fault” message=”ogsi:FaultMessage”/>

</operation>

<sd:serviceData name=”MathData”

type=”data:MathDataType”

minOccurs=”1”

maxOccurs=”1”

mutability=”mutable”

modifiable=”false”

nillable=”false”>

</sd:serviceData>

</gwsdl:portType>

</definitions>

MathSDE.xsd

<?xml version=”1.0” encoding=”UTF-8”?>

<wsdl:definitions name=”MathData”

targetNamespace=”

xmlns:tns=”

xmlns:wsdl=”

<wsdl:types>

<schema targetNamespace=”

attributeFormDefault=”qualified”

elementFormDefault=”qualified”

xmlns=”

<complexType name=”MathDataType”>

<sequence>

<element name=”value” type=”int”/>

<element name=”lastOp” type=”string”/>

<element name=”numOps” type=”int”/>

</sequence>

</complexType>

</schema>

</wsdl:types>

</wsdl:definitions>

Math.wsdd

<?xml version=”1.0”?>

<deployment name=”defaultServerConfig” xmlns=”

xmlns:java=”

<service name=”mathtutorial/core/factory/MathFactoryService” provider=”Handler” style=”wrapped”>

<parameter name=”name” value=”MathService Factory”/>

<parameter name=”instance-name” value=”MathService Instance”/>

<parameter name=”instance-schemaPath” value=”schema/mathtutorial.core.factory/Math/MathService.wsdl”/>

<parameter name=”instance-baseClassName” value=”mathtutorial.core.factory.impl.MathImpl”/>

<!-- Start common parameters -->

<parameter name=”allowedMethods” value=”*”/>

<parameter name=”persistent” value=”true”/>

<parameter name=”className” value=”org.gridforum.ogsi.Factory”/>

<parameter name=”baseClassName” value=”org.globus.ogsa.impl.ogsi.PersistentGridServiceImpl”/>

<parameter name=”schemaPath” value=”schema/ogsi/ogsi_factory_service.wsdl”/>

<parameter name=”handlerClass” value=”org.globus.ogsa.handlers.RPCURIProvider”/>

<parameter name=”factoryCallback” value=”org.globus.ogsa.impl.ogsi.DynamicFactoryCallbackImpl”/>

<parameter name=”operationProviders” value=”org.globus.ogsa.impl.ogsi.FactoryProvider”/>

</service>

</deployment>

build.properties

ogsa.root=/user/csckmst/css1tt/gt3

interface.name=Math

package.dir=./mathtutorial/core/factory

package=mathtutorial.core.factory

namespace2mappings.mappings

http\://

http\://

http\://

http\://

http\://

Client.java

package mathtutorial.core.factory.client;

import org.gridforum.ogsi.ExtensibilityType; import org.gridforum.ogsi.ServiceDataValuesType;

import org.globus.ogsa.utils.AnyHelper;

import org.globus.ogsa.utils.QueryHelper;

import mathtutorial.core.factory.service.MathServiceGridLocator;

import mathtutorial.core.factory.Math.MathPortType;

import mathtutorial.core.factory.MathDataType;

import java.net.URL;

public class Client

{

public static void main(String[] args)

{

try

{

// Get command-line arguments

URL GSH = new java.net.URL(args[0]);

int a = Integer.parseInt(args[1]);

// Get a reference to the Math PortType

MathServiceGridLocator mathServiceLocator = new MathServiceGridLocator();

MathPortType math = mathServiceLocator.getMathServicePort(GSH);

// Get Service Data Element “MathData”

ExtensibilityType extensibility = math.findServiceData(QueryHelper.getNamesQuery(“MathData”));

ServiceDataValuesType serviceData = AnyHelper.getAsServiceDataValues(extensibility);

MathDataType mathData = (MathDataType) AnyHelper.getAsSingleObject(serviceData, MathDataType.class);

// Write service data

System.out.println(“Value: “ + mathData.getValue());

System.out.println(“Previous operation: “ + mathData.getLastOp());

System.out.println(“# of operations: “ + mathData.getNumOps());

// Call remote method

math.add(a);

}catch(Exception e)

{

System.out.println(“ERROR!”);

e.printStackTrace();

}

}

}