Polish WebSocket samples

pull/2063/head
Phillip Webb 10 years ago
parent 8928012943
commit c22aee9817

@ -73,8 +73,8 @@
<module>spring-boot-sample-web-jsp</module> <module>spring-boot-sample-web-jsp</module>
<module>spring-boot-sample-web-ui</module> <module>spring-boot-sample-web-ui</module>
<module>spring-boot-sample-web-velocity</module> <module>spring-boot-sample-web-velocity</module>
<module>spring-boot-sample-websocket</module>
<module>spring-boot-sample-websocket-jetty</module> <module>spring-boot-sample-websocket-jetty</module>
<module>spring-boot-sample-websocket-tomcat</module>
<module>spring-boot-sample-websocket-undertow</module> <module>spring-boot-sample-websocket-undertow</module>
<module>spring-boot-sample-ws</module> <module>spring-boot-sample-ws</module>
<module>spring-boot-sample-xml</module> <module>spring-boot-sample-xml</module>

@ -14,13 +14,14 @@
* limitations under the License. * limitations under the License.
*/ */
package samples.websocket.config; package samples.websocket;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer; import org.springframework.boot.context.web.SpringBootServletInitializer;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.EnableWebSocket; import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer; import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
@ -36,10 +37,11 @@ import samples.websocket.echo.EchoWebSocketHandler;
import samples.websocket.reverse.ReverseWebSocketEndpoint; import samples.websocket.reverse.ReverseWebSocketEndpoint;
import samples.websocket.snake.SnakeWebSocketHandler; import samples.websocket.snake.SnakeWebSocketHandler;
@SpringBootApplication @Configuration
@EnableAutoConfiguration
@EnableWebSocket @EnableWebSocket
public class SampleWebSocketsApplication extends SpringBootServletInitializer implements public class SampleJettyWebSocketsApplication extends SpringBootServletInitializer
WebSocketConfigurer { implements WebSocketConfigurer {
@Override @Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
@ -49,11 +51,7 @@ public class SampleWebSocketsApplication extends SpringBootServletInitializer im
@Override @Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(SampleWebSocketsApplication.class); return application.sources(SampleJettyWebSocketsApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(SampleWebSocketsApplication.class, args);
} }
@Bean @Bean
@ -86,4 +84,8 @@ public class SampleWebSocketsApplication extends SpringBootServletInitializer im
return new ServerEndpointExporter(); return new ServerEndpointExporter();
} }
public static void main(String[] args) {
SpringApplication.run(SampleJettyWebSocketsApplication.class, args);
}
} }

@ -1,19 +1,20 @@
<!-- <!--
Licensed to the Apache Software Foundation (ASF) under one or more Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership. this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0 The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with (the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
--> -->
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>

@ -1,19 +1,20 @@
<!-- <!--
Licensed to the Apache Software Foundation (ASF) under one or more Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership. this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0 The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with (the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
--> -->
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>

@ -1,19 +1,20 @@
<!-- <!--
Licensed to the Apache Software Foundation (ASF) under one or more Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership. this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0 The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with (the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
--> -->
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>

@ -1,19 +1,20 @@
<!-- <!--
Licensed to the Apache Software Foundation (ASF) under one or more Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership. this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0 The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with (the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
--> -->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">

@ -42,12 +42,11 @@ import org.springframework.web.socket.client.standard.StandardWebSocketClient;
import samples.websocket.client.GreetingService; import samples.websocket.client.GreetingService;
import samples.websocket.client.SimpleClientWebSocketHandler; import samples.websocket.client.SimpleClientWebSocketHandler;
import samples.websocket.client.SimpleGreetingService; import samples.websocket.client.SimpleGreetingService;
import samples.websocket.config.SampleWebSocketsApplication;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
@RunWith(SpringJUnit4ClassRunner.class) @RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = SampleWebSocketsApplication.class) @SpringApplicationConfiguration(classes = SampleJettyWebSocketsApplication.class)
@WebAppConfiguration @WebAppConfiguration
@IntegrationTest("server.port:0") @IntegrationTest("server.port:0")
@DirtiesContext @DirtiesContext

@ -42,16 +42,16 @@ import org.springframework.util.SocketUtils;
import org.springframework.web.socket.client.WebSocketConnectionManager; import org.springframework.web.socket.client.WebSocketConnectionManager;
import org.springframework.web.socket.client.standard.StandardWebSocketClient; import org.springframework.web.socket.client.standard.StandardWebSocketClient;
import samples.websocket.SampleJettyWebSocketsApplication;
import samples.websocket.client.GreetingService; import samples.websocket.client.GreetingService;
import samples.websocket.client.SimpleClientWebSocketHandler; import samples.websocket.client.SimpleClientWebSocketHandler;
import samples.websocket.client.SimpleGreetingService; import samples.websocket.client.SimpleGreetingService;
import samples.websocket.config.SampleWebSocketsApplication;
import samples.websocket.echo.CustomContainerWebSocketsApplicationTests.CustomContainerConfiguration; import samples.websocket.echo.CustomContainerWebSocketsApplicationTests.CustomContainerConfiguration;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
@RunWith(SpringJUnit4ClassRunner.class) @RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = { SampleWebSocketsApplication.class, @SpringApplicationConfiguration(classes = { SampleJettyWebSocketsApplication.class,
CustomContainerConfiguration.class }) CustomContainerConfiguration.class })
@WebAppConfiguration @WebAppConfiguration
@IntegrationTest @IntegrationTest
@ -63,14 +63,6 @@ public class CustomContainerWebSocketsApplicationTests {
private static int PORT = SocketUtils.findAvailableTcpPort(); private static int PORT = SocketUtils.findAvailableTcpPort();
@Configuration
protected static class CustomContainerConfiguration {
@Bean
public EmbeddedServletContainerFactory embeddedServletContainerFactory() {
return new JettyEmbeddedServletContainerFactory("/ws", PORT);
}
}
@Test @Test
public void echoEndpoint() throws Exception { public void echoEndpoint() throws Exception {
ConfigurableApplicationContext context = new SpringApplicationBuilder( ConfigurableApplicationContext context = new SpringApplicationBuilder(
@ -99,6 +91,16 @@ public class CustomContainerWebSocketsApplicationTests {
assertEquals("Reversed: !dlrow olleH", messagePayloadReference.get()); assertEquals("Reversed: !dlrow olleH", messagePayloadReference.get());
} }
@Configuration
protected static class CustomContainerConfiguration {
@Bean
public EmbeddedServletContainerFactory embeddedServletContainerFactory() {
return new JettyEmbeddedServletContainerFactory("/ws", PORT);
}
}
@Configuration @Configuration
static class ClientConfiguration implements CommandLineRunner { static class ClientConfiguration implements CommandLineRunner {
@ -145,6 +147,7 @@ public class CustomContainerWebSocketsApplicationTests {
public GreetingService greetingService() { public GreetingService greetingService() {
return new SimpleGreetingService(); return new SimpleGreetingService();
} }
} }
} }

@ -37,4 +37,5 @@ public class SnakeTimerTests {
SnakeTimer.broadcast(""); SnakeTimer.broadcast("");
assertThat(SnakeTimer.getSnakes().size(), is(0)); assertThat(SnakeTimer.getSnakes().size(), is(0));
} }
} }

@ -7,9 +7,9 @@
<artifactId>spring-boot-samples</artifactId> <artifactId>spring-boot-samples</artifactId>
<version>1.2.0.BUILD-SNAPSHOT</version> <version>1.2.0.BUILD-SNAPSHOT</version>
</parent> </parent>
<artifactId>spring-boot-sample-websocket</artifactId> <artifactId>spring-boot-sample-websocket-tomcat</artifactId>
<name>Spring Boot WebSocket Sample</name> <name>Spring Boot WebSocket Tomcat Sample</name>
<description>Spring Boot WebSocket Sample</description> <description>Spring Boot WebSocket Tomcat Sample</description>
<url>http://projects.spring.io/spring-boot/</url> <url>http://projects.spring.io/spring-boot/</url>
<organization> <organization>
<name>Pivotal Software, Inc.</name> <name>Pivotal Software, Inc.</name>

@ -14,13 +14,14 @@
* limitations under the License. * limitations under the License.
*/ */
package samples.websocket.config; package samples.websocket;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer; import org.springframework.boot.context.web.SpringBootServletInitializer;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.EnableWebSocket; import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer; import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
@ -36,10 +37,11 @@ import samples.websocket.echo.EchoWebSocketHandler;
import samples.websocket.reverse.ReverseWebSocketEndpoint; import samples.websocket.reverse.ReverseWebSocketEndpoint;
import samples.websocket.snake.SnakeWebSocketHandler; import samples.websocket.snake.SnakeWebSocketHandler;
@SpringBootApplication @Configuration
@EnableAutoConfiguration
@EnableWebSocket @EnableWebSocket
public class SampleWebSocketsApplication extends SpringBootServletInitializer implements public class SampleTomcatWebSocketApplication extends SpringBootServletInitializer
WebSocketConfigurer { implements WebSocketConfigurer {
@Override @Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
@ -49,11 +51,7 @@ public class SampleWebSocketsApplication extends SpringBootServletInitializer im
@Override @Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(SampleWebSocketsApplication.class); return application.sources(SampleTomcatWebSocketApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(SampleWebSocketsApplication.class, args);
} }
@Bean @Bean
@ -86,4 +84,8 @@ public class SampleWebSocketsApplication extends SpringBootServletInitializer im
return new ServerEndpointExporter(); return new ServerEndpointExporter();
} }
public static void main(String[] args) {
SpringApplication.run(SampleTomcatWebSocketApplication.class, args);
}
} }

@ -0,0 +1,134 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!DOCTYPE html>
<html>
<head>
<title>Apache Tomcat WebSocket Examples: Echo</title>
<style type="text/css">
#connect-container {
float: left;
width: 400px
}
#connect-container div {
padding: 5px;
}
#console-container {
float: left;
margin-left: 15px;
width: 400px;
}
#console {
border: 1px solid #CCCCCC;
border-right-color: #999999;
border-bottom-color: #999999;
height: 170px;
overflow-y: scroll;
padding: 5px;
width: 100%;
}
#console p {
padding: 0;
margin: 0;
}
</style>
<script src="https://cdn.jsdelivr.net/sockjs/0.3.4/sockjs.min.js"></script>
<script type="text/javascript">
var ws = null;
function setConnected(connected) {
document.getElementById('connect').disabled = connected;
document.getElementById('disconnect').disabled = !connected;
document.getElementById('echo').disabled = !connected;
}
function connect() {
var target = document.getElementById('target').value;
ws = new SockJS(target);
ws.onopen = function () {
setConnected(true);
log('Info: WebSocket connection opened.');
};
ws.onmessage = function (event) {
log('Received: ' + event.data);
};
ws.onclose = function () {
setConnected(false);
log('Info: WebSocket connection closed.');
};
}
function disconnect() {
if (ws != null) {
ws.close();
ws = null;
}
setConnected(false);
}
function echo() {
if (ws != null) {
var message = document.getElementById('message').value;
log('Sent: ' + message);
ws.send(message);
} else {
alert('WebSocket connection not established, please connect.');
}
}
function log(message) {
var console = document.getElementById('console');
var p = document.createElement('p');
p.style.wordWrap = 'break-word';
p.appendChild(document.createTextNode(message));
console.appendChild(p);
while (console.childNodes.length > 25) {
console.removeChild(console.firstChild);
}
console.scrollTop = console.scrollHeight;
}
</script>
</head>
<body>
<noscript><h2 style="color: #ff0000">Seems your browser doesn't support Javascript! Websockets rely on Javascript being enabled. Please enable
Javascript and reload this page!</h2></noscript>
<div>
<div id="connect-container">
<div>
<input id="target" type="text" size="40" style="width: 350px" value="/echo"/>
</div>
<div>
<button id="connect" onclick="connect();">Connect</button>
<button id="disconnect" disabled="disabled" onclick="disconnect();">Disconnect</button>
</div>
<div>
<textarea id="message" style="width: 350px">Here is a message!</textarea>
</div>
<div>
<button id="echo" onclick="echo();" disabled="disabled">Echo message</button>
</div>
</div>
<div id="console-container">
<div id="console"></div>
</div>
</div>
</body>
</html>

@ -0,0 +1,33 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!DOCTYPE html>
<html>
<head>
<title>Apache Tomcat WebSocket Examples: Index</title>
</head>
<body>
<noscript><h2 style="color: #ff0000">Seems your browser doesn't support Javascript! Websockets rely on Javascript being enabled. Please enable
Javascript and reload this page!</h2></noscript>
<p>Please select the sample you would like to try.</p>
<ul>
<li><a href="./echo.html">Echo</a></li>
<li><a href="./reverse.html">Reverse</a></li>
<li><a href="./snake.html">Snake</a></li>
</ul>
</body>
</html>

@ -0,0 +1,141 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!DOCTYPE html>
<html>
<head>
<title>WebSocket Examples: Reverse</title>
<style type="text/css">
#connect-container {
float: left;
width: 400px
}
#connect-container div {
padding: 5px;
}
#console-container {
float: left;
margin-left: 15px;
width: 400px;
}
#console {
border: 1px solid #CCCCCC;
border-right-color: #999999;
border-bottom-color: #999999;
height: 170px;
overflow-y: scroll;
padding: 5px;
width: 100%;
}
#console p {
padding: 0;
margin: 0;
}
</style>
<script type="text/javascript">
var ws = null;
function setConnected(connected) {
document.getElementById('connect').disabled = connected;
document.getElementById('disconnect').disabled = !connected;
document.getElementById('reverse').disabled = !connected;
}
function connect() {
var target = document.getElementById('target').value;
ws = new WebSocket(target);
ws.onopen = function () {
setConnected(true);
log('Info: WebSocket connection opened.');
};
ws.onmessage = function (event) {
log('Received: ' + event.data);
};
ws.onclose = function () {
setConnected(false);
log('Info: WebSocket connection closed.');
};
}
function updateTarget() {
if (window.location.protocol == 'http:') {
document.getElementById('target').value = 'ws://' + window.location.host + document.getElementById('target').value;
} else {
document.getElementById('target').value = 'wss://' + window.location.host + document.getElementById('target').value;
}
}
function disconnect() {
if (ws != null) {
ws.close();
ws = null;
}
setConnected(false);
}
function reverse() {
if (ws != null) {
var message = document.getElementById('message').value;
log('Sent: ' + message);
ws.send(message);
} else {
alert('WebSocket connection not established, please connect.');
}
}
function log(message) {
var console = document.getElementById('console');
var p = document.createElement('p');
p.style.wordWrap = 'break-word';
p.appendChild(document.createTextNode(message));
console.appendChild(p);
while (console.childNodes.length > 25) {
console.removeChild(console.firstChild);
}
console.scrollTop = console.scrollHeight;
}
</script>
</head>
<body onload="updateTarget()">
<noscript><h2 style="color: #ff0000">Seems your browser doesn't support Javascript! Websockets rely on Javascript being enabled. Please enable
Javascript and reload this page!</h2></noscript>
<div>
<div id="connect-container">
<div>
<input id="target" type="text" size="40" style="width: 350px" value="/reverse"/>
</div>
<div>
<button id="connect" onclick="connect();">Connect</button>
<button id="disconnect" disabled="disabled" onclick="disconnect();">Disconnect</button>
</div>
<div>
<textarea id="message" style="width: 350px">Here is a message!</textarea>
</div>
<div>
<button id="reverse" onclick="reverse();" disabled="disabled">Reverse message</button>
</div>
</div>
<div id="console-container">
<div id="console"></div>
</div>
</div>
</body>
</html>

@ -0,0 +1,250 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Apache Tomcat WebSocket Examples: Multiplayer Snake</title>
<style type="text/css">
#playground {
width: 640px;
height: 480px;
background-color: #000;
}
#console-container {
float: left;
margin-left: 15px;
width: 300px;
}
#console {
border: 1px solid #CCCCCC;
border-right-color: #999999;
border-bottom-color: #999999;
height: 480px;
overflow-y: scroll;
padding-left: 5px;
padding-right: 5px;
width: 100%;
}
#console p {
padding: 0;
margin: 0;
}
</style>
<script src="https://cdn.jsdelivr.net/sockjs/0.3.4/sockjs.min.js"></script>
</head>
<body>
<noscript><h2 style="color: #ff0000">Seems your browser doesn't support Javascript! Websockets rely on Javascript being enabled. Please enable
Javascript and reload this page!</h2></noscript>
<div style="float: left">
<canvas id="playground" width="640" height="480"></canvas>
</div>
<div id="console-container">
<div id="console"></div>
</div>
<script type="text/javascript">
var Game = {};
Game.fps = 30;
Game.socket = null;
Game.nextFrame = null;
Game.interval = null;
Game.direction = 'none';
Game.gridSize = 10;
function Snake() {
this.snakeBody = [];
this.color = null;
}
Snake.prototype.draw = function(context) {
for (var id in this.snakeBody) {
context.fillStyle = this.color;
context.fillRect(this.snakeBody[id].x, this.snakeBody[id].y, Game.gridSize, Game.gridSize);
}
};
Game.initialize = function() {
this.entities = [];
canvas = document.getElementById('playground');
if (!canvas.getContext) {
Console.log('Error: 2d canvas not supported by this browser.');
return;
}
this.context = canvas.getContext('2d');
window.addEventListener('keydown', function (e) {
var code = e.keyCode;
if (code > 36 && code < 41) {
switch (code) {
case 37:
if (Game.direction != 'east') Game.setDirection('west');
break;
case 38:
if (Game.direction != 'south') Game.setDirection('north');
break;
case 39:
if (Game.direction != 'west') Game.setDirection('east');
break;
case 40:
if (Game.direction != 'north') Game.setDirection('south');
break;
}
}
}, false);
Game.connect();
};
Game.setDirection = function(direction) {
Game.direction = direction;
Game.socket.send(direction);
Console.log('Sent: Direction ' + direction);
};
Game.startGameLoop = function() {
if (window.webkitRequestAnimationFrame) {
Game.nextFrame = function () {
webkitRequestAnimationFrame(Game.run);
};
} else if (window.mozRequestAnimationFrame) {
Game.nextFrame = function () {
mozRequestAnimationFrame(Game.run);
};
} else {
Game.interval = setInterval(Game.run, 1000 / Game.fps);
}
if (Game.nextFrame != null) {
Game.nextFrame();
}
};
Game.stopGameLoop = function () {
Game.nextFrame = null;
if (Game.interval != null) {
clearInterval(Game.interval);
}
};
Game.draw = function() {
this.context.clearRect(0, 0, 640, 480);
for (var id in this.entities) {
this.entities[id].draw(this.context);
}
};
Game.addSnake = function(id, color) {
Game.entities[id] = new Snake();
Game.entities[id].color = color;
};
Game.updateSnake = function(id, snakeBody) {
if (typeof Game.entities[id] != "undefined") {
Game.entities[id].snakeBody = snakeBody;
}
};
Game.removeSnake = function(id) {
Game.entities[id] = null;
// Force GC.
delete Game.entities[id];
};
Game.run = (function() {
var skipTicks = 1000 / Game.fps, nextGameTick = (new Date).getTime();
return function() {
while ((new Date).getTime() > nextGameTick) {
nextGameTick += skipTicks;
}
Game.draw();
if (Game.nextFrame != null) {
Game.nextFrame();
}
};
})();
Game.connect = (function() {
Game.socket = new SockJS("/snake");
Game.socket.onopen = function () {
// Socket open.. start the game loop.
Console.log('Info: WebSocket connection opened.');
Console.log('Info: Press an arrow key to begin.');
Game.startGameLoop();
setInterval(function() {
// Prevent server read timeout.
Game.socket.send('ping');
}, 5000);
};
Game.socket.onclose = function () {
Console.log('Info: WebSocket closed.');
Game.stopGameLoop();
};
Game.socket.onmessage = function (message) {
// _Potential_ security hole, consider using json lib to parse data in production.
var packet = eval('(' + message.data + ')');
switch (packet.type) {
case 'update':
for (var i = 0; i < packet.data.length; i++) {
Game.updateSnake(packet.data[i].id, packet.data[i].body);
}
break;
case 'join':
for (var j = 0; j < packet.data.length; j++) {
Game.addSnake(packet.data[j].id, packet.data[j].color);
}
break;
case 'leave':
Game.removeSnake(packet.id);
break;
case 'dead':
Console.log('Info: Your snake is dead, bad luck!');
Game.direction = 'none';
break;
case 'kill':
Console.log('Info: Head shot!');
break;
}
};
});
var Console = {};
Console.log = (function(message) {
var console = document.getElementById('console');
var p = document.createElement('p');
p.style.wordWrap = 'break-word';
p.innerHTML = message;
console.appendChild(p);
while (console.childNodes.length > 25) {
console.removeChild(console.firstChild);
}
console.scrollTop = console.scrollHeight;
});
Game.initialize();
</script>
</body>
</html>

@ -42,12 +42,11 @@ import org.springframework.web.socket.client.standard.StandardWebSocketClient;
import samples.websocket.client.GreetingService; import samples.websocket.client.GreetingService;
import samples.websocket.client.SimpleClientWebSocketHandler; import samples.websocket.client.SimpleClientWebSocketHandler;
import samples.websocket.client.SimpleGreetingService; import samples.websocket.client.SimpleGreetingService;
import samples.websocket.config.SampleWebSocketsApplication;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
@RunWith(SpringJUnit4ClassRunner.class) @RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = SampleWebSocketsApplication.class) @SpringApplicationConfiguration(classes = SampleTomcatWebSocketApplication.class)
@WebAppConfiguration @WebAppConfiguration
@IntegrationTest("server.port:0") @IntegrationTest("server.port:0")
@DirtiesContext @DirtiesContext
@ -133,6 +132,7 @@ public class SampleWebSocketsApplicationTests {
public GreetingService greetingService() { public GreetingService greetingService() {
return new SimpleGreetingService(); return new SimpleGreetingService();
} }
} }
} }

@ -42,16 +42,16 @@ import org.springframework.util.SocketUtils;
import org.springframework.web.socket.client.WebSocketConnectionManager; import org.springframework.web.socket.client.WebSocketConnectionManager;
import org.springframework.web.socket.client.standard.StandardWebSocketClient; import org.springframework.web.socket.client.standard.StandardWebSocketClient;
import samples.websocket.SampleTomcatWebSocketApplication;
import samples.websocket.client.GreetingService; import samples.websocket.client.GreetingService;
import samples.websocket.client.SimpleClientWebSocketHandler; import samples.websocket.client.SimpleClientWebSocketHandler;
import samples.websocket.client.SimpleGreetingService; import samples.websocket.client.SimpleGreetingService;
import samples.websocket.config.SampleWebSocketsApplication;
import samples.websocket.echo.CustomContainerWebSocketsApplicationTests.CustomContainerConfiguration; import samples.websocket.echo.CustomContainerWebSocketsApplicationTests.CustomContainerConfiguration;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
@RunWith(SpringJUnit4ClassRunner.class) @RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = { SampleWebSocketsApplication.class, @SpringApplicationConfiguration(classes = { SampleTomcatWebSocketApplication.class,
CustomContainerConfiguration.class }) CustomContainerConfiguration.class })
@WebAppConfiguration @WebAppConfiguration
@IntegrationTest @IntegrationTest
@ -63,14 +63,6 @@ public class CustomContainerWebSocketsApplicationTests {
private static int PORT = SocketUtils.findAvailableTcpPort(); private static int PORT = SocketUtils.findAvailableTcpPort();
@Configuration
protected static class CustomContainerConfiguration {
@Bean
public EmbeddedServletContainerFactory embeddedServletContainerFactory() {
return new TomcatEmbeddedServletContainerFactory("/ws", PORT);
}
}
@Test @Test
public void echoEndpoint() throws Exception { public void echoEndpoint() throws Exception {
ConfigurableApplicationContext context = new SpringApplicationBuilder( ConfigurableApplicationContext context = new SpringApplicationBuilder(
@ -99,6 +91,16 @@ public class CustomContainerWebSocketsApplicationTests {
assertEquals("Reversed: !dlrow olleH", messagePayloadReference.get()); assertEquals("Reversed: !dlrow olleH", messagePayloadReference.get());
} }
@Configuration
protected static class CustomContainerConfiguration {
@Bean
public EmbeddedServletContainerFactory embeddedServletContainerFactory() {
return new TomcatEmbeddedServletContainerFactory("/ws", PORT);
}
}
@Configuration @Configuration
static class ClientConfiguration implements CommandLineRunner { static class ClientConfiguration implements CommandLineRunner {
@ -145,6 +147,7 @@ public class CustomContainerWebSocketsApplicationTests {
public GreetingService greetingService() { public GreetingService greetingService() {
return new SimpleGreetingService(); return new SimpleGreetingService();
} }
} }
} }

@ -14,13 +14,14 @@
* limitations under the License. * limitations under the License.
*/ */
package samples.websocket.config; package samples.websocket;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer; import org.springframework.boot.context.web.SpringBootServletInitializer;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.EnableWebSocket; import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer; import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
@ -36,7 +37,8 @@ import samples.websocket.echo.EchoWebSocketHandler;
import samples.websocket.reverse.ReverseWebSocketEndpoint; import samples.websocket.reverse.ReverseWebSocketEndpoint;
import samples.websocket.snake.SnakeWebSocketHandler; import samples.websocket.snake.SnakeWebSocketHandler;
@SpringBootApplication @Configuration
@EnableAutoConfiguration
@EnableWebSocket @EnableWebSocket
public class SampleUndertowWebSocketsApplication extends SpringBootServletInitializer public class SampleUndertowWebSocketsApplication extends SpringBootServletInitializer
implements WebSocketConfigurer { implements WebSocketConfigurer {

@ -1,19 +1,20 @@
<!-- <!--
Licensed to the Apache Software Foundation (ASF) under one or more Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership. this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0 The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with (the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
--> -->
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>

@ -1,19 +1,20 @@
<!-- <!--
Licensed to the Apache Software Foundation (ASF) under one or more Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership. this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0 The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with (the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
--> -->
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>

@ -1,19 +1,20 @@
<!-- <!--
Licensed to the Apache Software Foundation (ASF) under one or more Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership. this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0 The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with (the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
--> -->
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>

@ -1,19 +1,20 @@
<!-- <!--
Licensed to the Apache Software Foundation (ASF) under one or more Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership. this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0 The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with (the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
--> -->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">

@ -42,7 +42,6 @@ import org.springframework.web.socket.client.standard.StandardWebSocketClient;
import samples.websocket.client.GreetingService; import samples.websocket.client.GreetingService;
import samples.websocket.client.SimpleClientWebSocketHandler; import samples.websocket.client.SimpleClientWebSocketHandler;
import samples.websocket.client.SimpleGreetingService; import samples.websocket.client.SimpleGreetingService;
import samples.websocket.config.SampleUndertowWebSocketsApplication;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
@ -133,6 +132,7 @@ public class SampleWebSocketsApplicationTests {
public GreetingService greetingService() { public GreetingService greetingService() {
return new SimpleGreetingService(); return new SimpleGreetingService();
} }
} }
} }

@ -42,10 +42,10 @@ import org.springframework.util.SocketUtils;
import org.springframework.web.socket.client.WebSocketConnectionManager; import org.springframework.web.socket.client.WebSocketConnectionManager;
import org.springframework.web.socket.client.standard.StandardWebSocketClient; import org.springframework.web.socket.client.standard.StandardWebSocketClient;
import samples.websocket.SampleUndertowWebSocketsApplication;
import samples.websocket.client.GreetingService; import samples.websocket.client.GreetingService;
import samples.websocket.client.SimpleClientWebSocketHandler; import samples.websocket.client.SimpleClientWebSocketHandler;
import samples.websocket.client.SimpleGreetingService; import samples.websocket.client.SimpleGreetingService;
import samples.websocket.config.SampleUndertowWebSocketsApplication;
import samples.websocket.echo.CustomContainerWebSocketsApplicationTests.CustomContainerConfiguration; import samples.websocket.echo.CustomContainerWebSocketsApplicationTests.CustomContainerConfiguration;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
@ -63,14 +63,6 @@ public class CustomContainerWebSocketsApplicationTests {
private static int PORT = SocketUtils.findAvailableTcpPort(); private static int PORT = SocketUtils.findAvailableTcpPort();
@Configuration
protected static class CustomContainerConfiguration {
@Bean
public EmbeddedServletContainerFactory embeddedServletContainerFactory() {
return new UndertowEmbeddedServletContainerFactory("/ws", PORT);
}
}
@Test @Test
public void echoEndpoint() throws Exception { public void echoEndpoint() throws Exception {
ConfigurableApplicationContext context = new SpringApplicationBuilder( ConfigurableApplicationContext context = new SpringApplicationBuilder(
@ -99,6 +91,16 @@ public class CustomContainerWebSocketsApplicationTests {
assertEquals("Reversed: !dlrow olleH", messagePayloadReference.get()); assertEquals("Reversed: !dlrow olleH", messagePayloadReference.get());
} }
@Configuration
protected static class CustomContainerConfiguration {
@Bean
public EmbeddedServletContainerFactory embeddedServletContainerFactory() {
return new UndertowEmbeddedServletContainerFactory("/ws", PORT);
}
}
@Configuration @Configuration
static class ClientConfiguration implements CommandLineRunner { static class ClientConfiguration implements CommandLineRunner {
@ -145,6 +147,7 @@ public class CustomContainerWebSocketsApplicationTests {
public GreetingService greetingService() { public GreetingService greetingService() {
return new SimpleGreetingService(); return new SimpleGreetingService();
} }
} }
} }

@ -1,133 +0,0 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!DOCTYPE html>
<html>
<head>
<title>Apache Tomcat WebSocket Examples: Echo</title>
<style type="text/css">
#connect-container {
float: left;
width: 400px
}
#connect-container div {
padding: 5px;
}
#console-container {
float: left;
margin-left: 15px;
width: 400px;
}
#console {
border: 1px solid #CCCCCC;
border-right-color: #999999;
border-bottom-color: #999999;
height: 170px;
overflow-y: scroll;
padding: 5px;
width: 100%;
}
#console p {
padding: 0;
margin: 0;
}
</style>
<script src="https://cdn.jsdelivr.net/sockjs/0.3.4/sockjs.min.js"></script>
<script type="text/javascript">
var ws = null;
function setConnected(connected) {
document.getElementById('connect').disabled = connected;
document.getElementById('disconnect').disabled = !connected;
document.getElementById('echo').disabled = !connected;
}
function connect() {
var target = document.getElementById('target').value;
ws = new SockJS(target);
ws.onopen = function () {
setConnected(true);
log('Info: WebSocket connection opened.');
};
ws.onmessage = function (event) {
log('Received: ' + event.data);
};
ws.onclose = function () {
setConnected(false);
log('Info: WebSocket connection closed.');
};
}
function disconnect() {
if (ws != null) {
ws.close();
ws = null;
}
setConnected(false);
}
function echo() {
if (ws != null) {
var message = document.getElementById('message').value;
log('Sent: ' + message);
ws.send(message);
} else {
alert('WebSocket connection not established, please connect.');
}
}
function log(message) {
var console = document.getElementById('console');
var p = document.createElement('p');
p.style.wordWrap = 'break-word';
p.appendChild(document.createTextNode(message));
console.appendChild(p);
while (console.childNodes.length > 25) {
console.removeChild(console.firstChild);
}
console.scrollTop = console.scrollHeight;
}
</script>
</head>
<body>
<noscript><h2 style="color: #ff0000">Seems your browser doesn't support Javascript! Websockets rely on Javascript being enabled. Please enable
Javascript and reload this page!</h2></noscript>
<div>
<div id="connect-container">
<div>
<input id="target" type="text" size="40" style="width: 350px" value="/echo"/>
</div>
<div>
<button id="connect" onclick="connect();">Connect</button>
<button id="disconnect" disabled="disabled" onclick="disconnect();">Disconnect</button>
</div>
<div>
<textarea id="message" style="width: 350px">Here is a message!</textarea>
</div>
<div>
<button id="echo" onclick="echo();" disabled="disabled">Echo message</button>
</div>
</div>
<div id="console-container">
<div id="console"></div>
</div>
</div>
</body>
</html>

@ -1,32 +0,0 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!DOCTYPE html>
<html>
<head>
<title>Apache Tomcat WebSocket Examples: Index</title>
</head>
<body>
<noscript><h2 style="color: #ff0000">Seems your browser doesn't support Javascript! Websockets rely on Javascript being enabled. Please enable
Javascript and reload this page!</h2></noscript>
<p>Please select the sample you would like to try.</p>
<ul>
<li><a href="./echo.html">Echo</a></li>
<li><a href="./reverse.html">Reverse</a></li>
<li><a href="./snake.html">Snake</a></li>
</ul>
</body>
</html>

@ -1,140 +0,0 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!DOCTYPE html>
<html>
<head>
<title>WebSocket Examples: Reverse</title>
<style type="text/css">
#connect-container {
float: left;
width: 400px
}
#connect-container div {
padding: 5px;
}
#console-container {
float: left;
margin-left: 15px;
width: 400px;
}
#console {
border: 1px solid #CCCCCC;
border-right-color: #999999;
border-bottom-color: #999999;
height: 170px;
overflow-y: scroll;
padding: 5px;
width: 100%;
}
#console p {
padding: 0;
margin: 0;
}
</style>
<script type="text/javascript">
var ws = null;
function setConnected(connected) {
document.getElementById('connect').disabled = connected;
document.getElementById('disconnect').disabled = !connected;
document.getElementById('reverse').disabled = !connected;
}
function connect() {
var target = document.getElementById('target').value;
ws = new WebSocket(target);
ws.onopen = function () {
setConnected(true);
log('Info: WebSocket connection opened.');
};
ws.onmessage = function (event) {
log('Received: ' + event.data);
};
ws.onclose = function () {
setConnected(false);
log('Info: WebSocket connection closed.');
};
}
function updateTarget() {
if (window.location.protocol == 'http:') {
document.getElementById('target').value = 'ws://' + window.location.host + document.getElementById('target').value;
} else {
document.getElementById('target').value = 'wss://' + window.location.host + document.getElementById('target').value;
}
}
function disconnect() {
if (ws != null) {
ws.close();
ws = null;
}
setConnected(false);
}
function reverse() {
if (ws != null) {
var message = document.getElementById('message').value;
log('Sent: ' + message);
ws.send(message);
} else {
alert('WebSocket connection not established, please connect.');
}
}
function log(message) {
var console = document.getElementById('console');
var p = document.createElement('p');
p.style.wordWrap = 'break-word';
p.appendChild(document.createTextNode(message));
console.appendChild(p);
while (console.childNodes.length > 25) {
console.removeChild(console.firstChild);
}
console.scrollTop = console.scrollHeight;
}
</script>
</head>
<body onload="updateTarget()">
<noscript><h2 style="color: #ff0000">Seems your browser doesn't support Javascript! Websockets rely on Javascript being enabled. Please enable
Javascript and reload this page!</h2></noscript>
<div>
<div id="connect-container">
<div>
<input id="target" type="text" size="40" style="width: 350px" value="/reverse"/>
</div>
<div>
<button id="connect" onclick="connect();">Connect</button>
<button id="disconnect" disabled="disabled" onclick="disconnect();">Disconnect</button>
</div>
<div>
<textarea id="message" style="width: 350px">Here is a message!</textarea>
</div>
<div>
<button id="reverse" onclick="reverse();" disabled="disabled">Reverse message</button>
</div>
</div>
<div id="console-container">
<div id="console"></div>
</div>
</div>
</body>
</html>

@ -1,249 +0,0 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Apache Tomcat WebSocket Examples: Multiplayer Snake</title>
<style type="text/css">
#playground {
width: 640px;
height: 480px;
background-color: #000;
}
#console-container {
float: left;
margin-left: 15px;
width: 300px;
}
#console {
border: 1px solid #CCCCCC;
border-right-color: #999999;
border-bottom-color: #999999;
height: 480px;
overflow-y: scroll;
padding-left: 5px;
padding-right: 5px;
width: 100%;
}
#console p {
padding: 0;
margin: 0;
}
</style>
<script src="https://cdn.jsdelivr.net/sockjs/0.3.4/sockjs.min.js"></script>
</head>
<body>
<noscript><h2 style="color: #ff0000">Seems your browser doesn't support Javascript! Websockets rely on Javascript being enabled. Please enable
Javascript and reload this page!</h2></noscript>
<div style="float: left">
<canvas id="playground" width="640" height="480"></canvas>
</div>
<div id="console-container">
<div id="console"></div>
</div>
<script type="text/javascript">
var Game = {};
Game.fps = 30;
Game.socket = null;
Game.nextFrame = null;
Game.interval = null;
Game.direction = 'none';
Game.gridSize = 10;
function Snake() {
this.snakeBody = [];
this.color = null;
}
Snake.prototype.draw = function(context) {
for (var id in this.snakeBody) {
context.fillStyle = this.color;
context.fillRect(this.snakeBody[id].x, this.snakeBody[id].y, Game.gridSize, Game.gridSize);
}
};
Game.initialize = function() {
this.entities = [];
canvas = document.getElementById('playground');
if (!canvas.getContext) {
Console.log('Error: 2d canvas not supported by this browser.');
return;
}
this.context = canvas.getContext('2d');
window.addEventListener('keydown', function (e) {
var code = e.keyCode;
if (code > 36 && code < 41) {
switch (code) {
case 37:
if (Game.direction != 'east') Game.setDirection('west');
break;
case 38:
if (Game.direction != 'south') Game.setDirection('north');
break;
case 39:
if (Game.direction != 'west') Game.setDirection('east');
break;
case 40:
if (Game.direction != 'north') Game.setDirection('south');
break;
}
}
}, false);
Game.connect();
};
Game.setDirection = function(direction) {
Game.direction = direction;
Game.socket.send(direction);
Console.log('Sent: Direction ' + direction);
};
Game.startGameLoop = function() {
if (window.webkitRequestAnimationFrame) {
Game.nextFrame = function () {
webkitRequestAnimationFrame(Game.run);
};
} else if (window.mozRequestAnimationFrame) {
Game.nextFrame = function () {
mozRequestAnimationFrame(Game.run);
};
} else {
Game.interval = setInterval(Game.run, 1000 / Game.fps);
}
if (Game.nextFrame != null) {
Game.nextFrame();
}
};
Game.stopGameLoop = function () {
Game.nextFrame = null;
if (Game.interval != null) {
clearInterval(Game.interval);
}
};
Game.draw = function() {
this.context.clearRect(0, 0, 640, 480);
for (var id in this.entities) {
this.entities[id].draw(this.context);
}
};
Game.addSnake = function(id, color) {
Game.entities[id] = new Snake();
Game.entities[id].color = color;
};
Game.updateSnake = function(id, snakeBody) {
if (typeof Game.entities[id] != "undefined") {
Game.entities[id].snakeBody = snakeBody;
}
};
Game.removeSnake = function(id) {
Game.entities[id] = null;
// Force GC.
delete Game.entities[id];
};
Game.run = (function() {
var skipTicks = 1000 / Game.fps, nextGameTick = (new Date).getTime();
return function() {
while ((new Date).getTime() > nextGameTick) {
nextGameTick += skipTicks;
}
Game.draw();
if (Game.nextFrame != null) {
Game.nextFrame();
}
};
})();
Game.connect = (function() {
Game.socket = new SockJS("/snake");
Game.socket.onopen = function () {
// Socket open.. start the game loop.
Console.log('Info: WebSocket connection opened.');
Console.log('Info: Press an arrow key to begin.');
Game.startGameLoop();
setInterval(function() {
// Prevent server read timeout.
Game.socket.send('ping');
}, 5000);
};
Game.socket.onclose = function () {
Console.log('Info: WebSocket closed.');
Game.stopGameLoop();
};
Game.socket.onmessage = function (message) {
// _Potential_ security hole, consider using json lib to parse data in production.
var packet = eval('(' + message.data + ')');
switch (packet.type) {
case 'update':
for (var i = 0; i < packet.data.length; i++) {
Game.updateSnake(packet.data[i].id, packet.data[i].body);
}
break;
case 'join':
for (var j = 0; j < packet.data.length; j++) {
Game.addSnake(packet.data[j].id, packet.data[j].color);
}
break;
case 'leave':
Game.removeSnake(packet.id);
break;
case 'dead':
Console.log('Info: Your snake is dead, bad luck!');
Game.direction = 'none';
break;
case 'kill':
Console.log('Info: Head shot!');
break;
}
};
});
var Console = {};
Console.log = (function(message) {
var console = document.getElementById('console');
var p = document.createElement('p');
p.style.wordWrap = 'break-word';
p.innerHTML = message;
console.appendChild(p);
while (console.childNodes.length > 25) {
console.removeChild(console.firstChild);
}
console.scrollTop = console.scrollHeight;
});
Game.initialize();
</script>
</body>
</html>
Loading…
Cancel
Save