Does axon cache support hazelcast cache?

Hi

Configuration already shared as part of this chain. Is any configuration missing? Please LMK.

Thanks
Deepak Gupta

Hi Deepak,

looking at the code, I still don’t think I have the full thing.
Your aggregate invokes new MyEntity(event.getGroupCapacity()), but in your Entity code, I don’t see that constructor (just the default one).

Cheers,

Allard

Added the MyEntity code again with another constructor. Is it issue with cache that i am configuring here.?

public class MyEntity extends AbstractAnnotatedEntity
implements Serializable {

private int capacity = Integer.MAX_VALUE;

/**

  • Creates a new entity. Used for serialization only.
    */
    public MyEntity() {
    }

public MyEntity(int capacity){
this.capacity=capacity;
}

@CommandHandler
public JoinCommandStatus joinGroup(JoinGroupCommand cmd) {
// business logic
apply(new GroupJoinedEvent(…));
}
}

Hi Allard

Does AR having entities in it supports caching event sourcing repository?

What i tried to do, putting all the command and event handler from entity to AR then it does not throw any exception.
But while same command and event handler as part of entity in AR, throws below exception mentioned in mail chain.?

Thanks & Regards
Deepak Gupta

Hi Deepak,

I just went through the code of Axon 2.x (haven’t looked at that for quite a while, to be honest). Although it looks like it should be supported (the field is not marked transient), the problem is that the AbstractEventSourcedEntity (which contains the reference to the Aggregate Root) is not Serializable. This causes Java Serialization to just use the default constructor.

So unfortunately, it seems that invoking subclasses directly on cached entities (via serialization) isn’t supported. You can actually invoke the “registerAggregateRoot” method on your entities to work around this issue. Not the most beautiful design (as it mingles with your business logic code), but it will get it working.

Note that Axon 3 has a different way of working with Aggregates. It does not have this issue.

Cheers,

Allard

Hi Allard

I tried to override the “registerAggregateRoot” in my entity of the AR. But it still throws the same issue.?

Is there any other way to do so. Please LMK.?

Thanks & Regardsf
Deepak Gupta

Hi Deepak,

you shouldn’t override the method, but invoke it from your aggregate root. Do getChildEntities() and for each element in there, call registerAggregateRoot(this).

Cheers,

Allard

Hi Allard,

I tried to run the below code in both constructor and “on()” method of AR. But still the same error persists. Please advise.

Code:

Collection<? extends EventSourcedEntity> childEntities = getChildEntities();
if (childEntities != null) {
for (EventSourcedEntity entity : childEntities) {
if (entity != null) {
entity.registerAggregateRoot(this);
}
}
}

AggregateRoot Snippet Code:

/**

  • The aggregate root entity for a group call.
    */
    public class MyAggregateRoot
    extends AbstractAnnotatedAggregateRoot {

private static final long serialVersionUID = 1234123412341234123L;

private static final Logger LOG =
LoggerFactory.getLogger(MyAggregateRoot.class);

// The group’s unique instance ID
@AggregateIdentifier
private String groupId;

@CommandHandlingMember
@EventSourcedMember
private MyEntity members;

// The group name
private String groupName;

private boolean ended;

/**

  • Creates a new group call aggregate root. Used for serialization only.
    */
    public MyAggregateRoot() {
    }

/**

  • Creates a new group call aggregate root in response to start group call commands.

Can you check (using breakpoints) if this code is properly invoked before the child entities are being accessed? Also, if you have multiple layers of child entities, you will have to recursively call the getChildEntities() method to register the root in all of them.

Do note that Axon 2 isn’t actively maintained anymore. If you have a chance to migrate to 3, support for this feature is much better…

Hi Allard

I have debugged the Axon Code using break points with the above changes in AR. But this code never got called. And for the second command when aggregate fetched from cache, then it does not have aggregate root in the entity. But same aggregate root in entity was present when i am adding the aggregate in cache during first command call. And later it called the command handler. We are not using multiple layers of child entities and we don’t any such plan to migrate to AXON 3.0 right now.

Is there any chance if we get any patch for this issue?

Thanks & Regards
Deepak Gupta

Hi Deepak,

how do you mean “it never got called”? The idea is that your code calls this method before you invoke any state changing methods on the aggregate. The entities need the reference to the aggregate root to be able to register the events for publication. Invoking the registerAggregate method ensures that this is set, even if the aggregate has been deserialized.

Cheers,

Allard

Hi Allard

Instead of doing all above changes, could we fork Axon 2.x and simply make AbstractEventSourcingEntity and AbstractAnnotatedEntity serializable? I think this would work.

Regards
Deepak Gupta

That might work, although I am not sure how Java serialization deals with recursive object trees.

But honestly, I don’t really see the problem to just invoke the “registerAggregateRoot” on these entities when you’ve loaded them from the cache. It’s not the most beautiful code (that’s why we’ve redesigned this model in Axon 3), but it gets the job done.

Another thing: what do you use the cache for? It is for optimization? Axon allows you to route commands to specific nodes, so that the aggregate can be cached in memory on that node. Serializing it and storing it remotely beats the purpose, actually. If the event sourcing process is too slow, you can also use snapshots to speed that up.

Cheers,

Allard

Hi Allard

After doing above changes, i was able to run the application with caching but i do not see any performance improvement while aggregate calls. Could you please suggest me how to invoke the “registerAggregateRoot” on these entities. Because i see that after fetching the aggregate from caching in doLoad method of CachingEventSourcingRepository, it internally calling the AxonCommandHandler class. I don’t know where to call the registerAggregateRoot.

Regards
Deepak Gupta

Hi,

this is what I tried to warn you for in one of my earlier mails. Caching, especially when using a cache that stores information remotely, is only useful for instances that would otherwise be expensive to construct. Aggregates, even when using event sourcing, generally aren’t expensive to build. Only when a large number of events is needed to do so. In that case, I would recommend using snapshots, instead of a cache.

Caching only really helps if you cache locally and in-heap.

Cheers,

Allard