How to disable a particular event handler from axon? - java

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.

Related

CDI 2 Event ordering with #Priority not work

The answer of this question describes that it is possible to sort CDI events with the #Priority annotation.
Execution order of different CDI Events in same transaction
Since CDI 2.0 (check here, Chapter 10.5.2), you may define an order using the #Priority annotation and specifying a number as its value. Observers with smaller priority values are called first and observers with no #Priority annotation gets de default priority (Priority.APPLICATION + 500). As with CDI 1.2, observers with same priority does not have any previously defined order and may be called by CDI container in any order.
CDI 2.0 observer ordering does not apply to asynchronous observer methods (per spec), as it's expected that observer methods get called as soon as it is possible and in different contexts. If you need some kind of ordering in you use case, you should make your asynchronous observer trigger the next event, instead of calling it from your "main" method.
So even if i fire Two different Event-Objects the order is not specified? – Noixes Jul 22 '20 at 6:45
Yes. Unless you are using CDI 2 and defining different priorities, the order is unspecified. You must realize that you may "discover" the order of a given implementation in such cases, but it is not recommended to rely on it because a future version of the same implementation may change it without colliding with the spec. –
But it doesn't work in my example:
#Stateless
public class EventTest {
#Inject
#QualifierA
private Event<String> eventA;
#Inject
#QualifierB
private Event<String> eventB;
#Test
public void test() throws VerarbeitungsException {
eventB.fire("B");
eventA.fire("A");
}
public void observerA(#Observes(during = TransactionPhase.AFTER_SUCCESS) #Priority(value = 1) #QualifierA String xml) {
send(xml);
}
public void observerB(#Observes(during = TransactionPhase.AFTER_SUCCESS) #Priority(value = 2) #QualifierB String xml) {
send(xml);
}
private void send(String xml){
System.out.println(xml);
}
}
In my testclass I fire event B and then A. The test log show B/A but I woud expact A/B as defined with #Priority. Im using WildFly14 with CDI 2.0. Does sorting of Events only work for observer for the same event/qualifier?
The ordering is between observers of the same event. But you defined two events, with different qualifiers.
To properly test the priority you should fire only one event, and set two observers for that event.
For example:
#Stateless
public class EventTest {
#Inject
#QualifierA
private Event<String> eventA;
#Test
public void test() throws VerarbeitungsException {
eventA.fire("A");
}
public void observerA(#Observes(during = TransactionPhase.AFTER_SUCCESS) #Priority(value = 1) #QualifierA String xml) {
send("A: " + xml);
}
public void observerB(#Observes(during = TransactionPhase.AFTER_SUCCESS) #Priority(value = 2) #QualifierB String xml) {
send("B: " + xml);
}
private void send(String xml){
System.out.println(xml);
}
}
Event qualifiers
The event qualifiers act as topic selectors, allowing the consumer to
narrow the set of events it observes. An event qualifier may be an
instance of any qualifier type. Observer methods
An observer method allows the application to receive and respond
synchronously to event notifications. And an async observer method
allows the application to receive and respond asynchronously to event
notifications. they both act as event consumers, observing events of a
specific type, with a specific set of qualifiers. Any Java type may be
observed by an observer method.
An observer method is a method of a bean class or extension with a
parameter annotated #Observes or #ObservesAsync.
An observer method will be notified of an event if:
the event object is assignable to the type observed by the observer method,
the observer method has all the event qualifiers of the event, and
either the event is not a container lifecycle event, or the observer method belongs to an extension.
Blockquote
In your code, you are specifically requesting that it observes events with different qualifiers. The ordering will not not be enforced.
Change it to and try:
public void observesFirst(#Observes(during = TransactionPhase.AFTER_SUCCESS) #Priority(value = 1) String xml) {
send(xml);
}
public void observesSecond(#Observes(during = TransactionPhase.AFTER_SUCCESS) #Priority(value = 2) String xml) {
send(xml);
}

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

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
}

best way to combine guava eventbus and AWT Event thread handling

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

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