The Aura Contextual Service Interface is designed to allow clients and information providing services to communicate using a small set of functions. As such, the Interface consists of a defined set of functions as well as a protocol that allows these functions to be invoked across the network. This document provides information on the protocol that is intended to be used as a guide for implementation.
The contextual service interface protocol utilizes HTTP as a transport mechanism and an XML based serialization scheme. The protocol used can be viewed as a simplified RPC protocol. While this protocol could be extended to be a full RPC protocol, it is not intended as such.
To call a function on the callee, the caller uses HTTP Post with the desired function name as the URL (e.g. /query). The body of the message is the serialized call. Persistent HTTP must not be used. The return value of the call is sent in the HTTP response.
This section lists several datatypes used in the the serialization protocol. (These datatypes are found on the wire and may be realized in the implementation of the service interface, but implementations need not actually create datatypes that match the datatypes found on the wire.)
Required fields (fields that will always appear whenever the type is serialized) are in bold. Optional fields are in italics. The psuedo-type "PType" is used to indicate that a field may contain any primitive type.
Attribute {
string name;
PType value;
}
DynamicAttribute {
string name;
PType value;
timeInstant lastUpdate;
double confidence;
PType accuracyMax;
PType accuracyMin;
long interval;
}
AttributeReq {
string name;
long minUpdateTime;
long maxUpdateTime;
timeInstant minUpdateTimeAbs;
timeInstant maxUpdateTimeAbs;
double minConf;
double maxConf;
PType minAccuracy;
PType maxAccuracy;
long minInterval;
long maxInterval;
}
(Note that attribute min and max requirements
must always appear in pairs if they appear at all.
Also, the updateTimeAbs and updateTime requirements
are two different ways of specifying update time
constaints. updateTimeAbs is absolute while
updateTime is relative. Hence, these two should not
be used together.)
QueryResult {
timeInstant time;
boolean complete;
List attribSets;
}
The attribSets member of QueryResult is a List of
Lists. The outer List contains "rows" of
inner lists of Attributes and DynamicAttributes.
This type is a vector that contains an arbitrary number elements of a arbitrary types (the types may be either primitive or complex). The name of each element in the list is "item". Note that unlike named elements of many complex datatypes (which should be generated in the shown order, but should be accepted in any order), the order of elements in a List is significant (or at least it must be treated as if it is significant).
ExpressionNodeAn expression node has an operator named "op" and one or two children named "eNode". The order of elements in an expression node is significant and should be op, eNode, eNode (if there are two ExpressionNode children). Currently, for leaf nodes two types of entries are supported: 1) the first eNode should be the attribute name and the second should be its value; 2) the both eNodes are attributes. The eNode members always include type information even for leaf nodes.
ServiceErrorUsed to return errors from callers to callees. There are two elements to this type a code element which contains the numeric error code and a description element which contains a description that spans one or more lines.
A call is enclosed inside a CallEnvelope which is an instance of a List. Naturally the order and types of all members of the list must match that of the method called.
Data returned from functions comes back in a ReturnEnvelope. The ReturnEnvelope has a single member returnValue whose type must always be specified. If the type is ServiceError then an error occurred and returnValue contains a ServiceError type describing the error.
Unsuccessful calls result in an error code being returned. Error codes are divided into classes and are defined as follows:
(Errors where the class is known but the exact error is not should be treated as the generic [x00] class error.)
Serialization is a straightforward process of converting the datatype to be serialized into a matching "tree" of XML. There is one XML element per data element. Each element is named after the name of the variable that it is serializing (with the exception of the special cases mentioned in the Datatypes section where multiple elements have the same name). Elements may have up to two attributes: "type" and "null". The type attribute is used to indicate the type of the element if it is not already clear in the context in which it is appearing. The null attribute indicates that this element is null.
Elements of complex datatypes appear as child elements. The children should appear in the order shown above, but for robustness, deserializers should accept them in any order. (Note that order of elements in Lists and ExpressionNodes may always be significant.) The names of the child elements are as shown above.
Note that clients can take some shortcuts in serialization and deserialization of data if they desire. For example, it is possible for clients to have a hard coded query or a query that they simply modify small parts of (using sprintf for example). While deserialization needs more complex processing due to its nature, there are still shortcuts that can be taken (for instance, timeInstance need not be implemented by clients that never care about time; in general clients simply ignore values they don't care about).
This example contains a call/return value sequence that was generated using the first Java service interface release by turning on serialization debugging. This is done by setting the Java property edu.cmu.aura.service.rpc.DebugSerialization to true. (e.g. java -D edu.cmu.aura.service.rpc.DebugSerialization=true MyClass).
This next example demonstrates an erroneous call. It was generated by introducing a bad attribute name "bogusAttributeName" into the previous call.
402