This second client doesn't connect to an existing instance. Instead, it first connects to the MathService factory, requests that a new instance be created, uses it, and then destroys it. This example has some important differences with respect to prior examples, so besides just printing the whole source code, we'll see some important lines in more detail.
package org.globus.progtutorial.clients.MathService; import org.gridforum.ogsi.OGSIServiceGridLocator; import org.gridforum.ogsi.Factory; import org.gridforum.ogsi.LocatorType; import org.globus.ogsa.utils.GridServiceFactory; import org.globus.progtutorial.stubs.MathService.service.MathServiceGridLocator; import org.globus.progtutorial.stubs.MathService.MathPortType; import java.net.URL; public class FactoryClient { 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 MathService Factory OGSIServiceGridLocator gridLocator = new OGSIServiceGridLocator(); Factory factory = gridLocator.getFactoryPort(GSH); GridServiceFactory mathFactory = new GridServiceFactory(factory); // Create a new MathService instance and get a reference // to its Math PortType LocatorType locator = mathFactory.createService(); MathServiceGridLocator mathLocator = new MathServiceGridLocator(); MathPortType math = mathLocator.getMathServicePort(locator); // Call remote method 'add' math.add(a); System.out.println("Added " + a); // Get current value through remote method 'getValue' int value = math.getValue(); System.out.println("Current value: " + value); // Destroy the instance math.destroy(); }catch(Exception e) { System.out.println("ERROR!"); e.printStackTrace(); } } }
This file is $TUTORIAL_DIR/org/globus/progtutorial/clients/MathService/FactoryClient.java |
First off, let's take a look at how we make the connection to the MathService Factory:
OGSIServiceGridLocator gridLocator = new OGSIServiceGridLocator(); Factory factory = gridLocator.getFactoryPort(GSH); GridServiceFactory mathFactory = new GridServiceFactory(factory);
This should look slightly familiar. Remember how, in previous examples, we could connect to MathService with just two lines (which look suspiciously like these two... just replace OGSIServiceGridLocator with MathServiceGridLocator and Factory with MathPortType). Remember: factories are themselves Grid Services. What the previous three lines do is obtain a reference to a factory. The following lines show how we can create a new MathService instance with that factory:
LocatorType locator = mathFactory.createService();
MathServiceGridLocator mathLocator = new MathServiceGridLocator();
MathPortType math = mathLocator.getMathService(locator);
First of all we call the createService method, which is a factory operation. This method returns the instance's locator, which we will use to get a reference to the Math PortType in the remaining two lines. After these three lines, we are ready to call the instance. These calls are exactly the same as the previous client. However, after we've made the calls, we have to destroy the instance. This is done by making a call to the destroy() method in the GridService portType. This method orders a Grid Service to destroy itself. Since MathPortType extends from GridService (as all Grid Services must extend), we can invoke the destroy method directly on our MathPortType.
math.destroy();
Let's give this new client a try:
javac \ -classpath ./build/classes/:$CLASSPATH \ org/globus/progtutorial/clients/MathService/FactoryClient.java
Now, let's run it. Remember, we don't have to create an instance because the client takes care of it. Also, the URL we pass as an argument is the factory GSH, not an instance GSH.
java \ -classpath ./build/classes/:$CLASSPATH \ org.globus.progtutorial.clients.MathService.FactoryClient \ http://127.0.0.1:8080/ogsa/services/progtutorial/core/first/MathFactoryService \ 5
If you run this program several times, you'll notice that the internal value is always the same. This is because each time we run the client, we're using a different instance (so each time we run the client, the instance always has an initial value of 0). Of course, in this example this might not make much sense. However, imagine that MathService offers dozens of complicated operations which require intermediate values to be remembered and that, once you've arrived at a final result, you have no more need for the instance. In that case, it makes sense to destroy the instance as soon as we're done with it, so we can free system resources.