Hi,
i am trying to make something eventually stupid work.
It is meant to be an example for a state-stored aggregate, see https://docs.axoniq.io/reference-guide/implementing-domain-logic/command-handling/state-stored-aggregates.
The example consists of an CartAggregate marked as @Entity, backed by a @MappedSuperClass Cart, which again is linked by @OneToMany to a list of CartEntry.
I am using mysql as storage for events and aggregates.
Server startup will be fine, also first command-receival is working without issue. At this moment the list of CartEntry is empty.
But as soon as CartEntry contains at least one item i start getting:
javax.persistence.PersistenceException: org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions. Collection :
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:154)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:188)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:807)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:785)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:350)
at com.sun.proxy.$Proxy143.persist(Unknown Source)
at org.axonframework.modelling.command.GenericJpaRepository.doSaveWithLock(GenericJpaRepository.java:143)
at org.axonframework.modelling.command.GenericJpaRepository.doSaveWithLock(GenericJpaRepository.java:53)
at org.axonframework.modelling.command.LockingRepository.doSave(LockingRepository.java:149)
at org.axonframework.modelling.command.LockingRepository.doSave(LockingRepository.java:52)
at org.axonframework.modelling.command.AbstractRepository.doCommit(AbstractRepository.java:194)
at org.axonframework.modelling.command.AbstractRepository.prepareForCommit(AbstractRepository.java:180)
at org.axonframework.modelling.command.LockingRepository.prepareForCommit(LockingRepository.java:131)
at org.axonframework.modelling.command.LockingRepository.prepareForCommit(LockingRepository.java:52)
at org.axonframework.modelling.command.AbstractRepository.lambda$newInstance$0(AbstractRepository.java:86)
at org.axonframework.messaging.unitofwork.MessageProcessingContext.notifyHandlers(MessageProcessingContext.java:71)
at org.axonframework.messaging.unitofwork.DefaultUnitOfWork.notifyHandlers(DefaultUnitOfWork.java:106)
at org.axonframework.messaging.unitofwork.AbstractUnitOfWork.changePhase(AbstractUnitOfWork.java:222)
at org.axonframework.messaging.unitofwork.AbstractUnitOfWork.commitAsRoot(AbstractUnitOfWork.java:83)
at org.axonframework.messaging.unitofwork.AbstractUnitOfWork.commit(AbstractUnitOfWork.java:71)
at org.axonframework.messaging.unitofwork.DefaultUnitOfWork.executeWithResult(DefaultUnitOfWork.java:92)
at org.axonframework.commandhandling.SimpleCommandBus.handle(SimpleCommandBus.java:176)
at org.axonframework.commandhandling.SimpleCommandBus.doDispatch(SimpleCommandBus.java:141)
at org.axonframework.commandhandling.SimpleCommandBus.dispatch(SimpleCommandBus.java:110)
at org.axonframework.commandhandling.gateway.AbstractCommandGateway.send(AbstractCommandGateway.java:75)
at org.axonframework.commandhandling.gateway.DefaultCommandGateway.send(DefaultCommandGateway.java:73)
at org.axonframework.commandhandling.gateway.DefaultCommandGateway.sendAndWait(DefaultCommandGateway.java:90)
at com.lidl.mindshift.otc.commons.orchestration.CheckoutSagaTest.given_a_cart_when_cart_update_then_cart_updated(CheckoutSagaTest.java:80)
Spring Boot Config like this:
@Configuration
public class AxonConfig {
@Bean
public ObjectMapper objectMapper() {
final ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new MoneyModule());
return objectMapper;
}
@Bean
public CommandBus commandBus(TransactionManager transactionManager, AxonConfiguration axonConfiguration) {
SimpleCommandBus commandBus = SimpleCommandBus.builder()
.transactionManager(transactionManager)
.messageMonitor(axonConfiguration.messageMonitor(CommandBus.class, "commandBus"))
.build();
commandBus.registerHandlerInterceptor(
new CorrelationDataInterceptor<>(axonConfiguration.correlationDataProviders()));
return commandBus;
}
// https://docs.axoniq.io/reference-guide/configuring-infrastructure-components/event-processing/event-bus-and-event-store
// https://github.com/holisticon/axon-cdi/issues/13
// https://github.com/alexmacavei/cqrs-example/blob/master/src/main/java/ro/chronos/cqrsexample/config/AxonConfiguration.java
@PersistenceUnit
EntityManagerFactory entityManagerFactory;
@Bean
public EntityManagerProvider entityManagerProvider() {
return () -> entityManagerFactory.createEntityManager(SynchronizationType.SYNCHRONIZED);
}
@Bean
public EventStore eventStore(EventStorageEngine storageEngine, AxonConfiguration configuration) {
return EmbeddedEventStore.builder()
.storageEngine(storageEngine)
.messageMonitor(configuration.messageMonitor(EventStore.class, "eventStore"))
.build();
}
@Bean
public EventStorageEngine storageEngine(Serializer defaultSerializer,
DataSource dataSource,
@Qualifier("eventSerializer") Serializer eventSerializer,
AxonConfiguration configuration,
EntityManagerProvider entityManagerProvider,
TransactionManager transactionManager) throws SQLException {
return JpaEventStorageEngine.builder()
.snapshotSerializer(defaultSerializer)
.upcasterChain(configuration.upcasterChain())
.dataSource(dataSource)
.eventSerializer(eventSerializer)
.entityManagerProvider(entityManagerProvider)
.transactionManager(transactionManager)
.build();
}
}
If required i can provide some example on github, so far it might be i am overlooking something in the setup, where my persistence.xml looks like:
<persistence
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="2.1"
xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="default" transaction-type="RESOURCE_LOCAL">
<class>org.axonframework.eventsourcing.eventstore.jpa.DomainEventEntry</class>
<class>org.axonframework.eventsourcing.eventstore.jpa.SnapshotEventEntry</class>
<class>org.axonframework.modelling.saga.repository.jpa.AssociationValueEntry</class>
<class>org.axonframework.modelling.saga.repository.jpa.SagaEntry</class>
<class>com.lidl.mindshift.otc.commons.orchestration.cart.CartAggregate</class>
<class>com.lidl.mindshift.otc.commons.orchestration.cart.domain.CartEntry</class>
<properties>
<property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>
<property name="javax.persistence.schema-generation.create-source" value="metadata"/>
<property name="javax.persistence.schema-generation.drop-source" value="metadata"/>
</properties>
</persistence-unit>
</persistence>
Any kind of hints would be welcome.