What is the EventBus in SAPUI5 for? - sapui5

Can anybody explain for what and when we are going to use EventBus methods? Also what kind the activities of the same.

EventBus in UI5 is a tool with which we can leverage publish-subscribe pattern in our app.
How do we get EventBus?
Currently, there are two APIs which return their own instance of EventBus:
Globally: sap.ui.getCore().getEventBus(); for
Standalone apps.
Component apps and their container app where developers have control over both.
Component-based: this.getOwnerComponent().getEventBus(); // this == controller. Especially for apps targeting Fiori Launchpad (FLP) where SAP explicitly warns not to get the EventBus from the core but from the component:
If you need an event bus, use the event bus of the component. By this, you avoid conflicting event names and make sure that your listeners are automatically removed when the component is unloaded. Do not use the global event bus.
Note
FLP destroys the component every time when the user navigates back Home.
Make sure to have the module sap/ui/core/EventBus required before calling getEventBus() to properly declare the dependency and to avoid possible sync XHR when requiring it.
sap.ui.define([ // or sap.ui.require
// ...,
"sap/ui/core/EventBus",
], function(/*...,*/ EventBus) { /*...*/ });
What is it for?
With EventBus, we can fire (via publish()), and listen (via subscribe()) to our own custom events freely:
Without having to use or extend any Control / ManagedObject / EventProvider classes,
Without knowing the existence of other involved listeners (if any),
Without accessing the object that fires the event (publisher). E.g.: No need to call thatManagedObj.attach*().
Publishers and subscribers stay ignorant to each other which makes loose coupling possible.
Analogous to the real world, EventBus is like a radio station. Once it starts to broadcast about all sorts of things on various channels, those, who are interested, can listen to a particular channel, get notified about a certain event, and do something productive with the given data. Here is an image that illustrates the basic behavior of an EventBus:
Sample code
Subscribe
{ // Controller A
onInit: function() {
const bus = this.getOwnerComponent().getEventBus();
bus.subscribe("channelABC", "awesomeEvent", this.shouldDoSomething, this);
},
shouldDoSomething: function(channelId, eventId, parametersMap) {
// Get notified when e.g. "doSomething" from Controller B is called.
},
}
Publish
{ // Controller B
doSomething: function(myData) {
const bus = this.getOwnerComponent().getEventBus();
bus.publish("channelABC", "awesomeEvent", { myData }); // broadcast the event
},
}
See API reference: sap/ui/core/EventBus

Related

When using MDA, should you differentiate between idempotent and non-idempotent event handlers?

The question assumes the use of Event Sourcing.
When rebuilding current state by replaying events, event handlers should be idempotent. For example, when a user successfully updates their username, a UsernameUpdated event might be emitted, the event containing a newUsername string property. When rebuilding current state, the appropriate event handler receives the UsernameUpdated event and sets the username property on the User object to the newUsername property of the UsernameUpdated event object. In other words, the handling of the same message multiple times always yields the same result.
However, how does such an event handler work when integrating with external services? For example, if the user wants to reset their password, the User object might emit a PasswordResetRequested event, which is handled by a portion of code that issues a 3rd party with a command to send an SMS. Now when the application is rebuilt, we do NOT want to re-send this SMS. How is this situation best avoided?
There are two messages involved in the interaction: commands and events.
I do not regard the system messages in a messaging infrastructure the same as domain events. Command message handling should be idempotent. Event handlers typically would not need to be.
In your scenario I could tell the aggregate root 100 times to update the user name:
public UserNameChanged ChangeUserName(string username, IServiceBus serviceBus)
{
if (_username.Equals(username))
{
return null;
}
serviceBus.Send(new SendEMailCommand(*data*));
return On(new UserNameChanged{ Username = userName});
}
public UserNameChanged On(UserNameChanged #event)
{
_username = #event.UserName;
return #event;
}
The above code would result in a single event so reconstituting it would not produce any duplicate processing. Even if we had 100 UserNameChanged events the result would still be the same as the On method does not perform any processing. I guess the point to remember is that the command side does all the real work and the event side is used only to change the state of the object.
The above isn't necessarily how I would implement the messaging but it does demonstrate the concept.
I think you are mixing two separate concepts here. The first is reconstructing an object where the handlers are all internal methods of the entity itself. Sample code from Axon framework
public class MyAggregateRoot extends AbstractAnnotatedAggregateRoot {
#AggregateIdentifier
private String aggregateIdentifier;
private String someProperty;
public MyAggregateRoot(String id) {
apply(new MyAggregateCreatedEvent(id));
}
// constructor needed for reconstruction
protected MyAggregateRoot() {
}
#EventSourcingHandler
private void handleMyAggregateCreatedEvent(MyAggregateCreatedEvent event) {
// make sure identifier is always initialized properly
this.aggregateIdentifier = event.getMyAggregateIdentifier();
// do something with someProperty
}
}
Surely you wouldn't put code that talks to an external API inside an aggregate's method.
The second is replaying events on a bounded context which could cause the problem you are talking about and depending on your case you may need to divide your event handlers into clusters.
See Axon frameworks documentation for this point to get a better understanding of the problem and the solution they went with.
Replaying Events on a Cluster
TLDR; store the SMS identifier within the event itself.
A core principle of event sourcing is "idempotency". Events are idempotent, meaning that processing them multiple times will have the same result as if they were processed once. Commands are "non-idempotent", meaning that the re-execution of a command may have a different result for each execution.
The fact that aggregates are identified by UUID (with a very low percentage of duplication) means that the client can generate the UUIDs of newly created aggregates. Process managers (a.k.a., "Sagas") coordinate actions across multiple aggregates by listening to events in order to issue commands, so in this sense, the process manager is also a "client". Cecause the process manager issues commands, it cannot be considered "idempotent".
One solution I came up with is to include the UUID of the soon-to-be-created SMS in the PasswordResetRequested event. This allows the process manager to only create the SMS if it does not yet already exist, hence achieving idempotency.
Sample code below (C++ pseudo-code):
// The event indicating a password reset was successfully requested.
class PasswordResetRequested : public Event {
public:
PasswordResetRequested(const Uuid& userUuid, const Uuid& smsUuid, const std::string& passwordResetCode);
const Uuid userUuid;
const Uuid smsUuid;
const std::string passwordResetCode;
};
// The user aggregate root.
class User {
public:
PasswordResetRequested requestPasswordReset() {
// Realistically, the password reset functionality would have it's own class
// with functionality like checking request timestamps, generationg of the random
// code, etc.
Uuid smsUuid = Uuid::random();
passwordResetCode_ = generateRandomString();
return PasswordResetRequested(userUuid_, smsUuid, passwordResetCode_);
}
private:
Uuid userUuid_;
string passwordResetCode_;
};
// The process manager (aka, "saga") for handling password resets.
class PasswordResetProcessManager {
public:
void on(const PasswordResetRequested& event) {
if (!smsRepository_.hasSms(event.smsUuid)) {
smsRepository_.queueSms(event.smsUuid, "Your password reset code is: " + event.passwordResetCode);
}
}
};
There are a few things to note about the above solution:
Firstly, while there is a (very) low possibility that the SMS UUIDs can conflict, it can actually happen, which could cause several issues.
Communication with the external service is prevented. For example, if user "bob" requests a password reset that generates an SMS UUID of "1234", then (perhaps 2 years later) user "frank" requests a password reset that generates the same SMS UUID of "1234", the process manager will not queue the SMS because it thinks it already exists, so frank will never see it.
Incorrect reporting in the read model. Because there is a duplicate UUID, the read side may display the SMS sent to "bob" when "frank" is viewing the list of SMSes the system sent him. If the duplicate UUIDs were generated in quick succession, it is possible that "frank" would be able to reset "bob"s password.
Secondly, moving the SMS UUID generation into the event means you must make the User aggregate aware of the PasswordResetProcessManager's functionality (but not the PasswordResetManager itself), which increases coupling. However, the coupling here is loose, in that the User is unaware of how to queue an SMS, only that an SMS should be queued. If the User class were to send the SMS itself, you could run into the situation in which the SmsQueued event is stored while the PasswordResetRequested event is not, meaning that the user will receive an SMS but the generated password reset code was not saved on the user, and so entering the code will not reset the password.
Thirdly, if a PasswordResetRequested event is generated but the system crashes before the PasswordResetProcessManager can create the SMS, then the SMS will eventually be sent, but only when the PasswordResetRequested event is re-played (which might be a long time in the future). E.g., the "eventual" part of eventual consistency could be a long time away.
The above approach works (and I can see that it should also work in more complicated scenarious, like the OrderProcessManager described here: https://msdn.microsoft.com/en-us/library/jj591569.aspx). However, I am very keen to hear what other people think about this approach.

Using class selectors to get Dojo widgets: Good or Bad?

I am using Dojo 1.9 for a web application I'm writing using WebSockets. When the client receives a message from the server, I need to update certain widgets with the data received.
// sock is the client-side of the websocket
sock.onmessage = function (dataIn) {
// clientManager defined elsewhere
clientManager.fireMessageReceived(dataIn);
};
Here's my problem: At the point that I receive the data, I don't have the ID's, DOM nodes or widgets to access the properties/values to be updated. clientManager deals specifically with sock events and doesn't have any specific knowledge of the widgets that its data will be updating. Also, it's possible to have multiple instances of the same widget, so I think trying to maintain a collection of existing widgets (or ID's) as a property of the client manager could get hairy pretty quickly.
So, my solution was to use CSS classes.
I created an empty class and assigned it to my widget:
.myXYZWidget {
}
so that in my fireMessageReceived function, I can use dojo/query to find it:
var myXYZWidgets = dojo.query(".myXYZWidget");
var i;
for (i = 0; i < myXYZWidgets.length; i++) {
var xyzWidget = registry.byNode(myXYZWidgets[0]);
... // Now I have my Dojo widget, I can upate to my heart's content
}
This works and I'm not seeing any major downsides to doing this, but is this ok or is this bad bad bad? Can anyone in the community that has a knowledge of Dojo confirm this solution or suggest a better one?
A class is not necessarily CSS. So you're not using CSS to get Dojo widgets, you're just accessing the widgets by a selector/query.
If I think about your problem I would think about the publisher/subscriber pattern where your websocket is your publisher (since it receives data and needs to emit it to your widgets) and your widgets are your subscribers.
Subscriber(s) (widgets)
Luckily for you dojo has something for it and it's called the dojo/topic module. When you create your widget, you somehow want to make sure that it's a subscriber of the data your websocket receives. To do that, I would do something like this (I'm using a dijit/form/Select in my example, but you can rewrite it to whatever you want):
lang.mixin(mySelect, {
__getData: function(data) {
this.addOption(data);
}
});
mySelect.own(topic.subscribe("my/event", lang.hitch(mySelect, '__getData')));
What happens here is pretty easy (altough it might look hard). The first thing I do is to make sure my widget has an extra method called __getData. This method will receive the data from the websocket and will update its own based on the data.
Then I make sure the widget is subscribed to events with the name my/event (you will see what this means in a while).
Publisher (websocket)
Then at the level of your websocket code, you want to publish to a topic called my/event so that your widgets will know about it.
You can do that like this:
topic.publish("my/event", myData);
Where myData is the data you received from your websocket.
So now the flow is complete. Your websocket code will emit data to who wants to listen. The listeners (widgets) will use the data and do something with it, for example adding items to themself.
I also made a JSFiddle showing a complete example. This solution might look more complex, but I think it's pragmatically more correct.

MassTransit Subscriptions and Receiving Own Messages

I am trying to implement a proof of concept service bus using MassTransit. I have three applications which need to communicate changes of a common entity type between each other. So when the user updates the entity in one application, the other two are notified.
Each application is configured as follows with their own queue:
bus = ServiceBusFactory.New(sbc =>
{
sbc.UseMsmq();
sbc.VerifyMsmqConfiguration();
sbc.ReceiveFrom("msmq://localhost/app1_queue");
sbc.UseSubscriptionService("msmq://localhost/subscription");
sbc.UseControlBus();
sbc.Subscribe(subs =>
{
subs.Handler<IMessage1>(IMessage1_Received);
});
});
There is also a subscription service application configured as follows:
subscriptionBus = ServiceBusFactory.New(sbc =>
{
sbc.UseMsmq();
sbc.VerifyMsmqConfiguration();
sbc.ReceiveFrom("msmq://localhost/subscription");
});
var subscriptionSagas = new InMemorySagaRepository<SubscriptionSaga>();
var subscriptionClientSagas = new InMemorySagaRepository<SubscriptionClientSaga>();
subscriptionService = new SubscriptionService(subscriptionBus, subscriptionSagas, subscriptionClientSagas);
subscriptionService.Start();
The problem is that when one of the applications publishes a message, all three applications receive it (including the original sender).
Is there any way to avoid this (without resorting to adding the application name to the message)?
Thanks,
G
So MassTransit is a pub/sub system. If you publish a message, everyone registered to receive it will. If you need only some endpoints to receive it, then you really need to directly send. It's just how this works.
You could include the source in your message and discard messages that aren't of interest to you. If you implement the Consumes.Accept interface, I think the Accept method would allow you to do so easily without mixing that into the normal consumption code.

Proper way of using MVVM Light Messenger

What is the proper way to use Messenger class ?
I know it can be used for ViewModels/Views communications, but is it a good approach to use it in for a technical/business service layer ?
For example, a logging/navigation service registers for some messages in the constructors and is aware when these messages occurs in the app. The sender (ViewModel ou Service) does not reference the service interface but only messenger for sending messages. Here is a sample service :
using System;
using System.Windows;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using App.Service.Interfaces;
using GalaSoft.MvvmLight.Messaging;
namespace App.Service
{
public class NavigationService : INavigationService
{
private PhoneApplicationFrame _mainFrame;
public event NavigatingCancelEventHandler Navigating;
public NavigationService()
{
Messenger.Default.Register<NotificationMessage<Uri>>(this, m => { this.NavigateTo(m.Content); });
}
public void NavigateTo(Uri pageUri)
{
if (EnsureMainFrame())
{
_mainFrame.Navigate(pageUri);
}
}
public void GoBack()
{
if (EnsureMainFrame()
&& _mainFrame.CanGoBack)
{
_mainFrame.GoBack();
}
}
private bool EnsureMainFrame()
{
if (_mainFrame != null)
{
return true;
}
_mainFrame = Application.Current.RootVisual as PhoneApplicationFrame;
if (_mainFrame != null)
{
// Could be null if the app runs inside a design tool
_mainFrame.Navigating += (s, e) =>
{
if (Navigating != null)
{
Navigating(s, e);
}
};
return true;
}
return false;
}
}
}
For me, the main use of a messenger is because it allows for communication between viewModels. Lets say you have a viewmodel that is used to provide business logic to a search function and 3 viewmodels on your page/window that want to process the search to show output, the messenger would be the ideal way to do this in a loosely-bound way.
The viewmodel that gets the search data would simply send a "search" message that would be consumed by anything that was currently registered to consume the message.
The benefits here are:
easy communication between viewmodels without each viewmodel having to know about each other
I can swap out the producer without affecting a consumer.
I can add more message consumers with little effort.
It keeps the viewmodels simple
Edit:
So, what about services?
ViewModels are all about how to present data to the UI. They take your data and shape it into something that can be presented to your View. ViewModels get their data from services.
A service provides the data and/or business logic to the ViewModel. The services job is to service business model requests. If a service needs to communicate/use other services to do its job these should be injected into the service using dependency injection. Services would not normally communicate with each other using a messenger. The messenger is very much about horizontal communication at the viewmodel level.
One thing I have seen done is to use a messenger as a mediator, where instead of injecting the service directly into a viewmodel the messenger is injected into the viewmodel instead. The viewmodel subscribes to an event and receives events containing models from the event. This is great if you're receiving a steady flow of updates or you're receiving updates from multiple services that you want to merge into a single stream.
Using a messenger instead of injecting a service when you're doing request/response type requests doesn't make any sense as you'll have to write more code to do this that you'd have to write just injecting the service directly and it makes the code hard to read.
Looking at your code, above. Imagine if you had to write an event for each method on there (Navigate, CanNavigate, GoBack, GoForward, etc). You'd end up with a lot of messages. Your code would also be harder to follow.

Employing GWT's RequestFactory within Activities

My CustomerActivity class happens also to be a presenter in the MVP sense. In response to actions by the user, the following code is called:
context.update(customer).fire(new Receiver<CustomerProxy>() {
public void onSuccess(CustomerProxy response) {
// set the view according to the response
}
});
When the above code executes, two things happen:
I receive an updated copy of the Customer, with which I can refresh the state of the view
An EntityProxyChange event is fired
The CustomerActivity listens for EntityProxyChange events because other Activities also make changes to customer records, and I want to keep the CustomerActivity up-to-date.
EntityProxyChange.registerForProxyType(eventBus, CustomerProxy.class,
new EntityProxyChange.Handler<CustomerProxy>() {
public void onProxyChange(EntityProxyChange<CustomerProxy> event) {
fetchCustomer(event.getProxyId());
// ...but what if it was me that made the change?
}
});
Since theupdate method already returns an up-to-date Customer, I don't need to fetch the customer again during processing of the EntityProxyChange; and I don't want to incur the cost of another call to the server if I can avoid it.
I was hoping that the EntityProxyChange class would provide me with the entity's version number, which I could compare with the version of the customer I have cached. No dice.
I suppose I can set some kind of inTheMiddleOfAnUpdateOperation flag, and check it before fetching the customer. Is that what people are doing? The idea makes me gag just a little bit. Can you suggest a better way to write an activity that listens for changes and makes changes to the same entity types?
I'm not sure this would work, but you could try to create another event bus :
final EventBus customerActivityEventBus = new SimpleEventBus();
Initialize a new RequestFactory with this eventBus and use it in the CustomerActivity.
customerActivityRequestFactory = GWT.create(CustomerRequestFactory.class);
customerActivityRequestFactory.initialize(customeActivityEventBus);
CustomerRequest context = customerActivityRequestFactory.customerRequest();
Your CustomerActivity will still listen to change events from the main eventBus but will not see the events it fired.
In your other activities, listen to events either only from the customerActivityEventBus or from both, depending on what you want.
Of course, keep only one main eventBus to use for events that are not from a Request Factory (ie. ActivityManager, PlaceHistoryHandler, etc ..)