seata报错json encode exception解决

版本

io.seata:seata-spring-boot-starter:1.3.0

现象

数据实体对象字段类型为LocalDateTime时启用全局事务报错

json encode exception, Type id handling not implemented for type java.lang.Object (by serializer of type com.fasterxml.jackson.databind.ser.impl.UnsupportedTypeSerializer)

解决

  1. 升级依赖io.seata:seata-spring-boot-starter:1.4.2
  2. 自定义序列化器
public class LocalDateTimeJacksonSerializer implements JacksonSerializer {
    private final static String DATETIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSSSSSSSS";
    private final static DateTimeFormatter DATETIME_FORMAT = DateTimeFormatter.ofPattern(DATETIME_PATTERN);

    @Override
    public Class<LocalDateTime> type() {
        return LocalDateTime.class;
    }

    @Override
    public JsonSerializer<LocalDateTime> ser() {
        return new LocalDateTimeSerializer(DATETIME_FORMAT);
    }

    @Override
    public JsonDeserializer<? extends LocalDateTime> deser() {
        return new LocalDateTimeDeserializer(DATETIME_FORMAT);
    }
}
  1. 添加SPI扩展配置
    META-INF/seata/io.seata.rm.datasource.undo.parser.spi.JacksonSerializer
LocalDateTimeJacksonSerializer

源码

  • 回滚解析器
    io.seata.rm.datasource.undo.parser.JacksonUndoLogParser
  1. io.seata:seata-spring-boot-starter:1.3.0中回滚日志解析器时间类型只对Timestamp类型处理
@Override
public void init() {
    module.addSerializer(Timestamp.class, timestampSerializer);
    module.addDeserializer(Timestamp.class, timestampDeserializer);
    module.addSerializer(SerialBlob.class, blobSerializer);
    module.addDeserializer(SerialBlob.class, blobDeserializer);
    module.addSerializer(SerialClob.class, clobSerializer);
    module.addDeserializer(SerialClob.class, clobDeserializer);
    mapper.registerModule(module);
    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
    mapper.enable(MapperFeature.PROPAGATE_TRANSIENT_MARKER);
}
  1. io.seata:seata-spring-boot-starter:1.4.2中增加了扩展点
@Override
public void init() {
    try {
        List<JacksonSerializer> jacksonSerializers = EnhancedServiceLoader.loadAll(JacksonSerializer.class);
        if (CollectionUtils.isNotEmpty(jacksonSerializers)) {
            for (JacksonSerializer jacksonSerializer : jacksonSerializers) {
                Class type = jacksonSerializer.type();
                JsonSerializer ser = jacksonSerializer.ser();
                JsonDeserializer deser = jacksonSerializer.deser();
                if (type != null) {
                    if (ser != null) {
                        module.addSerializer(type, ser);
                    }
                    if (deser != null) {
                        module.addDeserializer(type, deser);
                    }
                    LOGGER.info("jackson undo log parser load [{}].", jacksonSerializer.getClass().getName());
                }
            }
        }
    } catch (EnhancedServiceNotFoundException e) {
        LOGGER.warn("JacksonSerializer not found children class.", e);
    }
    module.addSerializer(Timestamp.class, timestampSerializer);
    module.addDeserializer(Timestamp.class, timestampDeserializer);
    module.addSerializer(SerialBlob.class, blobSerializer);
    module.addDeserializer(SerialBlob.class, blobDeserializer);
    module.addSerializer(SerialClob.class, clobSerializer);
    module.addDeserializer(SerialClob.class, clobDeserializer);
    mapper.registerModule(module);
    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
    mapper.enable(MapperFeature.PROPAGATE_TRANSIENT_MARKER);
}
上一篇:【Java用法】常用的 T,E,K,V,?,S,U所代表的含义


下一篇:nested exception is org.apache.ibatis.binding.BindingException 【Mabatis】Mapper 参数 bean与String同时使用