Implementing Event Snapshots in Axon 3

If all events have sequence number 0, you’re either creating a new aggregate instance each time (instead of invoking a new one), or aren’t using an Event Sourcing repository. In the latter case, Snapshotting doesn’t make sense, because the aggregate is already stored as state anyway. If it’s the former, then probably your aggregate design (or ‘test’ scenario) is faulty.

Cheers,

Allard

I have issue deploying Axon application, here is my configuration and error message.
Enter code here...

`

@Configuration
public class AxonConfig {

@Autowired
private AxonConfiguration axonConfiguration;
@Autowired
private EventBus eventBus;

@Bean
public com.isslng.schooloffice.handler.AccountCommandHandler accountCommandHandler() {
return new com.isslng.schooloffice.handler.AccountCommandHandler(axonConfiguration.repository(Account.class), eventBus);
}
@Bean
public SagaConfiguration TransactionPostManagementSagaConfiguration() {
return SagaConfiguration.trackingSagaManager(TransactionPostManagementSaga.class);
}

@Autowired
public void configure(@Qualifier(“localSegment”) SimpleCommandBus simpleCommandBus) {
simpleCommandBus.registerDispatchInterceptor(new BeanValidationInterceptor<>());
}

}

`

Enter code here...

Enter code here...

`

`

`

@Data
@Slf4j
@Aggregate
public class Account {//extends AbstractAggregateRoot {

@AggregateIdentifier
private String id;
private String AccountName;
private List userId;
private AccountingType type;

public Account() {
}

@CommandHandler
public Account(CreateAccountCommand command){
apply(new CreateAccountEvent(command.getId(),command.getAccountName(), command.getUserId()));
}

public void debit(Double amount, String transactionId) {
log.info(“Post debit with payload {}”, transactionId);
apply(new SourceAccountDebitedEvent(id, transactionId, amount));
}

public void credit(Double amount, String transactionId) {
apply(new DestinationAccountCreditedEvent(id,transactionId, amount ));
}

@EventSourcingHandler
public void on(CreateAccountEvent event) {
this.id = event.getId();
this.AccountName = event.getAccountName();
this.userId = event.getUserId();
}
public enum AccountingType{
DEBIT,
CREDIT;
}
}

@Slf4j
@Transactional
public class AccountCommandHandler {

private Repository repository;
private EventBus eventBus;

// @Autowired
public AccountCommandHandler(Repository repository, EventBus eventBus) {
this.repository = repository;
this.eventBus = eventBus;
}

@CommandHandler
public void handle(DebitAccountCommand command) {
try {
log.info(“Post DebitAccountCommand with payload {}”,command);
Aggregate AccountAggregate = repository.load(command.getAccount());
AccountAggregate.execute(account ->
account.debit(command.getAmount(), command.getTransactionId()));
} catch (AggregateNotFoundException exception) {
eventBus.publish(asEventMessage(new DebitAccountNotFoundEvent(command.getTransactionId())));
}
}

@CommandHandler
public void handle(CreditAccountCommand command) {
try {
log.info(“Post DebitAccountCommand with payload {}”,command.toString());
Aggregate AccountAggregate = repository.load(command.getAccount());
AccountAggregate.execute(account -> account
.credit(command.getAmount(), command.getTransactionId()));

}
catch (AggregateNotFoundException exception) {
eventBus.publish(asEventMessage(new CreditAccountNotFoundEvent(command.getTransactionId())));
}
}
}

Error starting ApplicationContext. To display the auto-configuration report re-run your application with ‘debug’ enabled.
2017-07-20 16:51:56.860 ERROR 16504 — [st-startStop-37] o.s.b.d.LoggingFailureAnalysisReporter :

This is a typical symptom of two beans with the same name. You probably have a class called AccountRepository that acts as your Query repository. Having an Account aggregate, this also (automatically) creates a bean called ‘accountRepository’. Spring attempts to inkect one bean, where the other type is expected.

The solution is to rename your queryRepository bean (using @Repository(‘beanName’) or by renaming the class itself).

Hope this helps.
Cheers,

Allard

Thanks for your prompt response. Have changed the class name and the error is clear … Now I’m having new one.
`

java.lang.IllegalStateException: Default configuration requires the use of event sourcing. Either configure an Event Store to use, or configure a specific repository implementation for class com.aggregate.Account
at org.axonframework.common.Assert.state(Assert.java:42)
at org.axonframework.config.AggregateConfigurer.lambda$new$9(AggregateConfigurer.java:98)
at org.axonframework.config.Component.get(Component.java:73)
at org.axonframework.config.AggregateConfigurer.repository(AggregateConfigurer.java:186)
at org.axonframework.config.DefaultConfigurer$ConfigurationImpl.repository(DefaultConfigurer.java:334)
at org.axonframework.spring.config.AxonConfiguration.repository(AxonConfiguration.java:92)
at com.config.AxonConfig.AccountCommandHandler(AxonConfig.java:33)
at com.config.AxonConfig$$EnhancerBySpringCGLIB$$60b61224.CGLIB$AccountCommandHandler$2()
at com.config.AxonConfig$$EnhancerBySpringCGLIB$$60b61224$$FastClassBySpringCGLIB$$e7f9e93f.invoke()
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:356)
at com.config.AxonConfig$$EnhancerBySpringCGLIB$$60b61224.AccountCommandHandler()
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1173)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1067)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:866)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542)
at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:668)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:634)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:682)
at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:553)
at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:494)
at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136)
at javax.servlet.GenericServlet.init(GenericServlet.java:158)
at com.liferay.portal.kernel.servlet.PortalDelegateServlet.doPortalInit(PortalDelegateServlet.java:64)
at com.liferay.portal.kernel.util.BasePortalLifecycle.portalInit(BasePortalLifecycle.java:44)
at com.liferay.portal.kernel.util.PortalLifecycleUtil.register(PortalLifecycleUtil.java:74)
at com.liferay.portal.kernel.util.PortalLifecycleUtil.register(PortalLifecycleUtil.java:58)
at com.liferay.portal.kernel.util.BasePortalLifecycle.registerPortalLifecycle(BasePortalLifecycle.java:54)
at com.liferay.portal.kernel.servlet.SecureServlet.init(SecureServlet.java:76)
at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1284)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1197)
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1087)
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:5266)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5554)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:652)
at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1263)
at org.apache.catalina.startup.HostConfig$DeployDirectory.run(HostConfig.java:1948)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)

`

Did you define an EventBus as a bean in your Spring configuration?

Just in case you’ve also used Axon 2: in Axon 3, the Event Store replaces the Event Bus altogether. So you would have either an Event Store, or an Event Bus. The latter is used only when you don’t have the intent to store the events.

Cheers,

Allard

Thanks for the clarification, I’m using eventbus… but I intend storing event. I will be glad if you point me to appropriate tutorial or guide to event store configuration.

Hi,

if you’re using Spring Boot with the Axon Spring Boot Starter, a JPA based Event Store is configured automatically when you have JPA configured (for which there is also a starter). In that case, you don’t need to configure anything.

If you’re not using Spring Boot, there is a chapter in the reference guide explaining how to configure an Event Store: https://docs.axonframework.org/part3/repositories-and-event-stores.html

Cheers,

Allard