Lightweight, extremely fast, and zero-gc message/event bus for Java 6+
Go to file
Filip Ristić 9eacace230 Update src/main/java/org/mbassy/MBassador.java
Removing "unchecked call" warnings.
2012-12-13 15:12:18 +01:00
maven/org/mbassy/mbassador release of 1.0.5.RC 2012-12-12 14:56:28 +01:00
src Update src/main/java/org/mbassy/MBassador.java 2012-12-13 15:12:18 +01:00
.gitignore mavenized 2012-11-19 15:22:11 +01:00
build.gradle release of 1.0.4.RC, fixed #8 2012-12-11 12:16:22 +01:00
LICENSE added license 2012-10-30 14:22:56 +01:00
pom.xml release of 1.0.5.RC 2012-12-12 14:56:28 +01:00
README.md release of 1.0.5.RC 2012-12-12 15:05:11 +01:00

Mbassador

Mbassador is a very light-weight message (event) bus implementation following the publish subscribe pattern. It is designed for ease of use and aims to be feature rich, extensible while preserving resource efficiency and performance.

It uses a specialized data structure to allow high throughput for concurrent access.

Read this documentation to get an overview of its features and how cool this message (event) bus actually is. You can also check out the performance comparison which also contains a partial list of the features of the compared implementations.

The current version is 1.0.5.RC

Table of contents:

Features

At its core MBassador offers the following features:

  • Annotation driven: To define and customize a message handler simply mark it with @Listener annotation
  • Delivers everything: Messages must not implement any interface and can be of any type (-> message bus is typed using generics with upper bound being Object.class). The class hierarchy of a message is considered during message delivery. This means that listeners will also receive subtypes of the message type they are listening for, e.g. a listener for Object.class receives everything.
  • Synchronous and asynchronous message delivery: A handler can be invoked to handle a message either synchronously or asynchronously. This is configurable for each handler via annotations. Message publication itself supports synchronous (method blocks until messages are delivered to all handlers) or asynchronous (fire and forget) dispatch
  • Weak references: Mbassador uses weak references to all listening objects to relieve the programmer of the burden to explicitly unregister listeners that are not used anymore (of course it is also possible to explicitly unregister a listener if needed). This is very comfortable in certain environments where objects are created by frameworks, i.e. spring, guice etc. Just stuff everything into the message bus, it will ignore objects without message handlers and automatically clean-up orphaned weak references after the garbage collector has done its job.
  • Filtering: Mbassador offers static message filtering. Filters are configured using annotations and multiple filters can be attached to a single message handler
  • Message envelopes: Message handlers can declare to receive an enveloped message. The envelope can wrap around different types of messages. This allows for a single handler to handle multiple message types
  • Handler priorities: A listener can be associated with a priority to influence the order of the message delivery
  • Error handling: Errors during message delivery are sent to an error handler of which a custom implementation can easily be plugged-in.
  • Ease of Use: Using Mbassador in your project is very easy. Create as many instances of Mbassador as you like (usually a singleton will do), mark and configure your message handlers with @Listener annotations and finally register the listeners at any Mbassador instance. Start sending messages to your listeners using one of Mbassador's publication methods (sync or async). Done!

Usage

Listener definition (in any bean):

    // every event of type TestEvent or any subtype will be delivered
    // to this handler
    @Listener
	public void handleTestEvent(TestEvent event) {
		// do something
	}

    // this handler will be invoked asynchronously
	@Listener(dispatch = Mode.Asynchronous)
	public void handleSubTestEvent(SubTestEvent event) {
        // do something more expensive here
	}

	// this handler will receive events of type SubTestEvent
    // or any subtabe and that passes the given filter(s)
    @Listener(priority = 10,
              dispatch = Mode.Synchronous,
              filters = {@Filter(MessageFilter.None.class),@Filter(MessageFilter.All.class)})
    public void handleFiltered(SubTestEvent event) {
       //do something special here
    }

    @Listener(dispatch = Mode.Synchronous, filters = @Filter(Filters.RejectSubtypes.class))
    @Enveloped(messages = {TestEvent.class, TestEvent2.class})
    public void handleSuperTypeEvents(MessageEnvelope envelope) {
        // detect the type of event here and then decide the course of action
    }

Creation of message bus and registration of listeners:

    // create as many instances as necessary
    // bind it to any upper bound
    MBassador<TestEvent> bus = new MBassador<TestEvent>(BusConfiguration.Default());
    ListeningBean listener = new ListeningBean();
    // the listener will be registered using a weak-reference
    bus.subscribe(listener);
    // objects without handlers will be ignored
    bus.subscribe(new ClassWithoutAnyDefinedHandlers());

Message publication:

    TestEvent event = new TestEvent();
    TestEvent subEvent = new SubTestEvent();

    bus.publishAsync(event); //returns immediately, publication will continue asynchronously
    bus.post(event).asynchronously(); // same as above
    bus.publish(subEvent);   // will return after each handler has been invoked
    bus.post(subEvent).now(); // same as above

Installation

This project contains a maven repository that will allow you to import MBassador as a dependency into your maven project. Currently this is all that will be provided because publishing to a central repository requires extra project setup that will be done as soon as enough people use this component. Until then, the following steps are necessary:
  1. Add the repository location to your pom.xml
    
    <repositories>
        <repository>
            <id>mbassador-github-repo</id>
            <url>https://raw.github.com/bennidi/mbassador/master/maven </url>
        </repository>
    </repositories>
    
  2. Add the MBassador dependency to your pom.xml. You can check which versions are available by browsing the git repository online.
    
        <dependency>
            <groupId>org.mbassy</groupId>
            <artifactId>mbassador</artifactId>
            <version>1.0.0.RC</version>
        </dependency>
    
  3. Run mvn clean package to have maven download and install the required version into your local repository

Of course you can always clone the repository and build from source

Roadmap

+ Checkout MBassador from one of the official maven repositories (as soon as the user base is big enough) + Spring integration with support for conditional message dispatch in transactional context (dispatch only after successful commit etc.). Currently in beta, see this repository + MessageEnvelope for each dispatch that is passed to the handler and can be used for communication between handlers during the running dispatch

Credits

The initial inspiration for creating this component came from looking at Google Guava's event bus implementation. Since it did not provide all the features we needed in our project, I decided to create my own implementation. When I saw that it outperformed the Guava implementation by far, I decided to share it with the community to see if others consider it worth a shot.

Contribute

Any feature requests and feedback are more than welcome. You may suggest improvements either by submitting an issue or by forking the repo and creating a pull request. I will try to respond as quickly as possible.

License

This project is distributed under the terms of the MIT License. See file "LICENSE" for further reference.