Catching AggregateNotFoundException in Axon 0.7

I just tried running my current project against trunk (0.7-SNAPSHOT) and got a fail on this simple test:

@Test(expected= AggregateNotFoundException.class)
public void shouldThrowWhenAggregateNotFound(){
commandBus.dispatch(new SomerCommand(AggregateIdentifierFactory.randomIdentifier()));
}

Obviously the (simple) command bus is now swallowing the AggregateNotFoundException that earlier was thrown back upon dispatch.

10:09:54,115 DEBUG SimpleUnitOfWorkInterceptor:52 - Incoming command. Creating new UnitOfWork instance
10:09:54,189 DEBUG SimpleUnitOfWorkInterceptor:54 - Registering new UnitOfWork instance with CurrentUnitOfWork
10:09:54,190 DEBUG SimpleUnitOfWorkInterceptor:58 - Proceeding interceptor chain
Hibernate: select top ? snapshotev0_.id as id6_, snapshotev0_.aggregateIdentifier as aggregat2_6_, snapshotev0_.sequenceNumber as sequence3_6_, snapshotev0_.serializedEvent as serializ4_6_, snapshotev0_.timeStamp as timeStamp6_, snapshotev0_.type as type6_ from SnapshotEventEntry snapshotev0_ where snapshotev0_.aggregateIdentifier=? and snapshotev0_.type=? order by snapshotev0_.sequenceNumber DESC
Hibernate: select domaineven0_.id as id5_, domaineven0_.aggregateIdentifier as aggregat2_5_, domaineven0_.sequenceNumber as sequence3_5_, domaineven0_.serializedEvent as serializ4_5_, domaineven0_.timeStamp as timeStamp5_, domaineven0_.type as type5_ from DomainEventEntry domaineven0_ where domaineven0_.aggregateIdentifier=? and domaineven0_.type=? and domaineven0_.sequenceNumber>=? order by domaineven0_.sequenceNumber ASC
10:09:54,387 WARN LockingRepository:109 - Exception occurred while trying to load an aggregate. Releasing lock.
org.axonframework.repository.AggregateNotFoundException: The aggregate was not found
at org.axonframework.eventsourcing.EventSourcingRepository.doLoad(EventSourcingRepository.java:107)
at org.axonframework.eventsourcing.CachingEventSourcingRepository.doLoad(CachingEventSourcingRepository.java:88)
at org.axonframework.eventsourcing.CachingEventSourcingRepository.doLoad(CachingEventSourcingRepository.java:37)
at org.axonframework.repository.AbstractRepository.load(AbstractRepository.java:82)
at org.axonframework.repository.LockingRepository.load(LockingRepository.java:105)
at org.axonframework.repository.AbstractRepository.load(AbstractRepository.java:93)
at se.combol.reaper.core.command.AlarmUnitCommandHandler.handle(AlarmUnitCommandHandler.java:68)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.axonframework.util.AbstractHandlerInvoker.invokeHandlerMethod(AbstractHandlerInvoker.java:83)
at org.axonframework.commandhandling.annotation.AnnotationCommandHandlerAdapter.handle(AnnotationCommandHandlerAdapter.java:75)
at org.axonframework.commandhandling.DefaultInterceptorChain.proceed(DefaultInterceptorChain.java:54)
at org.axonframework.commandhandling.interceptors.SimpleUnitOfWorkInterceptor.startNewUnitOfWorkAndProceed(SimpleUnitOfWorkInterceptor.java:59)
at org.axonframework.commandhandling.interceptors.SimpleUnitOfWorkInterceptor.handle(SimpleUnitOfWorkInterceptor.java:48)
at org.axonframework.commandhandling.DefaultInterceptorChain.proceed(DefaultInterceptorChain.java:52)
at org.axonframework.commandhandling.SimpleCommandBus.dispatch(SimpleCommandBus.java:64)

Caused by: org.axonframework.eventstore.EventStreamNotFoundException: Aggregate of type [AlarmUnit] with identifier [53a1378a-b354-4f67-8eb2-195a653d0f64] cannot be found.
at org.axonframework.eventstore.jpa.JpaEventStore.readEvents(JpaEventStore.java:100)
at org.axonframework.eventsourcing.EventSourcingRepository.doLoad(EventSourcingRepository.java:105)
… 50 more
10:09:54,424 DEBUG SimpleUnitOfWorkInterceptor:65 - Rolling back UnitOfWork after execution error
10:09:54,428 DEBUG SimpleUnitOfWorkInterceptor:67 - UnitOfWork rolled back
10:09:54,429 DEBUG SimpleUnitOfWorkInterceptor:70 - Clearing UnitOfWork from CurrentUnitOfWork
10:09:54,429 ERROR SimpleCommandBus:68 - An error occurred while dispatching a command.
org.axonframework.repository.AggregateNotFoundException: The aggregate was not found
at org.axonframework.eventsourcing.EventSourcingRepository.doLoad(EventSourcingRepository.java:107)
at org.axonframework.eventsourcing.CachingEventSourcingRepository.doLoad(CachingEventSourcingRepository.java:88)
at org.axonframework.eventsourcing.CachingEventSourcingRepository.doLoad(CachingEventSourcingRepository.java:37)
at org.axonframework.repository.AbstractRepository.load(AbstractRepository.java:82)
at org.axonframework.repository.LockingRepository.load(LockingRepository.java:105)
at org.axonframework.repository.AbstractRepository.load(AbstractRepository.java:93)
at se.combol.reaper.core.command.AlarmUnitCommandHandler.handle(AlarmUnitCommandHandler.java:68)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.axonframework.util.AbstractHandlerInvoker.invokeHandlerMethod(AbstractHandlerInvoker.java:83)
at org.axonframework.commandhandling.annotation.AnnotationCommandHandlerAdapter.handle(AnnotationCommandHandlerAdapter.java:75)
at org.axonframework.commandhandling.DefaultInterceptorChain.proceed(DefaultInterceptorChain.java:54)
at org.axonframework.commandhandling.interceptors.SimpleUnitOfWorkInterceptor.startNewUnitOfWorkAndProceed(SimpleUnitOfWorkInterceptor.java:59)
at org.axonframework.commandhandling.interceptors.SimpleUnitOfWorkInterceptor.handle(SimpleUnitOfWorkInterceptor.java:48)
at org.axonframework.commandhandling.DefaultInterceptorChain.proceed(DefaultInterceptorChain.java:52)
at org.axonframework.commandhandling.SimpleCommandBus.dispatch(SimpleCommandBus.java:64)

Caused by: org.axonframework.eventstore.EventStreamNotFoundException: Aggregate of type [AlarmUnit] with identifier [53a1378a-b354-4f67-8eb2-195a653d0f64] cannot be found.
at org.axonframework.eventstore.jpa.JpaEventStore.readEvents(JpaEventStore.java:100)
at org.axonframework.eventsourcing.EventSourcingRepository.doLoad(EventSourcingRepository.java:105)
… 50 more

java.lang.AssertionError: Expected exception: org.axonframework.repository.AggregateNotFoundException
at org.junit.internal.runners.statements.ExpectException.evaluate(ExpectException.java:32)

The dispatch implementation in SimpleCommandBus looks like this:

try {
interceptorChain.proceed(new CommandContextImpl(command, handler));
} catch (Error e) {
throw e;
} catch (Throwable throwable) {
logger.error(“An error occurred while dispatching a command.”, throwable); // swallows all exceptions
}

Should it swallow all exceptions by design or is this a bug?
If by design what is the recommended solution?
Should I use command callbacks instead when dispatching?

Regards,

Ola

Hi Ola,

this time a can honestly say that it is not a bug, it’s a feature. The single-parameter method (that was made deprecated in 0.6) has a different purpose in 0.7: fire-and-forget.

If you are interested in the result of command execution, you should use the callback parameter.

This is the only API I could find to provide transparent support for asynchronous command buses, which becomes increasingly important when building large-scale processing applications (i.e. when command handlers are spread over a cluster).

If you have any further questions, don’t hesitate to let me know.

Cheers,

Allard

I suspected that, just checking.

I have another test failing now.
It is an acceptance test that is using a root aggregate repository to verify that the aggregate have been created.

public void myAggregateAcceptanceTest(){
CreateMyAggregateCommand cmd = new CreateMyAggregateCommand();
commandBus.dispatch(cmd); // this works fine, a UoW is created and successfully committed.

// this will create an implicit UoW, see EventSourcingRepository.doLoad:116
MyAggregate aggregate = myAggregateRepository.load(cmd.getAggregateIdentifier());
assertNotNull(aggregate); // ok

aggregateEntry = myAggregateEntryDAO.load(cmd.getAggregateIdentifier());
assertNotNull(aggregateEntry); // also ok

// From here when dispatching a new command it will join the Implicit UoW but it won’t commit it after it has been executed.
ChangeMyAggregateCommand cmd = new ChangeMyAggregateCommand(cmd.getAggregateIdentifier());
commandBus.dispatch(cmd);

// Here the test will fail since the implicit UoW has not been committed.
assertTrue(aggregateEntry.hasChanged()); // fail!
}

It seems like loading an AR outside a command handler will cause bad things to happen.
I guess this should not be a problem for most scenarios since you should only load them inside a command handler.
But what about testing?

Or could this be a bug?
It seems like the allowNesting should be set to true in order to avoid nesting:

SimpleUnitOfWorkInterceptor:

@Override
public Object handle(CommandContext context, InterceptorChain chain) throws Throwable {
if (**!**allowNesting && CurrentUnitOfWork.isStarted()) { // should it not be just allowNesting && …?
logger.debug(“Participating in existing UnitOfWork.”);
return chain.proceed(context);
}
return startNewUnitOfWorkAndProceed(context, chain);
}

Regards,

Ola

2010/9/17 Allard Buijze <buijze@gmail.com>

Ah, I have misinterpreted how unit of works are nested.
(I thought that nesting was the same as joining an existing UoW, but of course it is the opposite.)

Setting nesting to true should of course do the trick in this case.

2010/9/22 Ola Herrdahl <ola@kodar.se>