Both the binary protocol and the compact protocol assume a transport layer that exposes a bi-directional byte stream, for example a TCP socket. Both use the following exchange:
-
⇒ Client sends a
Message
(typeCall
orOneway
). The TMessage contains some metadata and the name of the method to invoke. -
⇒ Client sends method arguments (a struct defined by the generate code).
-
⇐ Server sends a
Message
(typeReply
orException
) to start the response. -
⇐ Server sends a struct containing the method result or exception.
The pattern is a simple half duplex protocol where the parties alternate in sending a Message
followed by a struct.
What these are is described below.
Although the standard Apache Thrift Java clients do not support pipelining (sending multiple requests without waiting for an response), the standard Apache Thrift Java servers do support it.
A message contains:
-
Name, a string.
-
Message type, a message types, one of
Call
,Reply
,Exception
andOneway
. -
Sequence id, a signed i32 integer.
The sequence id is a simple message id assigned by the client. The server will use the same sequence id in the message of the response. The client uses this number to detect out of order responses. Each client has an i32 field which is increased for each message. The sequence id simply wraps around when it overflows.
The name indicates the service method name to invoke. The server copies the name in the response message.
When the multiplexed protocol is used, the name contains the service name, a colon (:
) and the method name. The
multiplexed protocol is not compatible with other protocols.
The message type indicates what kind of message is sent. Clients send requests with messages of type Call
or
Oneway
(step 1 in the protocol exchange). Servers send responses with messages of type Exception
or Reply
(step
3).
Type Reply
is used when the service method completes normally. That is, it returns a value or it throws one of the
exceptions defined in the Thrift IDL file.
Type Exception
is used for other exceptions. That is: when the service method throws an exception that is not declared
in the Thrift IDL file, or some other part of the Thrift stack throws an exception. For example when the server could
not encode or decode a message or struct.
In the Java implementation (0.9.3) there is different behavior for the synchronous and asynchronous server. In the async
server all exceptions are send as a TApplicationException
(see 'Response struct' below). In the synchronous Java
implementation only (undeclared) exceptions that extend TException
are send as a TApplicationException
. Unchecked
exceptions lead to an immediate close of the connection.
Type Oneway
is only used starting from Apache Thrift 0.9.3. Earlier versions do not send messages of type Oneway
,
even for service methods defined with the oneway
modifier.
When client sends a request with type Oneway
, the server must not send a response (steps 3 and 4 are skipped). Note
that the Thrift IDL enforces a return type of void
and does not allow exceptions for oneway services.
The struct that follows the message of type Call
or Oneway
contains the arguments of the service method. The
argument ids correspond to the field ids. The name of the struct is the name of the method with _args
appended.
For methods without arguments an struct is sent without fields.
The struct that follows the message of type Reply
are structs in which exactly 1 of the following fields is encoded:
-
A field with name
success
and id0
, used in case the method completed normally. -
An exception field, name and id are as defined in the
throws
clause in the Thrift IDL’s service method definition.
When the message is of type Exception
the struct is encoded as if it was declared by the following IDL:
exception TApplicationException { 1: string message, 2: i32 type }
The following exception type
s are defined in the java implementation (0.9.3):
0
, unknown-
used in case the type from the peer is unknown.
1
, unknown method-
used in case the method requested by the client is unknown by the server.
2
, invalid message type-
no usage was found.
3
, wrong method name-
no usage was found.
4
, bad sequence id-
used internally by the client to indicate a wrong sequence id in the response.
5
, missing result-
used internally by the client to indicate a response without any field (result nor exception).
6
, internal error-
used when the server throws an exception that is not declared in the Thrift IDL file.
7
, protocol error-
used when something goes wrong during decoding. For example when a list is too long or a required field is missing.
8
, invalid transform-
no usage was found.
9
, invalid protocol-
no usage was found.
10
, unsupported client type-
no usage was found.
A struct is a sequence of zero or more fields, followed by a stop field. Each field starts with a field header and is followed by the encoded field value. The encoding can be summarized by the following BNF:
struct ::= ( field-header field-value )* stop-field field-header ::= field-type field-id
Because each field header contains the field-id (as defined by the Thrift IDL file), the fields can be encoded in any order. Thrift’s type system is not extensible; you can only encode the primitive types and structs. Therefore it is also possible to handle unknown fields while decoding; these are simply ignored. While decoding, the field type can be used to determine how to decode the field value.
Note that the field name is not encoded so field renames in the IDL do not affect forward and backward compatibility.
The default Java implementation (Apache Thrift 0.9.1) has undefined behavior when it tries to decode a field that has another field-type then what is expected. Theoretically this could be detected at the cost of some additional checking. Other implementation may perform this check and then either ignore the field, return a protocol exception, or perform a silent type cast.
A union is encoded exactly the same as a struct with the additional restriction that at most 1 field may be encoded.
An exception is encoded exactly the same as a struct.