org.axonframework.repository.ConcurrencyException



Hi there,


From the CQRS workshop at JTeam I got an impression that the axon framework takes care of concurrent access to aggregates, so we do not need to take that care by ourselves.


However, sometimes we get



org.axonframework.repository.ConcurrencyException: The aggregate of type [AsnRegistry] with identifier [4f35d970-9f0b-11df-981c-0800200c9a66] could not be saved, as a valid lock is not held. Either another thread has saved an aggregate,
or the current thread had released its lock earlier on.
at org.axonframework.repository.LockingRepository.save(LockingRepository.java:119)
at net.ripe.rs.service.impl.asn.AsnCommandHandler.handle(AsnCommandHandler.java:67)



and it’s quite easy to reproduce it by hammering command handler from JMeter.


We don’t do anything special in a command handler, pretty much copy-paste from sample application:


> @CommandHandler
> public void handle(AssignAsnCommand command) {
> AsnRegistry asnRegistry = repository.load(AsnRegistry.ID);
> asnRegistry.assignAsn(…);
> repository.save(asnRegistry);
> }























and a pretty much “standard” application context (see below).



So do you have a clue (or a pointer to where to look further) why we do have a ConcurrencyException?








Excerpt from application-context:



> >
>
> >
>
> >
>
> >
>
> >
>
> > 42
>
> > 42
>
> > 42
>
> > 42
>
> >
>
> >
>
> >
>
> >
>
> >
>
> >
>
> >
>
> >
>
> >
>
> >
>
> >
>
> >
>
> >
>
> >
>
> >
>
> >
>
> >
>
> >
>
> >
>
> >
>
> >
>
> >
>
> >
>
> >
>
> >
>
> >
>
> >
>
> >
>
> >




























|

Hi Oleg,

By default the LockingStrategy used is the OPTIMISTIC one. From the docs:

“The particular strategy does not prevent concurrent access. Instead, when concurrent modifications are detected, an exception is thrown.”

Given the documentation for this strategy, I would understand that the client is to manage concurrent access.

Cheers,

Hi,

Given the documentation for this strategy, I would understand that the client is to manage concurrent access.

Meaning,

When using the optimistic locking strategy (default): recover from this exception by loading the aggregate from the repository again, replaying all actions on it and saving it.

Have a look at the LockingRepository docs.

Cheers,

Oleg,

if you want concurrency control using locks, you can set the locking strategy to pessimistic on your repository. The default is optimistic, and as Rob stated before, that version throws an exception on concurrent access. Typically, commands that fail due to a ConcurrencyException can be retried. A pessimistic locking strategy will not result in a ConcurrencyException (unless the application is deployed on multiple machines).

Cheers,

Allard

Okay, got it. Thanks!

Hi Sankalp Sontakke,
We are facing concurrency exception org.axonframework.repository.ConcurrencyException: Concurrent modification detected for Aggregate identifier [ANDROID-com.tienganh123.android2-1.0], sequence: [582] when we are running our application on multiple instances using JMetter.
We can’t fix this bug? can I help you?

Vào 20:57:29 UTC+7 Thứ Sáu, ngày 04 tháng 2 năm 2011, Allard Buijze đã viết: