<document>
  <header>
    <product>resin</product>
    <title>Hessian 2.0 Specification (Draft 2)</title>
    <date>Jul 8, 2006</date>
    <description>
      <p>Hessian is a compact binary protocol for cross-platform web
      services and messaging.</p>
    </description>
  </header>

  <body>
    <localtoc/>

<s1 title="Design Goals">

<p>The <a href="http://hessian.caucho.com">Hessian home page</a>
contains the latest information about Hessian.</p>

<p>Unlike older binary protocols, Hessian is both self-describing,
compact, and portable across languages.  The wire protocol for web
services should be invisible to application writers, it should not require
external schema or IDL.</p>

<p>The Hessian protocol has the following design goals:</p>

<ul>
<li>It must not require external IDL or schema definitions,
i.e. the protocol should be invisible to application code.</li>
<li>It must have sufficient power to serialize Java, including circular references.</li>
<li>It must be language-independent.  In particular, it must allow non-Java clients to use web services.</li>
<li>It must be simple so it can be effectively tested and implemented.</li>
<li>It must be as fast as possible.</li>
<li>It must be as compact as possible.</li>
<li>It must support unicode strings.</li>
<li>It must support 8-bit binary data (i.e. without encoding or using attachments.)</li>
<li>It must allow web services to deployed as a Servlet.</li>
<li>It must have sufficient power to support EJB.</li>
<li>It must support encryption, compression, signature, and
transaction context envelopes.</li>
<li>Hessian 2.0 must be backwards compatible with Hessian 1.0.
Hessian 2.0 parsers must be read Hessian 1.0 messages.</li>
</ul>

</s1>

<s1 title="Hessian 2.0 Grammar">

<def title="Serialization Grammar">
           # starting production
top        ::= object

           # 8-bit binary data split into 64k chunks
binary     ::= 'b' b1 b0 &lt;binary-data> binary # non-final chunk
           ::= 'B' b1 b0 &lt;binary-data>        # final chunk
           ::= [x20-x2f] &lt;binary-data>        # binary data of length 0-15

           # boolean true/false
boolean    ::= 'T'
           ::= 'F'

           # time in UTC encoded as 64-bit long milliseconds since epoch
date       ::= 'd' b7 b6 b5 b4 b3 b2 b1 b0

           # 64-bit IEEE double
double     ::= 'D' b7 b6 b5 b4 b3 b2 b1 b0
           ::= x67                   # 0.0
           ::= x68                   # 1.0
           ::= x69 b0                # byte cast to double (-128.0 to 127.0)
           ::= x6a b1 b0             # short cast to double
           ::= x6b b3 b2 b1 b0       # 32-bit float cast to double

           # 32-bit signed integer
int        ::= 'I' b3 b2 b1 b0
           ::= [x80-xbf]             # -x10 to x3f
           ::= [xc0-xcf] b0          # -x800 to x7ff
           ::= [xd0-xd7] b1 b0       # -x40000 to x3ffff

           # list/vector length 
length     ::= 'l' b3 b2 b1 b0
           ::= x6e int

           # list/vector
list       ::= 'V' type? length? object* 'z'
           ::= 'v' int int object*   # type-ref, length

           # 64-bit signed long integer
long       ::= 'L' b7 b6 b5 b4 b3 b2 b1 b0
           ::= [xd8-xef]             # -x08 to x0f
           ::= [xf0-xff] b0          # -x800 to x7ff
           ::= [x38-x3f] b1 b0       # -x40000 to x3ffff
           ::= x77 b3 b2 b1 b0       # 32-bit integer cast to long

           # map/object
map        ::= 'M' type? (object object)* 'z'  # key, value map pairs
           ::= 'o' int object*           # Object instance - type-ref

           # null value
null       ::= 'N'

           # main production for object serialization
object     ::= null
           ::= binary
           ::= boolean
           ::= date
           ::= double
           ::= int
           ::= list
           ::= long
           ::= map
           ::= object-def object
           ::= remote
           ::= ref
           ::= string
           ::= xml

           # definition for an object (compact map)
object-def ::= 'O' type int string*

           # Object reference (e.g. circular trees and graphs)
ref        ::= 'R' b3 b2 b1 b0    # reference to nth map/list in stream
           ::= x4a b0             # reference to 1-255th map/list
           ::= x4b b1 b0          # reference to 1-65535th map/list

           # UTF-8 encoded character string split into 64k chunks
string     ::= 's' b1 b0 &lt;string-data> string  # non-final chunk
           ::= 'S' b1 b0 &lt;string-data>         # string of length 0-65535
           ::= [x00-x1f] &lt;string-data>         # string of length 0-31

           # map/list types for OO languages
type       ::= 't' b1 b0 &lt;type-string>         # type name
           ::= x75 int                         # type reference

           # UTF-8 encoded XML data
xml        ::= 'x' b1 b0 &lt;xml-data> xml
           ::= 'X' b1 b0 &lt;xml-data>
</def>

<def title="Envelope/Messaging/RPC Grammar">
top       ::= call
          ::= envelope
          ::= message
          ::= reply

          # RPC-style call
call      ::= 'c' x02 x00 method object* 'z'

          # Envelope for encryption/headers
envelope  ::= 'E' x02 x00 env-chunk* 'z'

          # header, body, footer
env-chunk ::= int (string object)* binary int (string object)*

fault     ::= 'f' (object object)* 'z'

          # message/streaming message
message   ::= 'p' x02 x00 object* 'z'
          ::= 'P' x02 x00 object* 'z'

          # RPC method name (possibly mangled for overloading)
method    ::= 'm' b1 b0 &lt;method-string>

          # RPC reply
reply     ::= 'r' x02 x00 object 'z'  # successful message/reply
          ::= 'r' x02 x00 fault 'z'   # exception/fault reply
</def>

</s1>

<s1 title="Serialization">

<p>Hessian's object serialization has 9 primitive types:</p>

<ol>
<li><a href="#boolean">boolean</a></li>
<li>32-bit <a href="#int">int</a></li>
<li>64-bit <a href="#long">long</a></li>
<li>64-bit <a href="#double">double</a></li>
<li>64-bit <a href="#date">date</a></li>
<li>UTF8-encoded <a href="#string">string</a></li>
<li>UTF8-encoded <a href="#xml">xml</a></li>
<li>raw <a href="#binary">binary</a> data</li>
<li><a href="#remote">remote</a> objects</li>
</ol>

<p>It has 2 combining constructs:</p>
<ol>
<li><a href="#list">list</a> for lists and arrays</li>
<li><a href="#map">map</a> for objects and hash tables.</li>
</ol>

<p>Finally, it has 2 special contructs:</p>
<ol>
<li><a href="#null">null</a> for null values</li>
<li><a href="#ref">ref</a> for shared and circular object references.</li>
</ol>

<p>Hessian 2.0 has 3 reference maps:</p>

<ol>
<li>An object/list reference map.</li>
<li>A type (class) reference map.</li>
<li>An object definition reference map.</li>
</ol>

<s2 title="binary data" type="defun">

<def title="binary grammar">
binary ::= b b1 b0 &lt;binary-data> binary
       ::= B b1 b0 &lt;binary-data>
       ::= [x20-x2f] &lt;binary-data>
</def>

<p>Binary data is encoded in chunks.  <var>'B'</var> represents the final chunk
and <var>'b'</var> represents any non-final chunk.  Each chunk has a 16-bit
length value.</p>

<s3 title="Compact: short binary">

<p>Binary data with length less than 15 may be encoded with a single
length byte [x20-x2f].</p>

</s3>

<s3 title="binary data examples">

<def title="binary data examples">
x20               # zero-length binary data

x23 x01 x02 x03   # 3 byte data

B x10 x00 ....    # 4k final chunk of data

b x04 x00 ....    # 1k non-final chunk of data
</def>

</s3>

</s2>

<s2 title="boolean" type="defun">

<def title="boolean grammar">
boolean ::= T
        ::= F
</def>

<p>The byte <var>'F'</var> represents false and the byte <var>'T'</var>
represents true.</p>

<example title="boolean examples">
T   # true
F   # false
</example>

</s2>

<s2 title="date" type="defun">

<def>
date ::= d b7 b6 b5 b4 b3 b2 b1 b0
</def>

<p>Date represented by a 64-bit long of milliseconds since the epoch, GMT.</p>

<example title="2:51:31 May 8, 1998 GMT">
d x00 x00 x00 xd0 x4b x92 x84 xb8
</example>

</s2>

<s2 title="double" type="defun">

<def title="double grammar">
double ::= D b7 b6 b5 b4 b3 b2 b1 b0
       ::= x67
       ::= x68
       ::= x69 b0
       ::= x6a b1 b0
       ::= x6b b3 b2 b1 b0
</def>

<p>A 64-bit IEEE floating pointer number.</p>

<s3 title="Compact: double zero">

<p>The double 0.0 can be represented by the byte <code>x67</code></p>

</s3>

<s3 title="Compact: double one">

<p>The double 1.0 can be represented by the byte <code>x68</code></p>

</s3>

<s3 title="Compact: double byte">

<p>Doubles between -128.0 and 127.0 with no fractional component
can be represented in two bytes by casting the byte value to a double.</p>

</s3>

<s3 title="Compact: double short">

<p>Doubles between -32768.0 and 32767.0 with no fractional component
can be represented in three bytes by casting the short value to a double.</p>

</s3>

<s3 title="Compact: double float">

<p>Doubles which are equivalent to their 32-bit float representation
can be represented as the 4-byte float and then cast to double.</p>

</s3>

<s3 title="double examples">

<example title="double examples">
x67          # 0.0
x68          # 1.0

x69 x00      # 0.0
x69 x80      # -128.0
x69 xff      # 127.0

x70 x00 x00  # 0.0
x70 x80 x00  # -32768.0
x70 xff xff  # 32767.0

D x40 x28 x80 x00 x00 x00 x00 x00  # 12.25
</example>

</s3>

</s2>

<s2 title="int" type="defun">

<def title="integer grammar">
int ::= 'I' b3 b2 b1 b0
    ::= [x80-xbf]
    ::= [xc0-xcf] b0
    ::= [xd0-xd7] b1 b0
</def>

<p>A 32-bit signed integer.  An integer is represented by the
byte <var>'I'</var> followed by the 4-bytes of the integer in big-endian
order</p>

<s3 title="Compact: single octet integers">

<p>Integers between -16 and 47 can be encoded by a single byte in the
range <code>x80</code> to <code>xbf</code>.
The value of the integer is <code>code - x90</code>.</p>

</s3>

<s3 title="Compact: two octet integers (byte)">

<p>Integers between -2048 and 2047 can be encoded in two bytes with
the leading byte in the range <code>xc0</code> to <code>xcf</code>.
The value of the integer is <code>256 * (code - xc8) + b0</code>.</p>

</s3>

<s3 title="Compact: three octet integers (short)">

<p>Integers between -262144 and 262143 can be encoded in three bytes with
the leading byte in the range <code>xd0</code> to <code>xd7</code>.
The value of the integer is <code>65536 * (code - xd4) + 256 * b1 + b0</code>.</p>

</s3>

<s3 title="int examples">

<example title="integer examples">
x90                # 0
x80                # -16
xbf                # 47

xc8 x00            # 0
xc0 x00            # -2048
xc7 x00            # -256
xcf xff            # 2047

xd4 x00 x00        # 0
xd0 x00 x00        # -262144
xd7 xff xff        # 262143

I x00 x00 x00 x00  # 0
I x00 x00 x01 x2c  # 300
</example>

</s3>

</s2>

<s2 title="list" type="defun">

<def title="list grammar">
list ::= V type? length? object* z
     ::= v int int object*
</def>

<p>An ordered list, like an array.  All lists have a type string,
a length, a list of objects, and a trailing 'z'.
The type string may be an arbitrary UTF-8 string understood
by the service (often a Java class name, but this isn't required.)
The length may be -1 to indicate that the list is variable length.
</p>

<p>Each <var>list</var> item is added to the reference list to handle
shared and circular elements.  See the
<var>ref</var> element.</p>

<p>Any parser expecting a <var>list</var> must also accept a <var>null</var>
or a shared <var>ref</var>.</p>

<note>The valid values of <var>type</var> are not specified in this
document and may depend on the specific application.  For example, a
Java EJB server which exposes an Hessian interface can use the <var>type</var>
information to instantiate the specific array type.
On the other hand, a Perl server would likely ignore the contents of <var>type</var>
entirely and create a generic array.
</note>

<s3 title="Compact: repeated list">

<p>Hessian 2.0 allows a compact form of the list for successive lists of
the same type where the length is known beforehand.
The type and length are encoded by integers, where the type is a reference to
an earlier specified type.</p>

</s3>

<s3 title="list examples">

<results title="serialization of a Java int[] = {0, 1}">
V
  t x00 x04 [int     # encoding of int[] type
  x6e x02            # length = 2
  x90                # integer 0
  x91                # integer 1
  z
</results>

<results title="anonymous variable-length list = {0, &quot;foobar&quot;}">
V
  x90                # integer 0
  x06 foobar         # "foobar"
  z
</results>

<example title="repeated list type">
V
  t x00 x04 [int   # type for int[] (save as type #1)
  x63 x02          # length 2
  x90              # integer 0
  x91              # integer 1
  z

v
  x91              # type reference to int[] (integer #1)
  x92              # length 2
  x92              # integer 2
  x93              # integer 3
</example>

</s3>

</s2>

<s2 title="long" type="defun">

<def>
long ::= L b7 b6 b5 b4 b3 b2 b1 b0
     ::= [xd8-xef]
     ::= [xf0-xff] b0
     ::= [x38-x3f] b1 b0
     ::= x77 b3 b2 b1 b0
</def>

<p>A 64-bit signed integer.  An long is represented by the
byte <var>'L'</var> followed by the 8-bytes of the integer in big-endian order
</p>

<s3 title="Compact: single octet longs">

<p>Longs between -8 and 15 are represented by a single byte in the
range <code>xd8</code> to <code>xef</code>.
The value of the long is <code>code - xe0</code>.</p>

</s3>

<s3 title="Compact: two octet longs (byte)">

<p>Longs between -2048 and 2047 are encoded in two bytes with
the leading byte in the range <code>xf0</code> to <code>xff</code>.
The value of the long is <code>256 * (code - xf8) + b0</code>.</p>

</s3>

<s3 title="Compact: three octet longs (short)">

<p>Longs between -262144 and 262143 are encoded in three bytes with
the leading byte in the range <code>x38</code> to <code>x3f</code>.
The value of the long is <code>65536 * (code - x3c) + 256 * b1 + b0</code>.</p>

</s3>

<s3 title="Compact: four octet longs (int)">

<p>Longs between which fit into 32-bits are encoded in five bytes with
the leading byte <code>x77</code>.</p>

</s3>

<example title="long examples">
xe0                  # 0
xd8                  # -8
xef                  # 15

xf8 x00              # 0
xf0 x00              # -2048
xf7 x00              # -256
xff xff              # 2047

x3c x00 x00          # 0
x38 x00 x00          # -262144
x3f xff xff          # 262143

x77 x00 x00 x00 x00  # 0
x77 x00 x00 x01 x2c  # 300

L x00 x00 x00 x00 x00 x00 x01 x2c  # 300
</example>

</s2>

<s2 title="map" type="defun">

<def>
map        ::= M type? (object object)* z
           ::= 'o' int object*

object-def ::= 'O' type int string*
</def>

<p>Represents serialized objects and Maps. The <var>type</var>
element describes the type of the map.  Objects are represented by a
map from field names to their values and <var>type</var> is the class
of the object itself.</p>

<p>The <var>type</var> may be empty, i.e. a zero length.  The parser is
responsible for choosing a type if one is not specified.
For objects, unrecognized keys will be ignored.</p>

<p>Each <var>map</var> is added to the reference list.  Any time the
parser expects a <var>map</var>, it must also be able to support a
<var>null</var> or a <var>ref</var>.</p>

<note>The <var>type</var> is chosen by the service.  Often it may be the
Java classname describing the service.</note>

<s3 title="Compact: object definition">

<p>Hessian 2.0 has a compact object form where the field names
are only serialized once.  Following objects only need to serialize
their values</p>

<p>The object definition includes a mandatory type string, the number of
fields, and the field names.  The object definition is stored in the
object definition map and will be referenced by object instances with
an integer reference.</p>

</s3>

<s3 title="Compact: object instantiation">

<p>Hessian 2.0 has a compact object form where the field names
are only serialized once.  Following objects only need to serialize
their values</p>

<p>The object instantiation creates a new object based on a previous
definition.   The integer value refers to the object definition.</p>

</s3>

<s3 title="map examples">

<example title="A sparse array">
map = new HashMap();
map.put(new Integer(1), "fee");
map.put(new Integer(16), "fie");
map.put(new Integer(256), "foe");

---

M
  x91       # 1
  x03 fee   # "fee"

  xa0       # 16
  x03 fie   # "fie"

  xb9 x00   # 256
  x03 foe   # "foe"

  z
</example>

<example title="Serialization of a Java Object">
public class Car implements Serializable {
  String color = "aquamarine";
  String model = "Beetle";
  int mileage = 65536;
}

---
M
  t x00 x13 com.caucho.test.Car  # type

  x05 color                # color field
  x0a aquamarine

  x05 model                # model field
  x06 Beetle

  x07 mileage              # mileage field
  I x00 x01 x00 x00
  z
</example>

<example title="Compact Object serialization">
class Car {
  String color;
  String model;
}

out.writeObject(new Car("red", "corvette"));
out.writeObject(new Car("green", "civic"));

---

O                        # object definition (#0)
  t x00 x0b example.Car  # type is example.Car
  x92                    # two fields
  x05 color              # color field name
  x05 model              # model field name

o
  x90                    # object definition #0
  x03 red                # color field value
  x08 corvette           # model field value

o
  x90                    # object definition #0
  x05 green              # color field value
  x05 civic              # model field value
</example>

<example title="Enumeration serialization">
enum Color {
  RED,
  GREEN,
  BLUE,
}

out.writeObject(Color.RED);
out.writeObject(Color.GREEN);
out.writeObject(Color.BLUE);
out.writeObject(Color.GREEN);

---

O                         # object definition #0
  t x00 x0b example.Color # type is example.Color
  x91                     # one field
  x04 name                # enumeration field is "name"

o                         # object #0
  x90                     # object definition ref #0
  x03 RED                 # RED value

o                         # object #1
  x90                     # object definition ref #0
  x05 GREEN               # GREEN value

o                         # object #2
  x90                     # object definition ref #0
  x04 BLUE                # BLUE value

x4a x01                   # object ref #1, i.e. Color.GREEN
</example>

</s3>

</s2>

<s2 title="null" type="defun">

<def title="null grammar">
null ::= N
</def>

<p>Null represents a null pointer.</p>

<p>The byte <var>'N'</var> represents the null pointer.</p>

<p><var>null</var> values are allowed in place of any <var>string</var>, <var>xml</var>,
<var>binary</var>, <var>list</var>, <var>map</var>, or <var>remote</var>.</p>
</s2>

<s2 title="ref" type="defun">
<p>An integer referring to a previous <var>list</var> or <var>map</var>
instance.  As each <var>list</var> or <var>map</var> is read from the
input stream, it is assigned the integer position in the stream,
i.e. the first <var>list</var> or <var>map</var> is '0', the next is '1', etc.
A later <var>ref</var> can then use the previous object.  Writers are not
required to generate <var>refs</var>, but parsers must be able to recognize them.
</p>

<def>
ref ::= R b3 b2 b1 b0
</def>

<p><var>ref</var> can refer to incompletely-read items.  For example, a
circular linked-list will refer to the first link before the entire list
has been read.</p>

<p>A possible implementation would add each <var>map</var> and <var>list</var> to an
array as it's read.  The <var>ref</var> will return the corresponding
object from the array.  To support circular structures, the
implementation would store the <var>map</var> or <var>list</var> immediately,
before filling in the object's contents.</p>

<p>Each &lt;list&gt; or &lt;array&gt; is stored into an array as it is
parsed.  &lt;ref&gt; selects one of the stored objects.  The first
object is numbered '0'.</p>

<example title="circular list">
list = new LinkedList();
list.head = 1;
list.tail = list;
</example>
<results>
M t x00 x0a LinkedList
  S x00 x04 head
  I x00 x00 x00 x01
  S x00 x04 tail
  R x00 x00 x00 x00
  z
</results>

<note><var>ref</var> only refers to <var>list</var> and <var>map</var> elements.
<var>string</var> and <var>binary</var>, in particular, will only share
references if they're wrapped in a <var>list</var> or <var>map</var>.</note>

</s2>

<s2 title="remote" type="defun">
<p>A reference to a remote object.  The remote has a
<var>type</var> and a utf-8 string representing the object's URL.</p>

<def>
remote ::= r t b1 b0 &lt;type-name> string
</def>

<results title="EJB Session Reference">
r t x00 x0c test.TestObj
  S x00 x24 http://slytherin/ejbhome?id=69Xm8-zW
</results>

</s2>

<s2 title="string" type="defun">

<def title="string grammar">
string ::= s b1 b0 &lt;utf-8-data> string
       ::= S b1 b0 &lt;utf-8-data>
       ::= [x00-x1f] &lt;utf-8-data>
</def>

<p>A 16-bit unicode character string encoded in UTF-8.
Strings are encoded in chunks.  <var>'S'</var> represents the final chunk
and <var>'s'</var> represents any non-final chunk.  Each chunk has a 16-bit
length value.</p>

<p>The length is the number of characters, which may be different than
the number of bytes.</p>

<p>String chunks may not split surrogate pairs.</p>

<s3 title="Compact: short strings">

<p>Strings with length less than 32 may be encoded with a single
byte length [x00-x1f].</p>

</s3>

<s3 title="string examples">

<example title="String examples">
x00             # "", empty string
x05 hello       # "hello"
x01 xc3 x83     # "\u00c3"

S x00 x05 hello # "hello"
</example>

</s3>

</s2>

<s2 title="xml" type="defun">

<def title="xml grammar">
xml ::= x b1 b0 &lt;utf-8-data> xml
    ::= X b1 b0 utf-8-data
</def>
<p>An XML document encoded as a 16-bit unicode character
string encoded in UTF-8.
XML data is encoded in chunks.  <var>'X'</var> represents the final chunk
and <var>'x'</var> represents any initial chunk.</p>

<p>Each chunk has a 16-bit
length value.  The length is the number of characters, which may
be different than the number of bytes.</p>

<example title="trivial XML document">
X x00 x10 &lt;top&gt;hello&lt;/top&gt;
</example>

<note>Because this document does not define the language mapping,
implementations are free to return a string when reading an <var>xml</var>
entity.</note>

</s2>

</s1>

<s1 title="Messages and Envelopes">

<p>Hessian message syntax organizes serialized data for messaging and RPC
applications.  The envelope syntax enables compression,
encryption, signatures, and any routing or context headers to wrap a
Hessian message.</p>

<ul>
<li>Call ('c'): contains a Hessian RPC call, with a method name and arguments.</li>
<li>Envelope ('E'): wraps a Hessian message for compression, encryption, etc.  Envelopes can be nested.</li>
<li>Message ('p'): contains a sequence of serialized Hessian objects.</li>
<li>Reply ('r'): contains a reply to a Hessian RPC call.</li>
</ul>

<s2 title="Call">

<def>
call ::= c x02 x00 m b1 b0 &lt;method-string> object* z
</def>

<p>A Hessian call invokes a method on an object with an argument
list.  The object is specified by the container, e.g. for a HTTP
request, it's the HTTP URL.  The arguments are
specified by Hessian serialization.</p>

<s3 title="Methods and Overloading">

<p>Method names must be unique.  Two styles of overloading are
supported: overloading by number of argumetns and overloading
by argument types.  Overloading is permitted by
encoding the argument types in the method names.  The types of
the actual arguments must not be used to select the methods.</p>

<p>Method names beginning with <var>_hessian_</var> are reserved.</p>

<p>Servers should accept calls with either the mangled method name
or the unmangled method name.  Clients should send the mangled method name.</p>

<note>See the Java binding for a possible overloading scheme.</note>

<example>add(int a, int b)</example>
<results>add_int_int</results>
<example>add(double a, double b)</example>
<results>add_double_double</results>
<example>add(shopping.Cart cart, shopping.Item item)</example>
<results>add_shopping.Cart_shopping.Item</results>

</s3>

<s3 title="Arguments">

<p>Arguments immediately follow the method in positional order.
Argument values use Hessian's serialization.</p>

<p>All arguments share references, i.e. the reference list
starts with the first argument and continues for all other arguments.
This lets two arguments share values.</p>

<example title="remote.eq(bean, bean)">
bean = new qa.Bean("foo", 13);

System.out.println(remote.eq(bean, bean));
</example>
<results>
c x02 x00
  m x00 x02 eq
  M t x00 x07 qa.Bean
    S x00 x03 foo
    I x00 x00 x00 x0d
    z
  R x00 x00 x00 x00
  z
</results>

<p>The number and type of arguments are fixed by the remote method.
Variable length arguments are forbidden.  Implementations
may take advantage of the expected type to improve performance.</p>

</s3>

<s3 title="Call examples">

<example title="obj.add2(2,3) call">
c x02 x00         # call for Hessian 2.0
  m x00 x04 add2  # method "add2"
  x92             # 2 - argument 1
  x93             # 3 - argument 2
  z               # end of argument marker
</example>

<example title="obj.add2(2,3) reply">
r x02 x00
  x95
  z
</example>

</s3>

</s2>

<s2 title="Envelope">

<def>
envelope ::= E x02 x00 m b1 b0 &lt;method-string> env-chunk* z

env-chunk ::= int (string object)* binary int (string object)*
</def>

<p>A Hessian envelope wraps a Hessian message, adding headers and footers
and possibly compressing or encrypting the wrapped message.  The envelope
type is identified by a method string, e.g.
"com.caucho.hessian.io.Deflation" or
"com.caucho.hessian.security.X509Encryption".
</p>

<p>Some envelopes may chunk the data, providing multiple header/footer
chunks.  For example, a signature envelope might chunk a large
streaming message to reduce the amount of buffering required to validate
the signatures.</p>

<s3 title="Envelope examples">

<example title="identity envelope">
E x02 x00
  m x00 x08 Identity   # "Identity" envelope does nothing to the body
  x90                  # no headers
  B x00 x0a            # binary wrapped body (12 bytes)
    p x02 x00          # wrapped message
    x05 hello          # "hello"
    z                  # end of wrapped message
  x90                  # no footers
  z                    # end of envelope
</example>

<example title="chunked identity envelope">
E x02 x00
  m x00 x08 Identity   # "Identity" envelope does nothing to the body
  x90                  # no headers
  B x00 x0c            # binary header for wrapped body (10 bytes)
    p x02 x00          # wrapped message
    x07 hello,         # "hello, "
    z                  # end of wrapped message
  x90                  # no footers

  x90                  # no headers
  B x00 x08            # binary wrapped body (10 bytes)
    p x02 x00          # wrapped message
    x05 world          # world
    z
  x90                  # no footers
  z                    # end of envelope
</example>

</s3>

<example title="compression envelope">
E x02 x00
  m x00 x09 Deflation  # "Deflation" envelope compresses the body
  x90                  # no headers
  B x00 x0a            # binary wrapped body (32 bytes)
    x78 x9c x4b...     # compressed message
  x90                  # no footers
  z                    # end of envelope
</example>

</s2>

<s2 title="Message">

<def>
message ::= p x02 x00 object* z
</def>

<p>A Hessian message contains a sequence
of Hessian serialized objects.  Messages can be used for multihop data
transfer or simply for storing serialized data.
</p>

</s2>

<s2 title="Reply">

<def>
valid-reply ::= r x02 x00 header* object z
fault-reply ::= r x02 x00 header* fault z
</def>

<s3 title="Value">
  
<p>A successful reply returns a single value and possibly
some header information.  </p>
  
<example title="integer 5 result">
r x01 x00
  I x00 x00 x00 x05
  z
</example>

</s3>
<s3 title="Faults">
<p>Failed calls return a <var>fault</var>.</p>

<p>Each fault has a number of informative fields, expressed like
&lt;map&gt; entries.  The defined fields are <var>code</var>, <var>message</var>,
and <var>detail</var>. <var>code</var> is one of a short list of strings
defined below.  <var>message</var> is a user-readable message.
<var>detail</var> is an object representing the exception.  In Java,
<var>detail</var> will be a serialized exception.</p>

<results title="Remote Call throws FileNotFoundException">
r x01 x00
  f
  S x00 x04 code
  S x00 x10 ServiceException

  S x00 x07 message
  S x00 x0e File Not Found

  S x00 x06 detail
  M t x00 x1d java.io.FileNotFoundException
    z
  z
</results>

<deftable>
<tr>
  <td>ProtocolException</td>
  <td>The Hessian request has some sort of syntactic error.</td>
</tr>
<tr>
  <td>NoSuchObjectException</td>
  <td>The requested object does not exist.</td>
</tr>
<tr>
  <td>NoSuchMethodException</td>
  <td>The requested method does not exist.</td>
</tr>
<tr>
  <td>RequireHeaderException</td>
  <td>A required header was not understood by the server.</td>
</tr>
<tr>
  <td>ServiceException</td>
  <td>The called method threw an exception.</td>
</tr>
</deftable>

</s3>

</s2>

<s2 title="Versioning">

<p>The call and response tags include a major and minor byte.  The
current version is 2.0.</p>

</s2>

</s1>

<s1 title="Service Location (URLs)">

<p>Hessian services are identified by URLs.  Typically, these will be
HTTP URLs, although protocols would be possible as well.</p>

<s2 title="Object Naming (non-normative)">

<p>
URLs are flexible
enough to encode object instances as well as simple
static service locations.  The URL uniquely identifies the
Hessian object.  Thus, Hessian can support
object-oriented services, e.g. naming services, entity beans, or
session beans, specified by the URL without requiring extra method parameters
or headers.</p>

<p>Object naming may use the query string convention that "?id=XXX"
names the object "XXX" in the given service.  This convention is recommented,
but not required.</p>

<p>For example, a stock quote service might have a
factory interface like http://foo.com/stock and object instances
like http://foo.com?id=PEET.  The factory interface would return valid
object references through the factory methods.</p>

</s2>

<s2 title="Object naming (non-normative)">

<p>As an example, the following format is used for EJB:</p>

<def>
http://hostname/hessian<var>/ejb-name</var>?id=<var>object-id</var>
</def>

<p><var>http://hostname/hessian</var> identifies the EJB container.
In Resin-EJB, this will refer to the EJB Servlet. 
"/hessian" is the servlet prefix (url-pattern.)  HTTP is just used as
an example; Hessian does not require the use of HTTP.
</p>

<p><var>/ejb-name</var>, the path info of the request, identifies the EJB name,
specifically the home interface.  EJB containers can contain several
entity and session beans, each with its own EJB home.  The <var>ejb-name</var>
corresponds to the ejb-name in the deployment descriptor.
</p>

<p><var>object-id</var> identifies the specific object.  For entity beans, the
object-id encodes the primary key.  For session beans, the object-id encodes
a unique session identifier.  Home interfaces have no ";ejbid=..." portion.
</p>

<example title="Example Entity Home Identifier">
http://localhost/hessian/my-entity-bean
</example>

<example title="Example Entity Bean Identifier">
http://localhost/hessian/my-entity-bean?ejbid=slytherin
</example>

<example title="Example Session Home Identifier">
http://localhost/hessian/my-session-bean
</example>

<example title="Example Session Bean Identifier">
http://localhost/hessian/my-session-bean?ejbid=M9Zs1Zm
</example>

</s2>

</s1>

<s1 title="Bytecode map">

<p>Hessian is organized as a bytecode protocol.  A Hessian
implementation is essentially a big switch statement on the initial
bytecode.</p>

<def title="Bytecode Encoding">
x00 - x1f    # utf-8 string length 0-32
x20 - x2f    # binary data length 0-16
x30 - x37    # reserved
x38 - x3f    # long from -x40000 to x3ffff
x40 - x41    # reserved
x42          # 8-bit binary data final chunk ('B')
x43          # reserved ('C' streaming call)
x44          # 64-bit IEEE encoded double ('D')
x45          # reserved ('E' envelope)
x46          # boolean false ('F')
x47          # reserved
x48          # reserved ('H' header)
x49          # 32-bit signed integer ('I')
x4a          # reference to 1-256th map/list
x4b          # reference to 1-65536th map/list
x4c          # 64-bit signed long integer ('L')
x4d          # map with optional type ('M')
x4e          # null ('N')
x4f          # object definition ('O')
x50          # reserved ('P' streaming message/post)
x51          # reserved
x52          # reference to map/list - integer ('R')
x53          # utf-8 string final chunk ('S')
x54          # boolean true ('T')
x55          # reserved
x56          # list/vector ('V')
x57          # reserved
x58          # utf-8 xml final chunk ('X')
x59 - x62    # reserved
x62          # 8-bit binary data non-final chunk ('b')
x63          # reserved ('c' call for RPC)
x64          # UTC time encoded as 64-bit long milliseconds since epoch ('d')
x65          # reserved
x66          # reserved ('f' for fault for RPC)
x67          # double 0.0
x68          # double 1.0
x69          # double represented as byte (-128.0 to 127.0)
x6a          # double represented as short (-32768.0 to 327676.0)
x6b          # double represented as float
x6c          # list/vector length ('l')
x6d          # reserved ('m' method for RPC call)
x6e          # list/vector compact length
x6f          # object instance ('o')
x70          # reserved ('p' - message/post)
x71          # reserved
x72          # reserved ('r' reply for message/RPC)
x73          # utf-8 string non-final chunk ('s')
x74          # map/list type ('t')
x75          # type-ref
x76          # compact vector ('v')
x77          # long encoded as 32-bit int
x78          # utf-8 XML non-final chunk ('x')
x79          # reserved
x7a          # list/map terminator ('z')
x7b - x7f    # reserved
x80 - xbf    # one-byte compact int (-x10 to x3f, x90 is 0)
xc0 - xcf    # two-byte compact int (-x800 to x3ff)
xd0 - xd7    # three-byte compact int (-x40000 to x3ffff)
</def>

</s1>

<s1 title="Copyright and Licensing">

<p>
Copyright 2000-2007 Caucho Technology, Inc. All Rights Reserved.
</p>

<p>Any party may implement this protocol for any purpose without royalty
or license fee, provided that the implementation conforms to this
specification.   Caucho Technology reserves the right to create a
test suite, freely available without royalty or license fee, to
validate implementation conformance.  The limited permissions granted
herein are perpetual and may not be revoked by Caucho Technology or
its successors or assigns.</p>

<p>This document and translations of it may be copied and furnished to
others, and derivative works that comment on or otherwise explain it
or assist in its implementation may be prepared, copied, published and
distributed, in whole or in part, without restriction of any kind,
provided that the above copyright notice and these paragraphs are
included on all such copies and derivative works.</p>

<p>This document and the information contained herein is provided on an
"AS IS" basis and CAUCHO TECHNOLOGY DISCLAIMS ALL WARRANTIES, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF
THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.</p>

</s1>

<s1 title="Changes">

<s2 title="changes in 2.0 draft 2">

<ul>
<li>Added envelope ('E') syntax.</li>
<li>Added post/message ('p') syntax.</li>
<li>Changed encoding to avoid name conflicts.</li>
<li>Split object definition/instance.</li>
<li>Expanded int and string single-byte range.</li>
</ul>

</s2>

<s2 title="changes in 2.0 draft 1">

<ul>
<li>Added compact encoding.</li>
</ul>

</s2>

<s2 title="changes in 1.0.2">

<ul>
<li>Clarified that length of XML and strings is in characters (Petr Gladkikh)
</li></ul>
</s2>

<s2 title="changes in 1.0">

<ul>
<li>Removed unidirectional messages.
</li></ul>
</s2>

<s2 title="changes in V3">

<ul>
<li>Added unidirectional messages
</li><li>Removed 'v' from reply
</li><li>changed length code to 'l'
</li><li>made <var>type</var> and <var>length</var> optional
</li></ul>

</s2>

<s2 title="changes in V2">

<ul>
<li>EJB naming: clarified examples especially for session beans (John Mitchell)
</li><li>Formal definitions: clarified grammar and added missing object (John Mitchell)
</li><li>Formal definitions: initial binary should use 'b' (John Mitchell)
</li></ul>

</s2>

</s1>
</body></document>
