Axon Framework: Convert XStream serialized events to Jackson Serializer in existing application - axon

We have an application that was written using the Axon Framework. Based on the issues we are having with XStream, the idea of converting to the Jackson serializer has been proposed.
Is it possible to convert the current events in the event store to a JSON representation using configuration options in Axon or are we going to have to handle this manually?

Axon Framework, nor any of the extensions, provide something out of the box to achieve this.
The most straightforward way to rewrite an event store is to write a basic event handling application that reads from store one and writes (with the desired adjustments) to store two.
From an effort perspective, that's something like this:
Construct basic Axon Framework application, reading from current XML store.
Configure the second EventStore in your application separately from Axon's Configurer. This second store's EventStorageEngine should receive the JacksonSerializer, whereas the default store should use the XStreamSerializer
Write an event handler that handles all events, keeping things like the timestamp (very important) intact. This handler should 'append' events into store two.
Start the application. The default Streaming Event Processor will read everything, give it to your Event Handler, that'll provide them to the second store.

Related

Axon stores events as XML instead of JSON

I'm new on Axon framework and i want to configure Axon in order to store events as JSON.
I'm using Spring-Boot and, as per documentation, i set some key/value in a .properties file
I expected to see events stored as JSON but i keep seeing XML in the serializedPayload of the MongoDB event store.
I think I have configured the serilializers correctly but obviously I'm doing something wrong
Please note that debugging the application it seems that JacksonSerializer class is never invocated and instead XStreamSerializer class is called even my key/value configuration.
So i need to understand why my jackson configuraton is not calling the right serializer
You have to configure the MongoEventStorageEngine to use the Serializer you want.
Looking at it's Builder (specially the javadoc), you can see it offers a snapshotSerializer and a eventSerializer methods while the javadoc states that both of them defaults to XStreamSerializer.
If you need help configuring it, I can point you to the mongo-axon-example where you can see a project configured and running.
The example is not using Jackson but it should be an easy addition to configure it here.
Even if the documentation doesn't seem to mention it, it is not enough to add the key/value in the .properties file. You need also to add the JacksonSerializer to the MongoEventStorageEngine as following:

Axoniq Event Handler Resuming from offset

I am looking at the AxonIQ framework and have managed to get a test application up and running. But I have a question about how EventHandlers should be treated when using a store that has persistence in the Read Model.
From my (possible naive) understanding. #EventHandler annotated methods in my Projection class get called from the beginning when first launched. This would mechanism seems to assume that the Projection utilises some kind of in volatile store (e.g. an in memory sql like h2) which is re-created from scratch during the application bootup.
However, if the store was persistent in something like Elastic Search, I would want the #EventHandler to resume from its last persisted event instead of from the beginning event.
Is there anyway to control the behaviour of the #EventHandler in this way?
Axon has two types of Event Processors: Subscribing and Tracking.
The Subscribing mode (which was the default up to Axon 3) will handle events in the thread that delivers them. That means you're at "the mercy" of the delivery guarantees of whichever component delivers the events.
The Tracking mode (which is the default since Axon 4 when using an Event Store or otherwise a source that supports it) will have events handled in dedicated threads, managed by the Event Processor itself. That means events are handled asynchronously from the actual publication mechanism.
The Tracking Event Processor uses Tokens to keep track of progress. These Tokens are stored in a TokenStore and updates as the Processor has correctly processed each incoming event (possibly batched). You decide where those tokens are stored. If you update a relational database, we recommend storing the tokens in the same database, so that event changes and tokens are updated atomically.
If you don't specify any TokenStore, it depends on whether you're on Spring Boot, in which case Axon will attempt to detect a suitable TokenStore implementation for you. Otherwise, it may very well just be an in-memory TokenStore, which causes Processors to re-initialize on every startup (and possibly start from the beginning).
To configure a TokenStore
On Spring (Boot), simply add a bean of type TokenStore with the implementation you want to use
When using Axon's Configuration API, on the EventProcessingConfigurer, use one of the registerTokenStore(...) methods.
When the Tracking Processor starts, it will check the Token Store for previous progress, and continue from there automatically.

Iis it possible to store all events in central RDBMS DB in micro service architecture using axon 3.3.3?

I would like to understand an Axon feature.
Currently, we are developing an application using microservice architecture.
We want to store all service events in a central RDBMS database, like for example PostgreSQL.
Is it possible to use such a store?
We have used the below configuration to store events in same domain DB:
#Bean
public AggregateFactory<UserAggregate> userAggregateFactory() {
SpringPrototypeAggregateFactory<UserAggregate> aggregateFactory =
new SpringPrototypeAggregateFactory<>();
aggregateFactory.setPrototypeBeanName("userAggregate");
return aggregateFactory;
}
Now we want to store events in a central Event Store DB, not with domain DB.
Firstly, the AggregateFactory within any Axon application does not define where or how your events are stored at all.
I instead suggest to read the Event Bus & Event Store section of the Axon Framework reference guide on the matter to explain how you can achieve this.
The short answer to your question is by the way yes, you can have a single Event Store backed by a RDBMS, like PostgreSQL, to store all your events in.
Between duplicated instances of a given application it is actually highly recommended to use the same storage location.
As soon as you are going to span different Bounded Context's, I would suggest to define different Event Stores per context though.
Concluding, you are using an old version of Axon Framework.
I would highly recommend to move the at least the latest Axon 3 release, being 3.4.3, but ideally you start using 4.1.2.
Note that there is no active development taking place on Axon 3 any more, hence the suggestion.

hiding method from certain layers in project

I was looking through an old project and wanted to see if anyone had a suggestion on how to hide certain methods from being called by various layers. This was a 3 tier project, webapplication -> web service -> database
In the application there is a User object for example. When a User was being updated, the webapplication would create a User object and pass it to the webservice. The webservice would use the DataAccessLayer to save the User object to the database. After looking at this I was wondering if instead I should have made a Save method in the User class. This way the service and simply call the Save on the User object which would trigger the db update.
However doing it this way would expose the Save to be called from the webapplication as well, correct? Since the webapplication also has access to the same User object.
Is there anyway around this, or is it better to avoid this altogether?
There is a separation of concerns by keepeing the User object as object that only holds data with no logic in it. you better keep it separated for the following reasons:
As you stated, it is a bad practice since the Save' functionality will be exposed to other places/classes where it is irrelevant for them (This is an important for programming generally).
Modifying the service layer - I guess you are using WCF web service as you can transfer a .NET object (c#/VB) to the service via SOAP. If you put the saving logic in the 'User' object, you can't replace it another webservice that receives a simple textual data structures like JSON or XML or simply doesn't support .NET objects.
Modifying the data storage layer - If you want, for example, to store the data inside a different place like other database such as MongoDB, RavenDB, Redis or what ever you want, you will have to reimplement each class that responsible for updating the data. This is also relevant for Unit Testing and Mocking, making them more complicated to interrogate.

Accessing data set over WCF without serializing the entire thing?

I'm very new at WCF (and .NET in general), so I apologize if this is common knowledge.
I'm designing a WCF solution (currently using Entity Framework to access the database). I want to grab a (possibly very large) set of data from the database, and return it to the client, but I don't want to serialize the entire set of data over the wire all at once, due to performance concerns.
I'd like to operation to return some sort of object to the client that represents the resulting data and I'd like to deal with that data on the client, being able to navigate through it backwards and forwards and retrieve the actual data over the wire as needed.
I don't want to write a lot client code to individually find out what rows meet my search criteria, then make separate calls to get each record if I can help it. I'm trying to keep the client as simple as possible.
Ideally, I'd like to write the client code similar to something like the below pseudocode:
Reference1.Service1Client MyService = new Reference1.Service1Client("Service1");
DelayedDataSet<MyRecordType> MyResultSet = MyService.GetAllCustomers();
MyResultSet.First();
while (!MyResultSet.Eof)
{
Console.Writeline(MyResultSet.CurrentRecord().CUSTFNAME + " " + MyResultSet.CurrentRecord().CUSTLNAME);
Console.Writeline("Press Enter to see the next customer");
Console.Readline();
MyResultSet.Next();
}
Of course, DelayedDataSet is something I just made up, and I'm hoping something like it exists in .NET.
The call to MyService.GetAllCustomers() would return this DelayedDataSet object, with would not actually contain the actual records. The actual data wouldn't come over the wire until CurrentRecord() is called. Next() and Previous() would simply update a cursor on the server side to point to the appropriate record. I don't want the client to have any direct visibility to the database or Entity Framework.
I'm guessing that the way I wrote the code probably won't work over WCF, and that the functions like CurrentRecord(), Next(), First(), etc. would have to be separate service contract operations. I guess I'm just looking for a way to do this without having to write all my own code to cache the results on the server, somehow persist the data sets server side, write all the retrieval and navigation code in my service library, etc. I'm hoping most of this is already done for me.
It seems like this would be a very commonly needed function. So, does something like this exist?
-Joe
No, that's not what WCF is designed to do.
In WCF, the very basic core architecture is that you have a client and a server, and nothing but (XML-)serialized data going between the two over the wire.
WCF is not a remote-procedure call method, or some sort of remote object mechanism - there is no connection between the client and the server except the serialized message that conforms to the service (and data) contracts defined between the two.
WCF is not designed to handle huge data volumes - it's designed to handle individual messages (GetCustomerByID(42) and such). Since WCF is from the ground up designed to be interoperable with other platforms (non - .NET, too - like Java, Ruby etc.) you should definitely not be using heavy-weight .NET specific types like DataSet anyway - use proper objects.
Also, since WCF ultimately serializes everything to XML and send it across a wire, all the data being passed must be expressible in XML schema - which excludes interfaces and/or generics.
From what I'm reading in your post, what you're looking for is more of a "in-proc" data access layer - not a service level. So if you want to keep going down this path, you should investigate the repository and unit-of-work patterns in conjunction with Entity Framework.
More info:
MSDN: What is Windows Communication Foundation?
WCF Essentials—A Developer's Primer
Picture of the very basic WCF architecture from that Primer - there's only a wire with a serialized message connecting client and server - nothing more; but serialization will always happen

Resources