DataBus Documentation



DataBus is a Java class library for developing highly dynamic, universal and modular applications. It allows software modules (called components) to talk to each other, exchanging data or sending events, without knowing anything from each other. They only thing these components needs to know is the type of data to exchange (the event type). For each event, there can be an unlimited number of consumers and producers. Consumers can also generate new events, acting as producers (such components are called filters). Think of the DataBus as a number of whiteboards (one board for each type of event), where all producers can write down their data, and the consumers can read from there (and write their responses or new data down).
  • unlimited number of event types, producers and consumers
  • event handling is done asynchronously (the producers do not wait for the consumers to catch up)
  • each consumer has its own event handler queue, decoupling its event handling method from the bus
  • recevining event order is the same for all consumers
  • event receving is decoupled from the consumerss event handling
  • it is possible to send events synchronously, reading a response object
  • the DataBus configuration is read from a single configuration file
  • each component can have a descriptor file, containing
    • name of the component
    • the class name of the component
    • additional information
    • information about the configuration of the component

Why use DataBus?

DataBus allows to build applications in a higly modular fashion. Because the individual components communicate with each other only through the events, they are independant of each other. They can be easily exchanged, without any other component noticing. This can even be done during runtime.
Communcation via events also requires the careful definition of the interfaces between the components. This will lead to higher code quality, because it requires more thinking before coding. It also allows for easier testing, because the interfaces are really simple.
Using events more communication makes the components simpler - they just dont't need to know much about other components.

APD as an example

The APD program contains the following components:
  • MP3 player (MADLibPlayerService or MPG123PlayerService)
  • playlist handler (PlayListManager)
  • LIRC remote control handler (LircControlService)
  • LCDProc status consumer (LcdProcPlayStatusWriter)
  • play status handler (QueueService)
These components use the following events:
  • PlayStatusEvent
  • PlayerEvent

playing MP3s

The registered MP3 playing component receives Player events. The play status handler sends a 'PLAY' command after the startup, conbtaining the first file to be played. The MP3 player then sends regularly the curent play status, which is used by the play status handler to determine when a song is finished. Then it sends a new 'PLAY' command, which contains the next file.

showing the curent status

The current play status send by the MP3 player is also received by the LCDProc status consumer. When the current song changes, the new title and artist are displayed in the LCD. Additionally, each second the time left for playing the current song is updated.

remote control

The LIRC remote control handler just takes the commands from the LIRC daemon, and sends the corresponding play commands.

other modules

Instead of using the LIRC service to control APD with a remote control, there are two additional modules:
  • LCDProcControlService, which interprets keypresses from LCDProc as play command
  • RemoteControlService, shich allows the control with a remote AWT client, connect via TCP
Both modules simply send PlayerEvents. So the MP3 player just doesn't need to know about these modules, as it just cares about events.