2. First programs in JADE
(version 0.3, sept 11, 2003)

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

Primitive Hello World

Let's start with a classic: the simplest JADE agent that can print Hello World . JADE Agents are defined as subclasses of the predefined class Agent and their initial code must be placed in a method called setup. The code for Hello World is shown below. To spice things up, we also have the Agent prints its name - with getLocalName. For such a simple example, we only need to import one class, Agent.

  import jade.core.Agent;

  public class HelloAgent extends Agent 
  { 
      protected void setup() 
      { 
          System.out.println("Hello World. ");
          System.out.println("My name is "+ getLocalName()); 
      }
  }

Note: The programs for all the examples in this chapter can be found in the code/ch_2 directory.

Here are the commands required to compile and run our agent (in UNIX) .

    % javac HelloAgent.java 
    % java jade.Boot fred:HelloAgent

The first line is obvious, but the second line requires some explanation. Basically, Agents are a bit like Java Applets in that they can't be executed directly; they must execute within a larger program which provides the necessary services. In the case of Applets, a browser or an Applet viewer is needed; for Jade agents the environment is provided by the class jade.Boot which finds which Agents to run from command line parameters. The parameter, here "fred:HelloAgent", indicates the class of the agent, HelloAgent, and provides it with a unique name (fred).

Jade environments are called containers. Typically, in a multi-agent application, there will be several containers (with agents) running on different machines. The first container started must be a main container which maintains a central registry of all the others so that agents can discover and interact with each other.

Below we show the output of execution. Jade first prints out a version message and the IOR (CORBA address) of the container before starting the HelloAgent.

   % javac HelloAgent.java 
   % java jade.Boot fred:HelloAgent
        
         This is JADE 3.0b1 - 2003/03/19 17:08:01
         downloaded in Open Source, under LGPL restrictions,
         at http://jade.cselt.it/
    
   IOR:000000000000001149444C3A464950412F4D54533A312E300000....
   .... 0020501000100010020000101090000000100010100
    Agent container Main-Container@JADE-IMTP://Jeans-Computer.local. is ready.
    
    Hello World. 
    My name is fred

You will notice that the system prompt "%" is missing. This is because the Jade container stays active after our agent has finished execution. It is waiting for messages from other containers or the possible arrival of mobile agents. To terminate the program and get back to the system prompt you need to type CTL-C.

Note: the Czech tutorial also starts with the Hello World example.

More realistic Agents

By putting our code in the setup method of the HelloAgent, we cheated. Agent actions are normally specified through Behaviour classes. More exactly, the actions are described in the "action" method of these Behaviours. The setup method only serves to create instances of these behaviours and linking them to the Agent object. The skeleton of an typical agent class is shown below:

    import jade.core.Agent;
    import jade.core.behaviours.*;
    
    public class myAgent extends Agent 
    {
        protected void setup() 
        {
            addBehaviour( new myBehaviour( this ) );
        }
        
        
        class myBehaviour extends SimpleBehaviour 
        {   
            public myBehaviour(Agent a) { 
                super(a);  
            }
            
            public void action() 
            {
               //...this is where the real programming goes !!
            }
            
            private boolean finished = false;
            
            public boolean done() {  
                return finished;  
            }
            
        } // ----------- End myBehaviour
        
    }//end class myAgent

Here, the Behaviour is defined to be a subclass of SimpleBehaviour, the most flexible of jade's predefined Behaviours. It is also positioned to be an internal class to the Agent. It could also have been implemented as an anonymous class or defined in a separate file. In all cases, it is usual to pass a reference to the owner agent (this) when creating a Behaviour.

A last point is the provision of a mechanism to terminate the behaviour. In Jade, as long as a behaviour is not "done", its action method will be called repeatedly after every event - such as receipt of a message or expiry of a timer delay. The example shows a common technique used to terminate the behaviour: a FINISHED flag which is tested in the "done" method and can be set in "action". Later we will also show how to use the "block" method to indicate that a behaviour has finished handling the current event and make it wait for the next event.

Simple0.java

Here is a more typical implementation of the HelloAgent.

    import jade.core.Agent;
    import jade.core.behaviours.*;
    
    
    public class Simple0 extends Agent 
    {
        protected void setup() 
        {
            addBehaviour( new B1( this ) );
        }
    }
    
    class B1 extends SimpleBehaviour 
    {   
        public B1(Agent a) { 
             super(a);  
        }
                  
        public void action() 
        {
           System.out.println( "Hello World! My name is " + 
                  myAgent.getLocalName() );
        }
        
        private boolean finished = false;
        public  boolean done() {  return finished;  }
        
    } //End class B1 

The example also shows two new things:

Here are the commands required (in UNIX) to compile and run our agent.

	% javac Simple0.java
	% java jade.Boot fred:Simple0

Below we show the output of execution. Jade first prints out a version message and the IOR (CORBA address) of the container before starting the Simple0 agent. The behaviour isn't quite what we had hoped for, in that the agent loops and keeps on printing its message until we abort execution.

    jean% java jade.Boot fred:Simple0
    
        This is JADE 3.0b1 - 2003/03/19 17:08:01
        downloaded in Open Source, under LGPL restrictions,
        at http://jade.cselt.it/
    
    IOR:000000000000001149444C3A464950412F4D54533A312E300000....
    .... 0020501000100010020000101090000000100010100
    Hello World! My name is fred
    Hello World! My name is fred
    Hello World! My name is fred
    Hello World! My name is fred
    ..... loops until stopped with CTL-C.... !

The problem here is that we haven't explicitely indicated that the action was "done".

Simple1.java

Here is our third try at the "Hello World" example. We add a local variable, "n", to the behaviour to terminate its operation after "action" has been called 3 times.

 /*****************************************************************
     Simple1.java:  Minimal agent with anonymous behaviour
 *****************************************************************/
     
 import jade.core.Agent;
 import jade.core.behaviours.*;
     
 public class Simple1 extends Agent 
 {       
     protected void setup() 
     {
         addBehaviour(  // -------- Anonymous SimpleBehaviour 
 
             new SimpleBehaviour( this ) 
             {
                 int n=0;
                 
                 public void action() 
                 {
                     System.out.println( "Hello World! My name is " + 
                         myAgent.getLocalName() );
                     n++;
                 }
         
                 public boolean done() {  return n>=3;  }
             }
         );
     }   //  --- setup ---
 }   //  --- class Simple1

This time the behaviour is implemented as an anonymous sub-class of SimpleBehaviour. The output is shown below:

    jean% java jade.Boot x:Simple1
        This is JADE 3.0b1 - 2003/03/19 17:08:01
        downloaded in Open Source, under LGPL restrictions,
        at http://jade.cselt.it/
    
    IOR:000000000000001149444C3A46...0010100
    Hello World! My name is x
    Agent container Main-Container@JADE-IMTP://Jeans-Computer.local. is ready.
    Hello World! My name is x
    Hello World! My name is x

In this case, the behaviour end properly but the program doesn't TERMINATE even though there is no more activity after the three lines are printed. This is because 1) the agent still exists and 2) the JADE environment which we started stays around to interact with other agents which could be started later in the network. This is more obvious if we use the GUI option.

JADE Options

When starting a Jade container, we can specify many options. In particular, the "-gui" option causes Jade to create a special "Remote Management Agent" with a graphical interface which shows all participating agents and containers. It can also be used to kill agents, start new ones or to trace messages sent between agents (with the "sniffer" tool). Here is the command to invoke the interface with our Simple1 example:
	jean% java jade.Boot -gui x:Simple1
and here is the resulting window [ Note: it takes some time to appear and may show up after our simple agent has finished ].

The display shows our program as a folder called "Main-Container" which contains our Simple1 agent along with three other agents created by JADE. These other agents are:

As Marti Alemany reminded me, the -gui option is a shortcut; you can also create RMA agents directly by using the full class name "jade.tools.rma.rma".

	% java jade.Boot myRMA:jade.tools.rma.rma 

In a typical Jade application, the various agents in the system are located in many different "containers" executing on several computers; but there is ONE central agent (the AMS) which keep track of all adresses. Similarly, there must be only one DF. The Jade program which runs the AMS and the DF is called the "Main-Container" and it must be started first. To ease interconnection between various containers, Jade makes good use of the standard Java RMI registry facilities (on port 1099). The Main-Container registers with the local RMI registry - even starting one if none already exists - and all other containers will look for its address in that registry. If a secondary container executes on the same computer as the Main-Container, it will connect to the existing AMS and the DF automatically. Only if it runs on a different computer, do we have to specify the host address of the Main-Container. Thus with secondary Jade environments (containers), we will use the following options:

Here is an example where we start 4 Jade containers on the same machine: 1) a main container with no other agents, 2) a container with a Simple1 agent called Fred, 3) another secondary container with another Simple agent and 4) finally a container for the RMA agent. Ideally we should start these containers in different windows so that the individual outputs are not mixed up.
	jean% java jade.Boot &
	jean% java jade.Boot -container Fred:Simple1 &
	jean% java jade.Boot -container Harry:Simple1  &
	jean% java jade.Boot -container -gui 
Personally, I would find it more natural to have a "-main" option for the Main-Container and let the others be 'secondary' by default instead of having to use the option "-container", but it's not my choice. Assuming that applications above are running on a machine whose internet address is "phobos.iro.umontreal.ca" and that I want to start yet another Simple agent on "deimos.iro.umontreal.ca", the following whould do the trick.
	deimos% java jade.Boot -container -host phobos Susan:Simple1
If I were on a remote site, like "bert.cs.wichita.edu", I should use:
	bert% java jade.Boot -container -host phobos.iro.umontreal.ca Susan:Simple1
There are other options which can be used with Jade. These are detailed, not in a User's Guide or Programmer's Guide where you would expect them to be but in the Administrator's Guide. However, the easiest way to get the documentation is to use the "-help" option of Jade:
	% java jade.Boot -help
But you have to remember the exact keyword "-help" because misspelled options are just ignored. In conclusion, here are the most useful options for the beginner: -gui, -container, -host and -help.

Agent Parameters

It is often useful to be able to pass parameters to agents. This is described in the Jade Programming Tutorial (sect. 3.4). On a command line, the parameters are placed in a list seperated by spaces after the "name:class" agent specifier. For example:
    % java jade.Boot fred:ParamAgent(3 "Hi there")
Here fred will be passed 2 parameters: an integer and a string. In standard Java, we are used to retrieving command arguments from a String array parameter to the static method main. With JADE, retrieving arguments is a bit different because the same mechanism is used both to pass arguments from a command line and to pass arguments to agents created by programming.

In Jade, the arguments are obtained by calling the method getArguments which returns an array of Objects which must be cast to Strings (in this case). Here is an example of a ParamAgent which can retrieve the arguments "3" and "Hi there" shown above.

/**************************************************************   
     ParamAgent.java:  Retrieving parameters
 **************************************************************/   
     
     import jade.core.Agent;
    
     public class ParamAgent extends Agent 
     { 
        protected void setup() 
        { 
            Object[] args = getArguments();
            String s;
            if (args != null) {
                for (int i = 0; i<args.length; i++) {
                    s = (String) args[i];
                    System.out.println("p" + i + ": " + s);
                }
                
                // Extracting the integer.
                int i = Integer.parseInt( (String) args[0] );
                System.out.println("i*i= " + i*i);
            }
        }
     }
    

The command line shown above doesn't work under UNIX or Mac OSX.

        jean% java jade.Boot fred:ParamAgent(1 "Hi there")
            tcsh: Badly placed ()'s.
With these systems, each agent specifier (name, class & argument list) must be quoted.
    % java jade.Boot 'fred:ParamAgent(3 "fred toto")'

        p0: 3
        p1: fred toto
        i*i= 9
Reversing single and double quotes can give surprising results; in this case: 3 arguments !!!
    jean% java jade.Boot "fred:ParamAgent(3 'fred toto')"
 
        p0: 3
        p1: 'fred
        p2: toto'
        i*i= 9

Duplicate Agents

We have already noted that a Jade application should have only ONE Main-Container. Actually, any attempt to start a second Main-Container on a given machine (often by forgetting the "-container" option) gives a run-time error.

A more subtle and disconcerting problem is with "local" names for agents. Jade refuses to create an agent with the same name as an existing agent, even if they are in different containers or on different machines. Furthermore the name comparison is case independent so that "Fred" and "fred" will be considered to be the same. This means that in a class project, naming conventions have to be enforced.

This also means that only one participating container can use the "-gui" option since the RMA agent is given the local name "RMA" by default and an attempt to start a second container with a "-gui" option gives rise to a name clash. However, if you create the agents directly and give them distinct names, you can have as many RMA agents as you want. Thus, by using name conventions, students participating in a joint project can all have their own gui interfaces. Typically student "st3" could start his Agent3 as follows:

% java jade.Boot -container -host mainHost st3RMA:jade.tools.rma.rma  st3:Agent3

A little problem

I hope you will avoid the dumb mistake that cost me several hours of frustration when I was installing Jade and trying to set up the path to Jade's libraries as outlined in the previous chapter. I was trying the following command and could not get the program to execute properly no matter how I changed the CLASSPATH.
	% java java.Boot fred:Simple0

Can you spot the error?


Top
Previous
Next