9. Exploring mobility

    Introduction
  1. Installing the software
  2. Your first programs
  3. Parallelism and Behaviours
  4. Agent communication
  5. Using the Directory Facilities (DF)
  6. Using Jade Behaviours
  7. Using ontologies
  8. Graphical Interfaces
  9. --> Mobility

Agent mobility is the ability for an agent program to migrate or to make a copy (clone) itself across one or multiple network hosts. With JADE framework, it is possible to build agents powering these abilities. However, the current version of JADE supports only intra-platform mobility, that is, an agent can move only within the same platform from container to container. The support for mobility in JADE consists of a set of API classes and methods that allow an agent to perform the required actions by itself or via the AMS, and a mobility specific ontology, MobilityOntology, contained in the package jade.domain.mobility.

More specifically, the Agent class in the package jade.core contains a set of methods that are dedicated for managing an agent mobility. These are the methods doMove(), beforeMove(), afterMove(), doClone(), beforeClone() and afterClone(). The three former methods handle the process of moving the agent whereas the three latter handle the process of cloning the agent, i.e., making a copy of itself.

9.1 Moving an agent

To move an agent, you just need to call the method doMove(Location) within your agent program passing in parameter to it the new destination of the agent which must be a Location object. The tricky point here is that you cannot create by yourself a Location object. To get a Location object, you must query this information with the AMS, by sending it a REQUEST with either a WhereIsAgentAction or a QueryPlatformLocationsAction (package jade.domain.JADEAgentManagement) as content message. A WhereIsAgentAction allows you to obtain with the location of a given agent. It requires one parameter, the identifier of the agent that your are querying the location. You provide it via the method setAgentIdentifier(AID) of this class. On the other hand, a QueryPlatformLocationsAction allows you to obtain all available locations within a given platform. It takes no parameter.

Here is how you can proceed. In the directory Mobility of this tutorial, you have the programs of our example on JADE mobility. this example consists of a controller agent with a gui which allows user to perform various commands such as create a new agent within the same platform, move the agent, clone the agent and kill the agent. For example to move an existing agent, the user first select the agent in the list of agents displayed by a JList, then he selects the location where he wants the agent to move and he presses the button "Move". When the controller agent receives the event via the method postGuiEvent(GuiEvent) that we discussed in the previous section (Building agent with integrated GUI), it composes a REQUEST message with a MoveAction object (of the package jade.domain.JADEAgentManagement) that it sends to the interested agent. The MoveAction object takes as parameter a MobileAgentDescription object that is mandatory. A MobileAgentDescription object is a set of tuples (name, value). Two among its parameters are mandatory - the identifier of the agent provided by the method setName(AID) - and the destination (container) where to move provided by the method setDestination(Location). When the agent receives this message it just extracts the information about the destination to move and it then calls its method doMove(Location) to start the moving process.

Note that to be able to use these objects, you must use the SLCodec language and the MobilityOntology (or the JADEManagementOntology) ontology and register them with the agents content manager.

The methods beforeClone() and afterClone() are provided for the agent to perform some specific tasks before and after moving. You must pay attention to the fact that when an agent migrates, not all its state variables move with it. This is the case for example of parameters that are platform or container-dependent such as the ontology and the language. For this reason, after the agent has moved you must register again the language and the ontology.

9.2 Cloning an agent

To clone an agent you follow exactly the same process as in agent moving. But, instead of using the MoveAction object as content of the REQUEST to the interested agent, you must use the CloneAction object which in fact extends the MoveAction class with an additional parameter - the new name of the cloned agent. You provide this name via the method setNewName(String) of the CloneAction class. When the agent receives the message it just calls its method doClone(Location, String) which takes as parameters the location where the cloned agent will start and its name which must be necessarily different from the original agent's name. In our example the controller agent generates automatically the new name by prefixing the agent's name with the string "Clone-".

As in the moving case, the beforeClone() and afterClone() methods are provided for the agent to perform some specific tasks before and after cloning.

9.3 The examples

The required files, ControllerAgent, ControllerAgentGui, MobileAgent and MobileAgentGui are in the directory Mobility. To run the example, just compile all files in the directory and execute the ControllerAgent:

		% javac *.java
		% java  jade.Boot xxx:ControllerAgent

The following fragments of codes show the important steps in coding both the Controller and the mobile Agent.

a. The ControllerAgent class

public class ControllerAgent extends GuiAgent {
-----------------------------------------------

...

protected void setup() {
------------------------

// Register language and ontology
getContentManager().registerLanguage(new SLCodec());
getContentManager().registerOntology(MobilityOntology.getInstance());

try {
// Create the container objects
home = runtime.createAgentContainer(new ProfileImpl());
container = new jade.wrapper.AgentContainer[3];
for (int i = 0; i < 5; i++){
container[0] = runtime.createAgentContainer(new ProfileImpl());
}
doWait(2000);

// Get available locations with AMS
sendRequest(new Action(getAMS(), new QueryPlatformLocationsAction()));

//Receive response from AMS
MessageTemplate mt = MessageTemplate.and(
MessageTemplate.MatchSender(getAMS()),
MessageTemplate.MatchPerformative(ACLMessage.INFORM));
ACLMessage resp = blockingReceive(mt);
ContentElement ce = getContentManager().extractContent(resp);
Result result = (Result) ce;
jade.util.leap.Iterator it = result.getItems().iterator();
while (it.hasNext()) {
Location loc = (Location)it.next();
locations.put(loc.getName(), loc);
}
}
catch (Exception e) { e.printStackTrace(); }

...
}


protected void onGuiEvent(GuiEvent ev) {
------------------------------------------

command = ev.getType();

...

if (command == MOVE_AGENT) {

String destName = (String)ev.getParameter(1);
Location dest = (Location)locations.get(destName);
MobileAgentDescription mad = new MobileAgentDescription();
mad.setName(aid);
mad.setDestination(dest);
MoveAction ma = new MoveAction();
ma.setMobileAgentDescription(mad);
sendRequest(new Action(aid, ma));

}
else if (command == CLONE_AGENT) {

String destName = (String)ev.getParameter(1);
Location dest = (Location)locations.get(destName);
MobileAgentDescription mad = new MobileAgentDescription();
mad.setName(aid);
mad.setDestination(dest);
String newName = "Clone-"+agentName;
CloneAction ca = new CloneAction();
ca.setNewName(newName);
ca.setMobileAgentDescription(mad);
sendRequest(new Action(aid, ca));

agents.add(newName);
myGui.updateList(agents);
}
...
}


void sendRequest(Action action) {
----------------------------------

ACLMessage request = new ACLMessage(ACLMessage.REQUEST);
request.setLanguage(new SLCodec().getName());
request.setOntology(MobilityOntology.getInstance().getName());
try {
getContentManager().fillContent(request, action);
request.addReceiver(action.getActor());
send(request);

}
catch (Exception ex) { ex.printStackTrace(); }
}

}//class Controller

 

b. The MobileAgent class

public class MobileAgent extends GuiAgent {
// ----------------------------------------

...

protected void beforeMove() {
// -------------------------------

System.out.println("Moving now to location : " + destination.getName());
myGui.setVisible(false);
myGui.dispose();
}

protected void afterMove() {
// ------------------------------

init();
myGui.setInfo("Arrived at location : " + destination.getName());
}

protected void beforeClone() {
// -------------------------------

myGui.setInfo("Cloning myself to location : " + destination.getName());
}

protected void afterClone() {
// ------------------------------

init();
}

void init() {
// ---------

// Register language and ontology
getContentManager().registerLanguage(new SLCodec());
getContentManager().registerOntology(MobilityOntology.getInstance());

// Create and display the gui
myGui = new MobileAgentGui(this);
myGui.setVisible(true);
myGui.setLocation(destination.getName());
}


class ReceiveCommands extends CyclicBehaviour {
// --------------------------------------------------

ReceiveCommands(Agent a) { super(a); }

public void action() {

ACLMessage msg = receive(MessageTemplate.MatchSender(controller));

if (msg == null) { block(); return; }

if (msg.getPerformative() == ACLMessage.REQUEST){

try {
ContentElement content = getContentManager().extractContent(msg);
Concept concept = ((Action)content).getAction();

if (concept instanceof CloneAction){

CloneAction ca = (CloneAction)concept;
String newName = ca.getNewName();
Location l = ca.getMobileAgentDescription().getDestination();
if (l != null) destination = l;
doClone(destination, newName);

}
else if (concept instanceof MoveAction){

MoveAction ma = (MoveAction)concept;
Location l = ma.getMobileAgentDescription().getDestination();
if (l != null) doMove(destination = l);

}
...
}
catch (Exception ex) { ex.printStackTrace(); }
...
}

} // class MobileAgent

 


Top
Previous
Next