Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 1
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 2
Getting Started with WebSocket and Server-Sent Event in Java
Arun Gupta blogs.oracle.com/arungupta, @arungupta
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 3 Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Insert Information Protection Policy Classification from Slide 16
Program Agenda
§ WebSocket Primer
§ Getting Started with WebSocket
§ Server-Sent Event Primer
§ Getting Started with Server-Sent Event
§ Resources
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 4
Interactive Web Sites
§ HTTP is half-duplex § HTTP is verbose § Hacks for Server Push
– Polling – Long Polling – Comet/Ajax
§ Complex, Inefficient, Wasteful
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 5
WebSocket to the Rescue
§ TCP based, bi-directional, full-duplex messaging § Originally proposed as part of HTML5 § IETF-defined Protocol: RFC 6455
– Handshake – Data Transfer
§ W3C defined JavaScript API – Candidate Recommendation
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 6
Establish a connection
Client
Handshake Request
Handshake Response Server
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 7
Handshake Request
GET /chat HTTP/1.1 Host: server.example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== Origin: http://example.com Sec-WebSocket-Protocol: chat, superchat Sec-WebSocket-Version: 13 "
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 8
Handshake Response
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= Sec-WebSocket-Protocol: chat "
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 9
Server Client
Handshake Request
Handshake Response
Connected !
Establishing a Connection
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 10
Peer (server)
Peer (client)
Connected !
open open
close
message
error
message message
message
message
Disconnected
WebSocket Lifecycle
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 11
WebSocket API www.w3.org/TR/websockets/
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 12 http://caniuse.com/websockets
Browser Support
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 13
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 14
Java API for WebSocket Features
§ API for WebSocket Endpoints/Client – Annotation-driven (@ServerEndpoint) – Interface-driven (Endpoint)
§ WebSocket opening handshake negotiation – Client (@ClientEndpoint)
§ Integration with Java EE Web container
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 15
Hello World
import javax.websocket.*; @ServerEndpoint("/hello") public class HelloBean { @OnMessage public String sayHello(String name) { return “Hello “ + name; } }"
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 16
Annotations Annotation Level Purpose
@ServerEndpoint" class Turns a POJO into a WebSocket Endpoint
@ClientEndpoint" class POJO wants to act as client
@OnMessage" method Intercepts WebSocket Message events
@PathParam" method parameter Flags a matched path segment of a URI-template
@OnOpen" method Intercepts WebSocket Open events
@OnClose" method Intercepts WebSocket Close events
@OnError" method Intercepts errors during a conversation
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 17
@ServerEndpoint Attributes
value" Relative URI or URI template e.g. “/hello” or “/chat/{subscriber-level}”
decoders" list of message decoder classnames
encoders" list of message encoder classnames
subprotocols" list of the names of the supported subprotocols
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 18
Custom Payloads
@ServerEndpoint( value="/hello", encoders={MyMessage.class}, decoders={MyMessage.class} ) public class MyEndpoint { . . . }"
"
"
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 19
Custom Payloads – Text
public class MyMessage implements Decoder.Text<MyMessage>, Encoder.Text<MyMessage> { private JsonObject jsonObject; public MyMessage decode(String s) { jsonObject = Json.createReader(new StringReader(s)).readObject(); return this;"
}"
public boolean willDecode(String string) { return true; // Only if can process the payload }"
"
public String encode(MyMessage myMessage) { return myMessage.jsonObject.toString(); } }"
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 20
Custom Payloads – Binary
public class MyMessage implements Decoder.Binary<MyMessage>, Encoder.Binary<MyMessage> { public MyMessage decode(byte[] bytes) { . . . return this;"
}"
public boolean willDecode(byte[] bytes) { . . . return true; // Only if can process the payload }"
"
public byte[] encode(MyMessage myMessage) { . . . } }"
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 21
Which methods can be @OnMessage ?
§ Exactly one of the following – Text: String, Java primitive or equivalent class, String and boolean, Reader, any type for which there is a decoder
– Binary: byte[], ByteBuffer, byte[] and boolean, ByteBuffer and boolean, InptuStream, any type for which there is a decoder
– Pong messages: PongMessage"
§ An optional Session parameter § 0..n String parameters annotated with @PathParam"§ Return type: String, byte[], ByteBuffer, Java primitive or class
equivalent or any type for which there is a encoder
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 22
Sample Messages
§ void m(String s);"§ void m(Float f, @PathParam(“id”)int id);"§ Product m(Reader reader, Session s);"§ void m(byte[] b); or void m(ByteBuffer b);"§ Book m(int i, Session s, @PathParam(“isbn”)String isbn, @PathParam(“store”)String store);"
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 23
Chat Server
@ServerEndpoint("/chat")"
public class ChatBean {"
static Set<Session> peers = Collections.synchronizedSet(…); @OnOpen public void onOpen(Session peer) { peers.add(peer); } @OnClose public void onClose(Session peer) { peers.remove(peer); } . . ."
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 24
Chat Server
. . . @OnMessage"
public void message(String message, Session client) {"
for (Session peer : peers) { peer.getBasicRemote().sendObject(message); } } }"
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 25
WebSocket Client
@ClientEndpoint public class HelloClient { @OnMessage public void message(String message, Session session) { // process message from server } } "
WebSocketContainer c = ContainerProvider.getWebSocketContainer(); c.connectToServer(HelloClient.class, “hello”);"
"
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 26
Interface-driven Endpoint
public class MyEndpoint extends Endpoint { @Override public void onOpen(Session session) { session.addMessageHandler(new MessageHandler.Text() { public void onMessage(String name) { try { session.getBasicRemote().sendText(“Hello “ + name); } catch (IOException ex) { } } }); } }"
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 27
How to view WebSocket messages ? Capture traffic on loopback
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 28
How to view WebSocket messages ? chrome://net-internals -> Sockets -> View live sockets
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 29
Server-Sent Events
§ Part of HTML5 Specification § Server-push notifications § Cross-browser JavaScript API: EventSource"§ Message callbacks § MIME type: text/eventstream"
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 30
EventSource API dev.w3.org/html5/eventsource/
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 31
Server-Sent Events Example
var url = ‘webresources/items/events’; var source = new EventSource(url);"
source.onmessage = function (event) { console.log(event.data); } source.addEventListener(“size”, function(event) {"
console.log(event.name + ‘ ‘ + event.data); }"
Client-side
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 32
Server-Sent Events Example
private final SseBroadcaster BROADCASTER = new SseBroadcaster(); @GET @Path("events”) @Produces(SseFeature.SERVER_SENT_EVENTS) public EventOutput fruitEvents() { final EventOutput eventOutput = new EventOutput(); BROADCASTER.add(eventOutput); return eventOutput; }
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 33
Server-Sent Events Example
@POST @Consumes(MediaType.APPLICATION_FORM_URLENCODED) public void addFruit(@FormParam("fruit")String fruit) { FRUITS.add(fruit); // Broadcasting an un-named event with the name of the newly added item in data BROADCASTER.broadcast(new OutboundEvent.Builder().data(String.class, fruit).build()); // Broadcasting a named "add" event with the current size of the items collection in data BROADCASTER.broadcast(new OutboundEvent.Builder().name("size").data(Integer.class, FRUITS.size()).build()); }
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 34
WebSocket and Server-Sent Event Competing technologies ? WebSocket Server-Sent Event
Over a custom protocol Over simple HTTP
Full Duplex, Bi-directional Server-Push Only, Client->Server is out-of-band (higher latency)
Native support in most browsers Can be poly-filled to backport
Not straight forward protocol Simpler protocol
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 35
WebSocket and Server-Sent Event Competing technologies ? WebSocket Server-Sent Event
Pre-defined message handlers Arbitrary events
Application-specific Built-in support for re-connection and event id
Require server and/or proxy configurations
No server or proxy changes required
ArrayBuffer and Blob No support for binary types
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 36
Resources
§ Java API for WebSocket – Specification: jcp.org/en/jsr/detail?id=356 – Reference Implementation: java.net/projects/tyrus – Part of Java EE 7 – Integrated in GlassFish Server 4.0
§ Server-Sent Event – Integrated in Jersey and GlassFish Server 4.0 – Not part of Java EE 7
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 37