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