[Hessian-interest] Hessian 4.0.7 not backward-compatible

Kruegler Daniel Daniel.Kruegler at bdal.de
Mon Oct 10 01:36:16 CDT 2011


Recently I stumbled across the fact that the new Hessian 4.0.7 library
in 2.0 mode cannot read valid output created from Hessian 1.0. Here is
a simple test case:

package test;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.Serializable;

import com.caucho.hessian.io.Hessian2Input;
import com.caucho.hessian.io.Hessian2Output;
import com.caucho.hessian.io.HessianInput;
import com.caucho.hessian.io.HessianOutput;

@SuppressWarnings("nls")
public final class BackwardCompatibilityBreakTest {

	static class Simple implements Serializable {

		private static final long serialVersionUID = -1444335175080756148L;

		String value;

		Simple(String value) {
			this.value = value;
		}

		@Override
		public String toString() {
			return "Simple [value=" + value + "]";
		}
	}

	static byte[] writeObject10(Object obj) throws IOException {
		ByteArrayOutputStream os = new ByteArrayOutputStream();
		HessianOutput out = new HessianOutput(os);
		out.writeObject(obj);
		out.close();
		byte[] result = os.toByteArray();
		return result;
	}

	static Object readObject10(byte[] data) throws IOException {
		ByteArrayInputStream is = new ByteArrayInputStream(data);
		HessianInput in = new HessianInput(is);
		Object result = in.readObject(null);
		in.close();
		return result;
	}

	static byte[] writeObject20(Object obj) throws IOException {
		ByteArrayOutputStream os = new ByteArrayOutputStream();
		Hessian2Output out = new Hessian2Output(os);
		out.writeObject(obj);
		out.close();
		byte[] result = os.toByteArray();
		return result;
	}

	static Object readObject20(byte[] data) throws IOException {
		ByteArrayInputStream is = new ByteArrayInputStream(data);
		Hessian2Input in = new Hessian2Input(is);
		Object result = in.readObject(null);
		in.close();
		return result;
	}

	public static void main(String[] args) throws Exception {
		byte data[];
		Object res;

		Simple obj = new Simple("Hi!");
		data = writeObject10(obj);
		res = readObject10(data);
		System.out.println(res);
		data = writeObject20(obj);
		res = readObject20(data);
		System.out.println(res);
		data = writeObject10(obj);
		res = readObject20(data);
		System.out.println(res);
	}

}

The output created for a 4.0.7 library is:

Simple [value=Hi!]
Simple [value=Hi!]
Exception in thread "main" com.caucho.hessian.io.HessianProtocolException: expected integer at 0x74
	at com.caucho.hessian.io.Hessian2Input.error(Hessian2Input.java:2882)
	at com.caucho.hessian.io.Hessian2Input.expect(Hessian2Input.java:2830)
	at com.caucho.hessian.io.Hessian2Input.readInt(Hessian2Input.java:789)
	at com.caucho.hessian.io.Hessian2Input.readType(Hessian2Input.java:2403)
	at com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:2084)
	at com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:1641)
	at test.BackwardCompatibilityBreakTest.readObject20(BackwardCompatibilityBreakTest.java:65)
	at test.BackwardCompatibilityBreakTest.main(BackwardCompatibilityBreakTest.java:82)

but worked as expected in 3.2.0.

I also verified that this is really a defect in the new Hessian2, not in the potentially new Hessian1,
because the byte output from Hessian1 has not changed since then.

As expected from a proper Hessian 1.0 output, the serialized output starts with

M t /type-string/ ....

The defect of the 2.0 deserializer seems to be that the readType() method misses the proper handling
of reading the /type-string/ after reading the t (116 decimal, 0x74 hex). Instead it attempts to read it as
an integer which (obviously) fails.

I notice that this seems to be correct according to the Hessian 2.0 spec, (which does no longer describe
the Hessian 1.0 type-string format starting with t), as described in

http://hessian.caucho.com/doc/hessian-serialization.html

If this is really intended, I wonder how it comes that the assertion made in

http://www.caucho.com/resin-3.0/protocols/hessian-2.0-spec.xtp

"Hessian 2 is a compaction of the Hessian protocol. All Hessian 1 codes are understood by Hessian 2. 
The extended codes provide compact formats for common values, e.g. storing an integer zero as a 
single byte instead of Hessian 1's 5 bytes."

and in

http://caucho.com/resin-3.1/doc/hessian-2.0-spec.xtp

"Hessian 2.0 must be backwards compatible with Hessian 1.0. Hessian 2.0 parsers must be 
read Hessian 1.0 messages."

IMO, should the format described in

http://hessian.caucho.com/doc/hessian-serialization.html

be the currently valid intention, this would really be no-go for us to use the Hessian protocol.

Thanks & Greetings from Bremen,

Daniel Krügler





More information about the hessian-interest mailing list