Chapter 6. Hands-on programming

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.

6.1. The client - server 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:

6.2. Initialization of the activity

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.

6.2.1. Design of the application with Init activity

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

6.2.2. Programming

6.2.2.1. InitializedHello

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

6.2.3. Execution

Execution is similar to the previous example; just use the InitializedHelloClient client class and InitializedHello server class.

6.2.3.1. Starting the server

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 &

6.2.3.2. Launching the client

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 

6.3. A simple migration example

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.

6.3.1. Required conditions

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 .

6.3.2. Design

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:

6.3.3. Programming

6.3.3.1. a) the MigratableHello class

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.

6.3.3.2. c) the client class

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.

6.3.4. Execution

- 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.

6.4. migration of graphical interfaces

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.

6.4.1. Design of the migratable application

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

6.4.2. Programming

6.4.2.1. HelloFrameController

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");
}          

6.4.2.2. HelloFrame

This is an example of a graphical class that could be associated with the active object (see code in Example C.33, “HelloFrame.java” ).

6.4.3. Execution

  • 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.