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序列化模块,直接引入并注册即可:
添加依赖
在pom.xml中引入moneta-jackson模块(版本与你的moneta保持一致):<dependency> <groupId>org.javamoney</groupId> <artifactId>moneta-jackson</artifactId> <version>1.4.2</version> </dependency>配置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(); } }明确指定Axon序列化器
修改application.yml,将序列化器配置明确指定为jackson(避免default可能的歧义):axon: serializer: general: jackson events: jackson messages: jackson
方式2:自定义Jackson序列化/反序列化器
如果不想引入额外模块,可以手动实现序列化逻辑:
编写序列化器和反序列化器
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)); } }注册自定义序列化器到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
相关产品推荐
相关产品推荐

