Agents on the move

Bolster your client apps by adding agent mobility

1 2 Page 2
Page 2 of 2

import java.rmi.Remote; import java.rmi.RemoteException;

interface AgentHost extends Remote { /** * Requests that an agent transfer occur. * * A remote host calls this method on behalf of an agent and * requests the local host transfer the agent. The local host * responds by either transferring the agent and returning true, or * by returning false. * * It throws IOException if problems occurred while serializing the * data. * * It throws IllegalAccessException if a class or initializer was not * accessible. * * It throws InstantiationException if the agent tried to instantiate * an abstract class or an interface, or if the instantiation failed * for some other reason. * * It throws ClassNotFoundException if a required class could not be * found. * * It throws TransferFailedException if the local host attempted the * transfer but it failed -- either because the specified host * couldn't be found, the specified host rejected the transfer, * or the transfer failed for some other reason. * * It throws AgentNotFoundException if the specified agent does not * exist on the specified host. * * It throws RemoteException if something unexpected happened during * the remote method invocation. * */

public boolean requestToTransfer(AgentIdentity agentidentity, AgentHost agenthost) throws IOException, IllegalAccessException, InstantiationException, ClassNotFoundException, TransferFailedException, AgentNotFoundException, RemoteException;

/** * Begins a transfer. * * It throws IOException if problems occurred while serializing the * data. * * It throws TransferFailedException if the transfer failed -- either * because the remote host rejected the transfer, or because the transfer * failed for some other reason. * * It throws AgentNotFoundException if the specified agent does not * exist on the specified host. * * It throws RemoteException if something unexpected happened during * the remote method invocation. * */

public void beginTransfer(AgentIdentity agentidentity) throws IOException, TransferFailedException, AgentNotFoundException, RemoteException;

/** * Ends a transfer. * * It throws IOException if problems occurred while serializing the * data. * * It throws TransferFailedException if the transfer failed -- either * because the remote host rejected the transfer, or the transfer * failed for some other reason. * * It throws AgentNotFoundException if the specified agent does not * exist on the specified host. * * It throws RemoteException if something unexpected happened during * the remote method invocation. * */

public void endTransfer(AgentIdentity agentidentity) throws IOException TransferFailedException, AgentNotFoundException, RemoteException;

/** * Transfers the agent's resource file. * * The local host calls this method to transfer an agent's resource * file from the remote host to the local host. * * It throws IOException if problems occurred while serializing the * data. * * It throws TransferFailedException if the transfer failed -- either * because the remote host rejected the transfer, or the transfer * failed for some other reason. * * It throws AgentNotFoundException if the specified agent does not * exist on the specified host. * * It throws RemoteException if something unexpected happened during * the remote method invocation. * */

public byte [] transferResourceFile(AgentIdentity agentidentity) throws IOException, TransferFailedException, AgentNotFoundException, RemoteException;

/** * Transfers the agent's datafile. * * The local host calls this method to transfer an agent's datafile * from the remote host to the local host. * * It throws IOException if problems occurred while serializing the * data. * * It throws TransferFailedException if the transfer failed -- either * because the remote host rejected the transfer, or the transfer * failed for some other reason. * * It throws AgentNotFoundException if the specified agent does not * exist on the specified host. * * It throws RemoteException if something unexpected happened during * the remote method invocation. * */

public byte [] transferDataFile(AgentIdentity agentidentity) throws IOException, TransferFailedException, AgentNotFoundException, RemoteException; }

The AgentHost interface extends the Remote interface, making implementations of the agent host interface usable with remote method invocation. This allows agent hosts on one machine to communicate with agent hosts on another machine in a transparent manner.

The AgentHostImplementation class provides a concrete implementation of this interface. It provides definitions for each of the five methods shown above.

import java.io.IOException;

import java.rmi.RemoteException;

import java.rmi.server.UnicastRemoteObject;

import java.util.Hashtable;

class AgentHostImplementation extends UnicastRemoteObject implements AgentHost { /** * Requests that an agent transfer occur. * */

public boolean requestToTransfer(AgentIdentity agentidentity, AgentHost agenthost) throws IOException, IllegalAccessException, InstantiationException, ClassNotFoundException, TransferFailedException, AgentNotFoundException, RemoteException { byte [] rgbResource = null; byte [] rgbData = null;

// In response to a request to transfer an agent, the local // host (this one) begins the transfer, transfers the resource // and data pieces, and ends the transfer.

agenthost.beginTransfer(agentidentity);

rgbResource = agenthost.transferResourceFile(agentidentity);

rgbData = agenthost.transferDataFile(agentidentity);

agenthost.endTransfer(agentidentity);

// The resource data is passed to a specialized class loader which // loads the classes that make up the agent from the resource // piece.

AgentClassLoader agentclassloader = new AgentClassLoader(rgbResource);

// The agent wrapper is loaded. The agent wrapper knows how to // construct an agent from the data piece.

Class c = agentclassloader.loadClass("AgentWrapper");

AgentWrapper agentwrapper = (AgentInterface)c.newInstance();

// The agent is created from the serialized agent stored in // the data piece.

agentwrapper.initialize(rgbData);

// The agent is started.

agentwrapper.startAgent();

// The agent's identity and the agent wrapper are stored in // a hash table for later use.

hashtableAgents.put(agentwrapper.getAgentIdentity(), agentwrapper);

return true; }

/** * Begins a transfer. * */

public void beginTransfer(AgentIdentity agentidentity) throws IOException, TransferFailedException, AgentNotFoundException, RemoteException { // This executes on the remote host.

// The agent wrapper is read from the table.

agentwrapper = (AgentWrapper)hashtableAgents.get(agentidentity);

// The agent is stopped.

agentwrapper.stopAgent(); }

/** * Ends a transfer. * */

public void endTransfer(AgentIdentity agentidentity) throws IOException, TransferFailedException, AgentNotFoundException, RemoteException { // This executes on the remote host.

// The agent is removed from the table.

hashtableAgents.remove(agentidentity); }

/** * Transfers the agent's resource file. * */

public byte [] transferResourceFile(AgentIdentity agentidentity) throws IOException, TransferFailedException, AgentNotFoundException, RemoteException { // This executes on the remote host.

// The agent wrapper is read from the table.

agentwrapper = (AgentWrapper)hashtableAgents.get(agentidentity);

// The resource bytes are returned.

return agentwrapper.getResourceBytes(); }

/** * Transfers the agent's data file. * */

public byte [] transferDataFile(AgentIdentity agentidentity) throws IOException, TransferFailedException, AgentNotFoundException, RemoteException { // This executes on the remote host.

// The agent wrapper is read from the table.

agentwrapper = (AgentWrapper)hashtableAgents.get(agentidentity);

// The data bytes are returned.

return agentwrapper.getDataBytes(); } }

As you can see, the code is very simple. It relies on RMI to provide transparent network communication between agent hosts, and on object serialization to transfer the agent. This saves us from having to write (and debug) complicated socket code.

Conclusion

This column has been about agent mobility. As it turns out, by doing mobility the way we have, we get agent persistence for almost nothing. That's because writing the byte arrays making up the resource and data pieces of an agent to permanent storage is no more difficult than sending them to another host. In fact, it's a bit easier. I leave it to you to do the work.

Next month we add a bit more wood to the pile. In addition to mobility, agents must be able to communicate with each other. Tune in then and I'll show you one way to pull it off.

Todd Sundsted has been writing programs since computers became available in convenient desktop models. Though originally interested in building distributed object applications in C++, Todd moved on to the Java programming language when it became the obvious choice for that sort of thing. In addition to writing, Todd is president of Etcee, which offers Java-centric training, mentoring, consulting, and development.

Learn more about this topic

  • Find out all you can on remote method invocation including a tutorial, the specification, the API reference, tools, and release notes from Sun's RMI Web page http://www.javasoft.com/products/jdk/1.1/docs/guide/rmi/index.html
  • Get complete information on object serialization, including the specification, the API reference, tools, and release notes from Sun's Object Serialization Web page http://www.javasoft.com/products/jdk/1.1/docs/guide/serialization/index.html
  • Cetus Links provides gobs of information on mobile agents http://www.cetus-links.org/oo_mobile_agents.html
  • The Distributed Systems Group (Technical University of Vienna) includes an interesting look at mobile code, agents, and Java http://www.infosys.tuwien.ac.at/Research/Agents/
  • Check out the Centre for Advanced Learning Technologies' Information TechnologiesAgent Technologies page for everything related to agent technology http://www.insead.fr/CALT/Encyclopedia/ComputerSciences/Agents/
  • IBM Aglets SDK (formerly Aglets Workbench) is an environment for programming mobile Internet agents in Java http://www.trl.ibm.co.jp/aglets/
  • Mitsubishi's Concordia is a framework for development and management of network-efficient mobile agent applications http://www.meitca.com/HSL/Projects/Concordia/
  • JATLite is a package of programs written in Java that allow users to quickly create new software agents that communicate robustly over the Internet http://java.stanford.edu/
  • Previous How-To Java articles

1 2 Page 2
Page 2 of 2