Writing an airfareQuote grid service
(as a wrapper to an already existing web service)
Writing the Web Service Client
(This is what i did, and by no means is the only and the correct way to do it):
Create a directory for the service : I created <gt>/airfarequote
The directory structure looks like this ::
build/
build.xml
lib/
schema/
build.properties data/
src/
Get the WSDL description of the service, and put in <gt>/airfarequote/schema
The wsdl of the service looks like this : (1)
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="urn:SBGAirFareQuotes.sbg.travel.ws.dsdata.co.uk"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:apachesoap="http://xml.apache.org/xml-soap"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:intf="urn:SBGAirFareQuotes.sbg.travel.ws.dsdata.co.uk"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:impl="urn:SBGAirFareQuotes.sbg.travel.ws.dsdata.co.uk"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<wsdl:types>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="urn:SBGAirFareQuotes.sbg.travel.ws.dsdata.co.uk">
<import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
<complexType name="AirFareQuoteRequest">
<sequence>
<element name="outwardDate" nillable="true" type="xsd:dateTime"/>
<element name="returnDate" nillable="true" type="xsd:dateTime"/>
<element name="originAirport" nillable="true" type="xsd:string"/>
<element name="destinationAirport" nillable="true" type="xsd:string"/>
</sequence>
</complexType>
<element name="AirFareQuoteRequest" nillable="true" type="impl:AirFareQuoteRequest"/>
<complexType name="AirFareQuote">
<sequence>
<element name="airlineName" nillable="true" type="xsd:string"/>
<element name="fare" type="xsd:float"/>
<element name="outwardTime" nillable="true" type="xsd:dateTime"/>
<element name="returnTime" nillable="true" type="xsd:dateTime"/>
<element name="errorOccurred" type="xsd:boolean"/>
<element name="scrapeError" type="xsd:boolean"/>
<element name="errorMessage" nillable="true" type="xsd:string"/>
</sequence>
</complexType>
<complexType name="ArrayOfAirFareQuote">
<complexContent>
<restriction base="soapenc:Array">
<attribute ref="soapenc:arrayType" wsdl:arrayType="impl:AirFareQuote[]"/>
</restriction>
</complexContent>
</complexType>
<element name="ArrayOfAirFareQuote" nillable="true" type="impl:ArrayOfAirFareQuote"/>
<complexType name="ArrayOf_xsd_string">
<complexContent>
<restriction base="soapenc:Array">
<attribute ref="soapenc:arrayType" wsdl:arrayType="xsd:string[]"/>
</restriction>
</complexContent>
</complexType>
<element name="ArrayOf_xsd_string" nillable="true" type="impl:ArrayOf_xsd_string"/>
</schema>
</wsdl:types>
<!-- Define the messages -->
<wsdl:message name="getAirFareQuoteResponse">
<wsdl:part name="getAirFareQuoteReturn" type="intf:ArrayOfAirFareQuote"/>
</wsdl:message>
<wsdl:message name="getAirlinesResponse">
<wsdl:part name="getAirlinesReturn" type="intf:ArrayOf_xsd_string"/>
</wsdl:message>
<wsdl:message name="getAirlinesRequest">
</wsdl:message>
<wsdl:message name="getAirFareQuoteRequest">
<wsdl:part name="in0" type="intf:AirFareQuoteRequest"/>
</wsdl:message>
<wsdl:portType name="SBGGetAirFareQuote">
<wsdl:operation name="getAirFareQuote" parameterOrder="in0">
<wsdl:input name="getAirFareQuoteRequest" message="intf:getAirFareQuoteRequest"/>
<wsdl:output name="getAirFareQuoteResponse" message="intf:getAirFareQuoteResponse"/>
</wsdl:operation>
<wsdl:operation name="getAirlines">
<wsdl:input name="getAirlinesRequest" message="intf:getAirlinesRequest"/>
<wsdl:output name="getAirlinesResponse" message="intf:getAirlinesResponse"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="SBGGetAirFareQuoteSoapBinding" type="intf:SBGGetAirFareQuote">
<wsdlsoap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="getAirFareQuote">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="getAirFareQuoteRequest">
<wsdlsoap:body use="encoded"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="urn:SBGAirFareQuotes.sbg.tr
avel.ws.dsdata.co.uk"/>
</wsdl:input>
<wsdl:output name="getAirFareQuoteResponse">
<wsdlsoap:body use="encoded"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="urn:SBGAirFareQuotes.sbg.tr
avel.ws.dsdata.co.uk"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getAirlines">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="getAirlinesRequest">
<wsdlsoap:body use="encoded"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="urn:SBGAirFareQuotes.sbg.tr
avel.ws.dsdata.co.uk"/>
</wsdl:input>
<wsdl:output name="getAirlinesResponse">
<wsdlsoap:body use="encoded"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="urn:SBGAirFareQuotes.sbg.tr
avel.ws.dsdata.co.uk"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="SBGGetAirFareQuoteService">
<wsdl:port name="SBGGetAirFareQuote" binding="intf:SBGGetAirFareQuoteSoapBinding">
<wsdlsoap:address
location="http://wavendon.dsdata.co.uk:8080/axis/services/SBGGetAirFareQuote"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
Use appropriate build.xml to generate stubs for this WSDL Description. build.xml includes the
following :
...
<copy file="./schema/airfarequote.wsdl" toDir="${build.schema}/${package.dir}/airfare"/>
<target name="stubs" unless="stubs.present" depends="setenv, generateWSDL">
<ant antfile="${build.services}" target="generateStubs">
<property name="schema.file.dir" value="${package.dir}/airfare"/>
<property name="schema.file" value="airfarequote.wsdl"/>
</ant>
</target>
<target name="compileStubs" depends="stubs">
<javac srcdir="${build.stubs}" destdir="${build.dest}" debug="${debug}"
deprecation="${deprecation}"
classpathref="classpath">
</javac>
</target>
...
Now you can do “ant stubs” in the <gt>/airfarequote directory to get the appropriate stubs
created in the build directory.
The stubs are generated in :
<gt>/airfarequote/build/stubs/uk/co/dsdata/ws/travel/sbg/SBGAirFareQuotes : (2)
AirFareQuote.java
AirFareQuoteRequest.java
SBGGetAirFareQuote.java
SBGGetAirFareQuoteService.java
SBGGetAirFareQuoteSoapBindingStub.java
SBGGetAirFareQuoteServiceGridLocator.java
SBGGetAirFareQuoteServiceLocator.java
So, we have the stub classes available for us to access the web service's interface. Now we can
write the client for accessing the interface.
package org.globus.ogsa.travel.impl;
import
import
import
import
import
import
AirfareClient.java (3)
java.net.URL;
java.text.DateFormat;
java.util.Date;
java.util.Calendar;
java.util.TimeZone;
java.util.GregorianCalendar;
import uk.co.dsdata.ws.travel.sbg.SBGAirFareQuotes.*;
// STUBS generated from the WSDL
public class AirFareClient {
public static AirFareQuote[] getAirFareQuotes (String outwardDate, String returnDate, String originAirport, String
destAirport) {
try {
AirFareQuote fareresponse[];
DateFormat df = DateFormat.getDateInstance();
Calendar cal1 = new GregorianCalendar();
Calendar cal2 = new GregorianCalendar();
cal1.setTimeZone(TimeZone.getDefault());
cal2.setTimeZone(TimeZone.getDefault());
AirFareQuoteRequest farerequest = new AirFareQuoteRequest();
cal1.setTime(df.parse(outwardDate));
farerequest.setOutwardDate(cal1);
cal2.setTime(df.parse(returnDate));
farerequest.setReturnDate(cal2);
farerequest.setOriginAirport(originAirport);
farerequest.setDestinationAirport(destAirport);
SBGGetAirFareQuoteServiceLocator airfareLocator = new SBGGetAirFareQuoteServiceLocator();
SBGGetAirFareQuote airfare = airfareLocator.getSBGGetAirFareQuote(new
URL("http://wavendon.dsdata.co.uk:8080/axis/services/SBGGetAirFareQuote"));
fareresponse = airfare.getAirFareQuote(farerequest);
// The actual request
return fareresponse;
} catch (Exception e) {
e.printStackTrace();
}
}
}
return null;
........... SOME HELPER FUNCTIONS HERE + main function ..................
Example output ::
% java org.globus.org.travel.impl.AirFareClient "Apr 28, 2003" "May 5, 2003" "LAX" "JFK"
Price : $495.3393
Airlines : Northwest Airlines
Leaving : 2003-4-27, 12:45:0 PM
Returning : 2003-5-5, 4:15:0 PM
Price : $1117.8
Airlines : Travelocity
Leaving : 2003-4-28, 8:0:0 AM
Returning : 2003-5-5, 11:0:0 AM
Price : $1341.2019
Airlines : American Airlines
Leaving : 2003-4-28, 10:0:0 AM
Returning : 2003-5-5, 9:0:0 AM
Writing the Grid Wrapper Service:
Create a directory for the service : I created <gt>/travel
Copy the JAR's of the previous client to somewhere in the java classpath.
Create the java files :
go to directory <gt>/travel/src/org/globus/ogsa/travel/impl -- this is where the java interface
and implementation go.
I created an interface called Flight in the file Flight.java
package org.globus.ogsa.travel.impl;
Flight.java (4)
public interface Flight {
public void monitorAirfare(String outdate, String indate, String fromAirport, String toAirport);
}
We need a Schema for our Service data, for which we can then generate stubs (in our case for
the MyAirFareQuote). Clients can subscribe for notification of changes in the service data.
FlightStatus.xsd (5)
<?xml version="1.0"?>
<wsdl:definitions name="FlightStatus"
targetNamespace="http://ogsa.globus.org/travel/Flight/status"
xmlns:tns="http://ogsa.globus.org/travel/Flight/status"
xmlns:gsdl="http://www.gridforum.org/namespaces/2002/10/gridServices"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
<wsdl:types>
<schema targetNamespace="http://ogsa.globus.org/travel/Flight/status"
attributeFormDefault="qualified"
elementFormDefault="qualified"
xmlns="http://www.w3.org/2001/XMLSchema">
<complexType name="MyAirFareQuoteType">
<sequence>
<element name="airlineName" nillable="true" type="string"/>
<element name="fare" type="float"/>
<element name="outwardTime" nillable="true" type="dateTime"/>
<element name="returnTime" nillable="true" type="dateTime"/>
<element name="errorOccurred" type="boolean"/>
<element name="scrapeError" type="boolean"/>
<element name="errorMessage" nillable="true" type="string"/>
</sequence>
</complexType>
</schema>
</wsdl:types>
<gsdl:serviceDataDescription name="MyAirFareQuote"
element="tns:MyAirFareQuoteType"
minOccurs="1"
maxOccurs="1"
mutability="mutable">
<documentation>The current best airfare quote</documentation>
</gsdl:serviceDataDescription>
</wsdl:definitions>
Implementation of the Service :
package org.globus.ogsa.travel.impl;
FlightImpl.java (6)
import org.globus.ogsa.travel.Flight.FlightPortType;
// Stubs generated from the WSDL (which in
// turn is generated from the Flight Interface)
import org.globus.ogsa.travel.Flight.status.MyAirFareQuoteType;
// Stub generated from
// the Service Data Schema
import org.globus.ogsa.travel.impl.AirFareClient;
import
import
import
import
import
import
// Airfare client from the previous section
org.globus.ogsa.impl.core.notification.NotificationServiceSkeleton;
org.globus.ogsa.GridContext;
org.globus.ogsa.GridServiceException;
org.globus.ogsa.ServiceData;
org.globus.ogsa.utils.AnyHelper;
org.gridforum.ogsa.ServiceDataType;
import java.rmi.RemoteException;
import java.net.URL;
import uk.co.dsdata.ws.travel.sbg.SBGAirFareQuotes.*;
// also import stubs from the previous client
// We extend NotificationServiceSkeleton here (to notify the subscribers of our service data)
public class FlightImpl extends NotificationServiceSkeleton implements FlightPortType {
private ServiceData airfareQuoteStatusData;
private MyAirFareQuoteType airfareStatus = new MyAirFareQuoteType();
public FlightImpl() {
super("Flight Fare Monitoring Agent");
}
public void postCreate(GridContext context) throws GridServiceException {
// ****** Initializing the Service Data
airfareQuoteStatusData = this.serviceData.create("MyAirFareQuote");
airfareQuoteStatusData.setValue(this.airfareStatus);
serviceData.add(airfareQuoteStatusData);
}
// ***** Reinitialize persistent properties after recovering from a service restart.
String indate = (String) getPersistentProperty("indate");
String outdate = (String) getPersistentProperty("outdate");
String fromairport = (String) getPersistentProperty("fromairport");
String toairport = (String) getPersistentProperty("toairport");
if(indate != null) {
monitorAirfare (indate,outdate,fromairport,toairport);
}
// Should work
// theoretically
// **** Save the current request as a persistent properties
public void saveRequest (String outdate, String indate, String fromairport, String toairport) throws RemoteException {
try {
setPersistentProperty("indate", indate);
setPersistentProperty("outdate", outdate);
setPersistentProperty("fromairport", fromairport);
setPersistentProperty("toairport", toairport);
flush();
} catch (Exception e) {
throw new RemoteException(e.toString());
}
}
public void monitorAirfare (String outdate, String indate, String fromairport, String toairport) {
try { saveRequest(outdate,indate,fromairport,toairport); }
catch (Exception e) { }
while(true) {
Calendar cal3 = Calendar.getInstance();
// ****** Using the Web Service client to get results
AirFareClient afc = new AirFareClient();
AirFareQuote fareresponse[] = afc.getAirFareQuotes (outdate,indate,fromairport,toairport);
if(fareresponse[0].getFare() != airfareStatus.getFare()) {
airfareStatus.setFare(fareresponse[0].getFare());
airfareStatus.setAirlineName(fareresponse[0].getAirlineName());
airfareStatus.setOutwardTime(fareresponse[0].getOutwardTime());
airfareStatus.setReturnTime(fareresponse[0].getReturnTime());
airfareQuoteStatusData.setValue(this.airfareStatus);
airfareQuoteStatusData.notifyChange();
}
// Notify all subscribers of change
/* No need to keep checking if the flight has already left */
if((cal3.getTime().compareTo(fareresponse[0].getOutwardTime().getTime())) > 0) { break; }
}
}
}
/* Keep checking this every 30 minutes */
try { Thread.currentThread().sleep(30*60*1000); }
catch(InterruptedException ie) {}
Create or modify build.xml. This is used by ant (something like make but platform independent
and uses xml)
<?xml version="1.0"?>
<project default="all" basedir=".">
<!-- Properties -->
<property file="build.properties"/>
<property file="${user.home}/build.properties"/>
<path id="classpath">
<pathelement location="${java.home}/../lib/tools.jar"/>
<pathelement location="${build.dest}"/>
<fileset dir="lib">
<include name="*.jar"/>
</fileset>
<fileset dir="${ogsa.root}/lib">
<include name="*.jar"/>
</fileset>
<pathelement path="${java.class.path}"/>
</path>
<property name="src.dir" value="./src"/>
<property name="build.dir" value="./build"/>
<property name="build.lib" value="${build.dir}/lib"/>
<property name="build.stubs" value="${build.dir}/stubs"/>
<property name="build.dest" value="${build.dir}/classes"/>
<property name="build.schema" value="${build.dir}/schema"/>
<property name="build.services" value="${ogsa.root}/build-services.xml"/>
<property name="build.packages" value="${ogsa.root}/build-packages.xml"/>
<property name="schema.origin" value="${ogsa.root}/schema"/>
<property name="stubs.dest" value="../stubs"/>
<!-- Package specific properties -->
<property name="package.dir" value="travel"/>
<property name="package.ns" value="ogsa.globus.org"/>
<property name="wsdl.ns" value="org.globus.ogsa"/>
<property name="services.namespace" value="${package.dir}.${package.ns}"/>
<property file="${ogsa.root}/ogsa.properties"/>
<!-- Targets -->
<target name="setenv">
<mkdir dir="${build.dest}"/>
<mkdir dir="${build.lib}"/>
<mkdir dir="${build.schema}"/>
<mkdir dir="${build.stubs}"/>
<available property="wsdl.present" type="dir" file="${build.schema}/${package.dir}" />
<available property="stubs.present" type="dir" file="${stubs.dest}" />
<copy toDir="${build.schema}">
<fileset dir="${schema.origin}"/>
</copy>
</target>
<!-- This generates the WSDL from the java interface and implementation
In this case, the wsdl file will be generated at <gt>/travel/build/schema/travel/Flight/FlightService.wsdl
-->
<target name="generateWSDL" unless="wsdl.present" depends="setenv">
<ant antfile="${build.services}" target="generateWSDL">
<property name="interface.package" value="${wsdl.ns}.${package.dir}.impl"/>
<property name="interface.name" value="Flight"/>
<property name="generated.dir" value="${package.dir}"/>
</ant>
<copy file="./schema/FlightStatus.xsd" toDir="${build.schema}/${package.dir}/Flight"/>
<ant antfile="${build.services}" target="decorateSDD">
<property name="sdd.file" value="FlightStatus.xsd"/>
<property name="wsdl.dir" value="travel/Flight"/>
<property name="wsdl.file" value="FlightService.wsdl"/>
<property name="import.sdd" value="import"/>
</ant>
</target>
<!-- This generates the stubs (JAX-RPC compliant interfaces) from the WSDL AND the Service Data Schema
In this case the stubs are generated at <gt>/travel/build/stubs/org/globus/ogsa/travel/ :
FlightPortType.java
FlightServiceGridLocator.java
FlightServiceSoapBindingStub.java
FlightService.java
FlightServiceLocator.java
and for the Schema at <gt>/travel/build/stubs/org/globus/ogsa/travel/status/MyAirFareQuoteType.java
-->
<target name="stubs" unless="stubs.present" depends="setenv, generateWSDL">
<ant antfile="${build.services}" target="generateStubs">
<property name="schema.file.dir" value="${package.dir}/Flight"/>
<property name="schema.file" value="FlightService.wsdl"/>
</ant>
<ant antfile="${build.services}" target="generateStubs">
<property name="schema.file.dir" value="${package.dir}/Flight"/>
<property name="schema.file" value="FlightStatus.xsd"/>
</ant>
</target>
<!-- This compiles the above generated stubs to generate class files -->
<target name="compileStubs" depends="stubs">
<javac srcdir="${build.stubs}" destdir="${build.dest}" debug="${debug}"
deprecation="${deprecation}"
classpathref="classpath">
</javac>
</target>
<!-- This compiles the java source files -->
<target name="compile" depends="compileStubs">
<javac srcdir="${src.dir}" destdir="${build.dest}" debug="${debug}"
deprecation="${deprecation}"
classpathref="classpath">
</javac>
</target>
<target name="stubjar" depends="compile">
<jar jarfile="${build.lib}/${package.dir}-stub.jar" basedir="${build.dest}" >
<include name="**/${package.dir}/**" />
<exclude name="**/${package.dir}/impl/**" />
</jar>
</target>
<!-- This packages the class files into a jar -->
<target name="jar" depends="stubjar">
<jar jarfile="${build.lib}/${package.dir}.jar" basedir="${build.dest}" >
<include name="**/${package.dir}/impl/**" />
</jar>
</target>
<!-- Just some gar creation, deployment, clean targets -->
<target name="rebuildGarTest">
<uptodate property="garBuild.notRequired" targetfile="${build.lib}/${package.dir}.gar">
<srcfiles dir="${src.dir}" includes="**/impl/guide/**/*.java"/>
<srcfiles dir="./" includes="guide-config.wsdd"/>
<srcfiles dir="./schema" includes="**/*.wsdl"/>
<srcfiles dir="./schema" includes="**/*.xsd"/>
</uptodate>
</target>
<target name="gar" depends="rebuildGarTest, jar" unless="garBuild.notRequired">
<copy todir="${build.lib}">
<fileset dir="${lib.dir}">
<include name="**/*.jar"/>
</fileset>
</copy>
<ant antfile="${build.packages}" target="makeGar">
<property name="gar.name" value="${build.lib}/${package.dir}.gar"/>
<property name="garlib.dir" value="${build.lib}"/>
<property name="garserverdeployment.file" value="${package.dir}-config.wsdd"/>
<property name="garschema.origin" value="${build.schema}/${package.dir}"/>
<property name="garschema.path" value="${package.dir}"/>
</ant>
</target>
<target name="redeployGarTest">
<uptodate property="garDeploy.notRequired" targetfile="${ogsa.root}/lib/${package.dir}.jar">
<srcfiles dir="${build.lib}" includes="${package.dir}.gar"/>
</uptodate>
</target>
<target name="deploy" depends="gar, redeployGarTest" unless="garDeploy.notRequired">
<dirname property="guide.dir" file="${build.lib}"/>
<ant dir="${ogsa.root}" inheritAll="false" target="deploy">
<property name="gar.name" value="${guide.dir}/lib/${package.dir}.gar"/>
</ant>
</target>
<target name="clean">
<delete dir="${build.dir}"/>
</target>
<target name="all" depends="gar"/>
</project>
Deploying the Service :
This is taken care of by creating a deployment descriptor : <package>-config.wsdd. In our case
it will be travel-config.wsdd :
<?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">
<service name="travel/FlightMonitorService" provider="Handler" style="wrapped">
<parameter name="allowedMethods" value="*"/>
<parameter name="className" value="org.globus.ogsa.impl.core.factory.DynamicFactoryImpl"/>
<parameter name="persistent" value="true"/>
<parameter name="schemaPath" value="schema/core/factory/factory_service.wsdl"/>
<parameter name="instanceSchemaPath" value="schema/travel/Flight/FlightService.wsdl"/>
<parameter name="handlerClass" value="org.globus.ogsa.handlers.RPCURIProvider"/>
<parameter name="instanceClass" value="org.globus.ogsa.travel.impl.FlightImpl"/>
<!-- To make the instance persistent -->
<parameter name="lifecycleMonitorClass" value="org.globus.ogsa.repository.DefaultServiceDeactivator"/>
<parameter name="instanceDeactivation" value="10000"/>
<parameter name="instanceLifecycle" value="persistent"/>
</service>
</deployment>
To deploy this service, go to the OGSA root <gt>, and call :
% ant deploy -Dgar.name="<path_to_gar_file>"
% ant deploy -Dgar.name="travel/build/lib/travel.gar" (in our case)
Writing the Client :
package org.globus.ogsa.travel.impl;
import
import
import
import
import
FlightClient.java (7)
org.gridforum.ogsa.GridServiceGridLocator;
org.gridforum.ogsa.GridServicePortType;
org.gridforum.ogsa.HandleType;
org.globus.ogsa.travel.Flight.FlightPortType;
org.globus.ogsa.travel.Flight.FlightServiceLocator;
public class FlightClient {
public static void main (String[] args) {
if (args.length < 2) {
System.err.println("Usage: FlightClient <handle> |monitorAirfare| |outbound-date| |return-date| |from airport|
|to airport|");
return;
}
try {
FlightServiceLocator flightLocator = new FlightServiceLocator();
GridServiceGridLocator gridLocator = new GridServiceGridLocator();
GridServicePortType gridService = gridLocator.getGridServicePort(new HandleType(args[0]));
gridLocator.registerSDEMappings();
FlightPortType flight = flightLocator.getFlightService(gridLocator.getEndpoint());
if (args[1].equalsIgnoreCase("monitorAirfare")) {
System.out.println("This call WILL NOT RETURN -> Listen for notifications to check status");
flight.monitorAirfare(args[2], args[3], args[4], args[5]);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Writing the Service Data Notification Listener :
package org.globus.ogsa.travel.impl;
FlightStatusListener.java (8)
import
import
import
import
import
import
org.globus.ogsa.impl.core.notification.NotificationSinkCallback;
org.globus.ogsa.impl.core.notification.NotificationSinkManager;
org.globus.ogsa.impl.core.service.ServicePropertiesImpl;
org.globus.ogsa.utils.AnyHelper;
org.gridforum.ogsa.ExtensibilityType;
org.gridforum.ogsa.ServiceDataType;
import
import
import
import
org.globus.ogsa.travel.Flight.status.FlightStatusType;
org.globus.ogsa.travel.Flight.status.MyAirFareQuoteType;
org.globus.ogsa.travel.Flight.status.MyAirFareQuoteRequestType;
org.globus.ogsa.travel.impl.AirFareClient;
import java.rmi.RemoteException;
public class FlightStatusListener extends ServicePropertiesImpl implements Runnable, NotificationSinkCallback {
private NotificationSinkManager manager;
private String sink;
public FlightStatusListener(NotificationSinkManager manager,
String source) throws Exception {
this.manager = manager;
this.sink = manager.addListener("MyAirFareQuote", null, source, this);
}
// This is the callback function on the receipt of a notification
public void deliverNotification(ExtensibilityType any) throws RemoteException {
try {
AirFareClient afc = new AirFareClient();
ServiceDataType serviceData = (ServiceDataType) AnyHelper.getAny(any);
MyAirFareQuoteType airfareStatus = (MyAirFareQuoteType) AnyHelper.getSingleAny(serviceData,
MyAirFareQuoteType.class);
System.out.println("Price
: $" + airfareStatus.getFare());
System.out.println("Airlines : " + airfareStatus.getAirlineName());
System.out.println("Leaving : " + afc.getStringDate(airfareStatus.getOutwardTime()));
System.out.println("Returning : " + afc.getStringDate(airfareStatus.getReturnTime()));
} catch (Exception e) {
e.printStackTrace();
}
}
public void run() {
try {
this.manager.removeListener(this.sink);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
if (args.length < 1) {
System.out.println("FlightStatusListener <source>");
return;
}
try {
NotificationSinkManager manager = NotificationSinkManager.getManager();
manager.startListening(NotificationSinkManager.MAIN_THREAD);
FlightStatusListener listener = new FlightStatusListener(manager, args[0]);
Runtime.getRuntime().addShutdownHook(new Thread(listener));
} catch (Exception e) {
e.printStackTrace();
}
}
}
Testing the Service :
Remember to source setenv.sh or setenv.csh (depending on your shell) before giving the
following commands
Just type "ant" in the <gt>/myexample (or the corresponding) directory to build the service and
the client. (this will take a while)
Deploy the service using the command stated previously
Start a grid service container by typing "ant startContainer" in the <gt> directory.
Startup a service using (in our case) :
% java org.globus.ogsa.impl.core.factory.client.CreateService
http://localhost:8080/ogsa/services/travel/FlightMonitorService myflight
In another window, start the notification listener :
% java org.globus.ogsa.travel.impl.FlightStatusListener
http://localhost:8080/ogsa/services/travel/FlightMonitorService/myflight
>> Waits for responses.. example response :
Price
: $405.3
Airlines : Travelocity
Leaving : 2003-4-28, 9:40:0 AM
Returning : 2003-5-9, 7:0:0 AM
Give a request to monitor the airfare for a certain date and between certain airports :
% java org.globus.ogsa.travel.impl.FlightClient
http://localhost:8080/ogsa/services/travel/FlightMonitorService/myflight monitorAirfare "Apr 26,
2003" "Apr 29, 2003" "LAX" "JFK"
>> This call WILL NOT RETURN -> Listen for notifications to check status
(and it hangs here – since we've put a sleep/poll continous routine in monitorAirfare)
© Copyright 2025 Paperzz