You've already seen quite sophisticated examples in the section Chapter 5, Introduction to ProActive Features. Here is an introduction to programming with ProActive.
The program that we will develop is a classic 'helloworld' example. We will increase the complexity of the example, so you get more familiar with different features of ProActive.
First, we will code a 'client-server' application, the server being an active object.
Second, we will see how we can control the activity of an active object.
Third, we will add mobility to this active object.
Eventually, we will attach a graphical interface to the active object, and will show how to move the widget between virtual machines (like in the penguin example).
This example implements a very simple client-server application. It
has an in-depth explanation in Section 13.10, “The Hello world example”; you might
wish to skim through it. Summarized, it is a client object displaying a
StringWrapper
received from a remote server.
The corresponding class diagram is the following:
Active objects, as their name indicates, have an activity of their own (an internal thread).
It is possible to add pre and post processing to this activity, just by implementing the interfaces InitActive and EndActive, that define the methods initActivity and endActivity.
The following example will help you to understand how and when you can initialize and clean the activity.
When instantiated, the activity of an object is automatically started, but it will first do what is written in the initActivity method.
Ending the activity can only be done from inside the active object (i.e. from a call to its own body). This is the reason why we have written a terminate method in the following example.
The InitializedHello class extends the Hello class, and implements the interfaces InitActive and EndActive.It acts a a server for the InitializedHelloClient class.
The main method is overriden so that it can instantiate the InitializedHello class
The source code of the InitializedHello class is in Example C.28, “InitializedHello.java”.
initActivity and endActivity here just log messages onto the console, so you can see when they are called.
initActivity is called at the creation of the active object, while endActive is called after the activity has terminated (thanks to the method terminate).
Here is the initActivity method:
public void initActivity(Body body) { System.out.println("I am about to start my activity"); }
Here is the endActivity method:
public void endActivity(Body body) { System.out.println("I have finished my activity"); }
The following code shows how to terminate the activity of the active object:
public void terminate() throws IOException { // the termination of the activity is done through a call on the // terminate method of the body associated to the current active object ProActive.getBodyOnThis().terminate(); }
The only differences from the the previous example is the classes instantiated, which are now InitializedHello (and not Hello) and InitializedHelloClient, and you will add a call to hello.terminate().
The source code of InitializedHello is in Example C.28, “InitializedHello.java”, and the code for InitializedHelloClient is in Example C.29, “InitializedHelloClient.java”.
So, create InitializedHelloClient.java and InitializedHello.java in src/org/objectweb/proactive/examples/hello
Now compile all proactive sources
cd compile windows>build.bat examples linux>build examples cd ..
Add './classes' directory to CLASSPATH to use these two new source files
windows>set CLASSPATH=.;.\classes;.\ProActive_examples.jar;.\ProActive.jar;.\lib\bcel.jar;.\lib\asm.jar;.\lib\log4j.jar;\ .\lib\xercesImpl.jar;.\lib\fractal.jar;.\lib\bouncycastle.jar linux>export CLASSPATH=.:./classes:./ProActive_examples.jar:./ProActive.jar:./lib/bcel.jar:./lib/asm.jar:./lib/log4j.jar:\ ./lib/xercesImpl.jar:./lib/fractal.jar:./lib/bouncycastle.jar
Execution is similar to the previous example; just use the InitializedHelloClient client class and InitializedHello server class.
linux> java -Djava.security.policy=scripts/proactive.java.policy \ -Dlog4j.configuration=file:scripts/proactive-log4j org.objectweb.proactive.examples.hello.InitializedHello windows> java -Djava.security.policy=scripts\proactive.java.policy \ -Dlog4j.configuration=file:scripts\proactive-log4j \ org.objectweb.proactive.examples.hello.InitializedHello &
linux> java -Djava.security.policy=scripts/proactive.java.policy -Dlog4j.configuration=file:scripts/proactive-log4j \ org.objectweb.proactive.examples.hello.InitializedHelloClient //localhost/Hello windows> java -Djava.security.policy=scripts\proactive.java.policy \ -Dlog4j.configuration=file:scripts\proactive-log4j org.objectweb.proactive.examples.hello.InitializedHelloClient //localhost/Hello
This program is a very simple one: it creates an active object that migrates between virtual machines. It is a extension of the previous client-server example, the server now being mobile.
The conditions for MigratableHello to be a migratable active object are:
- it must have a constructor without parameters: this is a result of a ProActive restriction : the active object having to implement a no-arg constructor. </ p>
- implement the Serializable interface (as it will be transferred through the network).</>
Hello, the superclass, must be able to be serialized, in order to be transferred remotely. It does not have to implement directly java.io.Serializable, but its attributes should be serializable - or transient. For more information on this topic, check Chapter 16, Active Object Migration .
We want to further enhance InitializedHello it by making migratable: we'd like to be able to move it across virtual machines.
Thus, we create a MigratableHello class, that derives from InitializedHello. This class will implement all the non-functionnal behavior concerning the migration, for which this example is created. The Hello class (and InitializedHello) is left unmodified.
Note that the migration has to be initiated by the active object itself. This explains why we have to write the moveTo method in the code of MigratableHello - i.e. a method that contains an explicit call to the migration primitive. (cf Chapter 16, Active Object Migration for migration documentation )
MigratableHello also implements a factory method for instanciating
itself as an active object : static MigratableHello
createMigratableHello(String: name)
The class diagram for the application is the following:
The code of the MigratableHello class is in Example C.30, “MigratableHello.java”.
MigratableHello derives from the Hello class from the previous example
MigratableHello being the active object itself, it has to:
- implement the Serializable interface
- provide a no-arg constructor
- provide an implementation for using ProActive's migration mechanism.
A new method getCurrentNodeLocation is added for the object to tell the node where it resides..
A factory static method is added for ease of creation.
The migration is initiated by the moveTo method:
/** method for migrating * @param destination_node destination node */ public void moveTo(String destination_node) { System.out.println("\n-----------------------------"); System.out.println("starting migration to node: " + destination_node); System.out.println("..."); try { // THIS MUST BE THE LAST CALL OF THE METHOD ProActive.migrateTo(destination_node); } catch (MigrationException me) { System.out.println("migration failed: " + me.toString()); } }
Note that the call to the ProActive primitive
migrateTo
is the last one of the method moveTo. See
Chapter 16, Active Object Migration for more information.
The entry point of the program is written in a separate class: MigratableHelloClient (see Example C.31, “MigratableHelloClient.java”).
It takes as arguments the locations of the nodes the object will be migrated to.
The program calls the factory method of MigratableHello to create an instance of an active object. It then moves it from node to node, pausing for a while between the transfers.
- start several nodes using the startnode
script.
windows>cd scripts/windows startNode.bat //localhost/n1 startNode.bat //localhost/n2 linux>cd scripts/linux ./startNode.sh //localhost/n1 ./startNode.sh //localhost/n2
- compile and run the program (run MigratableHelloClient), passing in parameter the urls of the nodes you'd like the agent to migrate to.
cd compile windows>build.bat examples linux>build examples cd ..
linux>java
-Djava.security.policy=scripts/proactive.java.policy
-Dlog4j.configuration=file:scripts/proactive-log4j
org.objectweb.proactive.examples.hello.MigratableHelloClient
//localhost/n1 //localhost/n2
windows>java
-Djava.security.policy=scripts\proactive.java.policy
-Dlog4j.configuration=file:scripts\proactive-log4j
org.objectweb.proactive.examples.hello.MigratableHelloClient
//localhost/n1 //localhost/n2
- observe the instance of MigratableHello migrating:
During the execution, a default node is first created. It then hosts the created active object. Then the active object is migrated from node to node, each time returning 'hello' and telling the client program where it is located.
Graphical interfaces are not serializable, yet it is possible to migrate them with ProActive.
The idea is to associate the graphical object to an active object. The active object will control the activation and desactivation of this graphical entity during migrations.
Of course, this is a very basic example, but you can later build more sophisticated frames.
We will write a new active object class, that extends MigratableHello. The sayHello method will create a window containing the hello message. This window is defined in the class HelloFrame
The code of the HelloFrameController is in Example C.32, “HelloFrameController.java”.
This class extends MigratableHello, and adds an activity and a migration strategy manager to the object .
It creates a graphical frame upon call of the sayHello method.
Here we have a more complex migration process than with the previous example. We need to make the graphical window disappear before and reappear in a new location after the migration (in this example though, we wait for a call to sayHello). The migration of the frame is actually controlled by a MigrationStrategyManager, that will be attached to the body of the active object.. An ideal location for this operation is the initActivity method (from InitActive interface), that we override:
/** * This method attaches a migration strategy manager to the current active object. * The migration strategy manager will help to define which actions to take before * and after migrating */ public void initActivity(Body body) { // add a migration strategy manager on the current active object migrationStrategyManager = new MigrationStrategyManagerImpl((Migratable) ProActive.getBodyOnThis()); // specify what to do when the active object is about to migrate // the specified method is then invoked by reflection migrationStrategyManager.onDeparture('clean'); }
The MigrationStrategyManager defines methods such as 'onDeparture', that can be configured in the application. For example here, the method 'clean' will be called before the migration, conveniently killing the frame:
public void clean() { System.out.println("killing frame"); helloFrame.dispose(); helloFrame = null; System.out.println("frame is killed"); }
This is an example of a graphical class that could be associated with the active object (see code in Example C.33, “HelloFrame.java” ).
Create a new class HelloFrameControllerClient: take the code of MigratableHelloClient used in the previous part, change the class declaration to HelloFrameControllerClient and replace the line
MigratableHello migratable_hello =
MigratableHello.createMigratableHello("agent1");
with
MigratableHello migratable_hello =
HelloFrameController.createHelloFrameController("agent1");
Similarly to the simple migration example (use the HelloFrameControllerClient class), you will start remote nodes and specify a migration path.
you have 2 ways for handling the display of the graphical objects:
look on the display screens of the machines
export the displays: in startNode.sh, you should add the following lines before the java command:
DISPLAY=myhost:0 export DISPLAY
The displayed window: it just contains a text label with the location of the active object.
© 2001-2007 INRIA Sophia Antipolis All Rights Reserved