How to publish Domain Events in axon framework - axon

In saga, I wanna publish domain events. but to instantiate DomainEventMessage, I need to put sequenceNumber but I have no idea how to obtain or generate it correctly.
public GenericDomainEventMessage(String type, String aggregateIdentifier, long sequenceNumber, T payload) {
this(type, aggregateIdentifier, sequenceNumber, payload, MetaData.emptyInstance());
}
Now what I do is dispatching dommand instead and let's axon handle it.
But problem now is I got tons of useless command class and command handling.
I wanna know how to publish domain events directly or a proper way to create DomainEventMessage

Related

Where to place domain services in AxonIQ

I have a user aggregate which is created using CreateUser command which consists of aggregate identifier and username.
Along with that i have domain service that communicates with mongo db and checks if username exists, if not it puts it there.
eg registerUsername(username) -> true / false whether it registered it or not
My question is, would it be good idea to create command handler on top of the user aggregate that would handle the CreateUser command and whether it has username or not will dispatch proper commands/events? like so:
#Component
class UserCommandHandler(
#Autowired
private val repository: Repository<User>,
#Autowired
private val eventBus: EventBus,
#Autowired
private val service: UniqueUserService
) {
#CommandHandler
fun createUser(cmd: CreateUser) {
if (this.service.registerUsername(cmd.username)) {
this.repository.newInstance { User(cmd.id) }
.handle(GenericCommandMessage(cmd))
} else {
this.eventBus.publishEvent(UserCreateFailed(cmd.id, cmd.username))
}
}
}
This question is not necessarily related to the set uniqueness in ddd but more of a question where should i put dependency of domain services? I could probably create user registration saga and inject that service inside saga but i think saga should only rely on command dispatching and not have any if/else logic.
I think the place to put your domain service depends on the use case at hand.
I typically try to have domain service do virtual no outbound calls to other services or databases, at all.
The domain service you're now conceiving however does exactly that to, like you're point out, solve the uniqueness issue.
In this situation, you could likely come by with the suggested approach.
You could also think of introducing a MessageHandlerInterceptor (or even fancier, a HandlerEnhancerDefinition as described here), specifically triggering on the create command and performing the desired check.
If it would be domain service like I depicted mine just now (e.g. zero outbound calls from domain service), then you can safely wire it in your command handling functions to perform some action.
If you're in a Spring environment, simply having your domain service as a bean and providing it as a parameter to your message handling function is sufficient for Axon to resolve it for you (through the means of ParameterResolvers, as described here).
Hope this helps you out #PolishCivil!

Meteor signaling without db write

I've been looking for a good way to do, but haven't found anything that doesn't seem hacky. I want to signal the client without going through the database and a subscription. For example, in a game I want to send a message to the client to display "Player 1 almost scores!". I don't care about this information in the long run, so I don't want to push it to the DB. I guess I could just set up another socket.io, but I'd rather not have to manage a second connection if there is a good way to go it within meteor. Thanks! (BTW, have looked at Meteor Streams, but it appears to have gone inactive)
You know that Meteor provides real-time communication from the server to clients through Publish and Subscribe mechanism, which is typically used to send your MongoDB data and later modifications.
You would like a similar push system but without having to record some data into your MongoDB.
It is totally possible re-using the Meteor Pub/Sub system but without the database part: while with Meteor.publish you typically return a Collection Cursor, hence data from your DB, you can also use its low-level API to send arbitrary real-time information:
Alternatively, a publish function can directly control its published record set by calling the functions added (to add a new document to the published record set), changed (to change or clear some fields on a document already in the published record set), and removed (to remove documents from the published record set). […]
Simply do not return anything, use the above mentioned methods and do not forget calling this.ready() by the end of your publish function.
See also the Guide about Custom publications
// SERVER
const customCollectionName = 'collection-name';
let sender; // <== we will keep a reference to the publisher
Meteor.publish('custom-publication', function() {
sender = this;
this.ready();
this.onStop(() => {
// Called when a Client stops its Subscription
});
});
// Later on…
// ==> Send a "new document" as a new signal message
sender.added(customCollectionName, 'someId', {
// "new document"
field: 'values2'
});
// CLIENT
const signalsCollectionName = 'collection-name'; // Must match what is used in Server
const Signals = new Mongo.Collection(signalsCollectionName);
Meteor.subscribe('custom-publication'); // As usual, must match what is used in Server
// Then use the Collection low-level API
// to listen to changes and act accordingly
// https://docs.meteor.com/api/collections.html#Mongo-Cursor-observe
const allSignalsCursor = Signals.find();
allSignalsCursor.observe({
added: (newDocument) => {
// Do your stuff with the received document.
}
});
Then how and when you use sender.added() is totally up to you.
Note: keep in mind that it will send data individually to a Client (each Client has their own Server session)
If you want to broadcast messages to several Clients simultaneously, then the easiest way is to use your MongoDB as the glue between your Server sessions. If you do not care about actual persistence, then simply re-use the same document over and over and listen to changes instead of additions in your Client Collection Cursor observer.
It's completly fine to use the database for such a task.
Maybe create a collection of "Streams" where you store the intended receiver and the message, the client subscribe to his stream and watches any changes on it.
You can then delete the stream from the database after the client is done with it.
This is a lot easier than reinventing the wheel and writing everything from scratch.

how to know what kind of clients are connected to signalr hub?

I'm using signalr on my site. I have just one class that inherits from hub, and several aspx forms with client code that have client functions called by the hub.
when a client connects to the hub I add it to a collection with a clientID, when a client disconnect I remove it from that collection. Just to know if any client is connected. As long as at least one client is connected, a timer call some methods that fill a data repository on the server that is propagated to clients.
then I usually do before calling customers things like this:
if (users.Count() > 0)
{
this.Clients.All.UpdateData(JsonConvert.SerializeObject(someData));
...
}
all this works fine. But what I need and can not find how to do it in the hub, is to know what clients are connected to know if I should create the data repository for those clients and avoid making unnecessary database queries.
eg.
myHub.cs
Timer_tick()
{
...
//Collect data to clients Type 1
...
Clients.All.UpdateDataType1(jsonData);
...
//Collect data to clients Type 2
...
Clients.All.UpdateDataType2(jsonData);
...
//Collect data to clients Type 3
...
Clients.All.UpdateDataType3(jsonData);
ClientType1.aspx.js (2 clients connected)
hub.client.UpdateDataType1= function (jsonData) {...);
ClientType2.aspx.js (0 clients connected)
hub.client.UpdateDataType2= function (jsonData) {...);
ClientType2.aspx.js (0 clients connected)
hub.client.UpdateDataType3= function (jsonData) {...);
I know when I call clients 2 and 3 function I not need worry about whether clients are connected. but I need to avoid to obtain data that I will not use. The goal is just obtain data I will use to the connected clients.
All I can do is see if there are clients, but not if there are clients of an specic js
Is there any way to know this?
You can use groups for that, and you can write JavaScript code reusable across pages. Before starting the connection, your JavaScript could do this:
$.connection.hub.qs = { referer: document.location.pathname };
This way you store the calling page in a query string key. Of course you can store whatever other information you think it's useful for your goal. Then you can have this in your hub:
public override Task OnConnected()
{
var referer = Context.Request.QueryString["referer"];
Groups.Add(Context.ConnectionId, referer);
}
This way each client will notify which library is using, and with the groups you created against the client information you can easily target them by client type. No need to store anything in memory, which has always a lot of drawbacks.
You can check that link to map users to conection. If you take a look at the in-memory solution, you will be able to retrieve a list of connected users.

Is there a way to set any property on hub that persists throughout the lifetime of a connection?

To set the right context, let me explain the problem. Till RC1, we used to implement GenerateConnectionIdPrefix() to prefix user Id to the connection Id. Then we could retrieve user id from the connection string anytime we need.
With RC2, we now cannot inherit IConnectionIdPrefixGenerator & implement GenerateConnectionIdPrefix anymore. So I was wondering what are other avenues available to set any property on the hub with our data, that persists throughout the lifetime of the connection.
Going through documentation, I realized setting query strings is one way, but that would mean we need to set it for every call. Setting a round trip state might be another option, but it looks like even that is persistent for a single round-trip and not entire lifetime.
So my end goal is set to property once at start on SignalR connection that can be used throughout the connection lifetime.
If there is nothing available now, are there any plans to add support to achieve something similar in next version?
[Update]
As suggested below, I tried to set a state Clients.Caller.Userid in the OnConnected method, then tried to access it in the subsequent call, I found that its null. Both calls are from same connection Id.
Look at the "Round-tripping state between client and server" section on https://github.com/SignalR/SignalR/wiki/Hubs.
Basically you can read and write from dynamic properties on Clients.Caller in Hub methods such as OnConnected or anything invoked by a client. Ex:
using System;
using System.Threading.Tasks;
using Microsoft.AspNet.SignalR;
namespace StateDemo
{
public class MyHub : Hub
{
public override Task OnConnected()
{
Clients.Caller.UserId = Context.User.Identity.Name;
Clients.Caller.initialized();
return base.OnConnected();
}
public void Send(string data)
{
// Access the id property set from the client.
string id = Clients.Caller.UserId;
// ...
}
}
}
State that is stored this way will be persisted for the lifetime of the connection.
If you want to learn how to access this state using the SignalR JS client look at the "Round-tripping state" section of https://github.com/SignalR/SignalR/wiki/SignalR-JS-Client-Hubs.
There are other ways to keep track of users without IConnectionIdPrefixGenerator discussed in the following SO answer: SignalR 1.0 beta connection factory

WCF Data Services ODATA

I am working on WCF Data Services. I have a function in my service which adds a record into a table in SQL DB and return the ID of the Inserted record.
I Used to Pass the values to be inserted in the form of Parameters to the Function.
For Example
public int Add(string Name, string Password)
{
// Here I will Add the record and return the ID of the record added in DB
}
But I dont want to do this way of passing in the form of parameters.
I want to pass the object directly.
Like
public int Add(User user)
{
// Here I will Add the record and return the ID of the record added in DB
}
I wrote the function like above in my services and my services project is successfull. When I update my ServiceRefrences I get Error.
It says only primitive types are supported. Is there any work around
this problem.
Thanks For Your Time in Answering my Question.
WCF Data Services (and OData protocol for that matter) only support passing primitive values as parameters to service operations.
The OData way of adding a new entity into an entity set is to send a POST with the entity in the payload to the entity set URL. In the WCF DS Service this will get translated into several calls to the IUpdatable interface on your context.

Resources