48

Is there a good lightweight framework for java that provides the publish/subscribe pattern?

Some ideal features

  • Support for generics
  • Registration of multiple subscribers to a publisher
  • API primarily interfaces and some useful implementations
  • purely in-memory, persistence and transaction guarantees not required.

I know about JMS but that is overkill for my need. The publish/subscribed data are the result of scans of a file system, with scan results being fed to another component for processing, which are then processed before being fed to another and so on.

EDIT: All within the same process. PropertyChangeListener from beans doesn't quite cut it, since it's reporting changes on properties, rather than publishing specific items. I could shoehorn ProprtyChangeListener to work by having a "last published object" property, and so published objects. PropertyChangeListeners don't support generics, and are entrenched in property change semantics, rather than pure publish/subscribe. The java.util Observer/Observable pattern would be good, but Oberver is a concrete class.

mdma
  • 56,943
  • 12
  • 94
  • 128
  • Within one process? Or across many processes and machines? – djna Jun 13 '10 at 15:58
  • Within a single process. – mdma Jun 13 '10 at 16:44
  • Is this a Spring application? – skaffman Jun 13 '10 at 16:50
  • @skaffman, yes the application is implemented in spring. The part I'm focusing on here that needs a simple publish/subscribe pattern is a RIA client, which uses spring to configure the interfaces to web service endpoints. The objects being published/subscribed are all local. – mdma Jun 13 '10 at 16:58
  • I'm a little confused with the references to JMS. If you are within a single process could one (or a couple) thread executor pools be adequate? If the threads are dynamically subscribing then could a loose wrapper around a series of BlockingQueue(s) work? A thread could choose to subscribe to a job by take-ing from the right queue. I've seen performance problems with various JMS implementations when you have portions of the work queue that are faster than others. – Gray Jun 13 '10 at 17:05

6 Answers6

31

It seems this fits the requirements:

EventBus from Google Guava Library - "Publish-subscribe-style communication between components without requiring the components to explicitly register with one another". It can also be an AsyncEventBus that will dispatch events on another thread.

Some extra options to consider:

  1. If it's in same process it's possible the Observer pattern can be used. Subscribers can add listeners and receive event notifications. Observable is already part of the Java API.

  2. FFMQ is a full Java, light-weight, Fast JMS 1.1 Queue implementation.

Marco Faustinelli
  • 3,734
  • 5
  • 30
  • 49
Andrejs
  • 26,885
  • 12
  • 107
  • 96
  • 2
    The Observer pattern seems to imply a knowledge of the observable and observer whereas true publish/subscribe permits code independence. EventBus from Guava looks better for this. – unludo May 06 '13 at 08:42
  • Another option would be using [MBassador](https://github.com/bennidi/mbassador) -- it is similar to Guava EventBus but claims to have better processing performance (see [benchmarks](https://github.com/bennidi/eventbus-performance)). On the downside it looks like it hasn't been updated for a while now. – msilb Jan 16 '21 at 11:22
11

JMS is as light or heavy as you configure it. We use for example HornetQ in one project with an in memory queue. It is easy to setup, doesn't need any JNDI based configuration and is really easy to use.

I believe that JMS as an API for Message Pub/Sub is as easy as it gets. (And not easier ;)

Timo Westkämper
  • 21,824
  • 5
  • 78
  • 111
  • 1
    Actually... for the publish/subscribe aka observer pattern the simplest and most basic thing there is... is the javax.beans package. ;) (PropertyChangeListener, PropertyChangeEvent, PropertyChangeSupport ...) – user268396 Jun 13 '10 at 16:13
  • @user268396, fair enough. For simple POJO state change pub/sub JavaBeans property listening is even simpler. – Timo Westkämper Jun 13 '10 at 16:21
  • @user268396 - I'm afraid PropertyChangeListener won't fit here. See my edit for reasons. – mdma Jun 13 '10 at 16:59
  • thanks for this suggestion. Perhaps was too hasty in dismissing JMS? – mdma Jun 13 '10 at 17:00
  • @mdma, maybe, I thought too before that JMS is all heavyweight J2EE, but it is actually quite lightweight if you pick the right provider. And if interface/provider separation is important for you, then JMS is probably the right approach. – Timo Westkämper Jun 13 '10 at 17:53
8

Since you're using Spring, I don't know if you're aware that Spring has its own lightweight event framework. It's used primarily within the framework itself, but it's perfectly usable by application code.

By default, it's synchronous pub/sub, but you can make it asynchronous using an ApplicationEventMulticaster.

skaffman
  • 398,947
  • 96
  • 818
  • 769
1

I think Camel is also a good candidate. Especially with the publish-subscribe pattern

Camel can be embedded and is lightweight. It proposes Enterprise Integration Patterns - many useful tools for integration, inside an application or even with other actors (hence 'Integration').

It compares to Spring Integration but more complete IMO.

unludo
  • 4,912
  • 7
  • 47
  • 71
0

If you are crossing process boundaries then some degree of "weight" is going to be incurred. Why do you say that JMS is heavyweight? The API is quite simple? There are supposedly light-weight implementations, for example link text heavier costs such a persistence and transactionality are optional.

What do you need that is lighter than this?

djna
  • 54,992
  • 14
  • 74
  • 117
0

Bob Lee has a QueueFile class at http://snipt.org/GWm/ that you might find interesting. It's a simple persistent queue and could be used by multiple consumers. It sounds like you don't need persistence, but since the whole thing is so lightweight it could still be useful.

Cagatay
  • 1,372
  • 1
  • 12
  • 16
  • You could access latest implementation from here: https://github.com/square/tape/blob/master/tape/src/main/java/com/squareup/tape/QueueFile.java –  Oct 20 '12 at 17:07