How to handle ConcurrencyException in Axon3

Hi!

Is there a way to handle ConcurrencyExceptions? Can someone point me to sample Code?

We are modifying one aggregate on 2 nodes. Therefore we got the ConcurrencyException.

As I already read, I can’t use ConflictResolvers for this Exception:
https://groups.google.com/forum/#!topic/axonframework/VOSbRZaL_wQ

So what is documented here can’t help in my case, right?

So is there a way to simply catch these Exceptions and repeat my command?
Any better Ideas? I don’t like to use a distributed command bus with routing to specific nodes for certain aggregates…

cu,
Dirk

Hi,

One way of resolving this is by using a retry scheduler on the command gateway. See https://docs.axonframework.org/v/3.0/part3/command-dispatching.html
In a project I’m working on this is what we’ve done to handle this use case.

Alternatively you could also opt for a distributed command bus. See the same link. That should ensure all commands are dealt with on the same instance and use the locking by the command gateway to ensure sequential handling of them. This may be a bit more complex than necessary for your use case though.

Regards,
Thomas

Ah - Thanks Thomas! That sounds very promising. I will try the retry scheduler.

Be aware that with retry the last command wins and potentially overwrites the state of a previous command execution. Just make sure this is what you want :slight_smile:

Jorg

I tried to modify the axon-bank example to create this retry scheduler. I added this to the AxonConfig class:

@Bean
public CommandGateway commandGateway(CommandBus commandBus) {

    ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(1);
    RetryScheduler retryScheduler = new IntervalRetryScheduler(scheduledThreadPool, 1, 100);
    return new DefaultCommandGateway(commandBus, retryScheduler);
}

But the Retry doesn’t seem to work - I’m still loosing events. Is this the way it’s intended to be configured?


Yes thanks - that won’t be a problem in this case :slight_smile:

Ok - I think I got it. 2 points I missed:

  1. The above configuration turned out to be correct, but I was using the commandBus in my JUnit Testcase.
    I had to explicitely use the commandGateway for the retry-mechanism to work.

  2. The thrown RepositoryException was a subclass of AxonNonTransient Exception. That had the effect, that the RetryScheduler didn’t retried at all!
    And that sounds strange to me. I will open another thread for this. My workaround was to subclass IntervalRetryScheduler and implement an “always transient” return:

@Override
protected boolean isExplicitlyNonTransient(Throwable failure) {
    return false;
}

Hi Dirk,

any exception extending AxonNonTransientException should not be retried, because a retry will cause the same exception to happen again (hence non-transient).
Which exact exception is your command throwing?

Note that ConcurrencyException extends AxonTransientException (explicitly indication a retry makes sense).

Cheers,

Allard

Hi Allard,

thanks for your reply. That was a bug and I opened a case for it. But the bug has already been fixed and will be contained in 3.0.3:
https://github.com/AxonFramework/AxonFramework/pull/275

cu,
Dirk