|PREV PACKAGE NEXT PACKAGE||FRAMES NO FRAMES|
|Egg||The interface that must be implemented by each egg.|
|EggContext||The execution context of an egg.|
|Message||Used to wrap an application message that is being sent from one egg to another.|
|Port||An egg message port.|
|EggBase||A convenience base class for a concrete egg implementation.|
|PortException||Exception raised if a port can not accept a message for any reason.|
|UnableToInitializeException||Raised by an egg that fails to initialize when the framework invokes
The main JEgg package
The intent of JEgg is to provide an application development framework that directly supports the Active Object pattern in such a way that multithreaded applications can be implemented without the application code having to manage (create, assign, destroy, or monitor) any physical execution threads. The approach used to achieve this goal is to restrict active objects to a message-based communication mechansim that the framework seeks to make as intuitive and simple to use as possible. Consequently, active objects do not interact via synchronous method calls. Instead, they communicate by sending each other messages which are delivered completely asynchronously, one-at-a-time, to the target object (two objects may receive messages concurrently, but each object will never receive its next message until it has completed handling of its current message). The public interface of each active object is featureless - all active objects look the same (from an API point-of-view) like eggs.
In addition to supporting message-based communication, the framework also takes care of loading, and instantiating the application eggs and "hooking them up" so that they can communicate (using messages). The framework "configures" each egg at runtime with references to the message ports of the other eggs it needs to message, as described in an application descriptor which is an XML file that you provide that describes the eggs composing the application and their interdependencies. A popular term for this "runtime configuration of dependencies" is Dependency Injection.
The end result of the message-based communication scheme and the absence of explicit dependence on physical threads is that each egg is highly cohesive and decoupled from the other eggs in the application. Notice that the interaction model is more peer-to-peer than client-server. The only distinguishing difference between eggs is the set of messages that each one will recognize and respond to. However, that difference is not exposed as a set of methods in a public interface. The only interface of an egg that matters is the set of message types (which are just ordinary application-supplied Java classes) that the egg supports.
An obvious consequence of the asynchronous messaging scheme is that it is
not an obvious and immediate error if one egg sends a message to another egg
that the latter doesn't recognize. It's up to the receiving egg to respond
with an appropriate error (e.g. an "exception" delivered to the sender as
a message rather than "raised"). In fact, since all application eggs must
at least be able to handle messages of type
(even if it is just to emit an error log entry), it is not possible to provoke
a runtime error simply by sending an incorrect message to an egg (of course
the receiving egg may be in an inappropriate state for the message which
may result in an error in the receiver).
Developers who naturally think in terms of active objects will have no difficulty in designing egg-based applications. Others, may find it more challenging. However, it is hoped that the effort may be found to be worthwhile and lead to simpler and more robust applications at the same level of sophistication as your requirements demand.
jegg package contains the primary classes in the
An egg is developed by implementing the
jegg.impl.EggBase convenience class is provided
as a shortcut which should be utilized unless there is some reason not to.
jegg.impl.EggBase, and implementing at least the
public void handle(Object) is a completely adequate
egg implementation. However, to tailor the egg to your application, you
should implement additional
handle methods. Each
handle method takes a single argument corresponding to the
type of message that method is able to process. There are no restrictions
(at this time) on the types of the messages. They can be any Java
object. When a message of a given type arrives at the egg, it will be
delivered to the handle method whose argument type most closesly matches
the concrete type of the message. As already stated, messages are delivered
At startup, the JEgg framework reads a description of the application eggs that it should instantiate from the application descriptor. The Egg Lifecycle section below describes the egg initialization in detail.
Eggs communicate with one another by sending messages over
messsage ports, which are instances of
Each egg has a only one message port. To initiate a message dialogue,
an egg must have a reference to the port of the egg that it will send
a message to. However, a message receiver can always respond to the
sending egg without having a reference to the sending egg's port if the
response is emitted during the handling of the message. Alternatively, the
receiver egg can obtain a reference to the sending egg's port from the
environment during the handling of the message, and save the port
for sending a response at a later time (see
The jegg application descriptor is used not only to describe to the JEgg framework
which eggs to instantiate at startup, but also to declare the dependencies of
each egg on any other application egg, if any. A dependency only needs to
be declared for eggs that will initiate a message exchange with one or
more other eggs in the application. Eggs that only always respond to messages
do not need to declare any dependencies. For eggs that declare a dependency,
the ports of any eggs they depend on will be delivered as messages (of type
jegg.Port) before any other application message is delivered
to the egg. The section Egg Lifecycle below describes egg initialization
More details on egg message sending is given in the section Egg Messaging below.
java jegg.EggLoader [application-descriptor]where application-descriptor is the optional path to the application descriptor that describes the application to load. If the application descriptor is not specified on the command line, the framework will search the classpath for a file named jegg.xml. If the command-line argument does not include a path and can't be found in the current directory, it is searched for along the class path.
<jegg> <basket name="unique-name" > <egg name="unique-egg-name" class="concrete-egg-class" > <uses name="other-egg-name" /> <property name="prop-name" value="prop-value" /> </egg> : : </basket> : : </jegg>
The <jegg> Tag
The <jegg> tag encloses the contents of the descriptor.
The <basket> Tag
The <basket> tag is used to group eggs together. Eggs in the same lt;basket> are assigned to the same message dispatcher. See
The <egg> Tag
The <egg> tag describes an application egg and takes the following attributes:
The <uses> Tag
The <egg> tag can have an optional nested <uses> tag that specifies the name of another egg that the current egg expects to exchange messages with. Any number of <uses> tags can be specified. The message port corresponding to the egg specified by the <uses> tag is delivered to the egg before the first application message is delivered. The message port is delivered to the egg as a message of type
jegg.Port, before the egg's
jegg.Egg.init() method is invoked.
An egg may lookup the port of any egg using the JEgg framework egg
locator service. See the
method for details.
The <property> Tag
The <egg> tag also can take an optional nested <property> tag used to make configuration properties, name-value pairs, available to the egg at runtime. Any number of <property> tags can be specified. The values specified in the <property> tag can be accessed by the egg at runtime through the
jegg.EggContext instance passed
to the egg by the framework through the
method which the egg must implement.
One egg sends a message (any Java object) to another by passing the
message object to the
jegg.Port.send() method on the
message port that belongs to the egg. The message port is delivered
to the dependent egg at startup as a result of a <uses> tag
associated with the egg in the application descriptor, or because the
egg called the
(for instance from the body of its
A message that is sent to an egg via its message port is delivered to
the egg by the message dispatcher assigned to it in the application
descriptor (the <egg> tag's enclosing <basket> tag). The
message dispatcher will never deliver more than one message at a time to
a given egg. The message is delivered to the egg by invoking the
method that has an argument whose type is the same as the concrete type of
the message, or its nearest ancestor (which may be the base
The port of the message sender can be accessed during the handling of
a message via the
jegg.EggContext.getFromPort of the egg's
An egg can send a response message to the egg that sent the currently
handled message by passing the response message object to the
jegg.EggContext.respond method of the its context instance.
An egg can bind to another egg's message port by passing the
message port to the
jegg.EggContext.bindToPort method on
the its context instance. This allows the binding egg to receive all messages
broadcast by the port's owner. An egg can broadcast a message
to all bound eggs by passing the message to the
method on its context instance.
An egg can send a message to itself by passing the message to the
send method on its own message port. The egg can get a
reference to its own message port by calling the
on its context instance.
Self-messaging is a useful way for an egg to trigger an action. For instance,
a timer can be used (see
to have a timeout message delivered to the egg at some time in the
future. The handler for the timeout message can serve as the notice to
send the special trigger message.
|PREV PACKAGE NEXT PACKAGE||FRAMES NO FRAMES|