Coordinating Java agents over the WWW P.Ciancarini and D.Rossi Dipartimento di Scienze dell'Informazione Mura Anteo Zamboni, 7 University of Bologna 40127 Bologna - Italy E-mail: fciancarini,
[email protected]
Abstract We introduce Jada, a programming toolkit for coordinating agents written in Java. Coordination among either concurrent threads or distributed Java objects is achieved via shared object spaces. By exchanging objects through object spaces, Java agents or applets can exchange data or synchronize their actions over the Internet, a LAN, a single host, or even inside a Java-enabled browser. The access to an object space is performed using a set of methods of an ObjectSpace object. Such operations inspired by the Linda language are powerful enough to solve several coordination problems. Moreover, we show how Jada can be used as a coordination kernel for more complex coordination architectures.
ii
,
1
1
INTRODUCTION
The WWW has a great potential for supporting distributed multiuser applications, especially after the introduction of Java. In fact, the WWW can be seen as a programming platform to integrate Internet-based services and multiuser applications in which proactive or reactive processing is required, like groupware or work ow [Evans and Rogers 1997; Chen and Cowie 1997]. In this paper we investigate how the WWW software architecture integrated by Java should be used to design distributed multiuser applications. Java is quite eective for this kind of applications, because it oers a uniform software platform to implement software running on heterogeneous architectures. However, although Java is multithreaded, it is not a language for distributed programming [Lea 1997]. Typically it must be integrated by libraries based on sockets to support distributed processing. Unfortunately, programming distributed systems using sockets is notoriously boring, dicult, and error-prone. An alternative strategy consists of adding to Java high-level coordination mechanisms [Ciancarini and Rossi 1997]. These mechanisms must usually take into account whether the Java application is accessed through a browser. HotJava, a WWW browser, has been the rst Internet application of Java. What made it dierent from other browsers is its ability to run Java code \embedded" within HTML documents. This way HTML documents become \active", namely it is easy to put animation in HTML pages. Moreover, the same mechanism can be used to extend a browser in a natural way, implementing, for example, editors, spreadsheet, and groupware applications made of distributed objects. The most important consequence of having Java-enabled browsers like HotJava is that a Java application can be \spread" around the network. The simplest way to take advantage of this feature is to think about a Java application just like a document. Watching a Java application means let it run in your host, possibly integrated within your browser. The Java way to obtain this is to build each piece of Java code to be run in a browser as an \applet". Currently, the standard Jada distributed object model is based on Remote Method Invocation (RMI), an object oriented RPC mechanism. The simple client/server relationship allowed by RMI is not exible enough to express all the kinds of relationships a distributed system can activate among its components [Lewis 1995]. RMI allows remote applets to enact a client/server relationship but things get more dicult when we have to program more complex cooperation protocols. If the WWW has to become an infrastructure for both developing and implementing business applications in distributed and collaborative environments, we need the ability to manage coordination among remote Java components. This is the topic of this paper, which has the following structure: in Sect.2 we introduce Jada, which extends Java with coordination mechanisms; in Sect.3 we discuss how we implemented
2
,
Jada; in Sect.4 we show some simple Jada programs. In Sect.5 we prove that Jada is an eective coordination kernel designing Shade, a transational coordination language for multiagent architectures; in Sect.6 we discuss how we implemented Shade using Jada; in Sect.7 we show some multiagent Shade programs. In Sect.8 we compare our approach with other similar systems; Sect.9 concludes the paper.
2
A TOOLKIT FOR PROGRAMMING DISTRIBUTED JAVA APPLICATIONS
Jada is a toolkit for Java that uses the principles of coordination languages to manage the cooperation of concurrent/distributed activities. We rst recall some basic notions on coordination languages [Carriero and Gelernter 1992]. Coordination concerns the actions for synchronization, communications and service invocation and provision. Computation is about the actions of processes. Coordination languages focus on the separation between coordination and computation, not meaning that they are independent or dual concepts, but meaning that they are orthogonal [Carriero and Gelernter 1992]. Most coordination languages include a small set of operations on shared data spaces, like Linda [Gelernter 1985] (where focus is on communication issues) or Laura [Tolksdorf 1992] (where focus is on service design issues). Jada introduces in Java the principle of coordination adding a minimal set of coordination primitives [Carriero and Gelernter 1992]: in particular, we add operations to access multiple object spaces. In fact, we designed Jada aiming for simplicity rather than performance. Jada, like Linda, is a minimalist coordination language. Dierently from other Linda-like implementations, which usually include a preprocessor because Linda slightly modi es the host language syntax, Jada is based on a set of classes to be used to access object spaces, allowing the users to keep their standard Java development tools. Using the in, out, and read methods to access object spaces concurrent (either local or remote) components can establish complex relationship, thus re ecting the real inter-dependencies among them. We now show more closely how Jada works, which are the classes introduced by the Jada package, and how we use them. Jada is implemented as a set of classes that allow either Java threads or Java applications to access associatively a shared coordination medium using a small set of operations useful to build a distributed application. A coordination medium can be either local to the application/applet (ObjectSpace, to be shared between threads) or remote (ObjectClient, to be shared between applications/applets). In the latter case an object space server (ObjectServer) must be running in a host accessible through the network.
,
3
2.1 Object Spaces An ObjectSpace is an object container oering a set of methods for accessing its contents. out is the method to put objects in the ObjectSpace, in and read are the methods to get objects from the ObjectSpace. To create an object space we write: ObjectSpace my object space=new ObjectSpace();
To put an object in the object space we write: my object space.out(new String("foo"));
To access the ObjectSpace we use an associative mechanism: the in method has as a parameter an object which is used as a matching pattern. The object the in method will return (if any) is taken from the object space and matches the given matching pattern (the same applies to the read method; the dierence between read and in is that in removes the object from the object space). The matching operations distinguish between formal and actual objects: a formal object is an instance of the Class class (the meta-class used by Java). Any other object is an actual object. The Jada matching rules are:
actual-actual: two actual items match if { they implement the JadaItem interface: the method matchesItem, applied to the object in the object space, passing as parameter the other object, returns true.
{ they do not implement the JadaItem interface: the method equals, applied to the object in the object space, passing as parameter the other object, returns true.
actual-formal: a formal item matches any object which is an instance of it.
formal-formal: two formal items match if they represent the same class.
The matching mechanism in Jada is object oriented; this means that inheritance is applied when matching two objects. The type returned by an in or read operation can be a subclass of the speci ed object (however, inheritance is not applied to formal-formal matching). For instance, object space.in(new Object()) is a swallower for any non-formal object stored in the object space. The Jada matching rules are simple yet powerful; however, sometimes they are not expressive enough. Since the actual-actual matching is customizable (using either equals or matchesItem) the mechanism is also very exible: we can write an integer wrapper class with ad-hoc matching rules so that an object matches
4
,
any object whom contents is less that the one given in the in or read call. But most of the times what's needed is a way to associate values (an integer with a string that represent the sense of the integer, such as "counter"; or a record such as name, address and phone number). Thus we introduce the Tuple class, an object container class with an extended matching mechanism.
2.2 Tuples In Jada a tuple is a set of objects (or items) implemented by the jada.Tuple class. This is an example of Jada tuple: Tuple my tuple=new Tuple(new Integer(10),"test");
Such a tuple includes two items (we say that its cardinality is two); the rst item is an Integer object, the second one is a String object. We de ne actual and formal items within a tuple the same way we de ned them for Jada. Two tuples a and b match if they have the same cardinality and each item of a matches the corresponding item of b. The usual Jada mechanism is used to check if the items match. Thus, the tuple Tuple a=new Tuple(new Integer(10),"test");
matches the tuple: Tuple b=new Tuple(new Integer(10),new String().getClass());
In order to exchange a tuple (or generally any object) two threads do not need to perform a pair of out and read operations at the same time (Jada does not need rendez-vous communication). In fact, suppose the threads ta and tb want to exchange a message: ta will put a message inside the object space, tb will read the message from the object space. If ta performs the out operation before tb performs the read operation it does not have to wait for tb: it simply continues its execution, the tuple is now stored into the object space. When tb performs the read operation it will be able to read it. Instead, if tb performs the read operation before ta performs the out operation, tb will be blocked until an object that satisfy the read request will become available (i.e. until ta performs the out operation). The in and read methods are indeed blocking. If you want the thread not to be blocked when a matching object for the in and read operations is not available you can use the in nb and read nb methods: they access the object space the same way as in and read but if no matching object is available they simply return null (more sophisticated avors of in and read that aborts after a time-out are available too).
,
5
2.3 ObjectServer and ObjectClient To allow remote access to an object space, the jada.net.ObjectServer and jada.net.ObjectClient classes are provided. A simple client/server architecture manages the object spaces; in fact, each object space is a shared remote resource accessed through an object space server. An object space server is addressed using the IP address of the host it runs on (as usual with socket connections, a speci c port number has to be speci ed). This way we can run as many object space servers as we like in a network, so that applications can independently operate on several, distributed object spaces. ObjectServer is a multithreaded server class which translates requests received from the ObjectClient class in calls to the methods of the ObjectSpace class. In fact, both ObjectServer and ObjectClient are based on ObjectSpace, and communicate using sockets. ObjectServer uses ObjectSpace to perform the requested operations. The ObjectClient class extends ObjectSpace changing its internals but keeping its interface and behavior (apart from some new constructor and few new methods). Thus, a ObjectClient object is used just like a ObjectSpace one, except that it provides access to a remote object space which can run in any host of the network. What ObjectClient does is to interface with a remote ObjectServer object (which holds the real object space) and requests it to perform the in, read and out operations and (eventually) to return the result.
2.4 Serialization To handle remote object space access we need our classes to provide:
a method to dump the object contents to a byte stream, in order to be able to send a tuple across a network or to save its state to a le. (dumpItem).
a method to restore a tuple given a set of bytes read from a byte stream. (buildItem).
These two tasks are operations we usually need when dealing with distributed objects and they are often referred as serialization operations. Starting with version 1.1 the Java language has integrated support for this kind of operations (which is, of course, needed by RMI). For historical reasons (Jada was born long before RMI) and to provide added exibility Jada, besides the Java build-in serialization mechanism allows two other serialization mechanism:
6
,
serialization via JadaItem. If the object we want to serialize implements JadaItem he must have de ned the code for the dumpItem and buildItem methods which are used respectively to dump the object to a stream and to build an object from a stream.
serialization via JadaSerializer. If the object we want to serialize does not implement JadaItem there must be a JadaSerializer object de ned for such object type that as been passed to the Jada runtime system using the addSerializer method of the JadaSystem class. This must be done on both client and server side. JadaSerializer is an interface that must be implemented by classes which are used to serialize objects. These classes must then have de ned the code for the dump and restore methods, which are used to serialize the object. When the Jada system is initialized the default serializer for the Integer, Float and String classes are provided to the system (we could use for those the build-in Java serialization support but in our preliminary tests the use of a JadaSerializer object has been faster).
The Tuple class itself extends JadaItem and then oers support for serialization but relies on serialization support by tuples' items in order to dump/restore them. We can also note that the Tuple class itself implements the JadaItem interface so we can use a Tuple object as a eld of a tuple.
3
SOME DETAILS ON THE IMPLEMENTATION
3.1 ObjectSpace An ObjectSpace object in Jada is an object container which oers a set of thread-safe access methods. Thread-safe means that accessing an ObjectSpace from dierent threads at the same time is safe since monitors are used to handle requests avoiding problems with critical regions. The methods are the usual in, read and out (along with their multiple, non-blocking and time outaware variants). All these methods are actually just wrappers for the doInRead and doOut methods, which are the real `engines" for this class. All the synchronization and repository management code is part of these methods. This allows to easily rede ne ObjectSpace behaviour by extending its class just like we did with ObjectClient. For example the doOut method of ObjectSpace takes care of putting the speci ed object in the object space or use it to reply pending in or read requests. The ObjectClient's version of doOut, instead, sends the tuples to an object server and asks it to manage the storing/replying. The same applies for ObjectClient's version of doInRead. We need indeed just to change these two methods to deal with a remote tuple manager (which is a ObjectServer object) and use socket connections to talk with it.
,
7
Thread3
Thread2
Thread1
ObjectSpace
Figure 1: Local threads accessing an object space
3.2 ObjectServer An ObjectServer object is used by ObjectClient objects to access a (possibly remote) object space. An ObjectServer includes an ObjectSpace object to manage the object space. Each time an ObjectClient performs a request the ObjectServer spawns a new thread to perform the requested operation. From the architectural point of view an ObjectServer/ObjectClient is like a stub/skeleton system (and indeed we also wrote a version of Jada that uses RMI to access a remote ObjectSpace object but such an implementation turned out to be much slower than our original code). If we analyze the behavior of a Jada program we distinguish two main cases:
the use of an ObjectSpace shared among concurrent threads belonging to the same application, a situation symbolically depicted in Fig.1. Each shape in such a picture represents a thread running within an application. Thread1, Thread2, and Thread3 are interacting with the object space (using ObjectSpace methods). The ObjectSpace object manages their access and takes care of handling critical regions managing. Note that some of the thread may have blocked calling a method to perform a blocking in or read operation.
the use of an ObjectSpace shared among concurrent threads belonging to dierent applications. In this case we have to use an ObjectServer/ObjectClient architecture to access the shared space, as we show in Fig.2. Thread1 and Thread2 are now part of an application while Thread3 is part of a dierent one. The former ones are using the same ObjectClient object to access the object space, while the latter one uses a private object space. When a thread performs a request calling a method of the ObjectClient object, the request if forwarded to the ObjectServer object, using a network connection, which runs
8
,
ObjectServer
Thread3proxy
Thread2proxy
Thread1proxy
ObjectSpace
ObjectClient
Thread3
Thread2
Thread1
ObjectClient
Figure 2: Remote threads accessing an object space
,
9
a thread to handle it. Each thread run by the object server then corresponds to a remote thread which made a request (actually this is not always true because of the optimizations we applied; such a concept, however, easier to understand). We can see how the former situation is automatically replicated in the latter one inside the application which runs the ObjectServer, where the threads that are created to handle remote requests behave just like the threads in a local ObjectSpace, giving evidence to the implicit scalability of Jada's architecture.
4
PROGRAMMING WITH JADA
Using Jada to allow threads to exchange data is quite an easy task but we can do even better. We can use Jada to coordinate threads, thus easily solving many well-known coordination problems:
5
server/client model: a server read requests in form of tuples from the tuple space. A client performs a request putting a tuple in the tuple space.
master/worker model: the master put jobs in form of tuples in the tuple space, then reads results from the tuple space. Workers read jobs from the tuple space, execute their task, and then put the result into the tuple space.
producer/consumer model: we decouple a producer and a consumer using the tuple space as temporary repository for data to be exchanged.
mutual exclusion: we can use a tuple as a "token" to enter a critical section: any thread need to get such a token to enter the section. Upon exiting the section the thread releases the token (i.e. the token tuple can be put back into the tuple space)
message passing, either synchronous or asynchronous: a sender puts the message into the tuple space (and in the synchronous case waits for an ack tuple). The receiver reads the message from the tuple space (and in the synchronous case puts an ack tuple in the tuple space).
FROM SIMPLE COORDINATION TO RULE-BASED TRANSACTIONS
Jada is especially useful for WWW applications which need support for rule-based processes, work ows, and logically distributed transactions. However, there are situations in which Jada cannot be used because it is based on singleton object transactions, whereas in several cases we need to test, delete, or replace multisets of objects.
10
,
Multiset rewriting is a powerful coordination paradigm which allows a natural de nition of a logically distributed system as a set of coordinable, concurrent agents [Andreoli et al. 1993]. Instead of singletons including single object, multiset rewriting is based on the concept of multiset, namely a set whose elements can have multiple copies. In the basic multiset rewriting model, a number of rewriting rules are associated to a multiset. A rewriting rule is simply a pair of multisets: one called the head, and one called the body. A rule res when the rule head matches a submultiset of target multiset; the result of the ring consists of deleting from the target multiset all elements corresponding to the head, and writing back in the target elements corresponding to the rule body. A language based on the multiset rewriting model is Shade, a rule-based coordination language for agents. Active objects (agents) react to the stimula coming from their environment, obeying to some coordination rules. In Shade each agent has a multiset representing its own state and a set of rewriting rules associated to that multiset. Communication among agents is performed by putting items in the receiver(s) multiset. Java applets are certainly active. When they run in dierent browsers they need to coordinate, for instance to implement groupware applications. Thus, we introduce Shade/Java, extending Jada with a concept of logically distributed transaction which we call coordination rule.
5.1 Shade A Shade program is a collection of classes; each object in a Shade application is an instance of a class. We can think of each object in a Shade application as an agent in a agent world. Each class in the Shade program contains a set of methods which are coordination rules de ning the behavior of the objects which are instances of that class. A class can be extended using inheritance, i.e. its behavior can be modi ed adding new rules. Objects are class instances and have a state. An object state (its multiset, in this case a tuple space) changes when a coordination rule res, rewriting the state, or when the object receives a message. A Shade rule has a head and a body. The head is a guard is used to trigger the method itself and gets items from the tuple space, while the body puts items in it. When a rule is activated (by satisfying a guard which can remove matching items from the tuple space or simply check for their existence) an action is performed. The action is one of:
writing items in the object's tuple space;
writing items in other objects' tuple spaces; (i.e. sending a message)
,
11
create a new object.
In Shade coordinables are active objects; the coordination medium is a tuple space, whose properties are similar to Interaction Abstract Machines [Andreoli et al. 1993]. This means that the action of writing in other objects' tuple spaces is performed by a special form of multicast. A message's address is a pattern; messages are delivered to each object whose name matches the given pattern. This way we can easily express with the same basic mechanism point-to-point, multicast, and broadcast communications. Messages are persistent: when a new object is created, it receives all messages generated before its creation whose addresses match its own name. Each object in Shade has a name, a class, and a state. The name is the pattern used to deliver messages. The type de nes the object behavior (a Shade program is indeed a collection of classes de nitions, where a class is a set of rules). The state is the contents of the multiset associated to the object. Consider the following simple program: class ping class = f in do ping; send pong, do pong # in done; terminate
g.
class pong class = f in do pong; send ping, do ping # in done; terminate
g.
The example shows two classes: the ping class and the pong class. The behavior described by ping class is composed of two methods (they are separated by a #). The rst method is activated when the item ping appears in the object's multiset. When the method is activated, a message is sent to the object whose name matches pong; the message is the item do pong. When the message is delivered, the item
12
,
is put into pong's multiset. If pong is an instance of the pong class class this message triggers pong class's rst method and so on. The second method of both classes is triggered by the item done and causes the termination of the object. Methods are composed of elds. Each eld is either a trigger for the method itself or an action. Triggering elds are: do pong
read items list: the method is triggered when the items of the items list are contained in the object's multiset.
in items list: the method is triggered when the items of the items list are contained in the object's
multiset; if so, the items are removed from the multiset. Action elds are:
with fcodeg: code written in a host language performs the computations needed for the out, send and create elds (see below).
out items list: the items in the em items list are put into the object's multiset.
send destination,items list: a message containing items list items is generated and sent to each object whose name matches the destination pattern.
create name,class,where,items list: an object with name name, with behavior described by the class class is created. The initial multiset of this object is items list. where describes when the object can
be located.
terminate: the object is terminated.
5.2 Shade/Java Shade/Java is a syntactic extension of Java with coordination features of Shade: rules are in fact translated to methods that are executed by concurrent threads. Each object's tuple space is an ObjectSpace containing just Tuple objects. A Shade/Java program consists of a set of classes; each class may include a set of rules with the following operations:
read list of tuples: read matching tuples from local tuple space, reporting a substitution if any.
in list of tuples: fetch matching tuples from local tuple space, reporting a substitution if any.
13
,
with method: execute a Java method which returns a boolean value.
out list of tuples: put in local tuple space tuples in list of tuples. Remark: out
terminate
terminates
the local tuple space.
send dest,list of tuples: send to dest tuple space the list of tuples.
create class,object,list of tuples: create a new tuple space named object inheriting from class class with initial state list of tuples.
Each Shade/Java rule includes two parts: head including read, in, and with. The head is a transaction over the local tuple space. If all operations can be performed, they commit and the body is executed. body including send, create, and out.
Interobject communication is always represented by a send[to,tuple] operation, but it can have three avors:
broadcasting if to is \ ": all objects receive the tuple.
multicasting if to is a class name: only instance objects of such a class receive the tuple.
unicasting if to is an object name: only that object receives the tuple.
Receivers are responsible of receiving a tuple, i.e. they look in the tuple space for tuples matching their names. Moreover, the tuple space is persistent, namely a new born object receives all relevant tuples even if they were sent before its creation. We describe now a code fragment which coordinates the subscription of some participants to an auction. We de ne three classes: one for the auctioneer, one for the participant, and a time-server used to signal a timeout after n seconds. class auctioneer { in ("start_auction"); send [participant, ("begin_subscription")], [alarm, ("time", 10)]; out ("wait_subscription"); # read ("wait_subscription");
14
,
in ("subscribed", ?s:part_#1); send [participant, ("subscribe_OK")]; # in ("time_out"), ("wait_subscription"); out("show_first_item"); # ...
// starts showing items
}
class participant { in ("begin_subscription"); read (s:?name); send [auctioneer_name, ("subscribed", name)]; # ...
// wait item
}
class time_server { in ("time", ?i:sleep_time); with sleep(sleep_time); send [auctioneer_name, ("time_out")]; }
The system could be started with the following main. create [participant, participant_#1, ("participant_#1")]; ... create [participant, participant_#n, ("participant_#n")]; create [time_server, time_name, ]; create [auctioneer, auctioneer_name, ("start_auction")];
In g. 3 we see a possible trace in which the second participant tries to subscribe too late, and is forbidden to join the auction. Initially the auctioneer only can re a method, which activates all participants and the time
15
,
time_server
auctioneer
part_#1
part_#2
("start_auction")
partecipant_#1
partecipant_#2
...
partecipant_#2 ("begin_subscription") ("time",10)
partecipant_#1 ("begin_subscription")
time
("wait_subscription") ("subscribed",partecipant_#1)
partecipant_#1 ("subscribe_OK") ("wait_subscription") ("time_out")
("show_first_item")
Figure 3: A possible trace server. The local state of an auctioneer includes tuple ("start auctioneer") before ring; it includes ("wait subscription") after ring. The local state of a participant initially includes its name only; after the auctioneer initialization it contains also the tuple ("begin subscription"), while the time server contains the tuple (10). Now all objects can execute a method, so that all participants subscribing within 10 seconds join the auction. This example shows the behavior of a Shade/Java program: items in the object space are used to represent the actual object's state (e.g. ("start auctioneer"), ("begin subscription"), etc). The state is usually changed by rules that re when an event occurs (e.g. a timeout is raised); this programming style is possible because of the powerful multiset rewriting paradigm and its multiple object transaction performed
16
,
by Shade/Java.
6
IMPLEMENTING A COORDINATION LANGUAGE ON A COORDINATION KERNEL
The rst implementation of Shade was based on C, Prolog, and Tcl/Tk/Expect [Castellani et al. 1996; Ciancarini et al. 1997]. Prolog was used as host language (in with clauses); Tcl/Tk was used for programming user interfaces, while Shade coordination was implemented in a mixture of Expect (a scripting language based on Tcl/Tk) and C plus socket libraries. Since we intended to use Shade over the WWW, we have switched the host language to Java which has been our uniform reference and, coupled with HTML, also our universal implementation platform (thus we abandoned C, Prolog, and Tcl/Tk/Expect). The current Shade implementation is completely written in Jada; moreover, the agent language to be used in with clauses is Java as well. This means that Shade/Java is an extension of Jada with the primitives of the Shade coordination model. In fact, the Shade/Java compiler is actually a precompiler for the Java compiler extended with Jada classes. Active objects can be created at any time and can stay on any host. Each object communicates with the global object space and has a private tuple space. Each object includes the code of its class; the code consists of a set of methods which are parallel threads themselves. If the private tuple space, which represents the object local state, contains a tuple multiset satisfying the guard of a method, such a method res. If no method can re the object suspends, waiting for new tuples coming from outside. Parallel threads can synchronize either using Java mechanisms (i.e. monitor synchronization primitives) or using Linda-like operations on tuples in the local state, as usually done with Jada [Ciancarini and Rossi 1997]. The object space is a meta tuple space [Ciancarini 1994] which implements send and create Shade operations. Both operations put in the object space special tuples, which are then \interpreted" by the runtime support. The object space is implemented using two tables: a message table and an object table. The message table includes tuples (dest,msg) created with out. Objects query the message table associatively looking for tuples. Such a table is persistent, meaning that it is independent from both senders and possible receivers of tuples. The object table includes tuples (class name, object name, tuple list) created with create.
,
17
In the current implementation objects are created on the host running the object space; We plan a new implementation in which each class can be declared as \rooted" in a host, so that a new object would be created on that host. Here is a summary of the behavior of all Shade components:
the objects: - check for rules to re and run them - send create and send requests to the remote tuple space - read new messages from the remote message space
The tuple space: - listens for connection with objects - manages object creation and message storing
Such a centralized approach to storing messages is useful to coordinate applets in browsers whose default security mechanism allows only to connect the server the applet code is loaded from.
7
AGENT PROGRAMMING WITH SHADE/JAVA
We now show how to use Shade/Java for designing, building, and coordinating a WWW multiagent application. This example demonstrates the WWW potential for ruling work ows of applications in the eld of electronic commerce. We have to build an auction bidding system distributed over the Internet in order to provide services for the following users:
Auctioneer, who sells items to the best oer;
Participants, who buy items by participating to the auction;
Observers, who are (passive) auction spectators.
We distinguish the following phases: Phase 0 : The auctioneer makes the auction public via newsgroups, mailing lists, and a WWW site. The auctioneer provides for an information package explaining the modalities for the users interested in the auction. Users can either simply observe the auction, or actively participate to the bidding. In the rst
18
,
case, they will be informed of the bids, but they could not buy an item. In the second case, they could actively participate to the bidding, sending bids for an item, if they have produced some credentials (a credit card number, for example). Phase 1 : The auctioneer puts an item up for auction. The auctioneer decides the timeout waiting time for the reception of the participant messages, TIMEOUT, as long as he likes. Moreover, the auctioneer can send noti cation messages to all the users that are connected to the auction. Phase 2 : The auctioneer sends a communication to all the registered participants and the observers who are connected. The communication contains the CURRENTBID, which at this time is the BASEPRICE of the item. Phase 3 : When the participant receives a communication containing the CURRENTBID for a given item, he can send one of the following answers:
{ NEWBID: if the participant wants to send a new bid higher then the CURRENTBID; { UNSUBSCRIBE: if the participant wants to give up. Phase 4 : The auctioneer receives the answers from participants until TIMEOUT. The auctioneer will react to the reception of such answers according to the following schema:
{ if the communicationis NEWBID then the auctioneer compares NEWBID with CURRENTBID. If NEWBID is greater than CURRENTBID then NEWBID becomes the new value CURRENTBID, and the auctioneer sends a communication containing the new value for the CURRENTBID to all the participants and observers. The auctioneer then resets the time and the phase 4 restarts.
{ if the communication is UNSUBSCRIBE, the auctioneer eliminates the participant from the list of participants.
After TIMEOUT the auctioneer informs all the participants that the item was sold, if the value of CURRENTBID is higher than the value of the BASEPRICE. The auctioneer proceeds then putting on sale other items, if any (phase 1), or closing the auction. If the value of CURRENTBID is equal to the value of BASEPRICE the auctioneer archives the item as UNSOLD, and proceeds with the selling of other items, if any, otherwise he closes the auction. All participants and observers can see the progress of the bidding via WWW browsers.
,
19
7.0.1 Interface
The interface we have designed is shown in Fig.4. We have used HTML3 frames to format the interface page.
Figure 4: Auction bidding over WWW: bidder interface This page, to be used by auction bidding customers, includes three frames. The rst one, top left, shows the item to be sold. The second, top right, is a form usable to insert a bid, to skip this auction to the next item, and to see the auctioneer's gavel falling when the item is sold. The last one, in the bottom of the page, shows a owing string denoting the current bid and the bidder name. 7.0.2 Applets
Fig.5 depicts the applet agents we use to animate such an interface page, in positions corresponding
20
,
to those shown in Fig.4. bid
agent next_item
agent cartoon
agent
display agent
Figure 5: Applets in the auction system Agent bid is interactive: it allows a customer to place a bid. This applet is always active waiting for user input. The customer using such an interactive agent has to choose an amount to increment the current bid (displayed by applet display). The customer must insert in TextField his username; the amount is chosen by the (Choice) button (in g. 4 this shows $500); nally, the user has to press another button to send the oer. Agent next item is a button which allows to skip the current item on auction to another one. Agent cartoon animates a gavel representing that the current auction is still in progress, or it is nished (the gavel falls). The animation is based on a sequence of ve images. Agent display shows the current bid and its owner. This agent is especially critical, because it must show the same information to all bidders. The most critical agent is the auctioneer, which is the logic coordinator of the whole system and can run on any host. It decides when an oer is valid; it tells agent display about the current bid; it sells an item, etc. This agent is not displayed by an applet in an HTML page, however it is programmed in Shade. In g. 6 we show the logic structure of the auction bidding system. The tuple space has to run on a server machine running also the auctioneer for security constrains imposed by Java. Other agents have no constrains at all. We now describe and discuss the Shade/Java code implementing the behavior of agents in Fig. 4. We omit both the HTML code for rendering the page, and Java methods invoked by with clauses.
Applet auctioneer
21
,
auct agent
.. .
Tuple Space
Figure 6: Coordinating an auction system Agent auctioneer represents the auctioneer, so it has to show the items to be sold, receives and accepts bids, assigns a sale. The following Shade code implements the coordination of bidding. class auctioneer extends ShadeObject{ in ("begin"); out ("bid", "bid1"), ("next_item", "next1"), ("cartoon", "car1"), ("display", "dis1"), ("BasePrice", 5000), ("next_init", "init_2"), ("item#", 1); # in ("BasePrice", ?i:base_bid); read ("bid", ?s:bid), ("display", ?s:display), ("item#", ?i:num);
22
,
send [bid,("begin_auction", "auctioneer", base_bid, 0),("item#", num)], [display, ("begin_auction", "auctioneer", base_bid, 0)]; out ("auction_active"), ("first_timer"), ("current_bid", base_bid), ("TimeStamp", 0); #
The auctioneer starts the auction when its own local state contains a tuple ("begin"), that res the rst method above. Such a method initializes the local state with tuples for agents to be activated ( g. 4). When the rst item goes on sale, it is displayed by an agent of class display named dis1; the second item on sale will be again from class display but named dis2. The second method shown above coordinates the bidding. Each auction starts from a base price given as input; such a price must be sent to all agents (list bid) participating to the current auction. This message is sent by unicast to all agents of class bid listed in bid list. In fact, agent bid has name bid1 in all HTML pages participating to the auction of the rst item. The tuple whose rst argument is an id of the form "item#" denotes the item to be sold (in the demo, a picture, then a car, etc.). This is necessary to synchronize a participant, who could be still on a page showing an already sold item. The item id is used by the auctioneer agent to decide if a bid is valid, being raised for the current item. This allows to let the WWW browser to be free to make any oer, or load another HTML page outside the auction system, and possibly coming back to join again the auction. Integer inc_n; in ("new_bid", ?s:from, ?i:how, ?i:num_item_part), ("num_bid", ?i:num_bid), ("current_bid", ?i:current_bid); read ("auction_active"), ("item#", ?i:num_item_band); with inc_n = NewBid(from, how, num_bid, current_bid, num_item_part, num_item_band); out ("bid_checked", from, how, inc_n); # Integer new_timestamp; in ("bid_checked", ?s:from, ?i:how, ?i:inc_n),
,
23
("TimeStamp", ?i:timestamp); read ("bid", ?s:bid), ("display", ?s:display); with new_timestamp = UpdateStamp(timestamp); send [bid, ("current_bid", from, how, new_timestamp)], [display, ("current_bid", from, how, new_timestamp)]; out ("num_bid", inc_n), ("current_bid", how), ("TimeStamp", new_timestamp); #
These methods receive a bid, validate it, and if such a bid increases the current bid the new bid is broadcast to all participants. The rst method reads a bid (tuple whose rst argument is "new bid"), the current bid, and a counter which counts new bids, used to check if in a given time period new bids arrive. The Java method NewBid checks if the new bid is valid. If it is valid the counter is increased (its value is stored in variable inc n); if it is not valid such a Java method returns null. Finally, a tuple is generated used to re the next method. The second method sends to all display and bid agents, and increments the timestamp counter. In fact, each bid has a numeric id, used by both display and bid agents to keep in time order all bids. We remark that these two methods are implicitly sequential. in ("first_timer"); out ("sleep", 70); # in ("go_timer"); out ("sleep", 30); # in ("sleep", ?i:time); with Sleep(time); out ("check_time"); #
These methods implement a timeout function. We simulate the auctioneer's counting before slamming the gavel (so declaring the sale of an item, or withdrawing an item for which no oers were received). A timer (Sleep()) sends a signal after some (time). In this example, agents have 70 seconds to make
24
,
a rst bid, whereas other bids must arrive by 30 seconds from the last one. This dierence is justi ed in order to give time to each customer's browser to receive and display the interface page. The third method puts in the local state the tuple ("check time") which activates the next method. String tuple; in ("check_time"), ("num_bid", ?i:n); with tuple = CheckBid(n); out (tuple); # in ("no_more_bid"), ("auction_active"), ("next_init", ?s:next_init); read ("cartoon", ?s:cartoon), ("next_item", ?s:next_item); send [cartoon, ("sold_out")], [next_item, ("sold_out")]; out (next_init); # in ("continue"); out("num_bid", 0), ("go_timer"); #
When the timeout is over, the Java method CheckBid(n) checks if new valid bids are arrived. If yes (n > 0 string tuple is assigned the value "continue" and the timer is reset, else value is "no more bid" and the string "sold out" is multicast to all agents cartoon and next item interested in the current item, and the next auction starts. in ("init_2"), ("bid", "bid1"), ("next_item", "next1"), ("cartoon", "car1"), ("display", "dis1"), ("TimeStamp", ?i:timestamp1), ("item#", 1); out ("bid", "bid2"), ("next_item", "next2"),
,
("cartoon", "car2"), ("display", "dis2"), ("BasePrice", 1000), ("next_item", "next2"), ("next_init", "init_3"), ("item#", 2); # in ("init_3"), ("bid", "bid2"), ("next_item", "next2"), ("cartoon", "car2"), ("display", "dis2"), ("TimeStamp", ?i:timestamp2), ("item#", 2); out ("bid", "bid3"), ("next_item", "next3"), ("cartoon", "car3"), ("display", "dis3"), ("BasePrice", 20000), ("next_init", "finished"), ("item#", 3);
These two methods initialize the auction for two items. # in ("finished"); out (""); ##
The last method handles termination.
Applet bid Agent bid has two functions:
it sends oers to the auctioneer;
it knows at any time the updated current bid. Hence, its code is very simple.
25
26
,
class bid extends ShadeObject implements Runnable { Integer new_bid; in ("my_bid", ?s:my_name, ?i:my_bid); read ("last_bid", ?s:from, ?i:howmuch), ("item#", ?i:num); with
new_bid = NewBid(howmuch, my_bid);
send [b, ("new_bid", my_name, new_bid, num)]; #
This method is used when the user sends a bid using button \submit". The current bid amount (howmuch) is used to compute a new bid which is sent to auctioneer b together with the id of current item, to avoid possible confusion. in ("begin_auction", ?s:from, ?i:how, ?i:timestamp); out ("last_bid", from, how), ("TimeStamp", 1); # Integer new_timestamp; in ("current_bid", ?s:from1, ?i:how1, ?i:timestamp), ("last_bid", ?s:from2, ?i:how2), ("TimeStamp", ?i:prev_timestamp); with new_timestamp = UpdateBid(timestamp, prev_timestamp); out ("last_bid", from1, how1), ("TimeStamp", new_timestamp); ##
These methods manage tuple "last bid". The Java method UpdateBid() checks the sequence of the incoming bids, comparing their timestamp with a private counter.
Applet display Agent display shows the current bid as broadcasted by the auctioneer. The following code is very similar to last two methods of agent bid. class display extends ShadeObject implements Runnable{ Integer new_timestamp; in ("begin_auction", ?s:from, ?i:how, ?i:timestamp);
,
27
out ("TimeStamp", 1); # Integer new_timestamp; in ("current_bid", ?s:from, ?i:how, ?i:timestamp), ("TimeStamp", ?i:prev_timestamp); with
new_timestamp = UpdateBid(from, how, timestamp, prev_timestamp);
out ("TimeStamp", new_timestamp); ##
Both these methods are activated by tuples sent by the auctioneer.
Applet cartoon
Agent cartoon waits for the auctioneer's declaration that an item has been sold, then animate the gavel using the Java method GoMallet(). class cartoon extends ShadeObject implements Runnable { in ("sold_out"); with GoMallet(); out (""); ##
Applet next item Agent next item waits for tuple ("sold out") then activates button \next item" to load the next item page. class next_item extends ShadeObject implements Runnable { in ("sold_out"); with SoldItem(); out (""); ##
Java method SoldItem() sets the boolean variable which activates the button graphics.
8
RELATED WORK
28
,
Jada has been developed in the context of the PageSpace project [Ciancarini et al. 1996]. The main idea at the basis of PageSpace is to exploit coordination technology to enhance the WWW middleware. Other projects pursue a similar goal with dierent approaches. In fact, although it explicitly refers to Linda, the WWWinda approach [Gutfreund et al. 1994] is quite dierent from what we have described here. Since the integration between WWW browsers and their helper applications is extremely rudimental (it is only possible to activate the external application and to deliver the data to be displayed), the WWWinda research team designed a exible, modular WWW browser architecture based on the Linda programming language. Several independent tools, each implementing a dierent part of the whole WWW browser, are activated according to needs, sharing screen space, HTTP responses, and user interaction. This allows for a highly modular architecture, where new services and tools can be added without modi cations in a homogeneous framework. In order to allow cooperation among helper modules, these all make use of a shared tuple space. Tuples allow to upgrade the simple \activate with these data" paradigm of browsers' helper applications to a more complete coordination protocol. For instance, WWWinda has been used to coordinate a distributed digital orchestra, in which several browsers simulating musical instruments (possibly running on dierent machines) extract from the shared tuple space the tune to be played note by note. No instrument is aware of how many other instruments are present, and new ones can be added on the y, even in the middle of a performance. All features of WWWinda, that we de ne a \client-side coordination toolkit" are easily implementable in Jada. Instead, the WU Linda Toolkit [Schoenfeldinger 1995] is a simple interface between a WWW browser and a WWW server implementing a tuple space service. Access to the shared tuple space is provided to clients: users can ll in an HTML form with the appropriate Linda command to interact with the tuple space. The main application on show is a disc-load viewer that allows a rst glance check of current disk usage of the computers of a cluster of workstations. Each workstation hosts a WU Linda client which posts tuples in the shared tuple space describing the current load of the disks it controls. These tuples are then collected and rendered in a user-friendly way via HTMl to any browser querying the application. Again, all features of WU Linda, that we de ne a \server-side coordination toolkit" are easily implementable in Jada. Jada applets are very similar to Oblets, or \distributed active objects" [Brown and Najork 1996]. An oblet is a program written in Obliq and executed on a browser. Each oblet can use high-level primitives to communicate with other oblets running on possibly remote browsers. The Bauhaus \Turingware Web" designed in Yale (the homeland of Linda) is similar at least in spirit to the WU Linda toolkit [Hupfer 1996]. The main idea consists of using a standard browser to access a
,
29
Bauhaus server. Bauhaus is a coordination language based on nested multiple tuple spaces (multisets) which can be used in this case for both controlling the hierarchical structure of the pages of a web site, and for associating agents and their activities to the pages themselves. For instance, one attribute of a page could be the list of users \acting" in such a page, who are displayed by a graphic icon and can interact using some ad-hoc cooperation services. JavaSpaces [Waldo et al. 1997] provide mechanisms for distributed persistence and data exchange for code written in Java. The basic coordination model is at multiple tuple spaces. A tuple is called an entry, de ned as typed group of objects. An entry can be written in a JavaSpace, to be later searched or deleted by lookup operations. JavaSpaces support a transaction mechanism to build atomic multiple operations across multiple JavaSpaces. Moreover, active objects can ask a JavaSpace to notify when an entry is written that matches a given template. The actual implementation of JavaSpace is currently not available, thus is dicult to really compare it with our system.
9
CONCLUSION Jada provides:
coordination inside the object oriented programming framework: no syntax extension for Java, just a set of classes. Each data type used by Jada is a Java object.
dynamic tuple creation: being an object, a tuple can be created with new and many dierent constructors are provided in order to build a tuple from a string, an array of object or, simply, from a set of arguments (as seen before).
multithreading support: Jada is multithreading aware: dierent threads can access the same tuple space; blocking request are managed at thread-level.
open systems support: at any time threads or applications can perform operation on a tuple space.
multiple tuple associative access: we provided modi ed avors for the in and read requests in order to allow the use of multiple matching tuples.
We have shown how we used Jada as a kernel for building more complex Internet languages by introducing the Shade/Java language and extending the usual Linda mechanisms with the rewriting rules concept. We have used Shade/Java as a coordination platform to build distributed programs made of applets running in dierent WWW browsers. To put it very simply, Shade methods specify coordination protocols,
30
,
whereas Java objects control the graphic interface of a distributed application. We are currently engaged in developing the Shade/Java concept. We are especially interested in integrating the concept of coordination with interoperable platforms like CORBA. A similar approach has been explored in [Andreoli et al. 1996]. Both Jada and Shade are available for evaluation at page http://www.cs.unibo.it/~rossi/jada/.
Acknowledgements. We thank Robert Tolksdorf for discussions and suggestions. We thank for support Italian CNR and MURST.
REFERENCES Andreoli, J., P. Ciancarini, and R. Pareschi (1993), \Interaction Abstract Machines," In Trends in Object-Based Concurrent Computing , G. Agha, P. Wegner, and A. Yonezawa, Eds., MIT Press, Cambridge, MA, pp. 257{280. Andreoli, J., S. Freeman, and R. Pareschi (1996), \The Coordination Language Facility: Coordination of Distributed Objects," Theory and Practice of Object Systems 2 , 2, 77{94. Brown, M. and M. Najork (1996), \Distributed Active Objects," Computer Networks and ISDN Systems 28 , 7-11, 1037{1052. Carriero, N. and D. Gelernter (1992), \Coordination Languages and Their Signi cance," Communications of the ACM 35 , 2, 97{107. Castellani, S., P. Ciancarini, and D. Rossi (1996), \The ShaPE of ShaDE: a coordination system," Technical Report UBLCS 96-5, Dipartimento di Scienze dell'Informazione, Universita di Bologna, Italy. Chen, M. and J. Cowie (1997), \Java's role in distributed collaboration," Concurrency - Practice and Experience 9 , 6, 509{520. Ciancarini, P. (1994), \Distributed Programming with Logic Tuple Spaces," New Generation Computing 12 , 3, 251{284. Ciancarini, P., A. Fantini, and D. Rossi (1997), \A multi-agent process centered environment integrated with the WWW," In Proc. 6th IEEE Workshop on Enabling Technology: Infrastructure for Collaborative Enterprises (WETICE 97), IEEE Computer Society Press, Boston, pp. 113{120. Ciancarini, P., A. Knoche, R. Tolksdorf, and F. Vitali (1996), \PageSpace : An Architecture to Coordinate Distributed Applications on the Web," Computer Networks and ISDN Systems 28 , 7-11, 941{952. Ciancarini, P. and D. Rossi (1997), \Jada: Coordination and Communication for Java agents," In Mobile Object Systems: Towards the Programmable Internet , J. Vitek and C. Tschudin, Eds., volume 1222 of Lecture Notes in Computer Science , Springer-Verlag, Berlin, pp. 213{228. Evans, E. and D. Rogers (1997), \Using Java Applets and CORBA for Multi-User Distributed Applications," IEEE Internet Computing 1 , 3, 43{55. Gelernter, D. (1985), \Generative Communication in Linda," ACM Transactions on Programming Languages and Systems 7 , 1, 80{112.
,
31
Gutfreund, Y., J. Nicol, R. Sasnett, and V. Phuah (1994), \WWWinda: An Orchestration Service for WWW Browsers and Accessories," In Proc. 2nd Int. World Wide Web Conference , Chicago, IL. Hupfer, S. (1996), \Turingware: An Integrated Approach to Collaborative Computing," Ph.D. thesis, Dept. of Computer Science, Yale University, New Haven, CT. Lea, D. (1997), Concurrent Programming in Java. Design Principles and Patterns , Addison-Wesley. Lewis, T. (1995), \Where is Client/Server Software Headed?" IEEE Computer 28 , 4, 49{55. Schoenfeldinger, W. (1995), \WWW Meets Linda: Linda for Global WWW-Based Transaction," World Wide Web Journal 1 , 1, 259{276. Tolksdorf, R. (1992), \Laura: A Coordination Language for Open Distributed Systems," Technical Report 1992/35, Technische Universitat Berlin, Fachbereich 20 Informatik. Waldo, J. et al. (1997), \JavaSpace Speci cation - Revision 0.4," Technical report, Sun Microsystems, JavaSoft Lab.