Hello World!
The first example is intended to be the simplest possible instance of one actor talking to another, although the conversation takes place in a triangle among three actors. All they do is exchange one question-answer pair and then it's over.
The first thing to look at is the interface pair through which the actors communicate. As you can see they are just exchanging strings.
public interface HelloOutside {
void ask(String question, Closure closure);
}
public interface HelloInside {
String ask(String question);
}
|
Then we take a look at how the HelloActor expresses its need for others to talk with. The method name must begin with "need" but what the rest of the name is ignored. The important thing is the argument which is an instance of the outside interface. The actor can assume that there is an "other" interface available at all times.
private HelloOutside other
void needOthers(HelloOutside other) {
this.other = other
}
|
Now that the need is expressed and presumably satisfied, the HelloActor can make use of it in its chat() method, which prints messages before and after so that the output clearly reflects how it's all asynchronous. The second print statement is printed long before the other receives the question.
void chat() {
println "$name is about to speak."
other.ask("Hello, my name is $name: What is yours?") {
println "The reply was '$it'"
}
println "$name has spoken"
}
|
Now the HelloActor also has to offer the interface that lets its fellow actors chat with it, so it must implement the inside interface, much like a Java class would do.
public class HelloActor implements HelloInside {
// ...
String ask(String question) {
return "You asked '$question'. My name is $name."
}
// ...
}
|
Okay, the HelloActor is ready to do its business. What remains is building the agent scenario with a main script, which is just a piece of Groovy, with one special addition: the symbol "dx" which stands for dependency exchange. The dx is provided via the Groovy binding mechanism as a variable for the main script to use.
First thing here is to create a bunch of actors with names. Some nice Groovy syntax helps keep this simple. A list of names is fed to the "instantiate" method of the dependency exchange, which causes the HelloActor.groovy source file to be parsed.
names = [
"Gumby",
"Pokey",
"Rooney"
]
actors = names.collect { name ->
def actor = dx.instantiate('actors.HelloActor',name)
actor.name = name
return actor
}
|
Now that we have the actors created, we can specify how they are to be connected to each other when they decide to talk. Here there are no criteria and no feedback, but rather the matcher knows about the intended connections instead. The actors don't know, of course. The match closure makes use of the only implicit criterion that a Need object automatically assigns called "Identity" in order to do the lookup.
connections = [
"Gumby" : "Pokey",
"Pokey" : "Rooney",
"Rooney" : "Gumby",
]
dx.match(actors.HelloOutside.class) { criteria ->
connections.get(criteria.get("Identity"))
}
|
We're almost there. Now we just have to give each actor a jolt so that it starts acting, and this is best done from the main script. Remember that the method calls that acting produces are not immediately executed, but rather just scheduled for later.
for ( actor in actors ) {
actor.chat()
}
|
All the actors have done some chatting, but none of them have heard anything yet. To get the conversations moving we have to start satisfying the needs, so we set up a thread which sweeps through the needs every 100 milliseconds.
A brief pause of 1 second will give them all enough time to hear things and reply, and then we can shut down the dependency exchange and go home.
To run it, just type "ant helloworld" from within the example/hello directory.
helloworld:
[java] [INFO ] [GroovyDX.<init>] - Starting in src
[java] Starting HelloWorld.groovy
[java] Starting the HelloWorld Actor Scenario
[java] [INFO ] [GroovyDX.instantiate] - Parsing src/actors/HelloActor.groovy
[java] Gumby is about to speak.
[java] Gumby has spoken
[java] Pokey is about to speak.
[java] Pokey has spoken
[java] Rooney is about to speak.
[java] Rooney has spoken
[java] The reply was 'You asked 'Hello, my name is Rooney: What is yours?'. My name is Gumby.'
[java] The reply was 'You asked 'Hello, my name is Pokey: What is yours?'. My name is Rooney.'
[java] The reply was 'You asked 'Hello, my name is Gumby: What is yours?'. My name is Pokey.'
[java] Finished the HelloWorld Actor Scenario
[java] Finished HelloWorld.groovy
|
|