Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

best way to combine guava eventbus and AWT Event thread handling

Tags:

java

awt

guava

When you have a asynchronous event bus, and fire events, lets say within the model which get catched in the UI you have probably the following problem:

The registered handler gets executed in a worker thread, but all UI swing changes need to be executed within the AWT event thread. This means you need to envelope all your handler clode in EventQueue.invokeLater(...).

This looks like a lot of boiler plate code. I wonder if there is a smarter solution for that problem.

What about an extension to the guava event bus that marks a handler for execution within a special thread? This could be marked with a annotion e.g. @ExecuteWithinEDT:

class EventBusChangeRecorder {
  @Subscribe @ExecuteWithinEDT void recordCustomerChange(ChangeEvent e) {
    recordChange(e.getChange());
  }
}
like image 736
langm Avatar asked Mar 01 '12 16:03

langm


2 Answers

The handlers registered with an async event bus are executed on whatever thread the provided Executor chooses to run them on, not necessarily a worker thread.

What I've done is created an implementation of Executor that runs stuff on the event queue thread. It's pretty simple:

public class EventQueueExecutor implements Executor {
  @Override public void execute(Runnable command) {
    EventQueue.invokeLater(command);
  }
}

You can then just create your EventBus with that:

EventBus eventBus = new AsyncEventBus(new EventQueueExecutor());

Then all handlers will be executed on the event queue thread.

Edit:

An example of forwarding events:

public class EventForwarder {
  private final EventBus uiEventBus;

  public EventForwarder(EventBus uiEventBus) {
    this.uiEventBus = uiEventBus;
  }

  // forward all events
  @Subscribe
  public void forwardEvent(Object event) {
    uiEventBus.post(event);
  }

  // or if you only want a specific type of event forwarded
  @Subscribe
  public void forwardEvent(UiEvent event) {
    uiEventBus.post(event);
  }
}

Just subscribe that to your main event bus and post all events to the main event bus, but subscribe all UI components to the UI event bus.

like image 75
ColinD Avatar answered Sep 19 '22 22:09

ColinD


You can create an EventBus that dispatches only on the AWT thread:

EventBus mybus = new AsyncEventBus("awt",
    new Executor() {
        public void execute (Runnable cmd) {
            if (EventQueue.isDispatchThread()) {
                cmd.run();
            } else {
                EventQueue.invokeLater(cmd);
            }
        }
    });
like image 45
user1243452 Avatar answered Sep 21 '22 22:09

user1243452