Author: Dick Cowan, Menehune Software Inc.
Email: rm.cowan@verizon.net
Date: February 22, 2003. Revised: June 3, 2003
Java platform: J2SE
JADE version 2.5 and above.
JADE provides a simple mechanism to pass arguments to agents via the command-line or via the in-process interface.
For instance, the following command line passes 3 arguments to the agent FooAgent:
java jade.Boot foo:FooAgent(1 arg2 "This is argument 3")
the three arguments can then be extracted by the FooAgent code via a simple call
to the Agent method getArguments()
that returns an array of type java.lang.Object
.
public void setup() { Object[] args = getArguments(); String arg1 = args[0].toString(); // this returns the String "1" String arg2 = args[1].toString(); // this returns the String "arg2" String arg3 = args[2].toString(); // this returns the String "This is argument 3" }
The same arguments can be passed via the in-process interface as follows:
Object args = new Object[3]; args[0] = "1"; args[1] = "arg2"; args[3] = "This is argument 3"; AgentController dummy = ac.createNewAgent("foo", "FooAgent", args);
Because of the usage of an array of Object
rather than an array
of String
, the in-process interface can also pass complex arguments
to an agent, such as the reference to another Java object. If you want a String
argument, it is best to use the object argument's toString() method to fetch a
string representation of the object rather than simply casting it as a String.
The command line can also be effectively used in order to pass general properties to all the agents in the system. For instance, the following command line sets to 3 the value of the property named verbosity:
java jade.Boot -verbosity 3 foo:FooAgent(1 arg2 "This is argument 3")
The same property can be set also via the in-process interface, in particular by setting that value in the Profile object:
Profile p = new ProfileImpl(); p.setParameter("verbosity","3"); AgentContainer ac = rt.createAgentContainer(p);
In both cases, all agents can then get that value via the
getProperty
method call provided by the jade.core.Agent
class:
String verbosity = getProperty("verbosity", "0");
However, attempting to pass other than a few simple arguments via the command line is difficult. Particularly trying to do so in a platform neutral manner. LEAP also makes use of properties in lieu of passing arguments directly to the agent.
While working with the Agents for Mobility group at HP Labs, we recognized the need to provide agents with a richer and more flexible method of passing arguments to our agents than could be done from the command line. The classes we created became part of the JADE 2.5 release.
The classes of interest are BasicProperties, EnhancedProperties, and ExpandedProperties. The preceding links should take you to the API documentation for these classes. Briefly they are:
java jade.Boot foo:DemoAgent(import:myprop.properties)One property file may import from another, so inside myprop.properties you could include an import to another file. You can get at your environment variables using a key like ${CLASSPATH}. There are many convenient getter methods provided in BasicProperties.
Shown below are:
The two java files contain additional comments on implementation and usage.
Testing:
Optional testing:
import java.io.InputStream; import java.io.IOException; import jade.core.Agent; import jade.util.BasicProperties; import jade.util.ExpandedProperties; /** * Example of a useful base class for handing agent arguments. * Classes which formerly extended jade.Agent may now extend this class. */ public class BasicAgent extends Agent { public static String PROP_NAME = "setup.properties"; private BasicProperties properties = null; /** * Sets the agents properties. * @param aProperties The properties to be used. */ public void setProperties(BasicProperties aProperties) { properties = aProperties; } /** * Returns the agents properties. * If called and the properties are null, we will attempt to initialize * them from a property file located as a resource by the same class * loader which loaded this class. If this class is in a package, we * look for the property file using the same package name. For example, * if this class were called myAgent and is in a package named * com.foo.bar then, it will attempt to load com/foo/bar/setup.properties. * If no package name or class not in jar, loader will look in the same * place as it found the class. If it isn't there thats OK. * This process enables you to easily have a default collection of * properties which you include in the same jar file. You can change * individual properties from the command line or import another property * file. However, it always first initializes from the one described * above. * Examples: * 1. To import from a second file which will overlay the initial * properties: * java jade.Boot foo:DemoAgent(import:x.properties) * 2. To simply change one property: * java jade.Boot foo:DemoAgent(CalendarChoice:Custom) * * Note: Use the colon between property name and its value. Windows does * very strange things with an equal sign. */ public BasicProperties getProperties() { if (properties == null) { properties = new ExpandedProperties(); String defaultPropName = PROP_NAME; try { defaultPropName = this.getClass().getPackage().getName().replace('.','/') + "/" + defaultPropName; } catch (Exception any) { // ignore - likely class not in package. } InputStream propertyStream = this.getClass().getClassLoader(). getResourceAsStream(defaultPropName); if (propertyStream != null) { try { properties.load(propertyStream); } catch (IOException ioe) { System.err.println("Error reading:" + defaultPropName); System.exit(-1); } } } return properties; } /** * Jade calls this method on startup so we use it to initialize the * agents properties. First, it will call getArguments() to get * the arguments as an array of objects. Second, it creates a similar * size array of strings by calling toString() on each object. * Finally, it will call getProperties() to get the initial property set * and then add those provided as arguments. If the properties contain * "dump=true", the properties will be listed to standard out. */ protected void setup() { Object[] args = getArguments(); // JADE's getArguments if (args != null) { int len = args.length; String sargs[] = new String[len]; for (int i=0; i < len; i++) { sargs[i] = args[i].toString(); } ExpandedProperties newProperties = new ExpandedProperties(); newProperties.copyProperties(getProperties()); newProperties.parseArgs(sargs); setProperties(newProperties); } if (getProperties().getBooleanProperty("dump", false)) { System.out.println("----- " + getLocalName() + "'s properties:"); getProperties().list(System.out); System.out.println("----- end of properties -----"); } } }
import jade.core.Agent; import jade.core.behaviours.CyclicBehaviour; /** * Example to show usage of BasicAgent. * All it currently does is display its properties every N seconds * where N is specified by the property "delay.seconds". */ public class DemoAgent extends BasicAgent { int delaySeconds; class MyBehaviour extends CyclicBehaviour { public MyBehaviour( Agent a ) { super(a); } public void action() { while (true) { System.out.println("----- " + getLocalName() + "'s properties:"); getProperties().list(System.out); doWait(delaySeconds * 1000); } } } /** * This method is called by the agent container as part of the * agent intialization after the agent's contructor is called. */ protected void setup() { super.setup(); // To initialize our properties MyBehaviour b = new MyBehaviour(this); addBehaviour(b); System.out.println("Agent "+getLocalName()+" is running."); delaySeconds = getProperties().getIntProperty("delay.seconds", 10); System.out.println("Delay seconds=" + delaySeconds); } }
# Used by DemoAgent as its delay between displays delay.seconds=10 # Optional. Uncomment to choose calendar; VIEW is default # Choices are: View, Simple, Palm, all, any calendarChoice=Palm # Optional. Used when calendarChoice is Simple. SimpleCalendar.input=c:/pa/config/cowand-simplecalendar.properties # Optional. Used when calendarChoice is Palm. # The following specifies the name of the datebook file. # It should be modified to match your installation. PalmCalendar.datebook=c:/palm/dick_c/datebook/datebook.dat # If you want alarms set with event notices use the following. # Units of time may be minutes, hours, or days. PalmCalendar.datebook.alarm=15 minutes # These are used by the weather service. weather.state=HI weather.city=HONOLULU weather.zonecode=HIZ002 class.path=${CLASSPATH}