Package jegg

The main JEgg package

See:
          Description

Interface Summary
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.
 

Class Summary
EggBase A convenience base class for a concrete egg implementation.
 

Exception Summary
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 egg's init() method.
 

Package jegg Description

The main JEgg package

Introduction

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 java.lang.Object (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.

The JEgg package

The jegg package contains the primary classes in the JEgg framework.

The jegg.Egg and jegg.impl.EggBase Classes

An egg is developed by implementing the jegg.Egg interface. Alternatively, the jegg.impl.EggBase convenience class is provided as a shortcut which should be utilized unless there is some reason not to.

Extending jegg.impl.EggBase, and implementing at least the abstract 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 one-at-a-time.

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.

The jegg.Port Class

Eggs communicate with one another by sending messages over messsage ports, which are instances of jegg.Port. 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 jegg.EggContext.getFromPort()).

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 in detail.

More details on egg message sending is given in the section Egg Messaging below.

JEgg Application Execution

A JEgg application is loaded and executed using the jegg.EggLoader class:
    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.

The JEgg Application Descriptor

The application descriptor is an XML file that: The format of the application descriptor is:
  <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 Egg Message Dispatch below. The lt;basket> is assigned a unique name via its name attribute. If a given egg can take a long time to handle any of its messages, it should be assigned to its own lt;basket>. A lt;basket> without an name indicates the default lt;basket>.

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 jegg.EggContext.requestPort() 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 jegg.Egg.setContext method which the egg must implement.

JEgg Message Dispatching

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 jegg.EggContext.requestPort() method (for instance from the body of its init method).

Message Delivery

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 handle 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 handle(java.lang.Object) method).

The port of the message sender can be accessed during the handling of a message via the jegg.EggContext.getFromPort of the egg's context instance.

Responding to a Message

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.

Binding to a Message Port

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 jegg.EggContext.broadcast method on its context instance.

Self-messaging

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 jegg.EggContext.getPort 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 jegg.EggContext.createSingleShotTimer) 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.



Copyright © 2004 . All Rights Reserved.