MemCached CustomSerializingTranscoder Serialized Object

Was getting this error when I was trying to set a custom object:
memCachedClient.set(“customerObj”, 3600, new Customer(“John”, “Doe”));

2014-03-01 15:47:21.339 WARN net.spy.memcached.transcoders.SerializingTranscoder:  Caught CNFE decoding 150 bytes of data
2014-03-01T15:47:21.340137+00:00 app[web.1]: java.lang.ClassNotFoundException: com.example.model.Customer
2014-03-01T15:47:21.340436+00:00 app[web.1]: 	at java.net.URLClassLoader$1.run(URLClassLoader.java:217)
2014-03-01T15:47:21.340436+00:00 app[web.1]: 	at java.security.AccessController.doPrivileged(Native Method)
2014-03-01T15:47:21.340436+00:00 app[web.1]: 	at java.net.URLClassLoader.findClass(URLClassLoader.java:205)
2014-03-01T15:47:21.340436+00:00 app[web.1]: 	at java.lang.ClassLoader.loadClass(ClassLoader.java:321)
2014-03-01T15:47:21.340436+00:00 app[web.1]: 	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294)
2014-03-01T15:47:21.340436+00:00 app[web.1]: 	at java.lang.ClassLoader.loadClass(ClassLoader.java:266)
2014-03-01T15:47:21.340436+00:00 app[web.1]: 	at java.lang.Class.forName0(Native Method)
2014-03-01T15:47:21.340436+00:00 app[web.1]: 	at java.lang.Class.forName(Class.java:266)

This occurs because the memcached client is loaded using a classloader and the serialized object class is loaded using another classloader. To fix this you must pass to the memcahed client connector factory a custom transcoder.


 MemcachedClient mc = new MemcachedClient(
   new ConnectionFactoryBuilder()
   .setTranscoder(new CustomSerializingTranscoder()) //Add this line
   .setProtocol(ConnectionFactoryBuilder.Protocol.BINARY)
   .setAuthDescriptor(ad).build(),
package com.example.cache;

import java.io.ByteArrayInputStream;
import java.io.Closeable;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectStreamClass;

import net.spy.memcached.transcoders.SerializingTranscoder;

public class CustomSerializingTranscoder extends SerializingTranscoder{

    @Override
    protected Object deserialize(byte[] bytes) {
        final ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
        ObjectInputStream in = null;
        try {
            ByteArrayInputStream bs = new ByteArrayInputStream(bytes);
            in = new ObjectInputStream(bs) {
                @Override
                protected  Class<?> resolveClass(ObjectStreamClass objectStreamClass) throws IOException, ClassNotFoundException {
                    try {
                        return currentClassLoader.loadClass(objectStreamClass.getName());
                    } catch (Exception e) {
                        return super.resolveClass(objectStreamClass);
                    }
                }
            };
            return in.readObject();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } finally {
            closeStream(in);
        }
    }

    private static void closeStream(Closeable c) {
        if (c != null) {
            try {
                c.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: