best way to combine guava eventbus and AWT Event thread handling - java

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());
}
}

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.

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);
}
}
});

Related

How to disable a particular event handler from axon?

We have a few event handlers configured in the code. But, I'd like to disable a particular event handler from axon.
Please note - I can do this using #Profile or #Conditional parameter. But, I am interested to know if there is any way like config at EventConfig to exclude the particular event handler from processing.
Please refer below code.
Event Source Config
public class AxonConfig {
public void configureProcessorDefault(EventProcessingConfigurer processingConfigurer) {
processingConfigurer.usingSubscribingEventProcessors();
}
}
Event handlers
#ProcessingGroup("this")
class ThisEventHandler {
// your event handlers here...
}
#ProcessingGroup("that")
class ThatEventHandler {
// your event handlers here...
}
#ProcessingGroup("other")
class OtherEventHandler {
// your event handlers here...
}```
The EventProcessingConfiguration that's constructed as a result of the EventProcessingConfigurer provides a means to retrieve your Event Processor instances. Furthermore, any EventProcessor implementation has a start() and shutDown() method.
You can thus stop the Event Processors that you want to stop.
The following piece of code would get that done for you:
class EventProcessorControl {
private final EventProcessingConfiguration processingConfig;
EventProcessorControl(EventProcessingConfiguration processingConfig) {
this.processingConfig = processingConfig;
}
public void startProcessor(String processorName) {
processingConfig.eventProcessor(processorName)
.ifPresent(EventProcessor::start);
}
public void stopProcessor(String processorName) {
processingConfig.eventProcessor(processorName)
.ifPresent(EventProcessor::shutDown);
}
}
As a side note, I would warn against only using the SubscribingEventProcessor. Of the Event Processor implementations, it provides the least amount of flexibility when it comes to performance, distribution and error handling. I'd much rather try using the PooledStreamingEventProcessor instead.

Why does my Spring #EventListener show different transactional behavior on event submission than when being called directly?

When using the #EventListener functionality with Spring Data's repositories the behavior is different than when calling the same code procedural.
My persistent objects publish events using the following base class:
public abstract class Aggregate {
#Transient
private transient final Set<Object> events = new LinkedHashSet<>();
protected <T> T registerEvent(T event) {
this.events.add(event);
return event;
}
#DomainEvents
Collection<Object> events() {
return Collections.unmodifiableSet(events);
}
#AfterDomainEventPublication
void clearEvents() {
this.events.clear();
}
}
My event listening class is implemented as follows:
class Service {
#EventListener
public void listener(SomeEvent event) {
someOtherRepository.save(someOtherPersistentObject);
someOtherCode();
}
}
When the listener is triggered and someOtherRepository's save(…) method fails a rollback will be issued. But someOtherCode() is executed regardless of the rollback.
But when I remove all #EventListening functionality and call the listener(…) method directly after the point where the originating repository is responsible for firing the event. Then I get a different behavior. Then someOtherCode() is never executed and the someOtherRepository.save(…) method fails immediately.
The original service responsible for publishing the event looks like this
public OriginatingService {
#Transactional
public void someMethod() {
originatingRepoDifferentFromSomeOtherRepo.save(something);
Why is this happening and is there a way to force the same behavior onto my event listening implementation?
Because writes to the database may be delayed until transaction commit i.e. when the transactional method returns.
Update as below to explicitly trigger an immediate flush:
#EventListener
public void listener(SomeEvent event) {
someOtherRepository.saveAndFlush(someOtherPersistentObject);
someOtherCode();
}

Event handlers in a separate class Axon 3.0.3

I've got a fairly simple CQRS setup here using Axon & Spring.
This is the configuration class.
#AnnotationDriven
#Configuration
public class AxonConfig {
#Bean
public EventStore eventStore() {
...
}
#Bean
public CommandBus commandBus() {
return new SimpleCommandBus();
}
#Bean
public EventBus eventBus() {
return new SimpleEventBus();
}
}
This is my Aggregate...
#Aggregate
public class ThingAggregate {
#AggregateIdentifier
private String id;
public ThingAggregate() {
}
public ThingAggregate(String id) {
this.id = id;
}
#CommandHandler
public handle(CreateThingCommand cmd) {
apply(new ThingCreatedEvent('1234', cmd.getThing()));
}
#EventSourcingHandler
public void on(ThingCreatedEvent event) {
// this is called!
}
}
This is my EventHandler in a separate .java file...
#Component
public class ThingEventHandler {
private ThingRepository repository;
#Autowired
public ThingEventHandler(ThingRepository thingRepository) {
this.repository = conditionRepository;
}
#EventHandler
public void handleThingCreatedEvent(ThingCreatedEvent event) {
// this is only called if I publish directly to the EventBus
// apply within the Aggregate does not call it!
repository.save(event.getThing());
}
}
I'm using the CommandGateway to send the original creation command. My CommandHandler in the Aggregate receives the command fine, but when I call apply within my Aggregate, passing a new Event, my EventHandler in the external class, does not get called. Only EventHandlers directly inside the Aggregate class are called.
If I try and publish an Event directly to the EventBus, my external EventHandler is called.
Any idea why my EventHandler in an external java class is not being called when I call apply within the Aggregate?
In Axon 3, the Event Store is a replacement for the Event Bus. It is basically a specialized implementation that doesn't only forward events to subscribed, but also stores them.
In your configuration, you have both an Event Bus and an Event Store. The Aggregate's events are probably published to the Event Store. Since you receive events in your handler when publishing directly to the Event Bus, your handlers are subscribed there.
The solution: remove the Event Bus from your configuration and use the Event Store exclusively.

Request-scoped ApplicationEventListener fails to receive events

I have the need to register a separate application event listener for each request. The listener's purpose is to catch events coming in from other REST requests, while the listener's request is blocked awaiting all the required events to come in.
I have code such as this:
#Component
// #Scope(WebApplicationContext.SCOPE_REQUEST)
public static class WhistleEventListener implements ApplicationListener<WhistleEvent> {
volatile Consumer<WhistleEvent> handler;
#Override
public void onApplicationEvent(WhistleEvent we) {
final Consumer<WhistleEvent> h = handler;
if (h != null) h.accept(we);
}
}
#Autowired WhistleEventListener whistleEventListener;
This code receives events, but as soon as I uncomment the #Scope annotation, it stops receiving events.
Are request-scoped application event listeners supported, are they supposed to work? If so, can I do something to make my listener work?
I suspect you have a misunderstanding of the application event dispatching mechanics: the event is dispatched against bean definitions, not bean instances, and each bean definition is resolved into an instance at the moment, and in the context, of event publication. That means that your event will be dispatched only to the request-scoped bean belonging to the request inside which the event is published, but you want the listeners of all current requests to be notified.
More generally, the purpose of a scope is to isolate scope instances, which contain separate bean instances. If you do not want isolation, you should use a scope that does not have separate instances, for instance the application scope.
That is, to dispatch events to other scope instances, you'd have to do the dispatching yourself, for instance like:
#Component
public class WhistleEventMediator implements ApplicationListener<WhistleEvent> {
// TODO: make thread safe
final Set<Consumer<WhistleEvent>> consumers;
void subscribe(Consumer<WhistleEvent> c) { ... }
void unsubscribe(Consumer<WhistleEvent> c) { ... }
#Override public void onApplicationEvent(WhistleEvent we) {
// delegate to subscribed consumers
}
}
#Component
#Scope(WebApplicationContext.SCOPE_REQUEST)
public class WhateverBean implements Consumer<WhistleEvent> {
#Inject
WhistleEventMediator mediator;
#PostConstruct
void init() {
mediator.subscribe(this);
}
#PreDestroy
void destroy() {
mediator.unsubscribe(this);
}
// handle whistle event
}

Handling received message in running thread

I have Threads that listens to incoming HTTP messages , i want to enable other developer that use my code to be able to use the messages that i received in any time. I saw in some mobile OS you can implement class and override onRecive function to receive the messages .
is this the right architecture to use in this case? if yes how could i implemented and if its not what is the best way to do it.
You can have a interface which another develoepr can implement and register with your code to be notified when a new message etc has arrived. There are any number of ways this can be achieved.
You could use the built in Observable class. or you could do something like this.
public interface Listener<T> {
public void onEvent(T t);
}
public class Listenable<T> {
private final List<Listener<T>> list = new CopyOnWriteArrayList<Listener<T>>();
public void register(Listener<T> listener) {
if (!list.contains(listener)) list.add(listener);
}
public void unregister(Listener<T> listener) {
list.remove(listener);
}
public void onEvent(T t) {
for (Listener<T> tListener : list)
tListener.onEvent(t);
}
}
The caller could implement the Listener interface or provide an object which does. It then registers this with the Listenable. The listenable can notify all registered listeners.
Take a look at the Observer Pattern.
You can have an interface called MessageListener:
public interface MessageListener{
void onMessage(String message);
}
Users of your library will create their own MessageListeners and will implement the onMessage method which defines what should be done when a message is received. They will also set (or register) this MessageListener with your "threads" before they are started.
Now whenever your thread gets a message, it will notify the listener(s) registered with it by calling the onMessage method.

Categories

Resources