Corda 3.1中含java.sql.Timestamp的Collateral状态类反序列化报错求助
解决Corda 3.1中
java.sql.Timestamp反序列化失败问题 你在Corda 3.1里遇到的这个问题很典型:包含java.sql.Timestamp成员的Collateral状态类反序列化时抛出java.io.NotSerializableException,哪怕已经把java.sql.Timestamp加入序列化白名单也没用。核心原因是Corda的序列化框架需要类有可被识别的反序列化构造函数,而java.sql.Timestamp的构造逻辑不符合它的要求。下面给你几个可行的解决方案:
推荐方案:改用Java 8时间API(java.time.Instant)
Corda官方本身就推荐使用Java 8引入的时间类,这些类天生兼容Corda的序列化机制,完全不需要额外配置:
- 把
Collateral类里的java.sql.Timestamp成员替换成java.time.Instant - 如果需要和数据库交互,只需要在数据访问层做简单转换:
// Instant转Timestamp Timestamp dbTimestamp = Timestamp.from(yourInstant); // Timestamp转Instant Instant appInstant = dbTimestamp.toInstant();
备选方案1:为java.sql.Timestamp编写自定义序列化器
如果业务上必须保留java.sql.Timestamp类型,可以给它写一个自定义序列化器,让Corda知道怎么处理它的序列化和反序列化:
- 先写序列化器类:
public class TimestampSerializer implements Serializer<Timestamp> { @Override public void serialize(Timestamp obj, SerializationOutput out) { // 序列化时只存时间戳的毫秒数 out.writeLong(obj.getTime()); } @Override public Timestamp deserialize(DeserializationInput in) { // 反序列化时用毫秒数重建Timestamp return new Timestamp(in.readLong()); } @Override public boolean isSerializerForType(Class<?> type) { return Timestamp.class.equals(type); } } - 然后在节点的
node.conf配置文件里注册这个序列化器,同时确保白名单配置正确:serialization { whitelist = [ "java.sql.Timestamp", "com.syne.cordapp.state.Collateral" ] customSerializers { "java.sql.Timestamp" = "com.your.package.TimestampSerializer" } } - 最后重启Corda节点,让配置生效
备选方案2:在Collateral类中手动处理时间字段
另一种思路是不在状态类里直接存Timestamp,而是转成Long类型存储,反序列化时再转回来:
public class Collateral implements ContractState { // 用Long存储时间戳的毫秒数,替代直接存Timestamp private Long timestampMillis; // 对外提供获取Timestamp的方法 public Timestamp getTimestamp() { return timestampMillis != null ? new Timestamp(timestampMillis) : null; } // 对外提供设置Timestamp的方法 public void setTimestamp(Timestamp timestamp) { this.timestampMillis = timestamp != null ? timestamp.getTime() : null; } // 其他状态类的成员变量和实现方法... }
这样处理后,Corda序列化时只会处理Long类型,完全避开了Timestamp的序列化问题。
内容的提问来源于stack exchange,提问作者balajimore
相关产品推荐
相关产品推荐

