javaapache-flexlcds

Flex / LCDS : Serializing InputStream as ByteArray using BeanProxy


I'm trying to serialize an object which has an InputStream. I need it to arrive on the flex client as a ByteArray.

Note - I can't implement IExternalizable on this class, as it's not mine.

I've registered a custom BeanProxy to do the conversion, however it doesn't appear to be working:

public class InputStreamBeanProxy extends BeanProxy {
    @Override
    public Object getInstanceToSerialize(Object instance) {

        InputStream stream = (InputStream) instance;
        Byte[] boxOfBytes;
            try {
                byte[] bytes = IOUtils.toByteArray(stream);
                boxOfBytes = new Byte[bytes.length];
                for (int i=0; i < bytes.length; i++)
                {
                   boxOfBytes[i] = bytes[i];
                }
            } catch (IOException e) {
                logger.error("Exception serializing inputStream: ", e);
                throw new RuntimeException(e);
            }
            return boxOfBytes;
       }
}

This proxy is then registered during startup as follows:

PropertyProxyRegistry.getRegistry().register(InputStream.class, new InputStreamBeanProxy());

I've set breakpoints in this code, and I see it being called as expected. However when the object arrives on the client, the input stream is typed as Object, and it contains no properties.

What am I doing wrong?


Solution

  • Ok - solved this.

    The problem is that when proxying an object, the value returned by getInstanceToSerialize is then serialized based on it's individual properties - ie serialized as an object.

    You cannot return a "primitive" type here (to quote the javadocs). By primitive, they refer to primtiive flashplayer types. Since I wanted byte[] to arrive as a ByteArray - which is a primitive type, my original approach doesn't work.

    Instead, the solution was to proxy the property of the owning class, rather than the InputStream directly.

    Here's the working proxy:

    public class InputStreamBeanProxy extends BeanProxy {
    
        @Override
        public Object getValue(Object instance, String propertyName) {
            Object value = super.getValue(instance, propertyName);
            if (value instanceof InputStream) {
                value = getByteArray((InputStream) value);
            }
            return value;
        }
    
        private byte[] getByteArray(InputStream stream) {
    
            try {
                byte[] bytes = IOUtils.toByteArray(stream);
                return bytes;
            } catch (IOException e) {
                logger.error("Exception serializing inputStream: ", e);
                throw new RuntimeException(e);
            }
        }
    
    }
    

    Assuming I was trying to serialize the following class:

    public class MyThing
    {
         InputStream myStream;
         ...
     }
    

    This would be registered as follows:

    PropertyProxyRegistry.getRegistry().register(MyThing.class, new InputStreamBeanProxy());