Use dynamic proxies to create a simple, powerful event bus (Part 1)

In this blog I’m going to walk you through one of my favourite uses for Java’s dynamic proxies.  Why favourite?  Because it takes a powerful, sometimes misunderstood, feature of Java and creates a simple, useful tool that we can use every day.

Event Buses

Event buses act as brokers or clearing houses for notifications. They provide a single point of contact where:

  1. Observers can register to be notified of events.
  2. Subjects can publish events as they occur.

Event buses are an evolution on the observer pattern. They share many of the same advantages (loose coupling and event broadcasting), while removing several shortcomings:

  1. Code duplication. Subjects no longer need to explicitly track their observers. The list of observers, along with the registration and notification logic, can be moved from each subject into the event bus.
  2. Decentralized event management. Event registration and notification are no longer spread out over a potentially large number of classes. Centralized management also aids in debugging, eases maintenance, and reduces our overall software complexity.
  3. Simplified event wiring. Observers do not need to seek out subjects to register their interest and subjects do not need to notify observers directly when events occur.

Dynamic Proxies

Dynamic proxies are a way to route calls from all methods on one or more Java interfaces to a single function automagically (without programming). This happens while your program is running and doesn’t require recompilation or restart. All it needs is a set of interfaces to automatically implement and a concrete implementation of the java.lang.reflect.InvocationHandler interface to receive the calls.

One Call, Many Receivers

What if we could call a method that instead of being invoked on one object was invoked on several objects automatically? For example, person.walkTo(store) invokes walkTo on a single person object. But what if we could invoke that call on many person objects at once without having to call a fireWalkTo method or create a WalkEvent class (a common way of implementing the observer pattern)? Well, that’s exactly what this event bus does. It lets subjects call methods on the listener interface then invokes those calls on all registered observers.

Java Event Bus - One Call, Many Receivers

Quick Example

Before we dive into the details, let’s look at a quick example of how the final product can be used.

First we create a listener interface:

Then we use WalkListener to both observer and publisher events:

Implementation Details

The Event Bus is made up of three collaborating classes: Event, EventSourceInvocationHandler, and EventBus. For most of our use-cases, EventBus is all we’ll need to work with. In some rare cases we may need direct access to the Event object — for example — to log all events flowing through the bus (regardless of type or method). We’ll discuss how to accomplish this in part 2 of this series.

Event Class

The Event class represents a single method invocation from an event source (publisher). It holds the actual invoked java.lang.reflect.Method along with any arguments that were passed into it.

EventSourceInvocationHandler Class

EventSourceInvocationHandler is the concrete implementation of InvocationHandler for use with dynamic proxies. Its invoke() method receives all event publisher method calls and posts them to the event bus for delivery.

EventBus Class

EventBus is where all the magic happens. It provides all of the registration, queuing, and delivery services to make the whole thing work. Let’s first look at the bus’ surface area, followed by implementation details of the business methods: getPublisher, addListener, deliverEvent, and publishEvent.

First the basic structure of the bus:

EventBus.getPublisher()

The getPublisher method takes an event source and a listener class then returns an instance of that listener we can call to publish events. The event source can be any object for now. In the next blog we’ll see how we can use it to filter the events observers receive.

EventBus.addListener()

Observers register for events by calling addListener() with the EventListener interface they are interested in and an object that implements it. CopyOnWriteArraySet is used because it is thread-safe without requiring much synchronization. This means we have the option to notify observers using separate threads without blocking registrations.

EventBus.deliverEvent()

Event delivery is performed by invoking the original method called by the producer on every registered observer.

EventBus.publishEvent()

Events are queued for delivery by adding a Runnable with the actual delivery task to the executor service. Executors are a great way to benefit from concurrency without the complexity (and subtle bugs) that come with writing multi-threaded code.

Next Time

That’s all for now. I hope you’ve found this application of dynamic proxies useful. Please leave a comment if you have any suggestions, questions, or ideas on dynamic proxies or event busses.

In the next part of this series, we’ll focus on several topics (exception handling, garbage collection, etc.) to help round out the bus’ feature set.

Download

The event bus download contains the entire source code (including Eclipse project). The source code is licensed under the terms of the Apache License, Version 2.0.

Java Exception Tracking

If you enjoyed this, I’ve got an exception tracking tool for Java coming out. Sign-up at StackHunter.com to be notified when it does.

About Dele Taylor

Dele Taylor is the founder of NorthConcepts.com, creators of Data Pipeline -- a data migration library for Java. You can follow him on Twitter, G+, and LinkedIn.
Dynamic Proxies, Event Bus, Java | permalink

Comments

  1. I wanted to get the rss-FEED but feed site shows me some XML errors…

  2. Dele Taylor

    Fara – can you give me an example of one of the XML errors you’re seeing with http://northconcepts.com/blog/feed/

  3. Pingback: Use dynamic proxies to create a simple, powerful event bus (Part 2) | North Concepts

  4. Jim Shi

    Hi, Dele,
    I don’t see eventSource is used by your code.
    What is purpose to have eventSource defined in the code?
    Thanks

    • Dele Taylor

      HI Jim,

      Good catch. It isn’t until part 2 of this series that eventSource is used for filtering.

      Thanks for taking the time to read this article and go through the code.

      Cheers,
      Dele

  5. I agree. A powerful bus will be created through these steps and methods posted. Great!

  6. Pingback: How to build a simple GWT event bus using Generators | North Concepts

  7. Dav

    Really enjoyed that- frankly never considered reflector interceptors (?) before- thanks :)

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">