The EventBus provides publish/subscribe event services for a single JVM.

The EventBus is especially suitable for Swing Applications, though it is usable in any context, even server-side. See the package description below for a complete description. The EventBus allows two components to communicate with each other without either of them knowing about the other (i.e., having a reference to the other). It is an alternative to the tight coupling introduced by the typical Swing addXXXListener event mechanism. When using the EventBus, the listener is subscribed to the EventBus instead of being added to a component. The component that normally sends events to its listener list instead publishes events to the EventBus.. The EventBus takes care of routing events from publishers to subscribers.

This simple example prints "Hello World" using class-based publication.

    class HelloThingy { //the same for all the examples
    	public String getWorld() {
    	   return "World";
    	}
    }

    class MySubscriber implements EventSubscriber {
       //EventSubscriber implementation
       public void onEvent(Object event) {
          HelloThingy helloEvent = (HelloThingy)event;
       	System.out.println("Hello"+helloEvent.getWorld());
       }
    }

    class HelloEventBus {
       public static void main(String args[]) {
          MySubscriber subscriber = new MySubscriber();
          EventBus.subscribe(HelloThingy.class, subscriber);
          EventBus.publish(new HelloThingy());
       }
    }

Alternatively, this example can be coded using EventBus annotations and the AnnotationProcessor:

    class MySubscriber {
       @EventSubscriber(eventClass=HelloThingy.class)
       public void printOutHelloWorld(HelloThingy event) {
       	System.out.println("Hello"+helloEvent.getWorld());
       }
    }

    class HelloEventBus {
       public static void main(String args[]) {
          MySubscriber subscriber = new MySubscriber();
          AnnotationProcessor.process(subscriber);//makes a subscriber to call subscriber.printOutHelloWorld
          EventBus.publish(new HelloThingy());
       }
    }

This second example prints "Hello World" using topic-based publication.

    class MySubscriber implements EventTopicSubscriber {
       //EventTopicSubscriber implementation
       public void onEvent(String topic, Object event) {
       	System.out.println(topic+" "+event);
       }
    }

    class HelloEventBus {
       public static void main(String args[]) {
          MySubscriber subscriber = new MySubscriber();
          EventBus.subscribe("Hello", subscriber);
          EventBus.publish("Hello", "World");
       }
    }

Alternatively, this example can also be coded using EventBus annotations and the AnnotationProcessor:

##

##

##

##

##

    class MySubscriber {
       @EventTopicSubscriber(topic="Hello");
       public void printOutHelloWorld(String topic, Object event) {
       	System.out.println(topic+" "+event);
       }
    }

    class HelloEventBus {
       public static void main(String args[]) {
          MySubscriber subscriber = new MySubscriber();
          AnnotationProcessor.process(subscriber);//makes a subscriber to call subscriber.printOutHelloWorld
          EventBus.publish("Hello", "World");
       }
    }

       Important: The EventBus uses WeakReferences by default, so this WILL NOT WORK
       since it uses an anonymous inner class:

       public static void main(String args[]) {
          EventBus.subscribe("Hello", new MySubscriber());
          //subscriber will likely get garbage collected - no Hello World!!!
          EventBus.publish("Hello", "World");
       }

       However you can subscribe strongly instead:

          public static void main(String args[]) {
             EventBus.subscribeStrongly("Hello", new MySubscriber());
             //subscriber will not get garbage collected
             EventBus.publish("Hello", "World");
             //In real apps use unsubscribe to make sure you don't create a memory leak (a.k.a. - loitering object)
             EventBus.unsubscribe(subscriber);
          }

    Though the term "Event Bus" refers to the entire package, the {@link org.bushe.swing.event.EventBus} class
       used above is a static wrapper around a global instance of an {@link org.bushe.swing.event.EventService},
       specifically a {@link org.bushe.swing.event.SwingEventService} implementation.  MySubscriber subscribes
       itself to the topic named "Hello".  When main() publishes the
       String "World" (the data object of the event) on the event topic "Hello",
       the Event Bus calls MySubscriber and "Hello World" is printed.

       An application may use multiple event services. There are two EventService implementations provided.
       One is the SwingEventService, which is useful for sending Swing events (The EventBus is a wrapper
       around a SwingEventService). The other is its parent, the {@link org.bushe.swing.event.ThreadSafeEventService}.
       As the name implies the ThreadSafeEventService can be used in multithreaded environments. The
       ThreadSafeEventService is the parent of the SwingEventService, so all provided
       EventService implementations can be used from multiple threads concurrently. The SwingEventService
       differs from the ThreadSafeEventService by ensuring that publications are posted on the
       Swing/AWT {@link java.awt.EventDispatchThread}.

       The EventBus is intented to be very simple to use. There is no setup required and the API is
       fairly small. You do, however, need to be careful with memory management for subscribers. A couple of tips:

          When calling subscribe(), keep a reference to the subscriber for as long as you want the
             subscription to last. For example, a JPanel that adds a subscriber to the EventBus will
             usually want to keep a reference to the subscriber as an instance variable, otherwise it
             will be garbage collected right away:

          Never call subscribeStrongly() with an anonymous inner class - unless you want to keep the subscription active
             until the VM exits.

    Two Analogies
    The EventBus is a different motif for Swing design that some Swing developers find
       difficult to understand at first.  There are two analogies to the EventBus that
       may aid understanding.  The first is messaging systems like JMS where one
       process publishes messages on a topic name to other processes.  For example,
       a stock quote server may publish "$305" on a topic named "GOOG".  Client
       applications may subscribe to the "GOOG" topic and update their ticker
       when they recieve messages for "GOOG".  The JMS system decouples the
       clients from the server.  The server code does not need to explicitly keep track of how many
       clients are active, where they are located, whether the clients are still up and
       running, which ones are interested in "GOOG", etc.  The JMS system takes
       care of the details.  Similarly, the clients don't have to know whether the server
       is still up and running, where it located, etc.  All you need are publish() and
       subscribe() and a good JMS implementation.
     Another analogy is a computer motherboard system bus.  Different components
       plug into the bus and receive and send messages to other componets on the bus.
       You don't need to hook your CPU directly into each component in your computer,
       nor does your video card hook up directly to your monitor.  This layer of decoupling
       makes things a lot easier on device manufacturers, chip designers, computer
       manufacturers and computer owners.
    The EventBus similarly solves many problems in Swing (or any appplication) by introducing this decoupling
       layer.
     Advantages

       Using the EventService avoids code bloat for handling events.  There is no
          need for:

             XXXEvent classes
             XXXEventListener interfaces
             XXXEventListener implementation
             addXXXListener methods
             removeXXXListener methods
             fireEventListener methods, which tend to be very buggy (they don't handle
                exceptions well, and don't fire in the expected backwards order of EventListenerList)
             (if desired) XXXEvent class are not necessary, but can be used for type
                safety.

        The Event Bus promotes loose coupling of components.  Components can communicate
          with each other without having to find each other and add and remove listeners
          from each other at appropriate times.

           Poor listener management is the primary cause of client "loitering
             objects" a.k.a. "memory leaks."  When listeners are not
             removed, the objects they refer to stay in memory, perhaps forever.
          Listener management in very dynamic GUIs, such as those that use increasing popular docking
             frameworks, is very difficult and error-prone.
          Loose coupling promotes unit testing.  When components are not tied to
             each other they are easier to test independently.
          Loose coupling promotes parallel development.  Developers can describe
             the contracts between components through the EventServiceEvents.  The components
             can be tested independently and then integrated.  This is impossible with the normal
             Swing listener mechanism.  For example, a framework component developer can work on a commoon
             progress component that subscribes to the EventBus to update its state.  A screen developer can
             build a screen that publishes ProgressEvents - the contract.  Both components can be created and
             tested separately and then integrated.
          The EventBus promotes component design and simple refactoring.  In the above example, the progress
             component
             can be swapped out or change its location or function, without changing the screen code.  The screen can
             continue publishing its ProgressEvent.  Using Swing EventListeners one or more controllers in a hierarchy
             and
             the components they control would normally have to be changed significantly each time the user decides they
             don't like the pretty progress bar you designed, or its location or function, etc.
          The design of the EventBus promotes the creation of Swing frameworks.  In the above example the Swing
             component is created that plugs into the EventBus to receive event.  Imagine the user interacting with
             a Swing component that was adapted to publishe high level events on an EventService.  Frameworks can plug
             into the EventService to handle the cross-cutting concerns of a client - validation, model management,
             data refresh, etc.
          Using multiple EventServices is an good method for keeping a GUI up to date with a server. Server
             updates (such as JMS messages, cache updates, database queries, etc.) can be published from the
             client's receiving thread to client-side data models in non-Swing threads (using the ThreadSafeEventService
             or directly to client-side components using the EventBus (or another SwingEventService).

    Features

       Event Service implementations are threadsafe - multiple
          threads can be publishing and subscribing at the same time.
       Event Services can be used in a typesafe manner by publishing
          typed {@link org.bushe.swing.event.EventServiceEvent}s and having listeners subscribe to EventServiceEvents
          by class.  It can also be used in a type unsafe manner by publishing Objects
          on topic names (Strings) and having listeners subscribe to those names by name or regular
          expression.
       Multiple EventServices can be used simulanteously to properly route event traffic.
       Using the SwingEventService ensures Swing events are safely published
          on the Swing EDT, either directly, or when necessary, through a SwingUtilities.invokeLater()
          call.
       Event Services allows veto event publication in a manner
          more safe than the JavaBeans VetoableEventListener.  In JavaBeans, VetoableChangeSupport.fireVetoChange()
          "if anyone vetos the change, then a new event [is fired] reverting everyone
          to the old value." The EventService tests all VetoableListeners first,
          and does not publish the event if any vetoable listener vetos it.  This avoids
          having to write "undo" code or transactional code needed in JavaBean'
          vetoable properties.
       Event Services allows easy listener management by using WeakReferences by default.
          All EventService subscribe(...) methods have a subscribeStrongly(...) siblng.  The subscribe(...)
          methods create a WeakReference of the subscriber and subscribe the weak reference.
          The subscriber can then get garbage collected normally, even while subscribed.
          When Subscribers subscribe weakly, they do not have to worry about unsubscribing, thus avoiding memory leaks.
          Using the subscribeStrongly(...) methods, the subscribers must be unsubscribed, otherwise memory leaks may occur.
       EventService support for Swing Containers allows Swing components to limit event
          publication to a component and its children.  Children can automatically subscribe
          to the Container EventService of their nearest parent through the {@link
          org.bushe.swing.event.ContainerEventServiceRegistrar},
          even if they don't yet have a parent (or if they move).  A parent can define
          itself the as a {@link org.bushe.swing.event.ContainerEventServiceSupplier}, if none are defined
          one is created on the RootPaneContainer automagically.

       The Event Service is a centralized processor of application events local to the
       process (client).  It does not provide any processing of events outside of the
       process.  In other words it does not move events from a server to a client - it
       is not a solution for Event Driven Architecture in an SOA, or any other multi-tier problem.
       However, the EventService is very useful as a mediator between server communications
       and the client code that needs it.  Each call from the server
       can be published on an EventService.  Any client-side component (Swing or non-Swing)
       can then subscribe to the client-side event and receive the updates.  This structure
       automatically makes your Swing app thread-safe in the incoming direction. In environments where
       the server provides frequent updates (say, every 2 seconds, depending on the speed of your client-side
       processing code), you should take care to throttle updates to the Swing EDT, perhaps coalescing
       many events into one. This can be done from the server side, of course, but the multithreaded
       EventService allows this to occur client-side as well assuming sufficient processing power on the
       client for the non-EDT threads (which is typically the case).

    Usage
    More usages will soon be available on the Event Bus wiki. See the main EventBus project page at
       http://eventbus.dev.java.net for a link to the wiki.
    An example of topic publishing is shown above, below is an example of typesafe publication by Event class.
       One nice usage of EventBus events is closing an application.  Typically you want to run some kind of routine
       when the user closes the application (an "Are you sure?" dialog, closing connections to servers, etc.).
       There are at least two places where an application is closed - the File->Exit
       menu and the JFrame's "X" button.  (or alt-F4 keystrok on Windows). The menu is an ActionListener and
       JFrame uses a Window listener. You could have the window listener call doClick() on the menu or call the menu's
       action and have the menu's action perform the work. This is less than ideal OO design, but is what Swing developers
       are
       often stuck with.  This gets even less elegant when another place in the application that closes the application
       -
       say an error catching routine (an AWTExceptionHandler or similar).

          Instead, let's make thing more elegant and easy by using the EventBus
       public class JFrame {
       public void initialize() {
       ...
       EventBus.subscribe(ApplicationClosingEvent.class, new EventSubscriber() {
           public void onEvent() {
               shutdown();
           }
       });
       ...
       }
       public void shutdown() {
          if (document.isModified()) {
              if (!userReallyWantsToShutDown()) {
                 return;
              }
          }
          closeServerSocket();
          close();
       }

       private void handleWickedBadError() {
          EventBus.publish(new ApplicationClosingEvent());
       }

       private void createMenu() {
          ...
          //An aside - the best way to create menus is with the SwingEventManager! See http://sam.dev.java.net  :-)
          //The exit menu item's action is a special EventBusAction that fires an ApplicationClosingEvent() when clicked.
          MenuItem exit = new JMenuItem(new EventBusAction() {
             protected EventServiceEvent getEventServiceEvent(ActionEvent event) {
                return new ApplicationClosingEvent();
             }
          });
          ...
       }

       Perhaps that doesn't look much better than calling shutdown() three times, but if this code is distributed
       three different files, it gets a little nasty.  You can expose shutdown(), but then you are on your way to the
       Swing spaghetti dinner table.

    Miscellany

    The EventBus uses Apache Commons Logging so it will integrate with your logging framework - log4j, java.util.logging,
       etc.
       The hope was to have the EventBus not dependent on any other jar, but we felt this tradeoff was worth it.
    A few of exception handling classes are included in the EventBus distributions. They don't have anything
       to do with the EventBus per se, but I simply didn't want to create another project for them. :-) SwingExcpetion
       is a handy exception when invokeLater() is called since the call stack that calls the invokeLater() can be captured
       (and is captured by the SwingEventService).

       The AWTExceptionHandler can plug into Swing to provide centralized handling of exceptions. Also included is a a
       dialog
       that handles excpetions, including emailing exceptions and copying them to the clipboard. It is a particularly handy
       when using the EventBus from multiple threads. When using the email feature of the dialog jdic.jar is required on the
       classpath and the associated binary (such as jdic.dll) are required in the java.library.path.