Asynchronous notifications from server to client.
HTTP as a transport mechanism is client-push only. There is no built-in, well supported mechanism for an HTTP server to pass events and notifications to a client.
For the File System Daemon, we have opted to use a per-server notification channel, that broadcasts notifications to clients that have requested a special URL. Each notification is given a key that allows the receiving clients to decide if they care about that notification. The notification message itself is a JSON-encoded serialized object, whose type is specified by a language-independent string.
A message on the notification channel looks like:
Key Type Length Serialized-Object\n(See {@link NotificationMarshaller} for a complete explanation of each field)
The notification channel is available at the URL http://localhost:port/notification (where the port is the current FSD port). After the client has connected to that URL (authenticating with the FSD's secret), an HTTP 200 response is returned, with the content type application/vnd.ibm.jazz-json-notification-1.0.
Note:
A client can request progress reports about a call by adding the X-Request-Progress to a request (the header value is defined in {@link Header#REQUEST_PROGRESS}, and may change over time). The header value is the key that identifies the request.
After a client makes a request with the X-Request-Progress header it can expect to see messages about the request on the notification channel. The messages are delivered asynchronously (ie, the messages show up while the original request is still blocked waiting for the response).
Each progress report is encoded in a message with the type progress (defined in {@link ProgressNotificationParm#TYPE}). The serialized object has the following four fields:
After the request has completed, the FSD may send more notifications with the given key. Those should be considered stale and discarded.
Note that the programming model for progress in Eclipse assumes that progress is being consumed locally, and may be very chatty. To limit the chatter on the notification channel, progress notifications are sent at most every 100ms (per request).
The following is a short conversation showing how the client and server communicate with a notification channel.
To begin, the client joins the notification channel:
GET /notification/ HTTP/1.1 X-Secret-Key: 5D6A035927AA1883E10BF584A488EEA3 User-Agent: Jakarta Commons-HttpClient/3.0 Host: 127.0.0.1:57640
The FSD responds with an HTTP 200, indicating that the client will receive notifications on that channel.
HTTP/1.1 200 OK Content-Type: application/vnd.ibm.jazz-json-notification-1.0
Now the client makes a request. The progress header is highlighted.
POST /service/com.ibm.team.filesystem.client.tests.internal.rest.services.IRestCancellationService/ProgressSynchronously HTTP/1.1 X-Secret-Key: 5D6A035927AA1883E10BF584A488EEA3 X-Request-Progress: auto.1220470793090.0 Host: 127.0.0.1:57640 Content-Length: 11 Content-Type: application/x-www-form-urlencoded text=cheese
The server sends repeated messages on the notification channel. The notification key is highlighted.
auto.1220470793090.0 progress 213 {
(unnecessary fields elided)
"cancelled": false,
"progress": 0.0,
"subTask": null,
"taskName": "cheese"
}
auto.1220470793090.0 progress 214 {
(unnecessary fields elided)
"cancelled": false,
"progress": 20.0,
"subTask": null,
"taskName": "cheese"
}
...
The server will eventually respond to the request. From this point, any notifications that the server sends with this key should be considered stale.
HTTP/1.1 200 OK
Content-Type: text/json; charset=utf-8
Content-Length: 496
{"soapenv:Body":{"_eQualifiedClassNa...
public class MyRestService implements IMyRestService, IJSONReceiver {
IServerNotificationChannel notifier;
public void setController(IServerController controller, JSONHandler handler) {
this.notifier = handler.getNotificationChannel();
}
...
Note that the notifier remains valid over the life of the class, regardless of the number of listeners on that channel.
When the FSD is shutting down, it will send a shutdown notifiction to all of its listeners. After the client has received a shutdown notification on a connection it should not attempt to reconnect. The shutdown notification key can be found in {@link OrderlyShutdownNotification#KEY}, and the notification class is {@link OrderlyShutdownNotification}.