I really love the Google Gauva EventBus, so much so that I want to include it in one of my Swing GridBagBuilder APIs . The goal is to take the Swing component and do something with it in any case and subscribe to the EventBus. The problem is that I think that the reflection operations performed by EventBus do not like my generics for any arbitrary type of event.
Essentially, the method accepts BiConsumer, where C is the Swing component, and E is an arbitrary type of event to subscribe to the EventBus.
public <E> void subscribe(EventBus eventBus, BiConsumer<C,E> consumer) { eventBus.register(new Object() { @Subscribe public void processEvent(E event) { try { consumer.accept(comp, event); } catch (Exception e) { e.printStackTrace(); } } }); }
The event bus seems to work, but I keep getting fancy ClassCastException errors. Is there any way to make this work? Or am I trying to achieve a lost cause?
UPDATE: Here is the SSCCE. It breaks down when there are several types of events, and somewhere the mechanisms of generics and internal reflection are messed up and cannot distinguish one type of event from another.
import java.awt.Component; import java.util.function.BiConsumer; import javax.swing.JButton; import com.google.common.eventbus.EventBus; import com.google.common.eventbus.Subscribe; public class EventBusTest<C extends Component> { private final C comp; public static void main(String[] args) { final EventBus eventBus = new EventBus(); EventBusTest<JButton> test = new EventBusTest<>(new JButton("Hello")); test.subscribe(eventBus, (JButton c, SomeEvent e) -> System.out.println("Hello")); test.subscribe(eventBus, (JButton c, SomeOtherEvent e) -> System.out.println("World")); eventBus.post(new SomeEvent()); } private EventBusTest(C comp) { this.comp = comp; } public<E> void subscribe(EventBus eventBus, BiConsumer<C,E> consumer) { eventBus.register(new Object() { @Subscribe public void processEvent(E event) { try { consumer.accept(comp, event); } catch (Exception e) { e.printStackTrace(); } } }); } private static final class SomeEvent {} private static final class SomeOtherEvent {} }
And so console printing ...
java.lang.ClassCastException: com.swa.rm.pricing.EventBusTest$SomeEvent cannot be cast to com.swa.rm.pricing.EventBusTest$SomeOtherEvent at com.swa.rm.pricing.EventBusTest$$Lambda$14/28594521.accept(Unknown Source) at com.swa.rm.pricing.EventBusTest$1.processEvent(EventBusTest.java:32) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at com.google.common.eventbus.EventSubscriber.handleEvent(EventSubscriber.java:74) at com.google.common.eventbus.SynchronizedEventSubscriber.handleEvent(SynchronizedEventSubscriber.java:47) at com.google.common.eventbus.EventBus.dispatch(EventBus.java:322) at com.google.common.eventbus.EventBus.dispatchQueuedEvents(EventBus.java:304) at com.google.common.eventbus.EventBus.post(EventBus.java:275) at com.swa.rm.pricing.EventBusTest.main(EventBusTest.java:21) Hello