[Embedlets-developer] Re: General event mechanism
Status: Alpha
Brought to you by:
tkosan
|
From: Andrzej J. T. <an...@ch...> - 2003-01-26 21:48:27
|
Ted discusses the event mechanism:
> I looked through the Embedlet traffic we generated on the
> JStamp list and actually I found a post or two from you
> that talked about a very general Event mechanism. At that
> time I did not have a good feel for why a general event
> mechanism was superior to a more tailored Event mechanism
> (like what is present in AWT) but after playing with the
> wiring tool mockup for the past couple of weeks I think I
> understand this better now.
> Are these the kind of ideas you were referring to when you
> talked about a 'general event mechanism'?
Not quite.....I don't like the use of a the event type specifier in the Event
Sender interface (see below), and there is probably no need for that.
The bones of the event management should probably be provided by an
Outpost Container service. So if you need to receive events you would
implement the EventConsumer interface and specify in the XML config file that
you want to receive events and of what kind (more on that later). Same thing if
you want to send events...you implement EventProducer and specify in the
XML that you will create events and of what type. Both interfaces will have a
method that allows you to get a reference to the Container's Event Service,
which you actuall do calls on. Something like this (for a listener).
public interface EventConsumer
{
public void receive( EmbedletEvent e );
}
Registration of the EventConsumer should be done transparently by the
Container! The component lifecycle (create/start/stop/destroy for instance)
would guarantee that you would not receive any events till after the start()
method was invoked, ensuring that your component was suitably initialized
first. All part of the Container responsibilities.
In the XML config defining an Embedlet that is an EventConsumer, you would
specify what types of events you wanted to receive.
That's the easy case, and is almost identical to Ted's example, but let's look
how an event sender might actually send a new event:
EmbedletEventService eventService = Outpost.getEventService();
EmbedletEvent event = eventService.getEventInstance();
event.setType( typeSpecifier );
// ...do some stuff with the event you want to send. Set data, etc.
eventService.send( event );
Note that with this approach the EventService could automatically ensure that
the Embedlet is only sending events of the types specified in the config XML (a
very useful cross-check). It also simplifies the Embedlet code, since the
container handles the routing of events to registered listeners....the Embedlet
doesn't care nor does it need to know.
What is a bit tricky is how to specify the Event Type in a globally unique way,
since you don't want a developer to end up with a situation where the event
types were duplicated by two different embedlets/components, for different
purposes.
One way is to use integers as event types, with a single EmbedletEvent class,
which is handy since it's compact and processing them is quite efficient (rather
than string compares), and you can use Select/case constructs in a single
receive() method to distinguish between different events. But the issue there
is how to ensure that different event types don't reuse the same integer
specifier.
One approach that bears investigation is where there is a base class (possibly
abstract) that is an EmbedletEvent. Specific types are created as subclasses
of the base class. The component's XML config file then would specify which
fully qualified Event subclasses it either consumed or produced, along with a
method to be called upon receipt of such an event. For instance, the XML
descriptor for an Embedlet that both sends and receives events might look
like:
<embedlet name=ChaeronGPS" class="com.chaeron.embedlets.GPS" >
<events>
<consumes class="com.chaeron.embedlets.events.NMEASentence"
method="receiveNMEASentence" />
<consumes class="com.chaeron.embedlets.events.GarminPacket"
method="receiveGarminPacket" />
<produces class="com.chaeron.embedlets.events.GPSEvent" />
<events>
</embedlet>
This would allow you to create a generic receiver method (that takes a
EmbedletEvent superclass and then do instanceof() comparisons) or multiple
methods that each receive a single specific event type (class).
Either runtime reflection or construction-time code generation could be used to
provide the glue between the container and the component for the event
handling, depending on the Outpost implementation being used.
What is interesting is that this approach could work for both threaded and co-
operative models of execution. We'ld need to design the Embedlet contract in
such a way that co-operative processing is possible, for those platforms where
threads are not available. The container can optionally use threaded
execution of the components if such is supported. Otherwise, it basically uses
the events to schedule execution across multiple components in a serial
manner. This means that all Embedlet operations should be conducted via
events (eg. writing to a back end server should be done by sending an
appropriate event that will perform the communication). Events could have a
priority value so that there would be some way to prioritize their execution as
well.
> So, here is what the SignalSender/SenderReceiver event idea
> evolved into:
>
>
> public interface EventSender
> {
> add(type of operation)Receiver(EventReceiver er);
> remove(type of operation)Receiver(EventReceiver er);
> EventReceiver[] get(type of operation)Receivers(); //get
> the receivers for a specific type.
> EventReceiver[] getAllReceivers(); //get a list of all
> receivers
>
> set(type of operation)Properties //Temporal
> properties, etc.
> get(type of operation)Properties
> }
>
> public interface EventReceiver //All Embedlets implement
> this interface.
> {
> receiveEmbedletEvent(EmbedletEvent ee);
> }
>
>
> For the Elevator Embedlet the following EventReceiver
> registration methods might be present:
>
> addFloorReceiver(EmbedletReceiver er); //For receiving
> Floor events like 'SetDirectionLights' and
> 'SetCurrentFloorDisplay'.
>
> addShaftReceiver(EmbedletReciever er); //For receiving
> Shaft events like 'MoveElevator'.
>
>
>
> The main way that a general event mechanism seems to differ
> from a more specific event mechanism like AWT's is that the
> type of 'Listener' passed into an AWT addXXXListener method
> is Listener type specific while the 'Listener' (Receiver)
> in a more general mechanism uses a single type of listener
> (in this case org.embedlet.EvenReceiver).
>
>
> It also appears to me that, in a general event system, the
> type of the Event is used to indicate what to do with the
> event. For example, if all Embedlet events inherit from
> EmbedletEvent then the Elevator Embedlet can send
> FloorEvents through the general event mechanism to
> controllers that are responsible for running each floor and
> ShaftEvents to the controller's that are responsible for
> running each elevator shaft, etc.
>
> Different EmbedletEvent types are created to handle all
> event needs.
Andrzej Jan Taramina
Chaeron Corporation: Enterprise System Solutions
http://www.chaeron.com
|