Jump to: navigation, search

Difference between revisions of "RAP/Protocol"

< RAP
(Data Type Reference)
(41 intermediate revisions by 3 users not shown)
Line 1: Line 1:
 
== Introduction ==
 
== Introduction ==
  
The RAP Protocol is the JSON-based format used within the HTTP-Requests from a RAP-client to a RAP-server. Compared with the previously used JavaScript and HTTP-fields based communication is will provide a number of advantages:
+
The term ''RAP Protocol'' is used to describe the JSON-based message format used in the HTTP communication between a RAP client and a RAP server.
 +
This protocol was  introduced in RAP 1.5 to replace the plain JavaScript responses that have been used in previous releases.
 +
As of RAP 2.0, the entire communication between client and server uses this protocol.
  
* It allowes to move all client-specific code from the server to the client.
+
=== Rationale ===
* It produces human readable messages, easing debugging.
+
* It allowes the client to create more informative error messages.
+
* It allowes to replace either ends as long as they process and create valid RAP-protocol messages.
+
  
The protocol is currently beeing developed in CVS HEAD. While not fully implemented, the communication will be mixed between old and new format, e.g. JavaScript-code with embedded JSON-objects. We expect to fully switch to the new format (at least the client-to-server direction) with the 1.5 release.
+
The idea of the RAP Protocol is to fully decouple RAP server and RAP client with the intention of making the client exchangeable.
 +
At this point of development, the most interesting use cases have been RAP clients for mobile devices (Android and iOS), written in the client's native language.
 +
As a consequence, all logic that is specific to the default RAP client has been moved from the server to the client.
 +
This includes logic that relies on the existence of JavaScript or the web browser's DOM.
 +
 
 +
A further objective for the design of the protocol was to avoid anything that would limit the protocol to the synchronization of RWT widgets.
 +
In fact, the protocol is also used for the synchronization of simple objects.
 +
 
 +
=== Advantages ===
 +
 
 +
Apart from the possiblity to connect alternative clients, the new protocol has a number of practical advantages over the previous one:
 +
 
 +
* It produces human readable messages and eases debugging of the communication. As an example, browser extension like FireBug allow browsing the JSON messages comfortably.
 +
* It allows the client to create more informative error messages. With the old protocol, in case of an error, it was not clear which statement in a large message caused the error. With the new protocol, the exact operation can be identified and a strack trace can be made available.
 +
* It allows to add client-independent client-side scripting.
  
 
== Protocol Format ==
 
== Protocol Format ==
The protocol is based on the JSON fromat as described here:
 
[ http://www.json.org/ ]
 
  
=== Message ===  
+
The message format is a valid subset of the JavaScript Object Notation ([http://www.json.org/ JSON]).
<source lang="javascript">  
+
As a consequence, messages can be parsed with every JSON parser.
{
+
The mime type of a response from a RAP server is <code>application/json</code> ([http://www.ietf.org/rfc/rfc4627.txt RFC 4627]).
   "meta" : MetaObject,
+
 
   "operations" : [ (OperationObject)* ]
+
Since JSON's grammar is already specified, we use a sloppy format to describe the protocol in the following in order to improve readability.
 +
In particular, we use the asterisk symbol <code>*</code> to indicate any number of items in an array or an object, skipping the comma that separates the items.
 +
For example, the following expression
 +
 
 +
<source lang="javascript">
 +
<Foo> ::= { <Key> : <Value> * }
 +
</source>
 +
 
 +
stands for either the empty object <code>{}</code>, an object with a single key-value pair <code>{ <Key> : <Value> }</code>, or one with multiple, comma separated key value pairs <code>{ <Key> : <Value> , <Key> : <Value> , ... }</code>.
 +
 
 +
We also skip the definition of the terminal symbols <code><string></code>, <code><number></code>, <code><boolean></code>, <code><any></code>, which refer to the types defined in JSON.
 +
 
 +
=== Message ===
 +
 
 +
There is exactly one message in a request and one in a response.
 +
A message contains a set of headers, followed by a list of operations.
 +
Even if a message does not contain any headers or operations, both parts have to be present.
 +
 
 +
<source lang="javascript">
 +
<Message> ::= {
 +
   "head" : <Headers> ,
 +
   "operations" : <Operations>
 
}
 
}
 
</source>
 
</source>
  
There is one message per request and one per response. (May differ while in development.)
+
=== Headers ===
  
=== MetaObject ===
+
This part contains headers that do not alter the state of the UI.
 +
 
 +
<source lang="javascript">
 +
<Headers> ::= { <HeaderName> : <HeaderValue> * }
 +
</source>
 +
 
 +
<source lang="javascript">
 +
<HeaderName> ::= <string> // name of the header
 +
<HeaderValue> ::= <any> // value of the header
 +
</source>
 +
 
 +
Example:
 
<source lang="javascript">
 
<source lang="javascript">
{  
+
head : {
   "requestCounter" : int
+
   "requestCounter" : 23
 
}
 
}
 
</source>
 
</source>
  
=== OperationObject ===
+
=== Operations ===
+
TODO
+
  
== Data Type Reference ==
+
The operations are commands that the peer must execute in the order they appear in the message.
 +
There are different types of operations: create, set, call, listen, notify, and destroy.
 +
Every operation has a target object. In case of a create operation, the target object is to be created, for all other operations, the target object must already exist.
  
In addition to the datatypes recognized by JSON itself, the RAP protocol also uses these composed types:
+
Operations must be processed in the order of their appearance in the message.
 +
 
 +
<source lang="javascript">
 +
  <Operations> ::= [ <Operation> * ]
 +
</source>
 +
<source lang="javascript">
 +
  <Operation> ::= <CreateOperation> | <SetOperation> | <CallOperation> | <ListenOperation> | <DestroyOperation> | <NotifyOperation>
 +
</source>
 +
 
 +
Example:
 +
 
 +
<source lang="javascript">
 +
operations : [
 +
  [ "destroy", "w23" ],
 +
  [ "create", "w42", "rwt.widgets.Button", { "visible" : false } ]
 +
]
 +
</source>
 +
 
 +
==== Create ====
 +
 
 +
A create operation instructs the peer to create an object of the given type and associate the given id with it.
 +
It may contain properties that should be initially set on the created objects.
 +
 
 +
<source lang="javascript">
 +
<CreateOperation> ::= [ "create", <TargetId>, <TypeName>, { <PropertyName> : <PropertyValue> * } ]
 +
</source>
 +
 
 +
<source lang="javascript">
 +
<TargetId> ::= <string> // the id of the object to create
 +
<TypeName> ::= <string> // the fully qualified name of the type
 +
<PropertyName> ::= <string> // the name of a property to set
 +
<PropertyValue> ::= <any> // the initial value for this property
 +
</source>
 +
 
 +
==== Set ====
 +
 
 +
A set operation instructs the peer to set a number of properties of the given target object.
 +
 
 +
<source lang="javascript">
 +
<SetOperation> ::= [ "set", <TargetId>, { <PropertyName> : <PropertyValue> * } ]
 +
</source>
 +
 
 +
<source lang="javascript">
 +
<TargetId> ::= <string> // the id of the object to set properties to
 +
<PropertyName> ::= <string> // the name of a property to set
 +
<PropertyValue> ::= <any> // the new value for this property
 +
</source>
 +
 
 +
==== Call ====
 +
 
 +
A call operation instructs the peer to call a method on the target object.
 +
 
 +
<source lang="javascript">
 +
<CallOperation> ::= [ "call", <TargetId>, <MethodName>, { <ParameterName> : <ParameterValue> * } ]
 +
</source>
 +
 
 +
<source lang="javascript">
 +
<TargetId> ::= <string> // the id of the object to call a method on
 +
<MethodName> ::= <string> // the name of the method to call
 +
<ParameterName> ::= <string> // the name of a method parameter
 +
<ParameterValue> ::= <any> // the value for the method parameter
 +
</source>
 +
 
 +
==== Listen ====
 +
 
 +
A listen operation instructs the peer to issue notify operations of the given event type on the target object.
 +
 
 +
<source lang="javascript">
 +
<ListenOperation> ::= [ "listen", <TargetId>, { <EventType> : <ListenToEvent> * } ]
 +
</source>
 +
 
 +
<source lang="javascript">
 +
<TargetId> ::= <string> // the id of the object to set properties to
 +
<EventType> ::= <string> // the name of an event type
 +
<ListenToEvent> ::= <boolean> // whether to listen to the given event or not
 +
</source>
 +
 
 +
==== Notify ====
 +
 
 +
A notify operation instructs the peer to dispatch an event of the given type on the target object.
 +
Notify operations must only be issued if the peer indicated its interest in this event type using a listen operation.
 +
 
 +
<source lang="javascript">
 +
<NotifyOperation> ::= [ "notify", <TargetId>, <EventType>, { <PropertyName> : <PropertyValue> * } ]
 +
</source>
 +
 
 +
<source lang="javascript">
 +
<TargetId> ::= <string> // the id of the object to call a method on
 +
<EventType> ::= <string> // the type of the event to dispatch
 +
<PropertyName> ::= <string> // the name of the event property
 +
<PropertyValue> ::= <any> // the value for the event property
 +
</source>
 +
 
 +
==== Destroy ====
 +
 
 +
A destroy operation instructs the peer to destroy the target object and to discard the id associated with it.
 +
 
 +
<source lang="javascript">
 +
<DestroyOperation> ::= [ "destroy", <TargetId> ]
 +
</source>
 +
 
 +
<source lang="javascript">
 +
<TargetId> ::= <string> // the id of the object to destroy
 +
</source>
 +
 
 +
== Usage in RAP ==
 +
 
 +
=== Common Data Types ===
 +
 
 +
The following composed types are used for common data types in RAP:
 +
 
 +
==== Point ====
 +
 
 +
<source lang="javascript">
 +
<Point> ::= [ <Left>, <Top> ]
 +
</source>
 +
<source lang="javascript">
 +
<Left> ::= <number> // integer, might be negative
 +
<Top> ::= <number> // integer, might be negative
 +
</source>
 +
 
 +
==== Rectangle ====
 +
 
 +
<source lang="javascript">
 +
<Bounds> ::= [ <Left>, <Top>, <Witdh>, <Height> ]
 +
</source>
 +
<source lang="javascript">
 +
<Left> ::= <number> // integer, might be negative
 +
<Top> ::= <number> // integer, might be negative
 +
<Witdh> ::= <number> // non-negative integer
 +
<Height> ::= <number> // non-negative integer
 +
</source>
 +
 
 +
==== Color ====
 +
 
 +
<source lang="javascript">
 +
<Color> ::= [ <Red>, <Green>, <Blue>, <Alpha> ]
 +
</source>
 +
<source lang="javascript">
 +
<Red> ::= <number> // integer between 0 and 255
 +
<Green> ::= <number> // integer between 0 and 255
 +
<Blue> ::= <number> // integer between 0 and 255
 +
<Alpha> ::= <number> // integer between 0 and 255
 +
</source>
 +
 
 +
Clients that don't support alpha values must hide the element if alpha is 0.
 +
 
 +
==== Image ====
 +
 
 +
<source lang="javascript">
 +
<Image> ::= [ <Url>, <Width>, <Height> ] | null
 +
</source>
 +
<source lang="javascript">
 +
<Url> ::= <string> // the source url to load the image from
 +
<Width> ::= <number> // positive integer defining the width of the image in px
 +
<Height> ::= <number> // positive integer defining the height of the image in px
 +
</source>
 +
 
 +
==== Gradient ====
 +
 
 +
<source lang="javascript">
 +
<Gradient> ::= [ <Colors>, <Stops>, <IsVertical> ] | null
 +
</source>
 +
<source lang="javascript">
 +
<Colors> ::= [ <Color> ] // the colors of the gradient
 +
<Stops> ::= [ <number> ] // the positions of the colors, values between 0 and 1, each equal or higher than the previous one
 +
<IsVertical> ::= <boolean> // whether the gradient is vertical
 +
</source>
 +
 
 +
The number of colors must match the number of stops.
 +
 
 +
==== Font ====
 +
 
 +
<source lang="javascript">
 +
<Font> ::= [ <Names>, <Size>, <Bold>, <Italic> ] | null
 +
</source>
 +
<source lang="javascript">
 +
<Names> ::= [ <string> ] // the names of the font families
 +
<Size> ::= <number> // the size of the font in pixel
 +
<Bold> ::= <boolean>
 +
<Italic> ::= <boolean>
 +
</source>
  
=== Bounds ===
+
The client has to use the first font-family of the names array it can display.
<code> [ int left, int top, int with, int height ] </code>
+
  
Note that left and top may be negative. No value may be null.
+
=== Object Type Reference ===
  
=== Color ===
+
t.b.d.
<code> [ int red, int gree, int blue, int alpha ] </code>
+
  
All values are to be between 0 and 255. The alpha value may be ignored by the client unless its 0.
+
=== Server and JavaScript-Client API ===
  
== Object Type Reference ==
+
t.b.d.
  
== Server and JavaScript-Client API ==
+
[[Category:RAP]]

Revision as of 06:27, 13 January 2013

Introduction

The term RAP Protocol is used to describe the JSON-based message format used in the HTTP communication between a RAP client and a RAP server. This protocol was introduced in RAP 1.5 to replace the plain JavaScript responses that have been used in previous releases. As of RAP 2.0, the entire communication between client and server uses this protocol.

Rationale

The idea of the RAP Protocol is to fully decouple RAP server and RAP client with the intention of making the client exchangeable. At this point of development, the most interesting use cases have been RAP clients for mobile devices (Android and iOS), written in the client's native language. As a consequence, all logic that is specific to the default RAP client has been moved from the server to the client. This includes logic that relies on the existence of JavaScript or the web browser's DOM.

A further objective for the design of the protocol was to avoid anything that would limit the protocol to the synchronization of RWT widgets. In fact, the protocol is also used for the synchronization of simple objects.

Advantages

Apart from the possiblity to connect alternative clients, the new protocol has a number of practical advantages over the previous one:

  • It produces human readable messages and eases debugging of the communication. As an example, browser extension like FireBug allow browsing the JSON messages comfortably.
  • It allows the client to create more informative error messages. With the old protocol, in case of an error, it was not clear which statement in a large message caused the error. With the new protocol, the exact operation can be identified and a strack trace can be made available.
  • It allows to add client-independent client-side scripting.

Protocol Format

The message format is a valid subset of the JavaScript Object Notation (JSON). As a consequence, messages can be parsed with every JSON parser. The mime type of a response from a RAP server is application/json (RFC 4627).

Since JSON's grammar is already specified, we use a sloppy format to describe the protocol in the following in order to improve readability. In particular, we use the asterisk symbol * to indicate any number of items in an array or an object, skipping the comma that separates the items. For example, the following expression

<Foo> ::= { <Key> : <Value> * }

stands for either the empty object {}, an object with a single key-value pair { <Key> : <Value> }, or one with multiple, comma separated key value pairs { <Key> : <Value> , <Key> : <Value> , ... }.

We also skip the definition of the terminal symbols <string>, <number>, <boolean>, <any>, which refer to the types defined in JSON.

Message

There is exactly one message in a request and one in a response. A message contains a set of headers, followed by a list of operations. Even if a message does not contain any headers or operations, both parts have to be present.

<Message> ::= {
  "head" : <Headers> ,
  "operations" : <Operations>
}

Headers

This part contains headers that do not alter the state of the UI.

<Headers> ::= { <HeaderName> : <HeaderValue> * }
<HeaderName> ::= <string> // name of the header
<HeaderValue> ::= <any> // value of the header

Example:

head : {
  "requestCounter" : 23
}

Operations

The operations are commands that the peer must execute in the order they appear in the message. There are different types of operations: create, set, call, listen, notify, and destroy. Every operation has a target object. In case of a create operation, the target object is to be created, for all other operations, the target object must already exist.

Operations must be processed in the order of their appearance in the message.

  <Operations> ::= [ <Operation> * ]
  <Operation> ::= <CreateOperation> | <SetOperation> | <CallOperation> | <ListenOperation> | <DestroyOperation> | <NotifyOperation>

Example:

operations : [
  [ "destroy", "w23" ],
  [ "create", "w42", "rwt.widgets.Button", { "visible" : false } ]
]

Create

A create operation instructs the peer to create an object of the given type and associate the given id with it. It may contain properties that should be initially set on the created objects.

<CreateOperation> ::= [ "create", <TargetId>, <TypeName>, { <PropertyName> : <PropertyValue> * } ]
<TargetId> ::= <string> // the id of the object to create
<TypeName> ::= <string> // the fully qualified name of the type
<PropertyName> ::= <string> // the name of a property to set
<PropertyValue> ::= <any> // the initial value for this property

Set

A set operation instructs the peer to set a number of properties of the given target object.

<SetOperation> ::= [ "set", <TargetId>, { <PropertyName> : <PropertyValue> * } ]
<TargetId> ::= <string> // the id of the object to set properties to
<PropertyName> ::= <string> // the name of a property to set
<PropertyValue> ::= <any> // the new value for this property

Call

A call operation instructs the peer to call a method on the target object.

<CallOperation> ::= [ "call", <TargetId>, <MethodName>, { <ParameterName> : <ParameterValue> * } ]
<TargetId> ::= <string> // the id of the object to call a method on
<MethodName> ::= <string> // the name of the method to call
<ParameterName> ::= <string> // the name of a method parameter
<ParameterValue> ::= <any> // the value for the method parameter

Listen

A listen operation instructs the peer to issue notify operations of the given event type on the target object.

<ListenOperation> ::= [ "listen", <TargetId>, { <EventType> : <ListenToEvent> * } ]
<TargetId> ::= <string> // the id of the object to set properties to
<EventType> ::= <string> // the name of an event type
<ListenToEvent> ::= <boolean> // whether to listen to the given event or not

Notify

A notify operation instructs the peer to dispatch an event of the given type on the target object. Notify operations must only be issued if the peer indicated its interest in this event type using a listen operation.

<NotifyOperation> ::= [ "notify", <TargetId>, <EventType>, { <PropertyName> : <PropertyValue> * } ]
<TargetId> ::= <string> // the id of the object to call a method on
<EventType> ::= <string> // the type of the event to dispatch
<PropertyName> ::= <string> // the name of the event property
<PropertyValue> ::= <any> // the value for the event property

Destroy

A destroy operation instructs the peer to destroy the target object and to discard the id associated with it.

<DestroyOperation> ::= [ "destroy", <TargetId> ]
<TargetId> ::= <string> // the id of the object to destroy

Usage in RAP

Common Data Types

The following composed types are used for common data types in RAP:

Point

<Point> ::= [ <Left>, <Top> ]
<Left> ::= <number> // integer, might be negative
<Top> ::= <number> // integer, might be negative

Rectangle

<Bounds> ::= [ <Left>, <Top>, <Witdh>, <Height> ]
<Left> ::= <number> // integer, might be negative
<Top> ::= <number> // integer, might be negative
<Witdh> ::= <number> // non-negative integer
<Height> ::= <number> // non-negative integer

Color

<Color> ::= [ <Red>, <Green>, <Blue>, <Alpha> ]
<Red> ::= <number> // integer between 0 and 255
<Green> ::= <number> // integer between 0 and 255
<Blue> ::= <number> // integer between 0 and 255
<Alpha> ::= <number> // integer between 0 and 255

Clients that don't support alpha values must hide the element if alpha is 0.

Image

<Image> ::= [ <Url>, <Width>, <Height> ] | null
<Url> ::= <string> // the source url to load the image from
<Width> ::= <number> // positive integer defining the width of the image in px
<Height> ::= <number> // positive integer defining the height of the image in px

Gradient

<Gradient> ::= [ <Colors>, <Stops>, <IsVertical> ] | null
<Colors> ::= [ <Color> ] // the colors of the gradient
<Stops> ::= [ <number> ] // the positions of the colors, values between 0 and 1, each equal or higher than the previous one
<IsVertical> ::= <boolean> // whether the gradient is vertical

The number of colors must match the number of stops.

Font

<Font> ::= [ <Names>, <Size>, <Bold>, <Italic> ] | null
<Names> ::= [ <string> ] // the names of the font families
<Size> ::= <number> // the size of the font in pixel
<Bold> ::= <boolean>
<Italic> ::= <boolean>

The client has to use the first font-family of the names array it can display.

Object Type Reference

t.b.d.

Server and JavaScript-Client API

t.b.d.