0

I have an Axon Command which has an moneta Money object.

import lombok.Getter;
import lombok.ToString;
import lombok.experimental.SuperBuilder;
import org.javamoney.moneta.Money;

import java.time.LocalDate;
import java.util.UUID;

@Getter
@SuperBuilder
@ToString
public class MyAxonCommand {

    private final UUID id;

    private final Money hoogte;
    private final LocalDate opleggingsdatum;
}

The axon serializer is configured as Jackson in the application.yml with:

axon:
  serializer:
    general: default
    events: default
    messages: default

When i send this command with axon there is an exception.

   commandGateway.sendAndWait(myAxonCommand.builder()
        .id(new UUID(1, 1))   
        .hoogte(Money.of(0, "EUR"))
        .opleggingsdatum(LocalDate.now())
        .build());

The exception thrown is Caused by:

18:07:37.456 [main] INFO  org.javamoney.moneta.DefaultMonetaryContextFactory  - Using custom MathContext: precision=256, roundingMode=HALF_EVEN
18:07:37.465 [main] INFO  nl.ind.handhaving.adapter.messaging.incoming.IndigoListener kvk:987654321 zn:Z1-31190106952 - INDiGO bericht ontvangen op methode: receiveMaatregelOpgelegd
18:07:37.928 [docker-java-stream--1691755530] INFO  docker.axonserver  - STDOUT: 2023-01-18 17:07:37.925  WARN 1 --- [nio-8024-exec-3] A.i.a.a.rest.DevelopmentRestController   : [<anonymous>] Request to delete all events in context "default".
18:07:37.941 [EventProcessor[nl.ind.handhaving.application.query]-0] WARN  org.axonframework.eventhandling.TrackingEventProcessor  - Error occurred. Starting retry mode.
org.axonframework.axonserver.connector.AxonServerException: The Event Stream has been closed, so no further events can be retrieved
    at org.axonframework.axonserver.connector.event.axon.EventBuffer.peekNullable(EventBuffer.java:178)
    at org.axonframework.axonserver.connector.event.axon.EventBuffer.hasNextAvailable(EventBuffer.java:144)
    at org.axonframework.eventhandling.TrackingEventProcessor.processBatch(TrackingEventProcessor.java:401)
    at org.axonframework.eventhandling.TrackingEventProcessor.processingLoop(TrackingEventProcessor.java:300)
    at org.axonframework.eventhandling.TrackingEventProcessor$TrackingSegmentWorker.run(TrackingEventProcessor.java:1072)
    at org.axonframework.eventhandling.TrackingEventProcessor$WorkerLauncher.cleanUp(TrackingEventProcessor.java:1263)
    at org.axonframework.eventhandling.TrackingEventProcessor$WorkerLauncher.run(TrackingEventProcessor.java:1240)
    at java.base/java.lang.Thread.run(Thread.java:833)
18:07:37.942 [EventProcessor[nl.ind.handhaving.application.query]-0] WARN  org.axonframework.eventhandling.TrackingEventProcessor  - Releasing claim on token and preparing for retry in 1s
18:07:37.945 [EventProcessor[nl.ind.handhaving.application]-0] WARN  org.axonframework.eventhandling.TrackingEventProcessor  - Error occurred. Starting retry mode.
org.axonframework.axonserver.connector.AxonServerException: The Event Stream has been closed, so no further events can be retrieved
    at org.axonframework.axonserver.connector.event.axon.EventBuffer.peekNullable(EventBuffer.java:178)
    at org.axonframework.axonserver.connector.event.axon.EventBuffer.hasNextAvailable(EventBuffer.java:144)
    at org.axonframework.eventhandling.TrackingEventProcessor.processBatch(TrackingEventProcessor.java:401)
    at org.axonframework.eventhandling.TrackingEventProcessor.processingLoop(TrackingEventProcessor.java:300)
    at org.axonframework.eventhandling.TrackingEventProcessor$TrackingSegmentWorker.run(TrackingEventProcessor.java:1072)
    at org.axonframework.eventhandling.TrackingEventProcessor$WorkerLauncher.cleanUp(TrackingEventProcessor.java:1263)
    at org.axonframework.eventhandling.TrackingEventProcessor$WorkerLauncher.run(TrackingEventProcessor.java:1240)
    at java.base/java.lang.Thread.run(Thread.java:833)
18:07:37.945 [EventProcessor[nl.ind.handhaving.application]-0] WARN  org.axonframework.eventhandling.TrackingEventProcessor  - Releasing claim on token and preparing for retry in 1s
18:07:37.947 [EventProcessor[nl.ind.handhaving.application]-0] INFO  org.axonframework.eventhandling.TrackingEventProcessor  - Released claim
18:07:37.949 [EventProcessor[nl.ind.handhaving.application.query]-0] INFO  org.axonframework.eventhandling.TrackingEventProcessor  - Released claim

org.axonframework.commandhandling.CommandExecutionException: org.javamoney.moneta.spi.JDKCurrencyAdapter

    at org.axonframework.axonserver.connector.ErrorCode.lambda$static$11(ErrorCode.java:88)
    at org.axonframework.axonserver.connector.ErrorCode.convert(ErrorCode.java:182)
    at org.axonframework.axonserver.connector.command.CommandSerializer.deserialize(CommandSerializer.java:164)
    at org.axonframework.axonserver.connector.command.AxonServerCommandBus.lambda$doDispatch$1(AxonServerCommandBus.java:161)
    at java.base/java.util.concurrent.CompletableFuture$UniApply.tryFire(CompletableFuture.java:646)
    at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510)
    at java.base/java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:2147)
    at io.axoniq.axonserver.connector.command.impl.CommandChannelImpl$CommandResponseHandler.onNext(CommandChannelImpl.java:372)
    at io.axoniq.axonserver.connector.command.impl.CommandChannelImpl$CommandResponseHandler.onNext(CommandChannelImpl.java:359)
    at io.grpc.stub.ClientCalls$StreamObserverToCallListenerAdapter.onMessage(ClientCalls.java:466)
    at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1MessagesAvailable.runInternal(ClientCallImpl.java:661)
    at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1MessagesAvailable.runInContext(ClientCallImpl.java:646)
    at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37)
    at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:133)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
    at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: AxonServerRemoteCommandHandlingException{message=An exception was thrown by the remote message handling component: org.javamoney.moneta.spi.JDKCurrencyAdapter, errorCode='AXONIQ-4002', server='134589@xxxxxxxxx}
    at org.axonframework.axonserver.connector.ErrorCode.lambda$static$11(ErrorCode.java:86)
    ... 16 more}

The Axonserver logging - running in a docker :

2023-01-18T17:30:30.237808536Z      _                     ____
2023-01-18T17:30:30.237852159Z     / \   __  _____  _ __ / ___|  ___ _ ____   _____ _ __
2023-01-18T17:30:30.237857221Z    / _ \  \ \/ / _ \| '_ \\___ \ / _ \ '__\ \ / / _ \ '__|
2023-01-18T17:30:30.237861155Z   / ___ \  >  < (_) | | | |___) |  __/ |   \ V /  __/ |
2023-01-18T17:30:30.237864060Z  /_/   \_\/_/\_\___/|_| |_|____/ \___|_|    \_/ \___|_|
2023-01-18T17:30:30.237866979Z  Standard Edition                        Powered by AxonIQ
2023-01-18T17:30:30.237869529Z 
2023-01-18T17:30:30.237872060Z version: 4.5.16
2023-01-18T17:30:30.326181167Z 2023-01-18 17:30:30.321  INFO 1 --- [           main] io.axoniq.axonserver.AxonServer          : Starting AxonServer using Java 11.0.14 on c32eb57825c4 with PID 1 (/app/classes started by root in /)
2023-01-18T17:30:30.331544104Z 2023-01-18 17:30:30.325  INFO 1 --- [           main] io.axoniq.axonserver.AxonServer          : No active profile set, falling back to 1 default profile: "default"
2023-01-18T17:30:33.989108312Z 2023-01-18 17:30:33.988  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8024 (http)
2023-01-18T17:30:34.235755158Z 2023-01-18 17:30:34.231  INFO 1 --- [           main] A.i.a.a.c.MessagingPlatformConfiguration : Configuration initialized with SSL DISABLED and access control DISABLED.
2023-01-18T17:30:37.126812182Z 2023-01-18 17:30:37.125  INFO 1 --- [           main] io.axoniq.axonserver.AxonServer          : Axon Server version 4.5.16
2023-01-18T17:30:39.285810090Z 2023-01-18 17:30:39.285  WARN 1 --- [           main] .s.s.UserDetailsServiceAutoConfiguration : 
2023-01-18T17:30:39.285860293Z 
2023-01-18T17:30:39.285865737Z Using generated security password: f23552a4-9623-4adb-831e-506eac6a10a9
2023-01-18T17:30:39.285868706Z 
2023-01-18T17:30:39.285871675Z This generated password is for development use only. Your security configuration must be updated before running your application in production.
2023-01-18T17:30:39.285874618Z 
2023-01-18T17:30:41.633817404Z 2023-01-18 17:30:41.633  INFO 1 --- [           main] io.axoniq.axonserver.grpc.Gateway        : Axon Server Gateway started on port: 8124 - no SSL
2023-01-18T17:30:41.667366113Z 2023-01-18 17:30:41.667  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8024 (http) with context path ''
2023-01-18T17:30:42.561266508Z 2023-01-18 17:30:42.555  INFO 1 --- [           main] io.axoniq.axonserver.AxonServer          : Started AxonServer in 12.861 seconds (JVM running for 13.412)
2023-01-18T17:30:57.342935513Z 2023-01-18 17:30:57.338  INFO 1 --- [grpc-executor-1] i.a.a.logging.TopologyEventsLogger       : Application connected: handhaving-service, clientId = 149931@v2l1-xxxxl, clientStreamId = 149931@v2l1-xxxxx.87e0f589-66d8-41ee-ab4a-7bc599cc2c01, context = default
2023-01-18T17:31:02.213813565Z 2023-01-18 17:31:02.213  WARN 1 --- [nio-8024-exec-3] A.i.a.a.rest.DevelopmentRestController   : [<anonymous>] Request to delete all events in context "default".
2023-01-18T17:31:04.567541554Z 2023-01-18 17:31:04.567  INFO 1 --- [grpc-executor-3] i.a.a.logging.TopologyEventsLogger       : Application disconnected: handhaving-service, clientId = 149931@xxxxx.87e0f589-66d8-41ee-ab4a-7bc599cc2c01, context = default: Platform connection completed by client

The issue seems to be that Axon is storing this Money object in a database, according the errorCode='AXONIQ-4002'. What can i do to fix this? Does Axon needs a hibernate UserType so Axon is able to store this Money object or some other kind of type converter?

It seems that the de-serializer in the axon server has problems with the Money object.

In order to store this Money object in a view database - where i store the event generated by the command - i had to make a type conversion for hibernate. this seems to be related to the occurred exception.

The project uses: Spring Boot 2.7.6 axon-spring-boot-starter 4.5.15 moneta 1.4.2 It al runs with Java Temurin 17.0.4 For axon we have no configuration for serializing so the default is used: XML

Jan
  • 61
  • 6
  • As long as the `Money` object can be serialized and deserialized by the Serializer you have set, things should be okay, @Jan. Can you append your question with which (AxonFramework) Serializer you have configured and how? – Steven Jan 18 '23 at 15:36
  • Furthermore, the exception is a "remote handling exception", meaning this exception is caught on the command dispatching side, while the command handling side throws an exception too. Is there some stack trace you can share from the message handler as well? – Steven Jan 18 '23 at 15:37
  • You are using invalid currency code. "EUR" is valid for euros. Also for proper serialization you would need https://github.com/zalando/jackson-datatype-money – Vaelyr Jan 22 '23 at 19:34
  • thanks @Vaelyr. I have experimented with github.com/zalando/jackson-datatype-money , but is looks like that the zolando serialisation is not working for the Currency code also. Appears that the serilisation is not used bij Axon. – Jan Jan 23 '23 at 08:39

2 Answers2

0

The problem is in the Moneta Money object. This money object has issues with the serialization and deserialization, which is causing the described problem.

Jan
  • 61
  • 6
0

As you are using XStream for serialization, I would guess the javamoney package is not whitelisted. To do that you need to override the default XStream bean which is autoconfigured by Axon:

@Bean
fun xStream(applicationContext: ApplicationContext): XStream {
  val xStream = XStream(CompactDriver())
  xStream.allowTypesByWildcard(autoConfigBasePackages(applicationContext))
  xStream.allowTypesByWildcard(arrayOf("org.javamoney.**"))
  return xStream
}
Vaelyr
  • 2,841
  • 2
  • 21
  • 34