Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to override ObjectOutputStream.writeStreamHeader()?

Tags:

The method ObjectOutputStream.writeStreamHeader() can be overridden to prepend or append data to the header. However, if that data is based on an argument passed to the derived class's constructor like:

public class MyObjectOutputStream extends ObjectOutputStream {

    public MyObjectOutputStream( int myData, OutputStream out ) throws IOException {
        super( out );
        m_myData = myData;
    }

    protected void writeStreamHeader() throws IOException {
        write( m_myData );            // WRONG: m_myData not initialized yet
        super.writeStreamHeader();
    }

    private final int m_myData;
}

it doesn't work because super() is called before m_myData is initialized and super() calls writeStreamHeader(). The only way I can think to work around this is by using ThreadLocal like:

public class MyObjectOutputStream extends ObjectOutputStream {

    public MyObjectOutputStream( int myData, OutputStream out ) throws IOException {
        super( thunk( myData, out ) );
    }

    protected void writeStreamHeader() throws IOException {
        write( m_myData.get().intValue() );
        super.writeStreamHeader();
    }

    private static OutputStream thunk( int myData, OutputStream out ) {
        m_myData.set( myData );
        return out;
    }

    private static final ThreadLocal<Integer> m_myData = new ThreadLocal<Integer>();
}

This seems to work, but is there a better (less clunky) way?

like image 956
Paul J. Lucas Avatar asked Jul 06 '09 07:07

Paul J. Lucas


1 Answers

There is a general way to solve this sort of problem. Make the class and inner class and reference a variable in the outer scope. (Note, this only works with -target 1.4 or greter, which is the default in current versions of javac. With -target 1.3 you will get an NPE.)

public static ObjectOutputStream newInstance(
    final int myData, final OutputStream out
) throws IOException {
    return new ObjectOutputStream(out) {
        @Override
        protected void writeStreamHeader() throws IOException {
            write(myData);
            super.writeStreamHeader();
        }
    };
}

But, it's probably easier just to write the data out before constructing the ObjectOuputStream.

like image 52
Tom Hawtin - tackline Avatar answered Oct 27 '22 09:10

Tom Hawtin - tackline