Mantis - Hessian
Viewing Issue Advanced Details
3663 minor always 09-01-09 20:00 12-16-09 15:10
danwatt  
ferg  
normal  
closed 4.0.1  
fixed  
none    
none 4.0.3  
0003663: Can't deserialize an object with an EnumSet
When serializing an object that has an EnumSet inside of it, or for that matter directly serializing an EnumSet, the serialization happens just fine. However, when deserializing, an InvocationTargetException is thrown.

Code demonstrating this issues is in the additional information.
import java.io.ByteArrayInputStream;
import java.util.EnumSet;
import org.apache.commons.io.output.ByteArrayOutputStream;
import com.caucho.hessian.io.Hessian2StreamingInput;
import com.caucho.hessian.io.Hessian2StreamingOutput;

public class HessianFail {
                public static enum Test{A,B};
               public static void main(String[] args) throws Exception {
                                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                                Hessian2StreamingOutput out = new Hessian2StreamingOutput(baos);
                                out.writeObject(EnumSet.noneOf(Test.class));
                                out.close();
                                Hessian2StreamingInput in = new Hessian2StreamingInput(new ByteArrayInputStream(baos.toByteArray()));
                                EnumSet<Test> e = (EnumSet<Test>) in.readObject();
                }
}

Stacktrace:
Exception in thread "main" com.caucho.hessian.io.HessianProtocolException: 'java.util.EnumSet$SerializationProxy' could not be instantiated
                at com.caucho.hessian.io.JavaDeserializer.instantiate(JavaDeserializer.java:282)
                at com.caucho.hessian.io.JavaDeserializer.readObject(JavaDeserializer.java:162)
                at com.caucho.hessian.io.SerializerFactory.readObject(SerializerFactory.java:501)
                at com.caucho.hessian.io.Hessian2Input.readObjectInstance(Hessian2Input.java:2098)
                at com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:2030)
                at com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:2014)
                at com.caucho.hessian.io.Hessian2Input.readStreamingObject(Hessian2Input.java:2267)
                at com.caucho.hessian.io.Hessian2StreamingInput.readObject(Hessian2StreamingInput.java:102)
                at HessianFail.main(HessianFail.java:22)
Caused by: java.lang.reflect.InvocationTargetException
                at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
                at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
                at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
                at java.lang.reflect.Constructor.newInstance(Constructor.java:494)
                at com.caucho.hessian.io.JavaDeserializer.instantiate(JavaDeserializer.java:278)
                ... 8 more
Caused by: java.lang.NullPointerException
                at java.util.EnumSet$SerializationProxy.<init>(EnumSet.java:392)
                ... 13 more

Notes
(0004287)
sugis   
11-05-09 12:55   
I've written a small patch that works around this issue. It's not a proper fix by any means, but it's good enough for me to make forward progress while I wait for a "real" fix from an actual developer...

=== modified file 'src/main/java/com/caucho/hessian/io/JavaDeserializer.java'
--- src/main/java/com/caucho/hessian/io/JavaDeserializer.java 2009-11-05 19:31:47 +0000
+++ src/main/java/com/caucho/hessian/io/JavaDeserializer.java 2009-11-05 20:19:55 +0000
@@ -54,6 +54,7 @@
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
+import java.util.EnumSet;
 import java.util.HashMap;
 
 import java.util.logging.*;
@@ -154,11 +155,32 @@
       throw new IOExceptionWrapper(_type.getName() + ":" + e.getMessage(), e);
     }
   }
-
+
+ private static class EnumSetSerializationProxy<E extends Enum<E>> {
+ Object elementType;
+ Object[] elements;
+ }
+
+ private <E extends Enum<E>> EnumSet<E> readEnumSet(AbstractHessianInput in, Class<E> klass) throws IOException {
+ EnumSetSerializationProxy<E> essp = new EnumSetSerializationProxy<E>();
+ int ref = in.addRef(essp);
+ essp.elementType = in.readObject();
+ essp.elements = (Object[])in.readObject();
+ EnumSet<E> obj = EnumSet.noneOf((Class<E>)essp.elementType);
+ for (Object element : essp.elements)
+ obj.add((E)element);
+ return obj;
+ }
+
   public Object readObject(AbstractHessianInput in, String []fieldNames)
     throws IOException
   {
     try {
+
+ if (_type.getName().equals("java.util.EnumSet$SerializationProxy")) {
+ return readEnumSet(in, Enum.class);
+ }
+
       Object obj = instantiate();
 
       return readObject(in, obj, fieldNames);
(0004340)
ferg   
12-16-09 15:10   
hessian/3bba