Hello, i’m using axon 4.0.3 + Spring Boot 2 default configuration.
Having published event to the EventStore and waiting for it to be catched by @SagaEventHandler I received the following exception:
javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process ‘persist’ call
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:292) ~[spring-orm-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at com.sun.proxy.$Proxy104.persist(Unknown Source) ~[na:na]
at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184) ~[na:1.8.0_191]
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) ~[na:1.8.0_191]
at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1382) ~[na:1.8.0_191]
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481) ~[na:1.8.0_191]
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) ~[na:1.8.0_191]
at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151) ~[na:1.8.0_191]
at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174) ~[na:1.8.0_191]
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:1.8.0_191]
at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418) ~[na:1.8.0_191]
at org.axonframework.eventsourcing.eventstore.jpa.JpaEventStorageEngine.appendEvents(JpaEventStorageEngine.java:276) ~[axon-eventsourcing-4.0.3.jar:4.0.3]
at org.axonframework.eventsourcing.eventstore.AbstractEventStorageEngine.appendEvents(AbstractEventStorageEngine.java:98) ~[axon-eventsourcing-4.0.3.jar:4.0.3]
What additional configuration is required for the EventStore to handle this case.
PS. Adding @Transactional on the method solves this problem, but i dont understand why this is neccessary.
My code (the following endpoint 127.0.0.1:8080/1 is worked but the other one 127.0.0.1:8080/1 is not)
@SpringBootApplication
class TestAxonApplication
class UserId(val userId: String = IdentifierFactory.getInstance().generateIdentifier()) : Serializable
class TestCommand(@TargetAggregateIdentifier val userId: UserId)
class TestedEvent(val userId: UserId)
fun main(args: Array<String>) {
runApplication<TestAxonApplication>(*args)
}
@RestController
@RequestMapping
class Controller(var commandGateway: CommandGateway, var eventStore: EventStore) {
@GetMapping("/1")
fun done(): UserId? {
return commandGateway.sendAndWait<UserId>(TestCommand(UserId()))
}
@GetMapping("/2")
fun failure() {
eventStore.publish(
GenericEventMessage.asEventMessage<Void>(
TestedEvent(UserId())
)
)
}
}
@Aggregate
class User() {
@AggregateIdentifier
private lateinit var userId: UserId
@CommandHandler
constructor(cmd: TestCommand) : this() {
AggregateLifecycle.apply(TestedEvent(cmd.userId))
}
@EventHandler
fun on(event: TestedEvent) {
this.userId = event.userId
}
}
@Saga
@ProcessingGroup("mySaga")
class MySaga {
@StartSaga
@SagaEventHandler(associationProperty = "userId")
fun start(event: TestedEvent) {
println("DONE ${event.userId.userId}")
}
}