Bael 389 - Chat-like app using the Java API for WebSocket (#1265)
* Project for " A Guide to the Java API for WebSocket" article * Setting dependencies correctly * Formatting adjustments * Removing tomcat7 maven plugin * Applying formatt - No spaces
This commit is contained in:
parent
181688a765
commit
c83c449fa5
|
@ -0,0 +1,41 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>java-websocket</artifactId>
|
||||
<packaging>war</packaging>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>java-websocket Maven Webapp</name>
|
||||
<url>http://maven.apache.org</url>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>javax.websocket</groupId>
|
||||
<artifactId>javax.websocket-api</artifactId>
|
||||
<version>1.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.8.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.5.1</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -0,0 +1,36 @@
|
|||
package com.baeldung.model;
|
||||
|
||||
public class Message {
|
||||
private String from;
|
||||
private String to;
|
||||
private String content;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString();
|
||||
}
|
||||
|
||||
public String getFrom() {
|
||||
return from;
|
||||
}
|
||||
|
||||
public void setFrom(String from) {
|
||||
this.from = from;
|
||||
}
|
||||
|
||||
public String getTo() {
|
||||
return to;
|
||||
}
|
||||
|
||||
public void setTo(String to) {
|
||||
this.to = to;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
package com.baeldung.websocket;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
import javax.websocket.EncodeException;
|
||||
import javax.websocket.OnClose;
|
||||
import javax.websocket.OnError;
|
||||
import javax.websocket.OnMessage;
|
||||
import javax.websocket.OnOpen;
|
||||
import javax.websocket.Session;
|
||||
import javax.websocket.server.PathParam;
|
||||
import javax.websocket.server.ServerEndpoint;
|
||||
|
||||
import com.baeldung.model.Message;
|
||||
|
||||
@ServerEndpoint(value = "/chat/{username}", decoders = MessageDecoder.class, encoders = MessageEncoder.class)
|
||||
public class ChatEndpoint {
|
||||
private Session session;
|
||||
private static final Set<ChatEndpoint> chatEndpoints = new CopyOnWriteArraySet<>();
|
||||
private static HashMap<String, String> users = new HashMap<>();
|
||||
|
||||
@OnOpen
|
||||
public void onOpen(Session session, @PathParam("username") String username) throws IOException, EncodeException {
|
||||
|
||||
this.session = session;
|
||||
chatEndpoints.add(this);
|
||||
users.put(session.getId(), username);
|
||||
|
||||
Message message = new Message();
|
||||
message.setFrom(username);
|
||||
message.setContent("Connected!");
|
||||
broadcast(message);
|
||||
}
|
||||
|
||||
@OnMessage
|
||||
public void onMessage(Session session, Message message) throws IOException, EncodeException {
|
||||
message.setFrom(users.get(session.getId()));
|
||||
broadcast(message);
|
||||
}
|
||||
|
||||
@OnClose
|
||||
public void onClose(Session session) throws IOException, EncodeException {
|
||||
chatEndpoints.remove(this);
|
||||
Message message = new Message();
|
||||
message.setFrom(users.get(session.getId()));
|
||||
message.setContent("Disconnected!");
|
||||
broadcast(message);
|
||||
}
|
||||
|
||||
@OnError
|
||||
public void onError(Session session, Throwable throwable) {
|
||||
// Do error handling here
|
||||
}
|
||||
|
||||
private static void broadcast(Message message) throws IOException, EncodeException {
|
||||
chatEndpoints.forEach(endpoint -> {
|
||||
synchronized (endpoint) {
|
||||
try {
|
||||
endpoint.session.getBasicRemote()
|
||||
.sendObject(message);
|
||||
} catch (IOException | EncodeException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package com.baeldung.websocket;
|
||||
|
||||
import javax.websocket.DecodeException;
|
||||
import javax.websocket.Decoder;
|
||||
import javax.websocket.EndpointConfig;
|
||||
|
||||
import com.baeldung.model.Message;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
public class MessageDecoder implements Decoder.Text<Message> {
|
||||
@Override
|
||||
public Message decode(String s) throws DecodeException {
|
||||
Gson gson = new Gson();
|
||||
Message message = gson.fromJson(s, Message.class);
|
||||
return message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean willDecode(String s) {
|
||||
return (s != null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(EndpointConfig endpointConfig) {
|
||||
// Custom initialization logic
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
// Close resources
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package com.baeldung.websocket;
|
||||
|
||||
import javax.websocket.EncodeException;
|
||||
import javax.websocket.Encoder;
|
||||
import javax.websocket.EndpointConfig;
|
||||
|
||||
import com.baeldung.model.Message;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
public class MessageEncoder implements Encoder.Text<Message> {
|
||||
@Override
|
||||
public String encode(Message message) throws EncodeException {
|
||||
Gson gson = new Gson();
|
||||
String json = gson.toJson(message);
|
||||
return json;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(EndpointConfig endpointConfig) {
|
||||
// Custom initialization logic
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
// Close resources
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
|
||||
</beans>
|
|
@ -0,0 +1,7 @@
|
|||
<!DOCTYPE web-app PUBLIC
|
||||
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
|
||||
"http://java.sun.com/dtd/web-app_2_3.dtd" >
|
||||
|
||||
<web-app>
|
||||
<display-name>Archetype Created Web Application</display-name>
|
||||
</web-app>
|
|
@ -0,0 +1,30 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Chat</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<input type="text" id="username" placeholder="Username"/>
|
||||
<button type="button" onclick="connect();" >Connect</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<textarea readonly="true" rows="10" cols="80" id="log"></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<input type="text" size="51" id="msg" placeholder="Message"/>
|
||||
<button type="button" onclick="send();" >Send</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
|
||||
<script src="websocket.js"></script>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,136 @@
|
|||
body {
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
font-size: 80%;
|
||||
background-color: #1f1f1f;
|
||||
}
|
||||
|
||||
#wrapper {
|
||||
width: 960px;
|
||||
margin: auto;
|
||||
text-align: left;
|
||||
color: #d9d9d9;
|
||||
}
|
||||
|
||||
p {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.button {
|
||||
display: inline;
|
||||
color: #fff;
|
||||
background-color: #f2791d;
|
||||
padding: 8px;
|
||||
margin: auto;
|
||||
border-radius: 8px;
|
||||
-moz-border-radius: 8px;
|
||||
-webkit-border-radius: 8px;
|
||||
box-shadow: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.button:hover {
|
||||
background-color: #ffb15e;
|
||||
}
|
||||
.button a, a:visited, a:hover, a:active {
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#addDevice {
|
||||
text-align: center;
|
||||
width: 960px;
|
||||
margin: auto;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#addDeviceForm {
|
||||
text-align: left;
|
||||
width: 400px;
|
||||
margin: auto;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
#addDeviceForm span {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#content {
|
||||
margin: auto;
|
||||
width: 960px;
|
||||
}
|
||||
|
||||
.device {
|
||||
width: 180px;
|
||||
height: 110px;
|
||||
margin: 10px;
|
||||
padding: 16px;
|
||||
color: #fff;
|
||||
vertical-align: top;
|
||||
border-radius: 8px;
|
||||
-moz-border-radius: 8px;
|
||||
-webkit-border-radius: 8px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.device.off {
|
||||
background-color: #c8cccf;
|
||||
}
|
||||
|
||||
.device span {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.deviceName {
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.removeDevice {
|
||||
margin-top: 12px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.device.Appliance {
|
||||
background-color: #5eb85e;
|
||||
}
|
||||
|
||||
.device.Appliance a:hover {
|
||||
color: #a1ed82;
|
||||
}
|
||||
|
||||
.device.Electronics {
|
||||
background-color: #0f90d1;
|
||||
}
|
||||
|
||||
.device.Electronics a:hover {
|
||||
color: #4badd1;
|
||||
}
|
||||
|
||||
.device.Lights {
|
||||
background-color: #c2a00c;
|
||||
}
|
||||
|
||||
.device.Lights a:hover {
|
||||
color: #fad232;
|
||||
}
|
||||
|
||||
.device.Other {
|
||||
background-color: #db524d;
|
||||
}
|
||||
|
||||
.device.Other a:hover {
|
||||
color: #ff907d;
|
||||
}
|
||||
|
||||
.device a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.device a:visited, a:active, a:hover {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.device a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
var ws;
|
||||
|
||||
function connect() {
|
||||
var username = document.getElementById("username").value;
|
||||
ws = new WebSocket("ws://" + document.location.host + "/java-websocket/chat/" + username);
|
||||
|
||||
|
||||
ws.onmessage = function(event) {
|
||||
var log = document.getElementById("log");
|
||||
console.log(event.data);
|
||||
var message = JSON.parse(event.data);
|
||||
log.innerHTML += message.from + " : " + message.content + "\n";
|
||||
};
|
||||
}
|
||||
|
||||
function send() {
|
||||
var content = document.getElementById("msg").value;
|
||||
var json = JSON.stringify({
|
||||
"content":content
|
||||
});
|
||||
|
||||
ws.send(json);
|
||||
}
|
Loading…
Reference in New Issue