<document>

The Burlap protocol was created to solve a specific problem:

> Allow Java Enterprise Java Beans (EJB) services to interoperate with non-Java servers and clients using an XML-based protocol.

The Burlap home page contains the latest information about Burlap.

The name "Burlap" was chosed for a simple reason: it's boring. The wire protocol for web services should be invisible to application writers. Wire protocols should not require external schema or IDL.

Given the EJB environment, the Burlap protocol has the following requirements:

- It must use the simplest possible subset of XML.
- It must not require external IDL or schema definitions; it should be invisible to application writers.
- It must have sufficient power to serialize Java.
- It must have sufficient power to support EJB.
- It must allow non-Java clients to use web services.
- It must allow web services to deployed as a Servlet.
- It must be simple so it can be effectively tested.
- It must be as fast as possible.
- It should support transaction contexts.

The design notes explain some of the design decision in creating the Burlap protocol.

The leading XML-based RPC protocols do not meet these requirements. UserLand's XML-RPC is insufficiently powerful to support Java serialization or EJB. Microsoft's SOAP is overly complicated and underdefined. In particular, it requires XML namespaces, attributes, overly complicated typing, and external schema.

Burlap uses SML (Simple Markup Language), a restricted subset of XML:

- Only elements and character data are allowed.
- No namespaces, no attributes, no processing instructions, no comments, no DTDs, no CDATA sections.
- No mixed content: an element may contain either elements or character data, but not both.
- Only UTF-8 encoding is allowed.
- Only numbered character entities, e.g. &#60;, and the standard XML entities (&lt;, &gt;, and &amp;) are allowed as escapes.
- All whitespace in character data is significant.

The smallness of SML allows less room for bugs, simplifies testing, and makes reasonably-fast implementations feasible. It forces conformance by eliminating ambiguities.

The SML grammar needs only six productions:

<def> tag-list ::= (S tag)* S tag ::= <name> tag-list </name> ::= <name> cdata </name> S ::= (' ' | '\t' | '\r' | '\n')* cdata ::= ([^<&] | &# [0-9]+ ; | &lt; | &gt; | &amp;)* name ::= [a-zA-Z:_] [a-zA-Z0-9.-_:]* </def> <note>SML explicitly forbids XML short tags, e.g. <tag/>, and the XML header, e.g. <?xml version='1.0'?></note>

Burlap's object serialization has 9 primitive types:

1. boolean
2. 32-bit int
3. 64-bit long
4. 64-bit double
5. ISO-8609 date
6. 16-bit UTF8-encoded string
7. 16-bit UTF8-encoded xml
8. base64 binary data
9. remote objects

It has 2 combining constructs:

1. list for lists and arrays
2. map for objects and hash tables.

Finally, it has 2 special contructs:

1. null for null values
2. ref for shared and circular object references.

Null represents a null pointer. The XML short form is forbidden, i.e. <null> must have separate open and close tags.

<null> values are allowed in place of any <string>, <xml>, <base64>, <list>, <map>, or <remote>.

<results> <null></null> </results>

A boolean value expressed as an integer, 0 or 1.

<results> <boolean>0</boolean> </results>

A 32-bit signed integer.

<results> <int>-32132</int> </results>

A 64-bit signed integer.

<results> <long>1000000000</long> </results>

A 64-bit IEEE floating pointer number.

<results> <double>1234.9431e12</double> </results>

A 16-bit unicode character string encoded in UTF-8. The UTF-8 encoding follows from the SML rules. Similarly, the only escapes allowed are &#xx;, &lt;, &gt;, and &amp;. All whitespace is significant.

<results> <string>Escape the less than symbol as &lt; or using the numeric escape &#38;</string> </results>

An XML document encoded as a 16-bit unicode character string encoded in UTF-8, following the rules for <string>. Special characters, like `<' must be escaped. The only escapes allowed are &#xx;, &lt;, &gt;, and &amp;. All whitespace is significant.

<results> <xml> &lt;top&gt; &lt;body test='foo'/&gt; &lt;/top&gt; </xml> </results> <note>Because this document does not define the language mapping, implementations are free to return a string when reading an <xml> entity.</note>

An ISO8609-encoded date.

<results> <date>19880508T095231Z</date> </results>

A base64-encoded binary stream. The base64 string may have whitespace after any triplet, but not within a triplet.

<results> <base64> zxc9Z9 m2z8== </base64> </results>

An ordered list, like an array. The <type> element describes the type of the list and the <length> element specifies the number of values in the list. Both <type> and <length> tags are required, but both may be empty. If the <length> is empty, the receiver will determine the list length from the actual number of elements before the </list>.

<def> list = (type, length, (%object;)*) </def>

Each <list> item is added to the reference list. See the <ref> element.

A <list> might also be represented by a <null> or <ref>. Parsers must be prepared to recognize any of those three.

<list> <type>[int</type> <length>3</length> <int>0</int> <int>1</int> <int>2</int> </list> <list> <type></type> <length>3</length> <int>0</int> <double>1.3</double> <string>foobar</string> </list> <note>The valid values of <type> are not specified in this document and may depend on the specific application. For example, a Java EJB server which exposes an Burlap interface can use the <type> information to instantiate the specific array type. On the other hand, a Perl server would likely ignore the contents of <type> entirely and create a generic array. </note>

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

<def> map ::= (type, ((%object;), (%object;))*) </def>

The <type> element is mandatory, although its value may be empty. For objects, unrecognized keys must be ignored.

Each <map> is added to the reference list. A <map> might also be represented as <null> or <ref>.

public class Car implements Serializable { String model = "Beetle"; String color = "aquamarine"; int mileage = 230431; } <results> <map> <type>com.caucho.test.Car</type> <string>model<string> <string>Beetle</string> <string>color<string> <string>aquamarine</string> <string>mileage<string> <int>230431</int> </map> map = new HashMap(); map.put(new Integer(1), "fee"); map.put(new Integer(75), "fie"); map.put(new Integer(932), "foe"); <results> <map> <type>java.util.HashMap</type> <int>1<int><string>fee</string> <int>75<int><string>fie</string> <int>932<int><string>foe</string> </map> <note>The <type> will depend on the specific protocol. EJB-based protocols will use Java classes.</note>

An integer referring to a previous <list> or <map> instance. As each <list> or <map> is read from the input stream, it is assigned an integer. A later <ref> can then use the previous object.

<def> ref ::= #CDATA </def>

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

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

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

list = new LinkedList(); listhead = 1; list.tail = list; <results> <map> <type>LinkedList</type> <string>head</string><int>1</int> <string>tail</string><ref>0</ref> </map> <note><ref> only to <list> and <map> elements. <string> and <base64>, in particular, can't share references.</note>

A reference to a remote object. The <type> element specifies the object type and the <string> element specifies the remote object's URL.

<def> remote ::= (type, string) </def>

Remote support is optional. Clients and servers don't need to support <remote> if the service doesn't need it.

<remote> <type>test.TestObj</type> <string>http://localhost/ejbhome;ejbid=69Xm8-zW</string> </remote> <note>Needed to support EJB in a reasonably portable way.</note>

A Burlap call invokes a method on an object with an argument list. The object is uniquely named by its URL. The arguments are specified by Burlap serialization.

<def> burlap:call ::= (%header;), method, (%object;)* </def> <burlap:call> <method>add2</method> <int>2</int> <int>3</int> </burlap:call> <burlap:reply> <value> <int>5</int> </value> </burlap:reply>

The URL uniquely identifies the Burlap object. This spec does not mandate any particular URL naming convention.

As an example, the following format is used for EJB:

<def> http://hostname/ejb/ejb-name;ejbid=object-id </def>

http://hostname/ejb identifies the EJB container. In Resin-EJB, this will refer to the EJB Servlet. HTTP is used as an example; Burlap does not require the use of HTTP.

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

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.

http://localhost/ejb/houses http://localhost/ejb/session;ejbid=M9Zs1Zm

Method names must be unique. 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.

Method names beginning with _burlap_ are reserved.

Servers should accept calls with either the mangled method name or the unmangled method name. Clients should send the mangled method name.

<note>See the Java binding for a possible overloading scheme.</note> <example>add(int a, int b) <results>add_int_int <example>add(double a, double b) <results>add_double_double <example>add(shopping.Cart cart, shopping.Item item) <results>add_shopping.Cart_shopping.Item

Arguments immediately follow the method in positional order. Argument values use Burlap's serialization.

<burlap:call> <method>add<method> <int>2</int> <int>3</int> </burlap:call>

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.

bean = new Bean("foo", 13); System.out.println(remote.eq(bean, bean)); <results> <burlap:call> <method>eq<method> <map> <type>Bean</type> <string>foo</string> <int>13</int> </map> <ref>0</ref> </burlap:call>

The number and type of arguments are fixed by the remote method. Variable length arguments are forbidden. In other words, implementations may take advantage of the expected type to improve performance.

Headers are key, value pairs introduced by a <header> tag.

The value of the header can be any serialized object. The reference array is reset for each header. So a header can't point to an object in another header.

For example, a request might include a transaction context in a header. The client could require that the server understand the transaction context or fail.

<burlap:call> <header>transaction<header> <remote>http://hostname/xa;ejbid=01b8e19a77</remote> <method>debit<method> <int>12300</int> </burlap:call>

Burlap requests and responses have no explicit version id. This is deliberate. There are several different changes that get lumped into a 'version', but each needs different handling. In each case, appropriate mechanisms already exist without adding a version.

1. If the Burlap meta-protocol itself changes, the new protocol will use a new top-level tag <burlap-2:call>. In other words the top element, burlap:call, signifies version 1.0.
2. If clients can take advantage of a new server capabilities, it should use <header> version.

<burlap:call> <method>debit<method> <int>12300</int> </burlap:call>

Burlap calls return either a <fault> or an object.

A successful reply returns a single <value> and possibly some header information.

<results> <burlap:reply> <value> <int>5</int> </value> </burlap:reply>

Failed calls return a <fault>.

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

<burlap:reply> <fault> <string>code</string> <string>ServiceException</string> <string>message</string> <string>File Not Found</string> <string>detail</string> <map> <type>java.io.FileNotFoundException</type> </map> </value> </burlap:reply> <deftable>
ProtocolException The Burlap request has some sort of syntactic error.
NoSuchObjectException The requested object does not exist.
NoSuchMethodException The requested method does not exist.
ServiceException The called method threw an exception.
</deftable>

Metadata is handled by special method calls, methods beginning with _burlap_.

_burlap_getAttribute(String key) returns a string. The following attributes are predefined by this spec:

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

A "Micro Burlap" implementation may omit support for the "double" type.

<def> tag-list ::= (S tag)* S tag ::= <name> tag-list </name> ::= <name> cdata </name> S ::= (' ' | '\t' | '\r' | '\n')* cdata ::= ([^<&] | &# [0-9]+ ; | &lt; | &gt; | &amp;)* name ::= [a-zA-Z:_] [a-zA-Z0-9.-_:]* </def> <def> <!DOCTYPE burlap:call> <!ENTITY % object "null | boolean | int | double | string | xml | base64 | date | ref | map | list | remote"> <!ENTITY % header "(header, (%object;))*"> <!ELEMENT burlap:call - - ((%header;), method, (%object;)*)> <!ELEMENT header - - #CDATA> <!ELEMENT method - - #CDATA> <!ELEMENT null - - EMPTY> <!ELEMENT boolean - - #CDATA> <!ELEMENT int - - #CDATA> <!ELEMENT double - - #CDATA> <!ELEMENT string - - #CDATA> <!ELEMENT xml - - #CDATA> <!ELEMENT base64 - - #CDATA> <!ELEMENT date - - #CDATA> <!ELEMENT ref - - #CDATA> <!ELEMENT map - - (type, ((%object;), (%object;))*)> <!ELEMENT list - - (type, length, (%object;)*)> <!ELEMENT type - - #CDATA> <!ELEMENT remote - - (type, string)> </def> <def> <!DOCTYPE burlap:reply> <!ENTITY % object "(null | boolean | int | double | string | xml | base64 | date | ref | map | list | remote)"> <!ENTITY % header "(header, (%object;))*"> <!ELEMENT burlap:reply - - ((%header;), (value | fault))> <!ELEMENT header - - #CDATA> <!ELEMENT value - - (%object;)> <!ELEMENT fault - - (string, (%object;))*> <!ELEMENT null - - EMPTY> <!ELEMENT boolean - - #CDATA> <!ELEMENT int - - #CDATA> <!ELEMENT double - - #CDATA> <!ELEMENT string - - #CDATA> <!ELEMENT xml - - #CDATA> <!ELEMENT base64 - - #CDATA> <!ELEMENT date - - #CDATA> <!ELEMENT ref - - #CDATA> <!ELEMENT map - - (type, ((%object;), (%object;))*)> <!ELEMENT list - - (type, length, (%object;)*)> <!ELEMENT type - - #CDATA> <!ELEMENT remote - - (type, string)> </def>

© Copyright 2000-2002 Caucho Technology, Inc. All Rights Reserved.

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.

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.

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.

- Removed <burlap:envelope> and <burlap:message>.

- Removed <require> header.

- Added <burlap:envelope> and <burlap:message>

- Added <xml>
- Clarified license.
- Allowed variable length arrays.

- <require> must preceed <header> in headers.
- <remote> requires a <type> and <string> value.

- Changed name of protocol from SML-RPC to "Burlap"
- Added and rewrote verbiage.
- base64 may have whitespace between triplets.

- Added Standard XML entities ('&lt;', '&gt;', '&amp;').

- <remote> now takes a single string content, the url.

</document>