0

My application has bunch of domain objects which get serialized into Redis store through spring-session. I'm trying to use Kryo (4.0.0) for automatic serialization without making objects explicitly serializable.

I'm getting the following error while trying to serialize objects that have not implemented Serializable.

com.esotericsoftware.kryo.KryoException: Error during Java serialization.
    com.esotericsoftware.kryo.serializers.JavaSerializer.write(JavaSerializer.java:51)
    com.esotericsoftware.kryo.Kryo.writeClassAndObject(Kryo.java:651)
    org.springframework.session.data.redis.KryoObjectSerializer.serialize(KryoObjectSerializer.java:51)
    org.springframework.data.redis.core.AbstractOperations.rawHashValue(AbstractOperations.java:168)
    org.springframework.data.redis.core.DefaultHashOperations.putAll(DefaultHashOperations.java:129)
    org.springframework.data.redis.core.DefaultBoundHashOperations.putAll(DefaultBoundHashOperations.java:86)
    org.springframework.session.data.redis.RedisOperationsSessionRepository$RedisSession.saveDelta(RedisOperationsSessionRepository.java:778)
    org.springframework.session.data.redis.RedisOperationsSessionRepository$RedisSession.access$000(RedisOperationsSessionRepository.java:670)
    org.springframework.session.data.redis.RedisOperationsSessionRepository.save(RedisOperationsSessionRepository.java:388)
    org.springframework.session.data.redis.RedisOperationsSessionRepository.save(RedisOperationsSessionRepository.java:245)
    org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.commitSession(SessionRepositoryFilter.java:245)
    org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.access$100(SessionRepositoryFilter.java:217)
    org.springframework.session.web.http.SessionRepositoryFilter.doFilterInternal(SessionRepositoryFilter.java:170)
    org.springframework.session.web.http.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:80)
    org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344)
    org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261)
JBWEB000071: root cause

java.io.NotSerializableException: mypck.UserDomain
    java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1183)
    java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1547)
    java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1508)
    java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431)
    java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177)
    java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1547)
    java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1508)
    java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431)
    java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177)
    java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1547)
    java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1508)
    java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431)
    java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177)
    java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:347)
    com.esotericsoftware.kryo.serializers.JavaSerializer.write(JavaSerializer.java:48)
    com.esotericsoftware.kryo.Kryo.writeClassAndObject(Kryo.java:651)
    org.springframework.session.data.redis.KryoObjectSerializer.serialize(KryoObjectSerializer.java:51)
    org.springframework.data.redis.core.AbstractOperations.rawHashValue(AbstractOperations.java:168)
    org.springframework.data.redis.core.DefaultHashOperations.putAll(DefaultHashOperations.java:129)
    org.springframework.data.redis.core.DefaultBoundHashOperations.putAll(DefaultBoundHashOperations.java:86)
    org.springframework.session.data.redis.RedisOperationsSessionRepository$RedisSession.saveDelta(RedisOperationsSessionRepository.java:778)
    org.springframework.session.data.redis.RedisOperationsSessionRepository$RedisSession.access$000(RedisOperationsSessionRepository.java:670)
    org.springframework.session.data.redis.RedisOperationsSessionRepository.save(RedisOperationsSessionRepository.java:388)
    org.springframework.session.data.redis.RedisOperationsSessionRepository.save(RedisOperationsSessionRepository.java:245)
    org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.commitSession(SessionRepositoryFilter.java:245)
    org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.access$100(SessionRepositoryFilter.java:217)
    org.springframework.session.web.http.SessionRepositoryFilter.doFilterInternal(SessionRepositoryFilter.java:170)
    org.springframework.session.web.http.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:80)
    org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344)
    org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261)

My Kryo initializer:

private Kryo getInstance() {
    Kryo kryo = new Kryo() { 
            @Override 
            public Serializer<?> getDefaultSerializer( final Class type ) { 
              if (AbstractPersistentCollection.class.isAssignableFrom( type )) { 
                  return new BeanSerializer( this, type );
              } else if (Serializable.class.isAssignableFrom( type )) {
                  return new JavaSerializer();
              } 

              return super.getDefaultSerializer( type ); 
            } 
          }; 

          kryo.setInstantiatorStrategy(new SerializingInstantiatorStrategy());

    return kryo;
}

Update 1:

com.esotericsoftware.kryo.KryoException: Error during Java serialization.
Serialization trace:
authentication (org.springframework.security.core.context.SecurityContextImpl)
    com.esotericsoftware.kryo.serializers.JavaSerializer.write(JavaSerializer.java:51)
    com.esotericsoftware.kryo.Kryo.writeObject(Kryo.java:575)
    com.esotericsoftware.kryo.serializers.ObjectField.write(ObjectField.java:80)
    com.esotericsoftware.kryo.serializers.FieldSerializer.write(FieldSerializer.java:505)
    com.esotericsoftware.kryo.Kryo.writeClassAndObject(Kryo.java:651)
    org.springframework.session.data.redis.KryoObjectSerializer.serialize(KryoObjectSerializer.java:52)
    org.springframework.data.redis.core.AbstractOperations.rawHashValue(AbstractOperations.java:168)
    org.springframework.data.redis.core.DefaultHashOperations.putAll(DefaultHashOperations.java:129)
    org.springframework.data.redis.core.DefaultBoundHashOperations.putAll(DefaultBoundHashOperations.java:86)
    org.springframework.session.data.redis.RedisOperationsSessionRepository$RedisSession.saveDelta(RedisOperationsSessionRepository.java:778)
    org.springframework.session.data.redis.RedisOperationsSessionRepository$RedisSession.access$000(RedisOperationsSessionRepository.java:670)
    org.springframework.session.data.redis.RedisOperationsSessionRepository.save(RedisOperationsSessionRepository.java:388)
    org.springframework.session.data.redis.RedisOperationsSessionRepository.save(RedisOperationsSessionRepository.java:245)
    org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.commitSession(SessionRepositoryFilter.java:245)
    org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.access$100(SessionRepositoryFilter.java:217)
    org.springframework.session.web.http.SessionRepositoryFilter.doFilterInternal(SessionRepositoryFilter.java:170)
    org.springframework.session.web.http.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:80)
    org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344)
    org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261)
JBWEB000071: root cause

java.io.NotSerializableException: mypkg.UserDomain
    java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1183)
    java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1547)
    java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1508)
    java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431)
    java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177)
    java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1547)
    java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1508)
Charith De Silva
  • 3,650
  • 4
  • 43
  • 47
  • There might be more in exception which is not shown here.. Can you show more ? – The Mighty Programmer Feb 04 '17 at 05:10
  • @theBeacon updated. – Charith De Silva Feb 04 '17 at 05:18
  • What part of 'java.io.NotSerializableException: mypck.UserDomain' don't you understand? – user207421 Feb 04 '17 at 08:46
  • @EJP I'm struggling to configure kryo when I have object which is serializable and it has composite object(s) that doesn't implement serializable. In nutshell above securitycontextimpl managed by spring security and it has authentication object and that in turn has this user domain object (which doesn't implement serializable). I'm using kryo to bring implicit serialisation on objects that are getting saved in to redis session store via spring-session. – Charith De Silva Feb 04 '17 at 11:29

1 Answers1

2

Since you are using Java serializer (cleared from exception), your Class mypck.UserDomain must implements serializable or Externalizable.

From Docs

Kryo's JavaSerializer and use the standard Java Serialization instead. This approach would be as slow as usual Java serialization, but would make your class serialize as long as Java serialization is able to serialize it. Of course, your classs should implement the Serializable or Externalizable interface as it is required by usual Java serialization.

The Reason of exception is

You might have been working on composite object, where container class is serializable but alteast one of contained class is not serializable.

Kyro takes serializer of class whose object you passed to Kryo.writeObject(...) API.

Also, remove

ryo.setInstantiatorStrategy(new SerializingInstantiatorStrategy()); will not work if object class whose object you passed in Kryo.readObject(...) does not implement serializable

Better, remove this, now all serialising will be done by Kryo (unified)

  public Serializer<?> getDefaultSerializer( final Class type ) { 
       if (AbstractPersistentCollection.class.isAssignableFrom( type )) { 
             return new BeanSerializer( this, type );
          } else if (Serializable.class.isAssignableFrom( type )) {
             return new JavaSerializer();
      } 
   }
The Mighty Programmer
  • 1,242
  • 12
  • 23