Basically, the Directory Facilitator agent (DF) is a yellow pages server. Provider agents may register (and deregister) the types of services they perform with the DF. Client agents may search the DF for providers of a given service.
The interface to the DF agent is through the DFService utility class. We also provide a DFUtils class.
Our provider agent has a single provider behavior that performs two distinct services called "ServiceA" and "ServiceB":
class ProviderBehavior extends CyclicBehaviour {
protected ACLMessage
makeReply(ACLMessage msg) {
String info = msg.getContent();
ACLMessage reply =
msg.createReply();
if
(info.equals("ServiceA")) {
reply.setContent("Performing
serviceA for " +
msg.getSender().getLocalName());
} else if
(info.equals("ServiceB")) {
reply.setContent("Performing
serviceB for " +
msg.getSender().getLocalName());
} else {
reply.setContent("What?");
}
return reply;
}
public ProviderBehavior(Agent a) {
super(a); }
public void action() {
ACLMessage msg = myAgent.receive();
if (msg != null)
myAgent.send(makeReply(msg));
block();
}
}
Of course we could have created two separate behaviors, one for each service.
During setup, the provider agent creates a DFD (DFAgent description record). The DFD will contain the AID of the agent plus information about the protocols, ontologies, languages, and services the agent supports:
DFAgentDescription dfd = new DFAgentDescription();
dfd.setName(getAID());
For each service the agent performs, we must create a service description and add it to the DFD. For example:
ServiceDescription serviceA
= new ServiceDescription();
serviceA.setType( "serviceA" );
serviceA.setName( getLocalName() );
Before registering the DFD, we must deregister previous incarnations:
DFAgentDescription list[] = DFService.search( this, dfd );
if ( list.length > 0 ) DFService.deregister(this);
Now we are ready to register the DFD:
DFService.register(this, dfd);
During takedown the provider agent must deregister itself:
DFService.deregister(this);
Here's the complete code:
public class ProviderAgent extends Agent {
protected void setup() {
DFAgentDescription dfd = new
DFAgentDescription();
dfd.setName(getAID());
ServiceDescription serviceA = new ServiceDescription();
serviceA.setType(
"serviceA" );
serviceA.setName( getLocalName()
);
ServiceDescription serviceB = new ServiceDescription();
serviceB.setType(
"serviceB" );
serviceB.setName( getLocalName()
);
try {
DFAgentDescription
list[] = DFService.search( this, dfd );
if ( list.length > 0 )
DFService.deregister(this);
dfd.addServices(serviceA);
dfd.addServices(serviceB);
DFService.register(this, dfd);
} catch (FIPAException fe) {
System.err.println(fe.getMessage());
}
addBehaviour(new demos.ProviderBehavior(this));
System.out.println("Agent
" + getLocalName() + " is ready!");
}
protected void takeDown() {
try {
DFService.deregister(this);
} catch (FIPAException fe) {
System.err.println(fe.getMessage());
}
System.out.println("Agent " + getLocalName() +
" is shutting down");
}
}
Our request agent has two behaviors, one that sends a "ServiceA" request to all agents that provide ServiceA, and another that sends a "ServiceB" request to all agents that provide ServiceB. The RequestB behavior searches the DF for all agents that provide "ServiceB":
AID[] providers = DFUtils.searchDF(myAgent, "ServiceB");
To send a request for "ServiceB" to provider i is simple:
ACLMessage msg = new ACLMessage(ACLMessage.REQUEST);
msg.setContent( "ServiceB" );
msg.addReceiver( providers[i]);
myAgent.send(msg);
Here's the complete code:
class RequestBBehavior extends OneShotBehaviour {
public RequestBBehavior(Agent a) {
super(a); }
public void action() {
AID[] providers = DFUtils.searchDF(myAgent,
"ServiceB");
if (providers != null) {
for(int i = 0; i <
providers.length; i++) {
ACLMessage msg = new ACLMessage(ACLMessage.REQUEST);
msg.setContent( "ServiceB" );
msg.addReceiver( providers[i]);
myAgent.send(msg);
msg= myAgent.blockingReceive();
if (msg!=null)
System.out.print("Response:
" + msg.getContent());
System.out.println("
from " +
msg.getSender().getLocalName()
);
} // for
} // if
}
}
Here's the code for the request agent:
public class RequestAgent extends Agent {
protected void setup() {
addBehaviour(new demos.RequestABehavior(this));
addBehaviour(new demos.RequestBBehavior(this));
}
}
public class DFUtils {
static void register( Agent a,
ServiceDescription sd) { ... }
static AID getService( Agent a, String
service ) { ... }
static AID [] searchDF( Agent a, String
service ) { ... }
}
static void register(
Agent a, ServiceDescription sd) {
DFAgentDescription dfd = new
DFAgentDescription();
dfd.setName(a.getAID());
try {
DFAgentDescription
list[] = DFService.search( a, dfd );
if ( list.length>0 )
DFService.deregister(a);
dfd.addServices(sd);
DFService.register(a, dfd);
}
catch (FIPAException fe) {
fe.printStackTrace();
}
}
static AID getService(
Agent a, String service ) {
DFAgentDescription dfd = new
DFAgentDescription();
ServiceDescription
sd = new ServiceDescription();
sd.setType(
service );
dfd.addServices(sd);
try
{
DFAgentDescription[] result =
DFService.search(a, dfd);
if (result.length>0)
return result[0].getName() ;
}
catch (FIPAException fe) {
fe.printStackTrace();
}
return
null;
}
static AID [] searchDF(
Agent a, String service ) {
DFAgentDescription dfd = new
DFAgentDescription();
ServiceDescription
sd = new ServiceDescription();
sd.setType(
service );
dfd.addServices(sd);
SearchConstraints ALL = new
SearchConstraints();
ALL.setMaxResults(new Long(-1));
try
{
DFAgentDescription[] result =
DFService.search(a, dfd, ALL);
AID[] agents = new
AID[result.length];
for (int i=0; i<result.length;
i++)
agents[i] =
result[i].getName() ;
return agents;
}
catch (FIPAException fe) {
fe.printStackTrace(); }
return
null;
}
In this example larry, curly, and moe are provider agents and abbot is a request agent:
Agent larry is ready!
Agent curly is ready!
Agent moe is ready!
Response: Performing serviceA for abbot from moe
Response: Performing serviceA for abbot from curly
Response: Performing serviceA for abbot from larry
Response: Performing serviceB for abbot from moe
Response: Performing serviceB for abbot from curly
Response: Performing serviceB for abbot from larry
We can start new containers in separate console windows using the command:
runjade -container
To start a container on a separate machine, we must specify the URL of the main container:
runjade -container -host myServer.cs.sjsu.edu
Of course once the container has started, it appears in the GUI and we can add agents to it:
Alternatively, we can add the agent at the command line:
runjade -container -host myServer.cs.sjsu.edu sue:demos.RequestAgent