Hi there,
For some background, I’m playing around with Axon Framework 4.0 + Spring Boot + JPA/Hibernate. To the best of my understanding, java.util.UUIDs
should be a supported type for an @AggregateIdentifier
. However, when using UUID as the identifier, there appears to be an issue fetching the JPA entity associated with the aggregate:
`
2018-10-21 23:42:31.756 INFO 87606 — [mmandReceiver-4] o.a.a.c.command.AxonServerCommandBus : DispatchLocal: failure n.s.o.l.commands.CompleteProjectCommand - Provided id of the wrong type for class n.s.o.l.domain.Project. Expected: class java.util.UUID, got class java.lang.String
java.lang.IllegalArgumentException: Provided id of the wrong type for class n.s.o.l.domain.Project. Expected: class java.util.UUID, got class java.lang.String
at org.hibernate.internal.SessionImpl.find(SessionImpl.java:3466) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.internal.SessionImpl.find(SessionImpl.java:3419) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_181]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_181]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_181]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_181]
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:305) ~[spring-orm-5.0.10.RELEASE.jar:5.0.10.RELEASE]
at com.sun.proxy.$Proxy130.find(Unknown Source) ~[na:na]
at org.axonframework.modelling.command.GenericJpaRepository.doLoadWithLock(GenericJpaRepository.java:110) ~[axon-modelling-4.0.jar:4.0]
at org.axonframework.modelling.command.GenericJpaRepository.doLoadWithLock(GenericJpaRepository.java:53) ~[axon-modelling-4.0.jar:4.0]
at org.axonframework.modelling.command.LockingRepository.doLoad(LockingRepository.java:118) ~[axon-modelling-4.0.jar:4.0]
at org.axonframework.modelling.command.LockingRepository.doLoad(LockingRepository.java:52) ~[axon-modelling-4.0.jar:4.0]
at org.axonframework.modelling.command.AbstractRepository.lambda$load$4(AbstractRepository.java:116) ~[axon-modelling-4.0.jar:4.0]
at java.util.HashMap.computeIfAbsent(HashMap.java:1127) ~[na:1.8.0_181]
at org.axonframework.modelling.command.AbstractRepository.load(AbstractRepository.java:115) ~[axon-modelling-4.0.jar:4.0]
at org.axonframework.modelling.command.AggregateAnnotationCommandHandler$AggregateCommandHandler.handle(AggregateAnnotationCommandHandler.java:364) ~[axon-modelling-4.0.jar:4.0]
at org.axonframework.modelling.command.AggregateAnnotationCommandHandler$AggregateCommandHandler.handle(AggregateAnnotationCommandHandler.java:352) ~[axon-modelling-4.0.jar:4.0]
at org.axonframework.modelling.command.AggregateAnnotationCommandHandler.handle(AggregateAnnotationCommandHandler.java:140) ~[axon-modelling-4.0.jar:4.0]
at org.axonframework.modelling.command.AggregateAnnotationCommandHandler.handle(AggregateAnnotationCommandHandler.java:53) ~[axon-modelling-4.0.jar:4.0]
at org.axonframework.messaging.DefaultInterceptorChain.proceed(DefaultInterceptorChain.java:57) ~[axon-messaging-4.0.jar:4.0]
at org.axonframework.messaging.interceptors.CorrelationDataInterceptor.handle(CorrelationDataInterceptor.java:65) ~[axon-messaging-4.0.jar:4.0]
at org.axonframework.messaging.DefaultInterceptorChain.proceed(DefaultInterceptorChain.java:55) ~[axon-messaging-4.0.jar:4.0]
at org.axonframework.messaging.unitofwork.DefaultUnitOfWork.executeWithResult(DefaultUnitOfWork.java:74) ~[axon-messaging-4.0.jar:4.0]
at org.axonframework.commandhandling.SimpleCommandBus.handle(SimpleCommandBus.java:176) [axon-messaging-4.0.jar:4.0]
at org.axonframework.commandhandling.SimpleCommandBus.doDispatch(SimpleCommandBus.java:141) [axon-messaging-4.0.jar:4.0]
at org.axonframework.commandhandling.SimpleCommandBus.dispatch(SimpleCommandBus.java:110) [axon-messaging-4.0.jar:4.0]
at org.axonframework.axonserver.connector.command.AxonServerCommandBus$CommandRouterSubscriber.dispatchLocal(AxonServerCommandBus.java:365) ~[axon-server-connector-4.0.jar:4.0]
at org.axonframework.axonserver.connector.command.AxonServerCommandBus$CommandRouterSubscriber.processCommand(AxonServerCommandBus.java:276) ~[axon-server-connector-4.0.jar:4.0]
at org.axonframework.axonserver.connector.command.AxonServerCommandBus$CommandRouterSubscriber.commandExecutor(AxonServerCommandBus.java:223) ~[axon-server-connector-4.0.jar:4.0]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[na:1.8.0_181]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_181]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_181]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_181]
at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_181]
Caused by: org.hibernate.TypeMismatchException: Provided id of the wrong type for class net.spantree.os.ledger.domain.Project. Expected: class java.util.UUID, got class java.lang.String
at org.hibernate.event.internal.DefaultLoadEventListener.checkIdClass(DefaultLoadEventListener.java:166) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:86) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1240) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.internal.SessionImpl.access$1900(SessionImpl.java:204) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.doLoad(SessionImpl.java:2835) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.load(SessionImpl.java:2816) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.internal.SessionImpl.find(SessionImpl.java:3445) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
… 33 common frames omitted
`
Steps to reproduce
- Checkout this project: https://gitlab.spantree.net/divideby0/axoniq-uuid-example
- Run
docker-compose up -d
- Run
./gradlew test --tests ProjectIntegrationTest
For convenience, this is the part of the test that is failing with the error:
From what I can tell, Axon’s DefaultJpaRepository
looks up all aggregate entities via the find
method of the JPA EntityManager
:
However, it doesn’t seem to introspect the aggregate type to determine if it needs to convert the command’s VersionedAggregateIdentifier
to its native value:
Even if the @AggregateIdentifier
is some other type, the VersionedAggregateIdentifier
will always be a String:
I noticed there was a identifierConverter
function passed into the builder of the DefaultJpaRepository
, but it appears to be hardcoded to the identity function which just returns the incoming argument:
What’s the best way to handle this in Axon 4.0? Are there ways of overriding the identifierConverter
for specific aggregate repositories?