`
`
Hey Allard, yes I did.
My repository currently looks like this:
`
package org.softech.flexbet.query;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface SaleAggregrateRepository extends JpaRepository<SaleEntry, String> {
}
`
The Aggregate:
`
package org.softech.flexbet.aggregates;
import org.axonframework.commandhandling.CommandHandler;
import org.axonframework.commandhandling.model.AggregateIdentifier;
import static org.axonframework.commandhandling.model.AggregateLifecycle.apply;
import org.axonframework.eventsourcing.EventSourcingHandler;
import org.axonframework.spring.stereotype.Aggregate;
@Aggregate(repository=“SaleAggregateRepository”)
public class Sale {
@AggregateIdentifier
String sale_id;
public Sale() {
}
@CommandHandler
public Sale(MakeSaleCommand command) {
apply(new SaleMadeEvent(command.getId(), command.getAgent_id(), command.getProduct_id(),
command.getProduct_price(), command.getSale_date_time()));
}
@CommandHandler
public void update(UpdateSaleCommand updateSaleCommand) {
apply (new UpdateSaleEvent(sale_id, updateSaleCommand.getProduct_price()));
}
/*
- Will be invoked by apply method or during replay
*/
@EventSourcingHandler
public void on(SaleMadeEvent event) {
this.sale_id = event.getId();
}
}
`
The SaleAPI:
`
package org.softech.flexbet.query;
import org.axonframework.commandhandling.gateway.CommandGateway;
import org.softech.flexbet.aggregates.MakeSaleCommand;
import org.springframework.web.bind.annotation.*;
import java.sql.Timestamp;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@RestController
public class SaleAPI {
private final SaleAggregrateRepository repository;
private final CommandGateway commandGateway;
// @Autowired
public SaleAPI(SaleAggregrateRepository repository, CommandGateway commandGateway){
this.repository = repository;
this.commandGateway = commandGateway;
}
@PostMapping
public void makeSale(@RequestBody Map<String,String> request){
String id = UUID.randomUUID().toString();
commandGateway.send(new MakeSaleCommand(id, request.get(“agent_id”), request.get(“product_id”),
Double.parseDouble(request.get(“product_price”)), Timestamp.valueOf(request.get(“sale_date_time”))));
}
@GetMapping
public List findAll(){
return repository.findAll();
}
@GetMapping("/{id}")
public SaleEntry findOne(@PathVariable(value = “id”,required = true)String id){
return repository.findOne(id);
}
}
`
ConfigurationClass:
`
`
package config;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import org.axonframework.common.transaction.TransactionManager;
import org.axonframework.common.caching.Cache;
import org.axonframework.eventsourcing.AggregateFactory;
import org.axonframework.eventsourcing.CachingEventSourcingRepository;
import org.axonframework.eventsourcing.EventCountSnapshotTriggerDefinition;
import org.axonframework.eventsourcing.Snapshotter;
import org.axonframework.eventsourcing.eventstore.EventStore;
import org.axonframework.spring.eventsourcing.SpringPrototypeAggregateFactory;
import org.softech.flexbet.aggregates.Sale;
import org.springframework.amqp.core.AmqpAdmin;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Exchange;
import org.springframework.amqp.core.ExchangeBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.QueueBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.axonframework.commandhandling.model.Repository;
import org.axonframework.common.caching.WeakReferenceCache;
import org.axonframework.common.lock.PessimisticLockFactory;
import org.axonframework.eventsourcing.GenericAggregateFactory;
import org.axonframework.eventsourcing.SnapshotTriggerDefinition;
import org.axonframework.messaging.annotation.ParameterResolverFactory;
import org.axonframework.spring.eventsourcing.SpringAggregateSnapshotter;
import org.springframework.cache.annotation.EnableCaching;
@Configuration
@EnableCaching
public class SaleConfig {
@Autowired
public void configure(AmqpAdmin admin) {
admin.declareExchange(exchange());
admin.declareQueue(queue());
admin.declareBinding(binding());
}
@Bean
public Exchange exchange() {
return ExchangeBuilder.fanoutExchange(“SaleEvents”).build();
}
@Bean
public Queue queue() {
return QueueBuilder.durable(“SaleEvents”).build();
}
@Bean
public Binding binding() {
return BindingBuilder.bind(queue()).to(exchange()).with("*").noargs();
}
@Bean
public AggregateFactory saleAggregateFactory() {
SpringPrototypeAggregateFactory aggregateFactory = new SpringPrototypeAggregateFactory<>();
aggregateFactory.setPrototypeBeanName(“sale”);
return aggregateFactory;
}
@Bean
public Cache cache(){
return new WeakReferenceCache();
}
@Bean
public SpringAggregateSnapshotter snapshotter(ParameterResolverFactory parameterResolverFactory, EventStore eventStore, TransactionManager transactionManager) {
Executor executor = Executors.newSingleThreadExecutor(); //Or any other executor of course
return new SpringAggregateSnapshotter(eventStore, parameterResolverFactory, executor, transactionManager);
}
@Bean
public SnapshotTriggerDefinition snapshotTriggerDefinition(Snapshotter snapshotter) throws Exception {
return new EventCountSnapshotTriggerDefinition(snapshotter, 3);
}
@Bean
public Repository SaleAggregateRepository(EventStore eventStore, SnapshotTriggerDefinition snapshotTriggerDefinition, Cache cache, ParameterResolverFactory parameterResolverFactory) {
return new CachingEventSourcingRepository<>(new GenericAggregateFactory<>(Sale.class), eventStore, new PessimisticLockFactory(), cache, parameterResolverFactory, snapshotTriggerDefinition);
}
}
`
`