1. Java EE 7 Websocket Chat
Creating a Chat Application using Java EE 7,
Websockets and GlassFish 4
2014 Micha Kops / www.hascode.com
2. Table of Contents
●
What we're going to build (I)
●
What we're going to build (II)
●
Prerequisites
●
Creating a new web app
●
Adding the Maven Embedded GlassFish Plugin
●
Websocket Endpoint
●
Chat Message Data Transfer Object
●
Converting Chat Messages
●
Encoder Implementation
●
The Client Side
●
Client DOM Scripts (I)
●
Client DOM Scripts (II)
●
Client DOM Scripts (III)
●
Client HTML (I)
●
Client HTML (II)
●
Build, deploy, run …
●
Tutorial, Sources and Links
2014 Micha Kops / www.hascode.com
4. What we're going to build (II)
●
●
●
●
A chat application client using Bootstrap and
jQuery
A user may register with a nickname for a
chatroom from a list of given rooms
Messages in a chat room are pushed to each
subscribed client using web sockets
A user may log out from the chat room
2014 Micha Kops / www.hascode.com
6. Creating a new web app
●
Using the javaee7-webapp Maven
Archetype
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
2014 Micha Kops / www.hascode.com
8. Websocket Endpoint
@ServerEndpoint(value = "/chat/{room}", encoders = ChatMessageEncoder.class, decoders = ChatMessageDecoder.class)
public class ChatEndpoint {
private final Logger log = Logger.getLogger(getClass().getName());
@OnOpen
public void open(final Session session, @PathParam("room") final String room) {
log.info("session openend and bound to room: " + room);
session.getUserProperties().put("room", room);
}
@OnMessage
public void onMessage(final Session session, final ChatMessage chatMessage) {
String room = (String) session.getUserProperties().get("room");
try {
for (Session s : session.getOpenSessions()) {
if (s.isOpen()
&& room.equals(s.getUserProperties().get("room"))) {
s.getBasicRemote().sendObject(chatMessage);
}
}
} catch (IOException | EncodeException e) {
log.log(Level.WARNING, "onMessage failed", e);
}
}
}
2014 Micha Kops / www.hascode.com
9. Chat Message Data Transfer
Object
package com.hascode.tutorial;
import java.util.Date;
public class ChatMessage {
private String message;
private String sender;
private Date received;
// getter, setter, toString omitted..
}
2014 Micha Kops / www.hascode.com
10. Converting Chat Messages
public class ChatMessageDecoder implements Decoder.Text<ChatMessage> {
@Override
public void init(final EndpointConfig config) {
}
@Override
public void destroy() {
}
@Override
public ChatMessage decode(final String textMessage) throws DecodeException {
ChatMessage chatMessage = new ChatMessage();
JsonObject obj = Json.createReader(new StringReader(textMessage))
.readObject();
chatMessage.setMessage(obj.getString("message"));
chatMessage.setSender(obj.getString("sender"));
chatMessage.setReceived(new Date());
return chatMessage;
}
@Override
public boolean willDecode(final String s) {
return true;
}
}
2014 Micha Kops / www.hascode.com
11. Encoder Implementation
public class ChatMessageEncoder implements Encoder.Text<ChatMessage> {
@Override
public void init(final EndpointConfig config) {
}
@Override
public void destroy() {
}
@Override
public String encode(final ChatMessage chatMessage) throws EncodeException {
return Json.createObjectBuilder()
.add("message", chatMessage.getMessage())
.add("sender", chatMessage.getSender())
.add("received", chatMessage.getReceived().toString()).build()
.toString();
}
}
2014 Micha Kops / www.hascode.com
12. The Client Side
●
●
●
●
●
●
●
We're using JavaScript to create the following stuff:
A websocket URL follows this schema:
ws://IP:PORT/CONTEXT_PATH/ENDPOINT_URL e.g
ws://0.0.0.0:8080/hascode/chat/java
A new websocket connection is created using the native WebSocket object e.g.
var wsocket = new WebSocket(‘ws://0.0.0.0:8080/hascode/chat/java’);
Registering a callback function to receive incoming messages from the server
goes like this: wsocket.onmessage = yourCallbackFunction;
Sending a message to the server is done by wsocket.send() .. pass a string,
binary data .. whatever you like ..
Closing a connection is simply done by wsocket.close()
There is a lot of useful information that I did not add to this tutorial from
keepalive-pings to the handshake protocol and other features .. one good
starting point for detailed information about websockets might be IETF RFC
6455
2014 Micha Kops / www.hascode.com
13. Client DOM Scripts (I)
var wsocket;
var serviceLocation = "ws://0.0.0.0:8080/hascode/chat/";
var $nickName;
var $message;
var $chatWindow;
var room = '';
function onMessageReceived(evt) {
//var msg = eval('(' + evt.data + ')');
var msg = JSON.parse(evt.data); // native API
var $messageLine = $('<tr><td class="received">' + msg.received
+ '</td><td class="user label label-info">' + msg.sender
+ '</td><td class="message badge">' + msg.message
+ '</td></tr>');
$chatWindow.append($messageLine);
}
function sendMessage() {
var msg = '{"message":"' + $message.val() + '", "sender":"'
+ $nickName.val() + '", "received":""}';
wsocket.send(msg);
$message.val('').focus();
}
2014 Micha Kops / www.hascode.com
14. Client DOM Scripts (II)
function connectToChatserver() {
room = $('#chatroom option:selected').val();
wsocket = new WebSocket(serviceLocation + room);
wsocket.onmessage = onMessageReceived;
}
function leaveRoom() {
wsocket.close();
$chatWindow.empty();
$('.chat-wrapper').hide();
$('.chat-signin').show();
$nickName.focus();
}
2014 Micha Kops / www.hascode.com
19. Tutorial, Sources and Links
●
Please feel free to take a look
at the full tutorial on my blog:
http://www.hascode.com/2013/08/
2014 Micha Kops / www.hascode.com