You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Axon命令中Java Moneta Money对象序列化异常解决问询

Axon Command中Java Moneta Money对象序列化问题解决

你遇到的AXONIQ-4002错误,根源是Axon的Jackson序列化器无法处理Java Moneta的Money类型,导致命令消息序列化失败,AxonServer拒绝消息后断开连接。Hibernate的UserType是用于数据库持久化的类型转换,和Axon的消息序列化机制完全独立,不需要为Axon配置Hibernate UserType。


解决方案:为Axon配置Jackson对Money类型的支持

解决核心是让Axon使用的Jackson序列化器能够正确处理Money对象,以下是两种常用实现方式:

方式1:使用官方Jackson模块(推荐)

Java Moneta提供了专门的Jackson序列化模块,直接引入并注册即可:

  1. 添加依赖
    在pom.xml中引入moneta-jackson模块(版本与你的moneta保持一致):

    <dependency>
        <groupId>org.javamoney</groupId>
        <artifactId>moneta-jackson</artifactId>
        <version>1.4.2</version>
    </dependency>
    
  2. 配置Axon的Jackson序列化器
    创建Spring配置类,将官方模块注册到Axon使用的ObjectMapper中:

    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.javamoney.moneta.jackson.JavaMoneyModule;
    import org.axonframework.serialization.json.JacksonSerializer;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class AxonSerializationConfig {
    
        @Bean
        public JacksonSerializer jacksonSerializer() {
            ObjectMapper objectMapper = new ObjectMapper()
                    .registerModule(new JavaMoneyModule())
                    .registerModule(new com.fasterxml.jackson.datatype.jsr310.JavaTimeModule()); // 处理LocalDate等JDK8时间类型
            return JacksonSerializer.builder()
                    .objectMapper(objectMapper)
                    .build();
        }
    }
    
  3. 明确指定Axon序列化器
    修改application.yml,将序列化器配置明确指定为jackson(避免default可能的歧义):

    axon:
      serializer:
        general: jackson
        events: jackson
        messages: jackson
    

方式2:自定义Jackson序列化/反序列化器

如果不想引入额外模块,可以手动实现序列化逻辑:

  1. 编写序列化器和反序列化器

    import com.fasterxml.jackson.core.JsonGenerator;
    import com.fasterxml.jackson.databind.JsonSerializer;
    import com.fasterxml.jackson.databind.SerializerProvider;
    import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
    import com.fasterxml.jackson.core.JsonParser;
    import com.fasterxml.jackson.databind.DeserializationContext;
    import org.javamoney.moneta.Money;
    
    import javax.money.Monetary;
    import java.io.IOException;
    
    // Money序列化器
    public class MoneySerializer extends JsonSerializer<Money> {
        @Override
        public void serialize(Money value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
            gen.writeStartObject();
            gen.writeNumberField("amount", value.getNumber().doubleValue());
            gen.writeStringField("currency", value.getCurrency().getCurrencyCode());
            gen.writeEndObject();
        }
    }
    
    // Money反序列化器
    public class MoneyDeserializer extends StdDeserializer<Money> {
        protected MoneyDeserializer() {
            super(Money.class);
        }
    
        @Override
        public Money deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
            p.nextToken();
            double amount = 0;
            String currencyCode = "";
            while (p.nextToken() != com.fasterxml.jackson.core.JsonToken.END_OBJECT) {
                String fieldName = p.getCurrentName();
                p.nextToken();
                if ("amount".equals(fieldName)) {
                    amount = p.getDoubleValue();
                } else if ("currency".equals(fieldName)) {
                    currencyCode = p.getText();
                }
            }
            return Money.of(amount, Monetary.getCurrency(currencyCode));
        }
    }
    
  2. 注册自定义序列化器到Axon
    在配置类中将自定义模块注册到ObjectMapper:

    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.databind.module.SimpleModule;
    import org.axonframework.serialization.json.JacksonSerializer;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class AxonSerializationConfig {
    
        @Bean
        public JacksonSerializer jacksonSerializer() {
            SimpleModule moneyModule = new SimpleModule();
            moneyModule.addSerializer(Money.class, new MoneySerializer());
            moneyModule.addDeserializer(Money.class, new MoneyDeserializer());
    
            ObjectMapper objectMapper = new ObjectMapper()
                    .registerModule(moneyModule)
                    .registerModule(new com.fasterxml.jackson.datatype.jsr310.JavaTimeModule());
            return JacksonSerializer.builder()
                    .objectMapper(objectMapper)
                    .build();
        }
    }
    

内容的提问来源于stack exchange,提问作者Jan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 13:10:26