#WebSockets and AeroGear's Pipe API ?
The AeroGear's Pipe/Pipeline API is pretty much build around the HTTP request-response principle. It's basically an abstraction layer for HTTP-REST or protocols that follow much of the REST principle, like OData.
The (here JavaScript
) API is build in an asynchronous manner, where callbacks are used to notify the caller about the (immediate) response, of the request/API-call. Two examples:
READ, or HTTP GET:
myPipe.read({
success: function( data ) {
// do stuff with data
},
error: function( data ) {
// read failed
}
});
SAVE, or HTTP PUT and/or HTTP POST:
myPipe.save(data,{
success: function( data ) {
// do stuff with data
},
error: function( data ) {
// read failed
}
});
WebSocket's Event API
The WebSocket API is more event-driven, compared to the request-response paradigm, which the Pipes are based on. Below is a quick introduction to the "event-driven" API of WebSocket:
// Create new WebSocket
var mySocket =�new WebSocket("ws://echo.websockets.org");
// Attach listeners, for different EVENTs
mySocket.onmessage = function(evt) {...};
mySocket.onopen = function(evt) {...};
mySocket.onclose = function(evt) {...};
mySocket.onerror = function(evt) {...};
Once the WebSocket connection is established, different events (e.g. message) can be received, without the client actively asking for data. Also, when sending bits from the client to the server, it is not required that the server needs to reply, like in the case of the established request-response principle.
WebSocket's interaction API
// send some data
mySocket.send(text_or_binary_data);
....
// close the connection, when needed:
mySocket.close();
In contrast to the Pipe (request-response), there is a close()
, on WebSocket. This makes sense, since it is a permanent connection.
Pipe versus WebSocket
As shown above, it does not make sense to create a WebSocketPipeImpl. A little testcase (in ObjC), shows the miss-match:
AGWebSocketAdapter* wsa = [AGWebSocketAdapter pipeForURL:[NSURL URLWithString:@"ws://echo.websocket.org"] authModule:nil];
NSDictionary* object = [NSDictionary dictionaryWithObjectsAndKeys:@"Dude", @"firstname", nil];
// handlers for 'receiving' and 'on error'; hrm...
// makes no sense, to abuse the read...
[wsa read:^(id responseObject) {
NSLog(@"\n\n=======> %@", responseObject);
} failure:^(NSError *error) {
NSLog(@"=======> %@", error);
}];
// callbacks are not really needed on 'send'... most of the time, at least
[wsa save:object success:nil failure:nil];
///// QUESTION: close.... otherwise the damn socket is up, 4ewa
Will AeroGear support WebSocket?
Yes, but NOT as a pipe implementation. In our last team meeting we talked about the above issues and how to support WebSocket, or more generally PUSH, in AeroGear.
AeroGear Notifier
The current idea is to introduce a new module, the AeroGear Notifier. This is a flexible notification mechanism, that can be used for several (technical) purposes:
- receiving 'websocket' events, when the app is online (active, tab/window being watched at)
- receiving 'native push' events, when the app is offline (inactive, not watching the tab/window)
- receiving 'custom events', e.g. via something like the Socket.io emitter or EventEmitter2
Integration with AeroGear
Inside of the (existing) AeroGear library, the Notifier can be used in several ways:
- As a utility to help data sync, in the datamanager api.
- On the side of a running Pipe. Based on a notification, the pipe can fetch the updates from the server
- While online, the notification (here via WebSocket) can contain the actual payload, so that the pipe does not issue a GET request, to fetch the updates
WebSocket will be a feature of the AeroGear library, without (current thinking) explicitly exposing it...
Messaging
Current thinking is that the AeroGear Notifier will NOT be used with messaging. But that's not really determined yet... Most-likely supporting STOMP over WebSocket would be the way to go. Message brokers usually support STOMP (-> HortnetQ, Apache ActiveMQ, RabbitMQ,...).
Technical issues with WebSocket
- we need fallbacks (client and server). See Engine.io blog for migrating, instead of naive thinking WebSocket works in a modern browser, and downing fallbacks (WS->Flash->Streaming->LongPolling), as this adds some latency...
- of course WSS:// always could work (see below)
- SSE (server-sent events) would be a nice "update" format/fallback - it basically standardizes http streaming.
- Support the JSR? Luckily the JSR can be user (server) outside of a JavaEE container.
- JSR defines NO fallback, just native WebSocket
- If mobile browser (at least Safari) goes to sleep, WebSocket connection is closed
- For 3g usually there are connection issues (thanks, you carriers and transparent proxy servers), try with TLS (
wss://secure.server.com
), good success rate... - In the real internet using TLS (not only for WS) is a good idea...