Using event gateway to publish events (Axon) - spring-boot

I am very new to Axon so bear with me. I have a command that starts the sessionCreated event in my aggregate. After that happens some other external code is executed multiple times. For each iteration I would like an event to be published without having to send a new command to the aggregate. I tried using EventGateway.publish and #EventHandler as shown below.
Code:
#Aggregate
public class SessionAggregate {
// aggregate logic
#EventHandler
public void on(OtherEvent event){
// code that never runs
}
}
public class ExternalLogic {
private final EventGateway eventGateway;
public void execute() {
// other code
eventGateway.publish(new OtherEvent());
}
}

This won't work. The Aggregate only reacts to CommandHandler calls and (in case you are using eventSourcing as storage) can replay its internal state via EventSourcingHandlers.
In addition, an aggregate is only active while handling a command, it is not permanently present in memory, so even if it would be notified, you wouldn't have any guarantee that it was called.

Related

Automatically log Application Events

In my application I have multiple custom Spring Application Events. I want to log every instance of these events occurring. Is there a way to do this automatically or do I have to manually log it every time?
You might create an event listener for the type of events you're interested in and log the event. Spring will register this listener and you'll basically done:
#Component
public class CustomEventListener implements ApplicationListener<CustomEvent> {
private static final Logger logger = ...;
#Override
public void onApplicationEvent(CustomEvent event) {
LOGGER.info("Got event: {}" , event);
}
}
However, you can't really use the same listener subscribed to multiple types of event unless they have an hierarchy (inheritance from some base event) You might be interested to read this thread it provides technical solutions in various cases.

What's the "Right Way" to send a data changed websocket event and ensure the database is committed in Spring Boot

Note: read the end of the answer for the way I implemented #Nonika's suggestions
What's the "right way" to send a websocket event on data insert?
I'm using a Spring Boot server with SQL/JPA and non-stomp websockets. I need to use "plain" websockets as I'm using Java clients where (AFAIK) there's no stomp support.
When I make a change to the database I need to send the event to the client so I ended up with an implementation like this:
#Transactional
public void addEntity(...) {
performActualEntityAdding();
sendEntityAddedEvent(eventData);
}
#Transactional
public void sendEntityAddedEvent(String eventData) {
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
#Override
public void afterCommit() {
sendEntityAddedEventAsync(eventData);
}
});
}
#Async
public void sendEntityAddedEventAsync(String eventData) {
// does the websocket session sending...
}
This works. If I would just call the sendEntityAddedEventAsync it would also work for real world scenarios but it fails on unit tests because the event would arrive before transaction commit. As such when the unit test invokes a list of the entities after the event it fails.
This feels like a hack that shouldn't be here. Is there a better way to ensure a commit?
I tried multiple alternative approaches and the problem is that they often worked for 10 runs of the unit tests yet failed every once in a while. That isn't acceptable.
I tried multiple approaches to solve this such as different transaction annotations and splitting the method to accommodate them. E.g read uncommitted, not supported (to force a commit) etc. Nothing worked for all cases and I couldn't find an authoritative answer for this (probably common) use case that wasn't about STOMP (which is pretty different).
Edit
One of my original attempts looked something like this:
// this shouldn't be in a transaction
public void addEntity(...) {
performActualEntityAdding();
sendEntityAddedEvent(eventData);
}
#Transactional
public void performActualEntityAdding(...) {
//....
}
#Async
public void sendEntityAddedEventAsync(String eventData) {
// does the websocket session sending...
}
The assumption here is that when sendEntityAddedEventAsync is invoked the data would already be in the database. It wasn't for a couple of additional milliseconds.
A few additional details:
Test environment is based on h2 (initially I mistakenly wrote hsql)
Project is generated by JHipster
Level 2 cache is used but disabled as NONE for these entities
Solution (based on #Nonika's answer):
The solution for me included something similar to this:
public class WebEvent extends ApplicationEvent {
private ServerEventDAO event;
public WebEvent(Object source, ServerEventDAO event) {
super(source);
this.event = event;
}
public ServerEventDAO getEvent() {
return event;
}
}
#Transactional
public void addEntity(...) {
performActualEntityAdding();
applicationEventPublisher.publishEvent(new WebEvent(this, evtDao));
}
#Async
#TransactionalEventListener
public void sendEntityAddedEventAsync(WebEvent eventData) {
// does the websocket session sending...
}
This effectively guarantees that the data is committed properly before sending the event and it runs asynchronously to boot. Very nice and simple.
Spring is using AdviceMode.PROXY for both #Async and #Transactional this is quote from the javadoc:
The default is AdviceMode.PROXY. Please note that proxy mode allows
for interception of calls through the proxy only. Local calls within
the same class cannot get intercepted that way; an Async annotation on
such a method within a local call will be ignored since Spring's
interceptor does not even kick in for such a runtime scenario. For a
more advanced mode of interception, consider switching this to
AdviceMode.ASPECTJ.
This rule is common for almost all spring annotations which requires proxy to operate.
Into your first example, you have a #Transactional annotation on both addEntity(..) and performActualEntityAdding(..). I suppose you call addEntity from another class so #Transactional works as expected. process in this scenario can be described in this flow
// -> N1 transaction starts
addEntity(){
performActualEntityAdding()//-> we are still in transaction N1
sendEntityAddedEvent() // -> call to this #Async is a class local call, so this advice is ignored. But if this was an async call this would not work either.
}
//N1 transaction commits;
That's why the test fails. it gets an event that there is a change into the db, but there is nothing because the transaction has not been committed yet.
Scenario 2.
When you don't have a #Transactional addEntity(..) then second transaction for performActualEntityAdding not starts as there is a local call too.
Options:
You can use some middleware class to call these methods to trigger
spring interceptors.
you can use Self injection with Spring
if you have Spring 5.0 there is handy #TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)

LiveData Object keeps being null after getValue() is called

I want to update a member variable of an object inside my Repository on a LiveData- Object. The problem is, that if I call the getValue() Method, I keep getting an NullPointerException, although the value does exist inside my Room- Library.
My question now is, how do I get the value from the LiveData Object without calling the observe() Method? (I am not able to call the observe method inside my repository, cause that method wants me to enter a LifeCycleOwner- reference, which is not present inside my repository).
Is there any way to get the value out of the LiveData- object?
My architecture looks like that:
ViewModel --> Repository --> Dao
You need to initialize LiveData object in ViewModel before observing it in Activity/Fragment like this
ProductViewModel.java
public ProductViewModel(DataRepository repository, int productId) {
mObservableProduct = repository.loadProduct(mProductId);
}
public LiveData<ProductEntity> getObservableProduct() {
return mObservableProduct;
}
Here observableProduct is LiveData for observing product details which is initialized in constructor and fetched using getObservableProduct() method
Then you can observe the LiveData in Activity/Fragment like this
MainActivity.java
productViewModel.getObservableProduct().observe(this, new Observer<ProductEntity>() {
#Override
public void onChanged(#Nullable ProductEntity productEntity) {
mProduct = productEntity;
}
});
As you already setup your code architecture like
Flow of LiveData is
DAO -> Repository -> ViewModel -> Fragment
You don't need to observe LiveData in repository because you cannot update UI from there. Observe it from Activity instead and update UI from there.
As you are saying its giving null on getValue(), make sure you are updating db and fetching db from single instance of DAO as per I worked with DAO it will not notify db update of one DAO instance to 2nd DAO instance with LiveData
Also you can observeForever as suggested by #Martin Ohlin, but it will not be lifecycle aware and may lead to crashes. Check your requirement before observing forever
Refer to this for Full LiveData Flow
Refer to this for DAO issues
Edit 1 - Without using LifecycleOwner
You can use void observeForever (Observer<T> observer) (reference) method to observe LiveData without providing any LifecycleOwner as I provided by using this context in above example.
This is how you can observe LiveData without providing any LifecycleOwner and observe the LiveData in repository itself
private void observeForeverProducts() {
mDatabase.productDao().loadAllProducts().observeForever(new Observer<List<ProductEntity>>() {
#Override
public void onChanged(#Nullable List<ProductEntity> productEntities) {
Log.d(TAG, "onChanged: " + productEntities);
}
});
}
But you need to call removeObserver(Observer) explicitly to stop observing the LiveData which was automatically done in previous case with LifecycleOwner. So as per documentation
You should manually call removeObserver(Observer) to stop observing this LiveData. While LiveData has one of such observers, it will be considered as active.
As this doesn't require LifecycleOwner you can call this in Repository without using this parameter as you mentioned which is missing in your repository
In order for the LiveData object works well you need to use the observe method. That is if you want to use the getValue() method and expecting a non-null response you need to use the observe method. Make sure initialize the LiveData object in your ViewModel as #adityakamble49 said in his answer. For initialize the object, you can pass the reference of your LiveData object which was created in your Repository:
ViewModel.java
private LiveData<Client> clientLiveData;
private ClientRepository clientRepo;
public ViewModel(ClientRepository clientRepo) {
this.clientRepo = clientRepo;
clientLiveData = clientRepo.getData();
}
Then you have to observe your ViewModel from the Activity and call the method that you want to update in your ViewModel (or Repo, but remember that Repo conects with the ViewModel and ViewModel with the UI: https://developer.android.com/jetpack/docs/guide ):
Activity.java
viewModel.getClient().observe(this, new Observer<Client>() {
#Override
public void onChanged(#Nullable Client client) {
viewModel.methodWantedInViewModel(client);
}
});
I hope it helps.
I'm not sure exactly what you are trying to accomplish here, but it is possible to observe without a LifeCycleOwner if you use
observeForever instead of observe.
Livedata is used to observe the data streams. In case you want to call the get a list of your entities stored within the Live Data. Something like this can be helpful.
public class PoliciesTabActivity extends AppCompatActivity {
private PolicyManualViewModel mViewModel;
private List<PolicyManual> policyManualList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_leaves_tab_manager);
mViewModel = ViewModelProviders.of(PoliciesTabActivity.this).get(PolicyManualViewModel.class);
//Show loading screen untill live data onChanged is triggered
policyManualList = new ArrayList<>();
mViewModel.getAllPolicies().observe(this, new Observer<List<PolicyManual>>() {
#Override
public void onChanged(#Nullable List<PolicyManual> sections) {
//Here you got the live data as a List of Entities
policyManualList = sections;
if (policyManualList != null && policyManualList.size() > 0) {
Toast.makeText(PoliciesTabActivity.this, "Total Policy Entity Found : " + policyManualList.size(), Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(PoliciesTabActivity.this, "No Policy Found.", Toast.LENGTH_SHORT).show();
}
}
});
}
}
One more thing - for others with a similar problem - be aware that live data queries will execute only if there is a live observer (i.e. view listening for updates). It won't fill itself just by "laying" there in declarations, like this:
val myLiveData = repository.readSomeLiveData ()
So make sure that you are observing somewhere your LiveData object, either in view or through Transformations.

#TransactionalEventListener is never being called in Spring Framework 4.2

I am implementing #EventListener from Spring 4.2 and it works fine. When I try to implement a #TransactionalEventListener it never gets called.
The ApplicationListenerMethodTransactionalAdapter makes the check:
if(TransactionSynchronizationManager.isSynchronizationActive())
and it is always false so it skips running the event because it says it is not in a transaction.
The code for the event listener is simply:
#TransactionalEventListener()
public void handleTransactionalAddEvent(Event event)
{
logger.info("Add Event: {}");
}
The code which publishes the event is as follows:
#Override
#Transactional
public Order addToOrder(String username, Long orderId)
{
Order order = getOrder(orderId, username);
publisher.publishEvent(new Event(order, Event.EventType.ADD));
... Code to do stuff to the order ...
updateOrder(order);
return order;
}
If I change the #TransactionEventListener to just be #EventListener, or I add the fallbackExecution attribute it will run fine, but with the #TransactionEventListener it never gets called.
I found out that we had a custom ApplicationEventMulticaster which was conflicting with the transactional event listeners. I removed it and now it works fine.
#TransactionalEventListener is used when its method should be within the transaction.
If no transaction is running, the listener is not invoked at all since we can’t honor the required semantics.

GWT Custom Events

Hey I have a problem getting my head around how custom GWT event Handlers work. I have read quite a bit about the topic and it still is some what foggy. I have read threads here on Stackoverflow like this one GWT Custom Event Handler. Could someone explain it in an applied mannar such as the following.
I have 2 classes a block and a man class. When the man collides with the block the man fires an event ( onCollision() ) and then the block class listens for that event.
Thanks
Events in general:
Events are always sent to inform about something (e.g. a change of state). Let's take your example with a man and a wall. Here we can imagine that there is a game where a user can walk as a man in a labyrinth. Every time a user hits the wall it should be informed about the collision so that it can react to it (e.g. a wall can render itself as a destroyed wall). This can be achieved by sending a collision event every time the collision with a wall is detected. This event is sent by a man and every object in the system interested in the event receives it and can react to it accordingly. Objects which want to receive events must register themselves as interested with event.
This is how events work in general in every system or framework (not only in GWT). In order to send and receive events in such systems you have to define:
What is sent (what do events look like)
Who receives events (event receivers)
Who sends events (event senders)
Then you can:
Register event receivers which want to receive events
Send events
Events in GWT:
Here I will show an example of using custom events in GWT. I will use an example of a system which is responsible for checking a mailbox and inform a user if there are new mails. Let's assume that in the system there are at least 2 components:
message checker responsible for checking the mailbox and
message displayer responsible for displaying new mails
Message checker sends events when a new mail is received and message displayer receives these events.
Step 1: Define events
Information about a new mail will be sent as an instance of MessageReceivedEvent class. The class contains a new mail (for the simplicity let's assume it is just a String).
Full source code of this class is presented below (the comment for it is below the source code).
public class MessageReceivedEvent extends GwtEvent<MessageReceivedEventHandler> {
public static Type<MessageReceivedEventHandler> TYPE = new Type<MessageReceivedEventHandler>();
private final String message;
public MessageReceivedEvent(String message) {
this.message = message;
}
#Override
public Type<MessageReceivedEventHandler> getAssociatedType() {
return TYPE;
}
#Override
protected void dispatch(MessageReceivedEventHandler handler) {
handler.onMessageReceived(this);
}
public String getMessage() {
return message;
}
}
MessageReceivedEventHandler is an interface that represents event receivers. Don't bother with it at the moment, this will be discussed later.
Every class representing a GWT event has to extend GwtEvent class. This class contains two abstract methods which must be implemented: getAssociatedType and dispatch. However in every event class they are usually implemented in a very similar way.
The class stores information about a received message (see constructor). Every event receiver can get it using getMessage method.
Step 2: Define event receivers
Each event type in GWT is associated to an interface representing receivers of this event type. In GWT receivers are called handlers. In the example an event receiver interface for MessageReceivedEvent will be named MessageReceivedEventHandler. The source code is below:
public interface MessageReceivedEventHandler extends EventHandler {
void onMessageReceived(MessageReceivedEvent event);
}
Each handler has to extend EventHandler interface. It should also define a method which will be invoked when an event occurs (it should take at least one parameter - an event). Here the method is named onMessageReceived. Each receiver can react on an event by implementing this method.
The only event receiver in the example is MessageDisplayer component:
public class MessageDisplayer implements MessageReceivedEventHandler {
#Override
public void onMessageReceived(MessageReceivedEvent event) {
String newMessage = event.getMessage();
// display a new message
// ...
}
}
Step 3: Define event senders
In the example the only event sender is a component responsible for checking mails - EventChecker:
public class MessageChecker implements HasHandlers {
private HandlerManager handlerManager;
public MessageChecker() {
handlerManager = new HandlerManager(this);
}
#Override
public void fireEvent(GwtEvent<?> event) {
handlerManager.fireEvent(event);
}
public HandlerRegistration addMessageReceivedEventHandler(
MessageReceivedEventHandler handler) {
return handlerManager.addHandler(MessageReceivedEvent.TYPE, handler);
}
}
Every event sender has to implement HasHandlers interface.
The most important element here is a HandlerManager field. In GWT HandlerManager as the name suggest manages event handlers (event receivers). As it was said at the beginning every event receiver that wants to receive events must register itself as interested. This is what handler managers are for. They make it possible to register event handlers an they can send a particular event to every registered event handler.
When a HanlderManager is created it takes one argument in its constructor. Every event has a source of origin and this parameter will be used as a source for all events send by this handler manager. In the example it is this as the source of events is MessageChecker.
The method fireEvent is defined in HasHandlers interface and is responsible for sending events. As you can see it just uses a handler manager to send (fire) and event.
addMessageReceivedEventHandler is used by event receivers to register themselves as interested in receiving events. Again handler manager is used for this.
Step 4: Bind event receivers with event senders
When everything is defined event receivers must register themselves in event senders. This is usually done during creation of objects:
MessageChecker checker = new MessageChecker();
MessageDisplayer displayer = new MessageDisplayer();
checker.addMessageReceivedEventHandler(displayer);
Now all events sent by checker will be received by displayer.
Step 5: Send events
To send an event, MessageChecker must create an event instance and send it using fireEvent method. This cane be done in newMailReceived method:
public class MessageChecker implements HasHandlers {
// ... not important stuff omitted
public void newMailReceived() {
String mail = ""; // get a new mail from mailbox
MessageReceivedEvent event = new MessageReceivedEvent(mail);
fireEvent(event);
}
}
I hope it is clear and will help :)
Since this question and the answer from Piotr GWT has added support for a slightly different way to create custom events. This event implementation is specific build to be used with the GWT's EventBus in the package com.google.web.bindery.event.shared. An example on how to build a custom event for GWT 2.4:
import com.google.web.bindery.event.shared.Event;
import com.google.web.bindery.event.shared.EventBus;
import com.google.web.bindery.event.shared.HandlerRegistration;
/**
* Here is a custom event. For comparison this is also a MessageReceivedEvent.
* This event extends the Event from the web.bindery package.
*/
public class MessageReceivedEvent extends Event<MessageReceivedEvent.Handler> {
/**
* Implemented by methods that handle MessageReceivedEvent events.
*/
public interface Handler {
/**
* Called when an {#link MessageReceivedEvent} event is fired.
* The name of this method is whatever you want it.
*
* #param event an {#link MessageReceivedEvent} instance
*/
void onMessageReceived(MessageReceivedEvent event);
}
private static final Type<MessageReceivedEvent.Handler> TYPE =
new Type<MessageReceivedEvent.Handler>();
/**
* Register a handler for MessageReceivedEvent events on the eventbus.
*
* #param eventBus the {#link EventBus}
* #param handler an {#link MessageReceivedEvent.Handler} instance
* #return an {#link HandlerRegistration} instance
*/
public static HandlerRegistration register(EventBus eventBus,
MessageReceivedEvent.Handler handler) {
return eventBus.addHandler(TYPE, handler);
}
private final String message;
public MessageReceivedEvent(String message) {
this.message = message;
}
#Override
public Type<MessageReceivedEvent.Handler> getAssociatedType() {
return TYPE;
}
public String getMessage() {
return message;
}
#Override
protected void dispatch(Handler handler) {
handler.onMessageReceived(this);
}
}
The event is used as follows:
To register your handler for this event with the eventbus call the static register method on the MessageReceivedEvent class:
MessageReceivedEvent.register(eventbus, new MessageReceivedEvent.Handler() {
public void onMessageReceived(MessageReceivedEvent event) {
//...do something usefull with the message: event.getMessage();
}
});
Now to fire the event on the eventbus call fireEvent with a newly constructed event:
eventBus.fireEvent(new MessageReceivedEvent("my message"));
Another implementation can be found in GWT's own EntityProxyChange event class. That implementation uses a alternative option of the EventBus. It uses the ability to add handlers that are bound to a specific source, via addHandlerToSource and can be triggered via eventBus.fireEventFromSource.
The event implementation given here is also more suitable when working with GWT's Activities.
I created my own widget by extending GWT's Composite class. I wanted to create my own custom event in this class. I wanted the events to be accessible to GWT's WindowBuilder Editor.
I learned a lot of from the answers on this page, but I had to make some changes.
I wanted to start from the Hilbrand Bouwkamp answer, because it was newer. But I ran into a couple of problems. 1) That answer made reference to the event bus. The even bus is a global variable owned by the main program. It's not clear how a widget library could get access to that. 2) I wasn't starting from scratch. I was was extending GWT library code. In order to make that work, I had to start from the GwtEvent class, rather than the Event class.
Piotr's answer is essentially correct, but it was very long. My class (indirectly) extends GWT's Widget class. Widget takes care of many details, such as creating a HandlerManager object. (I looked through the source code, and that's exactly how standard Widgets work, not by using an EventBus.)
I only had to add two things to my widget class to add a custom event handler. Those are shown here:
public class TrackBar extends Composite {
public HandlerRegistration addValueChangedHandler(TrackBarEvent.Handler handler)
{
return addHandler(handler, TrackBarEvent.TYPE);
}
private void fireValueChangedEvent(int value)
{
final TrackBarEvent e = new TrackBarEvent(value);
fireEvent(e);
}
My new event is almost exactly the same as Piotr's event class, shown above. One thing is worth noting. I started with getValue(), based on that example. Later I added getTrackBar() to give a lot more information. If I was starting from scratch I'd focus on the latter, not the former. The complete event class is shown below.
import com.google.gwt.event.shared.EventHandler;
import com.google.gwt.event.shared.GwtEvent;
public class TrackBarEvent extends GwtEvent< TrackBarEvent.Handler >
{
public interface Handler extends EventHandler {
void onTrackBarValueChanged(TrackBarEvent event);
}
static final Type<TrackBarEvent.Handler> TYPE =
new Type<TrackBarEvent.Handler>();
private final int value;
public TrackBarEvent(int value) {
this.value = value;
}
#Override
public Type<TrackBarEvent.Handler> getAssociatedType() {
return TYPE;
}
public int getValue() {
return value;
}
public TrackBar getTrackBar()
{
return (TrackBar)getSource();
}
#Override
protected void dispatch(Handler handler) {
handler.onTrackBarValueChanged(this);
}
}
If you happen to be using the GWTP framework on top of GWT, refer to this Stack.
GWTP is "A complete model-view-presenter framework to simplify your next GWT project."

Resources