Bads
Bads

Reputation: 774

Axon Server Command does not contain routing key

I am trying to migrate my application to Axon 4.0 with Axon server. Here is my code.

data class CreateTravelProductCommand(
    @TargetAggregateIdentifier val id: String,
    val productCreator: String
)

val id: String = ObjectId.get().toString()
val command = CreateTravelProductCommand(id=id, productCreator=request.creator)
commandGateway.sendAndWait(command)

But I got this error with my command.

org.axonframework.commandhandling.distributed.CommandDispatchException: The command [com.sunday.api.product.CreateTravelProductCommand] does not contain a routing key. at org.axonframework.commandhandling.distributed.AbstractRoutingStrategy.getRoutingKey(AbstractRoutingStrategy.java:57) ~[axon-messaging-4.0.jar:4.0] at org.axonframework.axonserver.connector.command.AxonServerCommandBus.dispatch(AxonServerCommandBus.java:114) ~[axon-server-connector-4.0.jar:4.0] at org.axonframework.commandhandling.gateway.AbstractCommandGateway.send(AbstractCommandGateway.java:75) [axon-messaging-4.0.jar:4.0] at org.axonframework.commandhandling.gateway.DefaultCommandGateway.send(DefaultCommandGateway.java:78) [axon-messaging-4.0.jar:4.0] at org.axonframework.commandhandling.gateway.DefaultCommandGateway.sendAndWait(DefaultCommandGateway.java:96) [axon-messaging-4.0.jar:4.0] at com.sunday.underwriting.product.ProductHandler.sendCreateProductCommand(ProductHandler.kt:40) [classes/:na] at com.sunday.underwriting.product.ProductHandler.access$sendCreateProductCommand(ProductHandler.kt:33) [classes/:na] at com.sunday.underwriting.product.ProductHandler$createProduct$product$1.invoke(ProductHandler.kt:97) [classes/:na] at com.sunday.underwriting.product.ProductHandler$createProduct$product$1.invoke(ProductHandler.kt:33) [classes/:na] at com.sunday.underwriting.product.ProductHandler$sam$java_util_function_Function$0.apply(ProductHandler.kt) [classes/:na] at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:100) [reactor-core-3.2.2.RELEASE.jar:3.2.2.RELEASE] at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onNext(FluxOnErrorResume.java:73) [reactor-core-3.2.2.RELEASE.jar:3.2.2.RELEASE] at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1476) [reactor-core-3.2.2.RELEASE.jar:3.2.2.RELEASE] at reactor.core.publisher.MonoSingle$SingleSubscriber.onComplete(MonoSingle.java:171) [reactor-core-3.2.2.RELEASE.jar:3.2.2.RELEASE] at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:136) [reactor-core-3.2.2.RELEASE.jar:3.2.2.RELEASE] at reactor.core.publisher.FluxFlatMap$FlatMapMain.checkTerminated(FluxFlatMap.java:794) [reactor-core-3.2.2.RELEASE.jar:3.2.2.RELEASE] at reactor.core.publisher.FluxFlatMap$FlatMapMain.drainLoop(FluxFlatMap.java:560) [reactor-core-3.2.2.RELEASE.jar:3.2.2.RELEASE] at reactor.core.publisher.FluxFlatMap$FlatMapMain.drain(FluxFlatMap.java:540) [reactor-core-3.2.2.RELEASE.jar:3.2.2.RELEASE] at reactor.core.publisher.FluxFlatMap$FlatMapMain.onComplete(FluxFlatMap.java:426) [reactor-core-3.2.2.RELEASE.jar:3.2.2.RELEASE] at reactor.core.publisher.DrainUtils.postCompleteDrain(DrainUtils.java:131) [reactor-core-3.2.2.RELEASE.jar:3.2.2.RELEASE] at reactor.core.publisher.DrainUtils.postComplete(DrainUtils.java:186) [reactor-core-3.2.2.RELEASE.jar:3.2.2.RELEASE] at reactor.core.publisher.FluxMapSignal$FluxMapSignalSubscriber.onComplete(FluxMapSignal.java:213) [reactor-core-3.2.2.RELEASE.jar:3.2.2.RELEASE] at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:136) [reactor-core-3.2.2.RELEASE.jar:3.2.2.RELEASE] at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:252) [reactor-core-3.2.2.RELEASE.jar:3.2.2.RELEASE] at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:136) [reactor-core-3.2.2.RELEASE.jar:3.2.2.RELEASE] at reactor.netty.channel.FluxReceive.terminateReceiver(FluxReceive.java:378) [reactor-netty-0.8.2.RELEASE.jar:0.8.2.RELEASE] at reactor.netty.channel.FluxReceive.drainReceiver(FluxReceive.java:202) [reactor-netty-0.8.2.RELEASE.jar:0.8.2.RELEASE] at reactor.netty.channel.FluxReceive.onInboundComplete(FluxReceive.java:343) [reactor-netty-0.8.2.RELEASE.jar:0.8.2.RELEASE] at reactor.netty.channel.ChannelOperations.onInboundComplete(ChannelOperations.java:325) [reactor-netty-0.8.2.RELEASE.jar:0.8.2.RELEASE] at reactor.netty.http.server.HttpServerOperations.onInboundNext(HttpServerOperations.java:442) [reactor-netty-0.8.2.RELEASE.jar:0.8.2.RELEASE] at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:141) [reactor-netty-0.8.2.RELEASE.jar:0.8.2.RELEASE] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) [netty-transport-4.1.29.Final.jar:4.1.29.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) [netty-transport-4.1.29.Final.jar:4.1.29.Final] at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) [netty-transport-4.1.29.Final.jar:4.1.29.Final] at reactor.netty.http.server.HttpTrafficHandler.channelRead(HttpTrafficHandler.java:188) [reactor-netty-0.8.2.RELEASE.jar:0.8.2.RELEASE] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) [netty-transport-4.1.29.Final.jar:4.1.29.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) [netty-transport-4.1.29.Final.jar:4.1.29.Final] at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) [netty-transport-4.1.29.Final.jar:4.1.29.Final] at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:438) [netty-transport-4.1.29.Final.jar:4.1.29.Final] at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:310) [netty-codec-4.1.29.Final.jar:4.1.29.Final] at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:284) [netty-codec-4.1.29.Final.jar:4.1.29.Final] at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:253) [netty-transport-4.1.29.Final.jar:4.1.29.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) [netty-transport-4.1.29.Final.jar:4.1.29.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) [netty-transport-4.1.29.Final.jar:4.1.29.Final] at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) [netty-transport-4.1.29.Final.jar:4.1.29.Final] at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1434) [netty-transport-4.1.29.Final.jar:4.1.29.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) [netty-transport-4.1.29.Final.jar:4.1.29.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) [netty-transport-4.1.29.Final.jar:4.1.29.Final] at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:965) [netty-transport-4.1.29.Final.jar:4.1.29.Final] at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163) [netty-transport-4.1.29.Final.jar:4.1.29.Final] at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:628) [netty-transport-4.1.29.Final.jar:4.1.29.Final] at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:563) [netty-transport-4.1.29.Final.jar:4.1.29.Final] at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:480) [netty-transport-4.1.29.Final.jar:4.1.29.Final] at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:442) [netty-transport-4.1.29.Final.jar:4.1.29.Final] at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:884) [netty-common-4.1.29.Final.jar:4.1.29.Final] at java.lang.Thread.run(Thread.java:748) [na:1.8.0_172]

Edit:

I just found out that if you keep the class in the same project, it is ok.

The problem is when you import the class from another project (Which used to work prior to axon server)

For example:

My project has dependencies of another project called api.

dependencies {
    compile project(':api')
}

If the class is declared in the api project, axon server library will throw error that it cannot find routing key. But if the class is declared in the main project it self, it works as expected. I think I should file this issue on github.

Upvotes: 1

Views: 1737

Answers (3)

jorrocks
jorrocks

Reputation: 181

I got the same problem when migrating from Axon 3.x to 4.0. The solution was related to the @TargetAggregateIdentifier - I was missing it off the 'CreateXXXCommand' that's handled by my aggregate. I'm pretty sure that adding @TargetAggregateIdentifier wasn't necessary for create commands (since it doesn't have to locate an existing aggregate) in Axon 3.x

At time of writing the Migration guide is incomplete https://docs.axoniq.io/reference-guide/3-migration/migration-guide

Upvotes: 2

Bads
Bads

Reputation: 774

The real issue is version mismatched between 2 projects. I had to correct version but intellij autoloader didn't work and the api project had the incorrect version.

I apologize for my stupidity

Upvotes: 1

Allard
Allard

Reputation: 2890

This is actually more related to Kotlin than Axon. Axon expects them on the Field or Getter method. Apparently, that's not where Kotlin places them be default.

Check out https://kotlinlang.org/docs/reference/annotations.html#annotation-use-site-targets

You probably need to annotate the property with @get:TargetAggregateIdentifier

Upvotes: 0

Related Questions