Skip to content

Configuration of Axon Server with JPA throwing error #15

@andrewtacchi2

Description

@andrewtacchi2

Trying out AF5 university demo Spring Boot branch and I've tried to update it to use a JPA data store for the projector/read model with correspondent TokenStore, just against a H2 database, but get errors even with the most basic setup I could configure.

Not sure if this is how I'm setting it up and needs an exmaple/documentation on how to configure AxonServer with JPA read models or a possible bug, so adding it here just in case it is more than a picnic error.

I get the following exception thrown

java.util.concurrent.CompletionException: java.lang.IllegalStateException: No value for key [HikariDataSource (HikariPool-1)] bound to thread
at java.base/java.util.concurrent.CompletableFuture.encodeRelay(CompletableFuture.java:368) ~[na:na]

My expectation was that just plugging JPA would work, but not sure this is correct.

My modified UniversitySpringBootAxonApplication to setup the TokenStore (based on the AutoJPAConfiguration spring auto config)

package io.axoniq.demo.university;

import io.axoniq.demo.university.faculty.write.classic.EnrollStudent;
import io.axoniq.demo.university.faculty.write.createcourse.CreateCourse;
import io.axoniq.demo.university.faculty.write.renamecourse.RenameCourse;
import io.axoniq.demo.university.shared.application.notifier.NotificationService;
import io.axoniq.demo.university.shared.ids.CourseId;
import io.axoniq.demo.university.shared.ids.StudentId;
import io.axoniq.demo.university.shared.infrastructure.notifier.LoggingNotificationService;
import org.axonframework.commandhandling.gateway.CommandGateway;
import org.axonframework.common.jpa.EntityManagerProvider;
import org.axonframework.common.transaction.TransactionManager;
import org.axonframework.configuration.ComponentRegistry;
import org.axonframework.eventhandling.processors.streaming.token.store.TokenStore;
import org.axonframework.eventhandling.processors.streaming.token.store.inmemory.InMemoryTokenStore;
import org.axonframework.eventhandling.processors.streaming.token.store.jpa.JpaTokenStore;
import org.axonframework.eventhandling.processors.streaming.token.store.jpa.JpaTokenStoreConfiguration;
import org.axonframework.extension.spring.config.SpringComponentRegistry;
import org.axonframework.extension.spring.messaging.unitofwork.SpringTransactionManager;
import org.axonframework.extension.springboot.TokenStoreProperties;
import org.axonframework.extension.springboot.util.RegisterDefaultEntities;
import org.axonframework.extension.springboot.util.jpa.ContainerManagedEntityManagerProvider;
import org.axonframework.serialization.json.JacksonConverter;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;

import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.logging.Level;
import java.util.logging.Logger;

@SpringBootApplication
@EnableConfigurationProperties(TokenStoreProperties.class)
@RegisterDefaultEntities(packages = {
        "org.axonframework.eventhandling.processors.streaming.token.store.jpa"
})
public class UniversitySpringBootAxonApplication {
	public static void main(String[] args) {
		SpringApplication.run(UniversitySpringBootAxonApplication.class, args);
	}

	@Bean
	public NotificationService notificationService() {
		return new LoggingNotificationService();
	}

//	@Bean
//	public TokenStore tokenStore() {
//		return new InMemoryTokenStore();
//	}

	@Bean
	EntityManagerProvider entityManagerProvider() {
		return new ContainerManagedEntityManagerProvider();
	}

	@Bean
	TokenStore tokenStore(
			EntityManagerProvider entityManagerProvider,
			TokenStoreProperties tokenStoreProperties,
			ObjectMapper defaultAxonObjectMapper) {
		var config = JpaTokenStoreConfiguration.DEFAULT.claimTimeout(tokenStoreProperties.getClaimTimeout());
		var converter = new JacksonConverter(defaultAxonObjectMapper);
		JpaTokenStore tokenStore = new JpaTokenStore(entityManagerProvider, converter, config);

		return tokenStore;
	}

	@Bean
	TransactionManager axonTransactionManager(PlatformTransactionManager transactionManager) {
		return new SpringTransactionManager(transactionManager);
	}

	@Component
	static class MySampleApplicationRunner implements ApplicationRunner {

		private final Logger logger = Logger.getLogger(this.getClass().getName());

		private final ComponentRegistry componentRegistry;

		MySampleApplicationRunner(ComponentRegistry componentRegistry) {
			this.componentRegistry = componentRegistry;
		}

		@Override
		public void run(ApplicationArguments args) throws Exception {
			try {
				var courseId = CourseId.random();
				var createCourse = new CreateCourse(courseId, "Event Sourcing in Practice", 3);
				var renameCourse = new RenameCourse(courseId, "Advanced Event Sourcing");
				var studentId = StudentId.random();
				var enrollStudent = new EnrollStudent(studentId, "Kermit", "The Frog");
				var commandGateway = ((SpringComponentRegistry) this.componentRegistry).configuration()
						.getComponent(CommandGateway.class);

				commandGateway.sendAndWait(createCourse);
				commandGateway.sendAndWait(renameCourse);
				commandGateway.sendAndWait(enrollStudent);
				logger.info("Successfully executed sample commands");
			} catch (Exception e) {
				logger.log(Level.SEVERE, "Error while executing sample commands: " + e.getMessage(), e);
			}
		}
	}
}

Updated the pom to include this

	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-data-jpa</artifactId>
	</dependency>
	<dependency>
		<groupId>com.h2database</groupId>
		<artifactId>h2</artifactId>
		<scope>runtime</scope>
	</dependency>

application.properties added with

spring.datasource.url=jdbc:h2:file:~/testdb
spring.datasource.username=sa
spring.jpa.hibernate.ddl-auto=update
spring.h2.console.enabled=true

Full stack trace below:
java.util.concurrent.CompletionException: java.lang.IllegalStateException: No value for key [HikariDataSource (HikariPool-1)] bound to thread
at java.base/java.util.concurrent.CompletableFuture.encodeRelay(CompletableFuture.java:368) ~[na:na]
at java.base/java.util.concurrent.CompletableFuture.uniComposeExceptionallyStage(CompletableFuture.java:1076) ~[na:na]
at java.base/java.util.concurrent.CompletableFuture.exceptionallyCompose(CompletableFuture.java:2411) ~[na:na]
at org.axonframework.messaging.unitofwork.UnitOfWork$UnitOfWorkProcessingContext.lambda$safe$2(UnitOfWork.java:274) ~[axon-messaging-5.0.0-SNAPSHOT.jar:5.0.0-SNAPSHOT]
at org.axonframework.messaging.unitofwork.UnitOfWork$UnitOfWorkProcessingContext.lambda$runNextPhase$8(UnitOfWork.java:409) ~[axon-messaging-5.0.0-SNAPSHOT.jar:5.0.0-SNAPSHOT]
at java.base/java.util.concurrent.CompletableFuture$UniCompose.tryFire(CompletableFuture.java:1150) ~[na:na]
at java.base/java.util.concurrent.CompletableFuture$Completion.run(CompletableFuture.java:482) ~[na:na]
at org.axonframework.common.DirectExecutor.execute(DirectExecutor.java:54) ~[axon-messaging-5.0.0-SNAPSHOT.jar:5.0.0-SNAPSHOT]
at java.base/java.util.concurrent.CompletableFuture.uniComposeStage(CompletableFuture.java:1184) ~[na:na]
at java.base/java.util.concurrent.CompletableFuture.thenComposeAsync(CompletableFuture.java:2352) ~[na:na]
at org.axonframework.messaging.unitofwork.UnitOfWork$UnitOfWorkProcessingContext.lambda$runNextPhase$9(UnitOfWork.java:409) ~[axon-messaging-5.0.0-SNAPSHOT.jar:5.0.0-SNAPSHOT]
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197) ~[na:na]
at java.base/java.util.concurrent.ConcurrentLinkedQueue.forEachFrom(ConcurrentLinkedQueue.java:1037) ~[na:na]
at java.base/java.util.concurrent.ConcurrentLinkedQueue$CLQSpliterator.forEachRemaining(ConcurrentLinkedQueue.java:894) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) ~[na:na]
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na]
at java.base/java.util.stream.ReferencePipeline.reduce(ReferencePipeline.java:662) ~[na:na]
at org.axonframework.messaging.unitofwork.UnitOfWork$UnitOfWorkProcessingContext.runNextPhase(UnitOfWork.java:411) ~[axon-messaging-5.0.0-SNAPSHOT.jar:5.0.0-SNAPSHOT]
at org.axonframework.messaging.unitofwork.UnitOfWork$UnitOfWorkProcessingContext.executeAllPhaseHandlers(UnitOfWork.java:359) ~[axon-messaging-5.0.0-SNAPSHOT.jar:5.0.0-SNAPSHOT]
at org.axonframework.messaging.unitofwork.UnitOfWork$UnitOfWorkProcessingContext.lambda$executeAllPhaseHandlers$5(UnitOfWork.java:362) ~[axon-messaging-5.0.0-SNAPSHOT.jar:5.0.0-SNAPSHOT]
at java.base/java.util.concurrent.CompletableFuture$UniCompose.tryFire(CompletableFuture.java:1150) ~[na:na]
at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510) ~[na:na]
at java.base/java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:2179) ~[na:na]
at org.axonframework.messaging.MessageStreamUtils$FirstResult.lambda$process$0(MessageStreamUtils.java:159) ~[axon-messaging-5.0.0-SNAPSHOT.jar:5.0.0-SNAPSHOT]
at java.base/java.util.Optional.ifPresentOrElse(Optional.java:198) ~[na:na]
at org.axonframework.messaging.MessageStreamUtils$FirstResult.process(MessageStreamUtils.java:158) ~[axon-messaging-5.0.0-SNAPSHOT.jar:5.0.0-SNAPSHOT]
at org.axonframework.messaging.EmptyMessageStream.onAvailable(EmptyMessageStream.java:63) ~[axon-messaging-5.0.0-SNAPSHOT.jar:5.0.0-SNAPSHOT]
at org.axonframework.messaging.DelayedMessageStream.lambda$onAvailable$2(DelayedMessageStream.java:119) ~[axon-messaging-5.0.0-SNAPSHOT.jar:5.0.0-SNAPSHOT]
at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:863) ~[na:na]
at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:841) ~[na:na]
at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510) ~[na:na]
at java.base/java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:2179) ~[na:na]
at org.axonframework.messaging.MessageStreamUtils$Reducer.lambda$process$2(MessageStreamUtils.java:127) ~[axon-messaging-5.0.0-SNAPSHOT.jar:5.0.0-SNAPSHOT]
at java.base/java.util.Optional.ifPresentOrElse(Optional.java:198) ~[na:na]
at org.axonframework.messaging.MessageStreamUtils$Reducer.process(MessageStreamUtils.java:126) ~[axon-messaging-5.0.0-SNAPSHOT.jar:5.0.0-SNAPSHOT]
at io.axoniq.axonserver.connector.impl.AbstractBufferedStream.onCompleted(AbstractBufferedStream.java:95) ~[axonserver-connector-java-2025.2.0-EAP.jar:2025.2.0-EAP]
at io.grpc.stub.ClientCalls$StreamObserverToCallListenerAdapter.onClose(ClientCalls.java:479) ~[grpc-stub-1.69.0.jar:1.69.0]
at io.grpc.PartialForwardingClientCallListener.onClose(PartialForwardingClientCallListener.java:39) ~[grpc-api-1.69.0.jar:1.69.0]
at io.grpc.ForwardingClientCallListener.onClose(ForwardingClientCallListener.java:23) ~[grpc-api-1.69.0.jar:1.69.0]
at io.grpc.ForwardingClientCallListener$SimpleForwardingClientCallListener.onClose(ForwardingClientCallListener.java:40) ~[grpc-api-1.69.0.jar:1.69.0]
at io.grpc.internal.ClientCallImpl.closeObserver(ClientCallImpl.java:564) ~[grpc-core-1.69.0.jar:1.69.0]
at io.grpc.internal.ClientCallImpl.access$100(ClientCallImpl.java:72) ~[grpc-core-1.69.0.jar:1.69.0]
at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed.runInternal(ClientCallImpl.java:729) ~[grpc-core-1.69.0.jar:1.69.0]
at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed.runInContext(ClientCallImpl.java:710) ~[grpc-core-1.69.0.jar:1.69.0]
at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37) ~[grpc-core-1.69.0.jar:1.69.0]
at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:133) ~[grpc-core-1.69.0.jar:1.69.0]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) ~[na:na]
at java.base/java.lang.Thread.run(Thread.java:1583) ~[na:na]
Caused by: java.lang.IllegalStateException: No value for key [HikariDataSource (HikariPool-1)] bound to thread
at org.springframework.transaction.support.TransactionSynchronizationManager.unbindResource(TransactionSynchronizationManager.java:198) ~[spring-tx-6.2.11.jar:6.2.11]
at org.springframework.orm.jpa.JpaTransactionManager.doCleanupAfterCompletion(JpaTransactionManager.java:633) ~[spring-orm-6.2.11.jar:6.2.11]
at org.springframework.transaction.support.AbstractPlatformTransactionManager.cleanupAfterCompletion(AbstractPlatformTransactionManager.java:1062) ~[spring-tx-6.2.11.jar:6.2.11]
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:847) ~[spring-tx-6.2.11.jar:6.2.11]
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:758) ~[spring-tx-6.2.11.jar:6.2.11]
at org.axonframework.extension.spring.messaging.unitofwork.SpringTransactionManager.commitTransaction(SpringTransactionManager.java:86) ~[axon-spring-5.0.0-SNAPSHOT.jar:5.0.0-SNAPSHOT]
at org.axonframework.extension.spring.messaging.unitofwork.SpringTransactionManager$1.commit(SpringTransactionManager.java:69) ~[axon-spring-5.0.0-SNAPSHOT.jar:5.0.0-SNAPSHOT]
at org.axonframework.messaging.unitofwork.TransactionalUnitOfWorkFactory.lambda$create$1(TransactionalUnitOfWorkFactory.java:88) ~[axon-messaging-5.0.0-SNAPSHOT.jar:5.0.0-SNAPSHOT]
at org.axonframework.messaging.unitofwork.ProcessingLifecycle.lambda$runOn$0(ProcessingLifecycle.java:91) ~[axon-messaging-5.0.0-SNAPSHOT.jar:5.0.0-SNAPSHOT]
at org.axonframework.messaging.unitofwork.UnitOfWork$UnitOfWorkProcessingContext.lambda$safe$2(UnitOfWork.java:269) ~[axon-messaging-5.0.0-SNAPSHOT.jar:5.0.0-SNAPSHOT]
... 47 common frames omitted

Metadata

Metadata

Labels

Status: Information RequiredUse to signal this issue is waiting for information to be provided in the issue's description.

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions