2013-02-06 67 views
0

编辑:使用KRYO 1.04Kryo无法序列化java.sql.Timestamp?

我现在序列化User类,它包含Scala中的一个java.sql.Timestamp场。出于某种原因,KRYO无法找到一个零参数的构造函数,并抛出一个错误:

Caused by: com.esotericsoftware.kryo.SerializationException: Class cannot be created (missing no-arg constructor): java.sql.Timestamp 
Serialization trace: 
created (com.threetierlogic.AccountService.models.User) 
     at com.esotericsoftware.kryo.Kryo.newInstance(Kryo.java:688) 
     at com.esotericsoftware.kryo.Serializer.newInstance(Serializer.java:75) 
     at com.esotericsoftware.kryo.serialize.FieldSerializer.readObjectData(FieldSerializer.java:200) 
     at com.esotericsoftware.kryo.serialize.FieldSerializer.readObjectData(FieldSerializer.java:220) 
     at com.esotericsoftware.kryo.serialize.FieldSerializer.readObjectData(FieldSerializer.java:200) 
     at com.esotericsoftware.kryo.Serializer.readObject(Serializer.java:61) 
     at com.esotericsoftware.kryo.Kryo.readObject(Kryo.java:589) 
     ... 84 more 
Caused by: java.lang.InstantiationException: java.sql.Timestamp 
     at java.lang.Class.newInstance0(Class.java:340) 
     at java.lang.Class.newInstance(Class.java:308) 
     at com.esotericsoftware.kryo.Kryo.newInstance(Kryo.java:676) 
     ... 90 more 

这是一个转换器类转换域对象进行了Riak的一部分。这里是我的转换器类:

/** 
* Kryo converter for passing domain objects into Riak 
*/ 
class UserConverter(val bucket: String) extends Converter[User] { 

    def fromDomain(domainObject: User, vclock: VClock): IRiakObject = { 
    val key = domainObject.guid 

    if(key == null) throw new NoKeySpecifedException(domainObject) 

    val kryo = new Kryo() 
    kryo.register(classOf[User]) 
    kryo.register(classOf[Timestamp]) 

    val ob = new ObjectBuffer(kryo) 
    val value = ob.writeObject(domainObject) 

    RiakObjectBuilder.newBuilder(bucket, key) 
     .withValue(value) 
     .withVClock(vclock) 
     .withContentType(Constants.CTYPE_OCTET_STREAM) 
     .build() 
    } 

    def toDomain(riakObject: IRiakObject): User = { 
    if(riakObject == null) null 

    val kryo = new Kryo() 
    kryo.register(classOf[User]) 
    kryo.register(classOf[Timestamp]) 
    val ob = new ObjectBuffer(kryo) 

    ob.readObject(riakObject.getValue(), classOf[User]) 
    } 
} 

是否需要扩展Timestamp并创建一个零参数构造函数?还是有更好的解决方法?

如果我需要升级到2.20,如果不写入文件,ObjectBuffer的替代品是什么?

回答

1

你可以做这样的事情:

class KryoSO { 
    import com.esotericsoftware.kryo.KryoSerializable 
    import de.javakaffee.kryoserializers.KryoReflectionFactorySupport 
    import com.esotericsoftware.kryo.Kryo 
    import com.esotericsoftware.kryo.Serializer 
    import java.io.{ InputStream, OutputStream } 
    import com.esotericsoftware.kryo.io.{ Output, Input } 
    import java.sql.Timestamp 

    object TimestampSerializer extends Serializer[Timestamp] { 
     override def write(kryo: Kryo, output: Output, t: Timestamp): Unit = { 
     output.writeLong(t.getTime(), true); 
     } 

     override def read(kryo: Kryo, input: Input, t: Class[Timestamp]): Timestamp = { 
     new Timestamp(input.readLong(true)); 
     } 

     override def copy(kryo: Kryo, original: Timestamp): Timestamp = { 
     new Timestamp(original.getTime()); 
     } 
    } 
    val kryo: Kryo = new KryoReflectionFactorySupport 
    kryo.addDefaultSerializer(classOf[Timestamp], TimestampSerializer) 

    def serialize(o: Any, os: OutputStream) = { 
     val output = new Output(os); 
     this.kryo.writeClassAndObject(output, o); 
     output.flush(); 
    } 

    def deserialize(is: InputStream): Any = { 
     kryo.readClassAndObject(new Input(is)); 
    } 

    } 
    val k = new KryoSO 
    val b = new java.io.ByteArrayOutputStream 
    val timestamp = new java.sql.Timestamp(System.currentTimeMillis()) 

    k.serialize(timestamp, b) 

    val result = k.deserialize(new java.io.ByteArrayInputStream(b.toByteArray())) 

    println(timestamp) 
    println(result.getClass) 
    println(result.isInstanceOf[java.sql.Timestamp]) 
    println(timestamp == result) 

结果:

2013-02-07 10:59:19.482 
class java.sql.Timestamp 
true 
true 
2

快速查看Kryo home page表明,如果没有零参数构造函数,您可以创建Kryo所谓的“Instantion策略”来处理该类。请参阅"Object Creation"部分。

+0

看起来它已经更新到2.20和我使用的是1.04。任何想法是什么替代是'ObjectBuffer'(没有意义指定一个文件)?我会继续阅读文档。 – crockpotveggies

+0

@DeLongey:我不知道。在我看到您的问题之前,我从未听说过Kryo ...... –