Skip to content

Commit c83c449

Browse files
Alex Vargaszhendrikse
authored andcommitted
Bael 389 - Chat-like app using the Java API for WebSocket (eugenp#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
1 parent 181688a commit c83c449

10 files changed

Lines changed: 408 additions & 0 deletions

File tree

java-websocket/pom.xml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
<groupId>com.baeldung</groupId>
5+
<artifactId>java-websocket</artifactId>
6+
<packaging>war</packaging>
7+
<version>0.0.1-SNAPSHOT</version>
8+
<name>java-websocket Maven Webapp</name>
9+
<url>http://maven.apache.org</url>
10+
11+
<properties>
12+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
13+
</properties>
14+
15+
<dependencies>
16+
<dependency>
17+
<groupId>javax.websocket</groupId>
18+
<artifactId>javax.websocket-api</artifactId>
19+
<version>1.1</version>
20+
</dependency>
21+
<dependency>
22+
<groupId>com.google.code.gson</groupId>
23+
<artifactId>gson</artifactId>
24+
<version>2.8.0</version>
25+
</dependency>
26+
</dependencies>
27+
28+
<build>
29+
<plugins>
30+
<plugin>
31+
<groupId>org.apache.maven.plugins</groupId>
32+
<artifactId>maven-compiler-plugin</artifactId>
33+
<version>3.5.1</version>
34+
<configuration>
35+
<source>1.8</source>
36+
<target>1.8</target>
37+
</configuration>
38+
</plugin>
39+
</plugins>
40+
</build>
41+
</project>
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.baeldung.model;
2+
3+
public class Message {
4+
private String from;
5+
private String to;
6+
private String content;
7+
8+
@Override
9+
public String toString() {
10+
return super.toString();
11+
}
12+
13+
public String getFrom() {
14+
return from;
15+
}
16+
17+
public void setFrom(String from) {
18+
this.from = from;
19+
}
20+
21+
public String getTo() {
22+
return to;
23+
}
24+
25+
public void setTo(String to) {
26+
this.to = to;
27+
}
28+
29+
public String getContent() {
30+
return content;
31+
}
32+
33+
public void setContent(String content) {
34+
this.content = content;
35+
}
36+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package com.baeldung.websocket;
2+
3+
import java.io.IOException;
4+
import java.util.HashMap;
5+
import java.util.Set;
6+
import java.util.concurrent.CopyOnWriteArraySet;
7+
8+
import javax.websocket.EncodeException;
9+
import javax.websocket.OnClose;
10+
import javax.websocket.OnError;
11+
import javax.websocket.OnMessage;
12+
import javax.websocket.OnOpen;
13+
import javax.websocket.Session;
14+
import javax.websocket.server.PathParam;
15+
import javax.websocket.server.ServerEndpoint;
16+
17+
import com.baeldung.model.Message;
18+
19+
@ServerEndpoint(value = "/chat/{username}", decoders = MessageDecoder.class, encoders = MessageEncoder.class)
20+
public class ChatEndpoint {
21+
private Session session;
22+
private static final Set<ChatEndpoint> chatEndpoints = new CopyOnWriteArraySet<>();
23+
private static HashMap<String, String> users = new HashMap<>();
24+
25+
@OnOpen
26+
public void onOpen(Session session, @PathParam("username") String username) throws IOException, EncodeException {
27+
28+
this.session = session;
29+
chatEndpoints.add(this);
30+
users.put(session.getId(), username);
31+
32+
Message message = new Message();
33+
message.setFrom(username);
34+
message.setContent("Connected!");
35+
broadcast(message);
36+
}
37+
38+
@OnMessage
39+
public void onMessage(Session session, Message message) throws IOException, EncodeException {
40+
message.setFrom(users.get(session.getId()));
41+
broadcast(message);
42+
}
43+
44+
@OnClose
45+
public void onClose(Session session) throws IOException, EncodeException {
46+
chatEndpoints.remove(this);
47+
Message message = new Message();
48+
message.setFrom(users.get(session.getId()));
49+
message.setContent("Disconnected!");
50+
broadcast(message);
51+
}
52+
53+
@OnError
54+
public void onError(Session session, Throwable throwable) {
55+
// Do error handling here
56+
}
57+
58+
private static void broadcast(Message message) throws IOException, EncodeException {
59+
chatEndpoints.forEach(endpoint -> {
60+
synchronized (endpoint) {
61+
try {
62+
endpoint.session.getBasicRemote()
63+
.sendObject(message);
64+
} catch (IOException | EncodeException e) {
65+
e.printStackTrace();
66+
}
67+
}
68+
});
69+
}
70+
71+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.baeldung.websocket;
2+
3+
import javax.websocket.DecodeException;
4+
import javax.websocket.Decoder;
5+
import javax.websocket.EndpointConfig;
6+
7+
import com.baeldung.model.Message;
8+
import com.google.gson.Gson;
9+
10+
public class MessageDecoder implements Decoder.Text<Message> {
11+
@Override
12+
public Message decode(String s) throws DecodeException {
13+
Gson gson = new Gson();
14+
Message message = gson.fromJson(s, Message.class);
15+
return message;
16+
}
17+
18+
@Override
19+
public boolean willDecode(String s) {
20+
return (s != null);
21+
}
22+
23+
@Override
24+
public void init(EndpointConfig endpointConfig) {
25+
// Custom initialization logic
26+
}
27+
28+
@Override
29+
public void destroy() {
30+
// Close resources
31+
}
32+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.baeldung.websocket;
2+
3+
import javax.websocket.EncodeException;
4+
import javax.websocket.Encoder;
5+
import javax.websocket.EndpointConfig;
6+
7+
import com.baeldung.model.Message;
8+
import com.google.gson.Gson;
9+
10+
public class MessageEncoder implements Encoder.Text<Message> {
11+
@Override
12+
public String encode(Message message) throws EncodeException {
13+
Gson gson = new Gson();
14+
String json = gson.toJson(message);
15+
return json;
16+
}
17+
18+
@Override
19+
public void init(EndpointConfig endpointConfig) {
20+
// Custom initialization logic
21+
}
22+
23+
@Override
24+
public void destroy() {
25+
// Close resources
26+
}
27+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<beans xmlns="http://java.sun.com/xml/ns/javaee"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
5+
</beans>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<!DOCTYPE web-app PUBLIC
2+
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
3+
"http://java.sun.com/dtd/web-app_2_3.dtd" >
4+
5+
<web-app>
6+
<display-name>Archetype Created Web Application</display-name>
7+
</web-app>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<html>
2+
<head>
3+
<title>Chat</title>
4+
</head>
5+
<body>
6+
7+
<table>
8+
<tr>
9+
<td colspan="2">
10+
<input type="text" id="username" placeholder="Username"/>
11+
<button type="button" onclick="connect();" >Connect</button>
12+
</td>
13+
</tr>
14+
<tr>
15+
<td>
16+
<textarea readonly="true" rows="10" cols="80" id="log"></textarea>
17+
</td>
18+
</tr>
19+
<tr>
20+
<td>
21+
<input type="text" size="51" id="msg" placeholder="Message"/>
22+
<button type="button" onclick="send();" >Send</button>
23+
</td>
24+
</tr>
25+
</table>
26+
</body>
27+
28+
<script src="websocket.js"></script>
29+
30+
</html>
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
body {
2+
font-family: Arial, Helvetica, sans-serif;
3+
font-size: 80%;
4+
background-color: #1f1f1f;
5+
}
6+
7+
#wrapper {
8+
width: 960px;
9+
margin: auto;
10+
text-align: left;
11+
color: #d9d9d9;
12+
}
13+
14+
p {
15+
text-align: left;
16+
}
17+
18+
.button {
19+
display: inline;
20+
color: #fff;
21+
background-color: #f2791d;
22+
padding: 8px;
23+
margin: auto;
24+
border-radius: 8px;
25+
-moz-border-radius: 8px;
26+
-webkit-border-radius: 8px;
27+
box-shadow: none;
28+
border: none;
29+
}
30+
31+
.button:hover {
32+
background-color: #ffb15e;
33+
}
34+
.button a, a:visited, a:hover, a:active {
35+
color: #fff;
36+
text-decoration: none;
37+
}
38+
39+
#addDevice {
40+
text-align: center;
41+
width: 960px;
42+
margin: auto;
43+
margin-bottom: 10px;
44+
}
45+
46+
#addDeviceForm {
47+
text-align: left;
48+
width: 400px;
49+
margin: auto;
50+
padding: 10px;
51+
}
52+
53+
#addDeviceForm span {
54+
display: block;
55+
}
56+
57+
#content {
58+
margin: auto;
59+
width: 960px;
60+
}
61+
62+
.device {
63+
width: 180px;
64+
height: 110px;
65+
margin: 10px;
66+
padding: 16px;
67+
color: #fff;
68+
vertical-align: top;
69+
border-radius: 8px;
70+
-moz-border-radius: 8px;
71+
-webkit-border-radius: 8px;
72+
display: inline-block;
73+
}
74+
75+
.device.off {
76+
background-color: #c8cccf;
77+
}
78+
79+
.device span {
80+
display: block;
81+
}
82+
83+
.deviceName {
84+
text-align: center;
85+
font-weight: bold;
86+
margin-bottom: 12px;
87+
}
88+
89+
.removeDevice {
90+
margin-top: 12px;
91+
text-align: center;
92+
}
93+
94+
.device.Appliance {
95+
background-color: #5eb85e;
96+
}
97+
98+
.device.Appliance a:hover {
99+
color: #a1ed82;
100+
}
101+
102+
.device.Electronics {
103+
background-color: #0f90d1;
104+
}
105+
106+
.device.Electronics a:hover {
107+
color: #4badd1;
108+
}
109+
110+
.device.Lights {
111+
background-color: #c2a00c;
112+
}
113+
114+
.device.Lights a:hover {
115+
color: #fad232;
116+
}
117+
118+
.device.Other {
119+
background-color: #db524d;
120+
}
121+
122+
.device.Other a:hover {
123+
color: #ff907d;
124+
}
125+
126+
.device a {
127+
text-decoration: none;
128+
}
129+
130+
.device a:visited, a:active, a:hover {
131+
color: #fff;
132+
}
133+
134+
.device a:hover {
135+
text-decoration: underline;
136+
}

0 commit comments

Comments
 (0)