<document>
  <header>
    <product>resin</product>
    <resin-2.0>$resin/ref/hessian.xtp</resin-2.0>
    <title>Hessian 1.1 Draft Specification</title>
    <date>Feb 10, 2004</date>
    <description>
      <p>Hessian is a compact binary protocol for connecting web
      services.</p>

      <p>Because Hessian is a small protocol, J2ME devices like cell-phones can use
      it to connect to Resin servers.  Because it's powerful, it can be used
      for EJB services.</p>
    </description>
  </header>

  <body>
    <summary/>

<section title="Design Goals">

<p>The Hessian web services protocol was created as a
lightweight binary alternative to the XML-based web services protocols.
</p>

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

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

<p>Given the EJB environment, the Hessian protocol has the
following requirements:</p>

<ul>
<li>It must support XML as a first class object.
<li>It must not require external IDL or schema definitions; it should be
invisible to application writers.
<li>It must have sufficient power to serialize Java.
<li>It must have sufficient power to support EJB.
<li>It must allow non-Java clients to use web services.
<li>It must allow web services to deployed as a Servlet.
<li>It must be simple so it can be effectively tested.
<li>It must be as fast as possible.
<li>It should support transaction contexts.
</ul>

</section>

<section title='Serialization'>

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

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

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

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

<defun title='null'>
<p>Null represents a null pointer.</p>

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

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

<example title='null'>
null ::= N
</example>
</defun>

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

<def>
boolean ::= T
        ::= F
</def>

<example title='boolean true'>
T
</example>

</defun>

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

<def>
int ::= I b32 b24 b16 b8
</def>

<example title='integer 300'>
I x00 x00 x01 x2c
</example>

</defun>

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

<def>
long ::= L b64 b56 b48 b40 b32 b24 b16 b8
</def>

<example title='long 300'>
L x00 x00 x00 x00 x00 x00 x01 x2c
</example>

</defun>

<defun title='double'>
<p>A 64-bit IEEE floating pointer number.</p>

<def>
double ::= D b64 b56 b48 b40 b32 b24 b16 b8
</def>

<example title='double 12.25'>
D x40 x28 x80 x00 x00 x00 x00 x00
</example>

</defun>

<defun title='date'>
<p>Date represented by a 64-bits long of milliseconds since the epoch.</p>

<def>
date ::= d b64 b56 b48 b40 b32 b24 b16 b8
</def>

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

</defun>

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

<def>
string ::= (s b16 b8 utf-8-data)* S b16 b8 utf-8-data
</def>

<example title='"Hello" string'>
S x00 x05 hello
</example>
</defun>

<defun title='xml'>
<p>An XML document encoded as a 16-bit unicode character
string encoded in UTF-8.
XML data is encoded in chunks.  <var/'X'/> represents the final chunk
and <var/'x'/> represents any initial chunk.  Each chunk has a 16-bit
length value.</p>

<def>
xml ::= (x b16 b8 utf-8-data)* X b16 b8 utf-8-data
</def>

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

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

</defun>

<defun title='binary'>
<p>A binary value.</p>

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

<def>
binary ::= (b b16 b8 binary-data)* B b16 b8 binary-data
</def>

</defun>

<defun title='list'>
<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>

<def>
list ::= V <var/type/>? <var/length/>? <var/object/>* z
</def>

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

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

<results title='serialization of a Java int[] = {0, 1}'>
V t x00 x04 [int
  l x00 x00 x00 x02
  I x00 x00 x00 x00
  I x00 x00 x00 x01
  z
</results>

<results title='anonymous variable-length list = {0, "foobar"}'>
V I x00 x00 x00 x00
  S x00 x06 foobar
  z
</results>

<note>The valid values of <var/type/> 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/>
information to instantiate the specific array type.
On the other hand, a Perl server would likely ignore the contents of <var/type/>
entirely and create a generic array.
</note>

</defun>

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

<def>
map ::= M t b16 b8 type-string (<var/object/>, <var/object/>)* z
</def>

<p>The <var/type/> 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/> is added to the reference list.  Any time the
parser expects a <var/map/>, it must also be able to support a
<var/null/> or a <var/ref/>.</p>

<example title='Serialization of a Java Object'>
public class Car implements Serializable {
  String model = "Beetle";
  String color = "aquamarine";
  int mileage = 65536;
}
</example>
<results>
M t x00 x13 com.caucho.test.Car
  S x00 x05 model
  S x00 x06 Beetle

  S x00 x05 color
  S x00 x0a aquamarine

  S x00 x07 mileage
  I x00 x01 x00 x00
  z
</results>

<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");
</example>
<results>
M I x00 x00 x00 x01
  S x00 x03 fee

  I x00 x00 x01 x00
  S x00 x03 fie

  I x00 x01 x00 x00
  S x00 x03 foe

  z
</results>

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

</defun>

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

<def>
ref ::= R b32 b24 b16 b8
</def>

<p><var/ref/> 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/> and <var/list/> to an
array as it's read.  The <var/ref/> will return the corresponding
object from the array.  To support circular structures, the
implementation would store the <var/map/> or <var/list/> immediately,
before filling in the object's contents.</p>

<p>Each &lt;list> or &lt;array> is stored into an array as it is
parsed.  &lt;ref> 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/> only refers to <var/list/> and <var/map/> elements.
<var/string/> and <var/binary/>, in particular, will only share
references if they're wrapped in a <var/list/> or <var/map/>.</note>

</defun>

<defun title='placeholder'>
<p>A placeholder for a reference.  In certain cases, such as a
writeReplace method, it's important to add two references
for the same object.  The 'P' is a placeholder for a following object.
</p>

<def>
placeholder ::= P
</def>

</defun>

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

<def>
remote ::= r t b16 b8 type-name S b16 b8 url
</def>

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

</defun>

</section>

<section title='Call'>

<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>

<def>
call ::= c x01 x00 <var/header/>* m b16 b8 method-string (<var/object/>)* z
</def>

<example title="obj.add2(2,3) call">
c x01 x00
  m x00 x04 add2
  I x00 x00 x00 x02
  I x00 x00 x00 x03
  z
</example>

<example title="obj.add2(2,3) reply">
r x01 x00
  I x00 x00 x00 x05
  z
</example>

<s3 title='Object Naming'>

<p>The URL uniquely identifies the Hessian object.  This spec does
not mandate any particular URL naming convention.</p>

</s3>

<s3 title="EJB naming (non-normative)">

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

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

<p><var/http://hostname/hessian/> 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/>, 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/>
corresponds to the ejb-name in the deployment descriptor.
</p>

<p><var/object-id/> 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>

</s3>

<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_/> 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 x01 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='Headers'>

<p>Headers are (string, object) pairs that preceed the arguments.</p>

<p>The value of the header can be any serialized object.</p>

<p>For example, a request might include a transaction context in a
header.</p>

<results title="Call with Distributed Transaction Context">
c x01 x00
  H x00 x0b transaction
  r t x00 x28 com.caucho.hessian.xa.TransactionManager
    S x00 x23 http://hostname/xa?ejbid=01b8e19a77
  m x00 x05 debug
  I x00 x03 x01 xcb
  z
</results>

</s3>

<s3 title='Versioning'>

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

</s3>

</section>

<section title='Reply'>

<def>
valid-reply ::= r x01 x00 <var/header/>* <var/object/> z
fault-reply ::= r x01 x00 <var/header/>* <var/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/>.</p>

<p>Each fault has a number of informative fields, expressed like
&lt;map> entries.  The defined fields are <var/code/>, <var/message/>,
and <var/detail/>. <var/code/> is one of a short list of strings
defined below.  <var/message/> is a user-readable message.
<var/detail/> is an object representing the exception.  In Java,
<var/detail/> 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 x13 java.io.FileNotFoundException
    z
  z
</results>

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

</s3>

</section>

<section title='Metadata (non-normative)'>

<p>Metadata is handled by special method calls, methods beginning
with <var/_hessian_/>.</p>

<p><var/_hessian_getAttribute(String&nbsp;key)/> returns a string.
The following attributes are predefined by this spec:</p>

<deftable>
<tr><th>attribute<th>meaning
<tr><td>home-class<td>Java class for the home interface.
<tr><td>remote-class<td>Java class for the object interface.
<tr><td>primary-key-class<td>Java class for the primary key.
</deftable>

</section>

<section title='Micro Hessian'>

<p>A "Micro Hessian" implementation may omit support for the "double" type.
</p>

</section>

<section title='Formal Definitions'>

<def>
<var/top/>     ::= <var/call/>
        ::= <var/reply/>

<var/call/>    ::= c x01 x00 <var/header/>* <var/method/> <var/object/>* z

<var/reply/>   ::= r x01 x00 <var/header/>* <var/object/> z
        ::= r x01 x00 <var/header/>* <var/fault/> z

<var/object/>  ::= <var/null/>
        ::= <var/boolean/>
        ::= <var/int/>
        ::= <var/long/>
        ::= <var/double/>
        ::= <var/date/>
        ::= <var/string/>
        ::= <var/xml/>
        ::= <var/binary/>
        ::= <var/remote/>
        ::= <var/ref/>
        ::= <var/list/>
        ::= <var/map/>
        ::= P <var/object/>

<var/header/>  ::= H b16 b8 header-string <var/object/>
<var/method/>  ::= m b16 b8 method-string

<var/fault/>   ::= f (<var/object/> <var/object/>)*

<var/list/>    ::= V <var/type/>? <var/length/>? <var/object/>* z
<var/map/>     ::= M <var/type/>? (<var/object/> <var/object/>)* z
<var/remote/>  ::= r <var/type/>? <var/string/>

<var/type/>    ::= t b16 b8 type-string
<var/length/>  ::= l b32 b24 b16 b8

<var/null/>    ::= N
<var/boolean/> ::= T
        ::= F
<var/int/>     ::= I b32 b24 b16 b8
<var/long/>    ::= L b64 b56 b48 b40 b32 b24 b16 b8
<var/double/>  ::= D b64 b56 b48 b40 b32 b24 b16 b8
<var/date/>    ::= d b64 b56 b48 b40 b32 b24 b16 b8
<var/string/>  ::= (s b16 b8 string-data)* S b16 b8 string-data
<var/xml/>     ::= (x b16 b8 xml-data)* X b16 b8 xml-data
<var/binary/>  ::= (b b16 b8 binary-data)* B b16 b8 binary-data
<var/ref/>     ::= R b32 b24 b16 b8
</def>

</section>

<section title="Copyright and Licensing">

&copy; Copyright 2000-2003 Caucho Technology, Inc. All Rights Reserved.

<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>

</section>

<section title="Changes">

<s3 title="changes in 1.1V3">

<ul>
<li>Added 'P' placeholder
</ul>

</s3>

<s3 title="changes in 1.0">

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

<s3 title="changes in V3">

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

</s3>

<s3 title="changes in V2">

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

</s3>

</section>
</document>