/*
* Copyright (c) 2015. Bearchoke
*/
package com.bearchoke.platform.persistence.mongo.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.thoughtworks.xstream.XStream;
import com.bearchoke.platform.persistence.mongo.axon.AxonMongoTemplate;
import com.bearchoke.platform.persistence.mongo.axon.AxonSagaMongoTemplate;
import org.axonframework.commandhandling.AsynchronousCommandBus;
import org.axonframework.commandhandling.CommandDispatchInterceptor;
import org.axonframework.commandhandling.gateway.CommandGateway;
import org.axonframework.commandhandling.gateway.CommandGatewayFactoryBean;
import org.axonframework.commandhandling.gateway.IntervalRetryScheduler;
import org.axonframework.commandhandling.interceptors.BeanValidationInterceptor;
import org.axonframework.eventhandling.EventBus;
import org.axonframework.eventhandling.SimpleEventBus;
import org.axonframework.eventsourcing.Snapshotter;
import org.axonframework.eventsourcing.SpringAggregateSnapshotter;
import org.axonframework.eventstore.mongo.MongoEventStore;
import org.axonframework.repository.LockManager;
import org.axonframework.repository.PessimisticLockManager;
import org.axonframework.saga.SagaRepository;
import org.axonframework.saga.repository.mongo.MongoSagaRepository;
import org.axonframework.saga.spring.SpringResourceInjector;
import org.axonframework.serializer.xml.XStreamSerializer;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskExecutor;
import org.springframework.data.mongodb.MongoDbFactory;
import javax.inject.Inject;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
/**
* Created by Bjorn Harvold
* Date: 7/19/14
* Time: 10:36 PM
* Responsibility:
*/
@Configuration
public class AxonCQRSConfig {
@Inject
private ObjectMapper objectMapper;
@Inject
private XStream xStream;
@Inject
@Qualifier("taskExecutor")
private TaskExecutor taskExecutor;
@Inject
@Qualifier("axonMongoDbFactory")
private MongoDbFactory mongoDbFactory;
@Bean(name = "commandBus", destroyMethod = "shutdown")
public AsynchronousCommandBus commandBus() {
AsynchronousCommandBus commandBus = new AsynchronousCommandBus();
List<CommandDispatchInterceptor> interceptors = new ArrayList<>(1);
interceptors.add(new BeanValidationInterceptor());
commandBus.setDispatchInterceptors(interceptors);
return commandBus;
}
@Bean(name = "commandGateway")
public CommandGateway commandGateway() {
CommandGateway commandGateway = null;
CommandGatewayFactoryBean factory = new CommandGatewayFactoryBean();
factory.setCommandBus(commandBus());
// create a retry scheduler to re-run the command that failed with an exception
// I put this in place to contend with concurrency exceptions [BH]
ScheduledExecutorService ses = Executors.newScheduledThreadPool(1);
factory.setRetryScheduler(new IntervalRetryScheduler(ses, 500, 2));
// factory.setGatewayInterface();
try {
factory.afterPropertiesSet();
commandGateway = (CommandGateway) factory.getObject();
} catch (Exception e) {
throw new RuntimeException(e);
}
return commandGateway;
}
// In case we want something more robust
// @Bean(name = "eventBus")
// public SpringMessagingEventBus eventBus() {
// SpringMessagingEventBus eventBus = new SpringMessagingEventBus();
// eventBus.setChannel(defaultInputChannel);
//
// return eventBus;
// }
@Bean(name = "eventBus")
public EventBus eventBus() {
EventBus eventBus = new SimpleEventBus();
return eventBus;
}
@Bean(name = "lockManager")
public LockManager lockManager() {
// OptimisticLockManager lockManager = new OptimisticLockManager();
PessimisticLockManager lockManager = new PessimisticLockManager(); // default Axon lock manager
return lockManager;
}
@Bean(name = "axonMongoTemplate")
public AxonMongoTemplate axonMongoTemplate() {
return new AxonMongoTemplate(mongoDbFactory);
}
@Bean(name = "axonSagaMongoTemplate")
public AxonSagaMongoTemplate mongoSagaTemplate() {
return new AxonSagaMongoTemplate(mongoDbFactory);
}
@Bean(name = "eventStore")
public MongoEventStore eventStore() {
// JacksonSerializer jsonSerializer = new JacksonSerializer(objectMapper);
XStreamSerializer xStreamSerializer = new XStreamSerializer(xStream);
return new MongoEventStore(xStreamSerializer, axonMongoTemplate());
}
@Bean(name = "sagaRepository")
public SagaRepository sagaRepository() {
MongoSagaRepository sagaRepository = new MongoSagaRepository(mongoSagaTemplate());
sagaRepository.setResourceInjector(new SpringResourceInjector());
return sagaRepository;
}
@Bean(name = "snapshotter")
public Snapshotter snapshotter() {
SpringAggregateSnapshotter sas = new SpringAggregateSnapshotter();
sas.setEventStore(eventStore());
sas.setExecutor(taskExecutor);
return sas;
}
}