Blackboard event router

Hi Henrik,

Thanks for the library.

I would like to ask you about the weak-references. Why use them? Well, I’m gonna tell you my case and maybe I’m even wrong to grasp the idea that the weak-reference is the culprit.

I am initializing Blackboard as suggested in the application start. So, after using my app for a while, I noticed my events were not being fired anymore. So, I began investigating and it seems, my listeners have been “unregistered” from the listeners map.

Don’t you think we should guarantee that events are being triggered successfully all the time?

Thanks a lot,

Marcos Alcantara

You’re absolutely right, and that’s a bug. I weak references would work in a slightly different way, but evidently, they didn’t.

I do a have a slightly tweaked version of Blackboard on my computer as we speak, but it’s currently a bit unpolished, thus I haven’t published it yet. I have plans to do some 10%-time on Friday, so expect some kind of update then (if I have enough time, that is).

Blackboard 2.0.1 is
now available
.

The changes are pretty extensive. Compared to 1.2.0, they’re the following:

  • API is incompatible with eariler releases
  • Notifier is removed completely
  • com.github.wolfie.blackboard.Event is now an interface
  • Blackboard.register() now accepts only interface-Listeners
  • The example application is cleaned up
  • Dependency for Google Collections is removed
  • Registering abstract Events is disallowed

I’ve tried to simplify the API, while making it harder to screw up by having bad code.

The
documentation
has been updated accordingly. I’d also recommend you to check out
the example application
, to get a better grasp on how using Blackboard looks like now.

Hi Henrik,
did this solve the problem with weak references and disconnecting listeners ?

Im actually thinking to embed BB to TPT, it seems using BB to handle various app events is much much simplier and easier.

Oh, right, I should’ve perhaps mentioned this in the previous post. BB uses hard references only now. No (un)natural object decay, and you get to keep your references throughout a BB’s lifetime, unless you remove a listener manually.

PS: there should be some kind of download sharing program in the Directory :slight_smile:

Hi,

I like the Blackboard tool a lot, but one thing bugs me about it - why do I have to annotate the listener method with @ListenerMethod on the listening class? The listening class has already implemented the interface and registered itself, shouldn’t that be enough?

Thanks,

Mark


Blackboard
has been updated again!

I’ve added some magic recognition code in there, to allow people to skip the
blackboard.register(listener, event);
routine, allowing Blackboard to automagically scan for existing Event/Listener pairs.

First of all, I’ve added a new annotation – @ListenerPair – which can be given to your Event class. It takes the corresponding Listener interface as its argument. This tells Blackboard how the listeners and events should be paired together. You don’t have to use the annotation, though, if you follow a new convention:
Write each Listener as a public inline interface to its corresponding Event
. Example:


@ListenerPair(MyListener.class) // this is not necessary, in this inline case
public class MyEvent implements Event {
  public interface MyListener implements Listener {
    @ListenerMethod
    public void react(Event event);
  }
}

So, if your events and listeners are structured this way, you don’t
have
to use the @ListenerPair annotation (although it’s recommended, to make it explicit).

The automatic registration can be done in one of two ways:


1)
As soon as you have instantiated the Blackboard instance, call
blackboard.discover()
. This sends Blackboard to an epic journey of magic code, which tries to find all listener/event pairs (according to the format mentioned above)
in and underneath the current package
. You can modify which package acts as a root, by using
blackboard.discoverFrom(Class)
instead, where Class is any class in the desired root package. This should work most of the times, but since it’s a bit magic, it can fail terribly. YMMV


2)
Skip the “discover()” call, and just don’t do anything. Each time you add a listener to Blackboard, that will be paired with a suitable Event just in time. This format
requires
the code style convention (with the inline interfaces), and annotations will not help you here.

So, here’s some lazy coding improvements. You are still allowed to register each pair manually (which will disable any magic thingies, by the way), and that’s always the most reliable way to register them. I have some ideas about 2.2.0, but those might need to wait for quite some while.

The discover() part is a little frightening, but the automatic connection on adding a listener sounds good.

I was re-reading this thread. The major use case I have for the blackboard is event propagation in a push() context.
This means that I often have listeners that should just go away when the user closes a window closed, and they must also be re-established if the window is reloaded. This is currently painful, as it requires carefully maintaining a cleanup routine invoked on the window close, and a similar routine on reload (URI handler).

Yeah. It’s just a helper function that I haven’t tested all too thoroughly. You’re free to use it, but you’re not forced to. I’m interested in hearing any experiences

This sounds like an intriguing feature. I’ll look into this. You could of course do the addlistener thing into a constructor, and garbage collect it manually whenever the window is closed. But, I’ll see what I can help here with.

Glorious news: There’s yet another release, now with
even more
heuristics!

@ListenerMethod is can now be deducted by Blackboard, thanks to even more magic code. If there really is one logical choice for the method, that will automatically be picked, in the following priority:

  1. Only one method has been annotated with @ListenerMethod
  2. The interface only has one method
  3. The interface has several methods, but only one accepts the type of event we’re trying to register.

Enjoy the lazy coding!

Hello,
First of all, thanks for a great add-on for Vaadin! But…it seems to be impossible to use BlackBoard with GAE as it does not implement serializable. Could you please tell if it will be implemented someday or somehow possible right now?

You’re very welcome! I’m glad you like it

That’s correct. Unfortunately, the java.lang.reflect.Method class, which is stored inside Blackboard is not serializable either. Therefore, in case I’ve understood it correctly, I can’t guarantee the whole Blackboard being serializable and thus I can’t put any of it as serializable. I’m sorry :confused:

Hi there,

I’m trying to use Blackboard on a Vaadin based portlet project. I’m facing some problems with Blackboard 2.1.1: when I fire() an event, it somehow stays somewhere in memory, and gets replayed each and every time another event of the same type is fired. I tried to debug your code a bit, but the latest source code from Github is not really the 2.1.1 one. Where can I find the sources?

Thanks in advance for your help,
c.

Hi!

That’s very weird. I’ve never had that kind of trouble. I’ve never tried Blackboard within a portlet, but it sounds highly unlikely that it would have something to do with that…

Hm. According to the package I just downloaded from the Directory (http://vaadin.com/directory#addon/blackboard), the sources are included in the jar (as they should be). If everything else fails, unzip the jar, and put the source files in your classpath (or something similar). Maybe you’re experiencing some classloader problems, which might explain what you’re experiencing (although, classloader problems often cause
unforeseen consequences
)

I’m afraid that I can’t help you more with this issue :(. If the issue doesn’t go away even after you’ve debugged it, I’d love to help you, given a bit more details about your problem.

PS: unfortunately, I’m unable to check my email constantly, and I seem to forget to check my email manually. So my replies might take some days…

Hi!

I’m using blackboard and it was working very fine until yesterday :slight_smile:
I disabled the explicit registration of events to use the magic registration and then it stopped working for one very particular case.

I have the following class that should react to 2 events managed by the blackboard (in bold):


public class TableChangesTable extends Table implements [b]
TableChangesListener
[/b], [b]
UseCaseClickListener
[/b], I18NListener {
  public TableChangesTable(){
    getBlackboard().addListener(this);
  }
}

If I look at the code to register the listeners on the addListener method of the blackboard I can see this:


    Collection<Class<? extends Listener>> registeredListenerClasses = getRegisteredListenerClasses(listenerClass);

    if (registeredListenerClasses.isEmpty()) {
      boolean success = false;

      if (magicRegistration) {
        success = magicRegisterAllListenerInterfacesIn(listener);
      }

      if (!success) {
        throw new NoMatchingRegistrationFoundException(listenerClass);
      } else {
        registeredListenerClasses = getRegisteredListenerClasses(listenerClass);
      }
    }

The magic registration should register both listeners. The problem is that in this particular case I already registered the UseCaseClickListener previously in my application, only the TableChangesListener in not registered yet and should be registered.

So when the blackboard calls this line : Collection<Class<? extends Listener>> registeredListenerClasses = getRegisteredListenerClasses(listenerClass); it can find the UseCaseClickListener, that means that the registeredListenerClasses is not empty and it does try to register the other one…

I hope I was clear enough :slight_smile:

If you have an idea or a fix then please tell me :slight_smile:

Thomas

Hi Henrik,

I just started to use your EventBus. Works great - Thank you very much.

One improvement could be the logging.

I want to log with Log4J - there is no easy possibility for that at the moment. I don’t want to log everything to System.out.

An easy solution could be to make your Log.logTo(PrintStream)-method accessible. I could pass in my own simple stupid PrintToLog4jPrintStream or something like that.

A more complex, but cleaner solution could be to use commons-logging.

Thank you very much,

Daniel

Hello,

Thank you very much for this add-on, the event bus management is easier but I just wanted to know how to build clean classes for the interface and the events.

interface extends Listener

void deleteUser(event1)
void addUser(event2)

Problem : I got a runtime error saying I can’t register the same method ??

Btw, i don’t understand very well the @ListenerMethod annotation, can you provide me some informations about it please ?

Thx !

Hi,

I use Blackboard with Maven and since 2.2.0 i cannot get the correct sources for the downloaded .jar

Has somebody ideas to resolve this issue?

Update: I got an error if i want debug blackboard: Absent Line Number Information.

thanks

Andre

A support to register an error handler for catching exceptions from listeners would be a great improvement. Now you need to remember to code try-catch block in every listener otherwise Blackboard eats the exceptions and prints stacktraces to console.

Such an addon is very important to have clean code in complex UI’s.

Currently we use the EventBus from guava (https://code.google.com/p/guava-libraries/wiki/EventBusExplained) and it works great.

An important design decision is if you should have a global Event Bus instance, an instance per session or an instance per Vaadin UI instance. We use one instance per UI instance to deliver events within a UI.