Remove Atmosphere sample to prepare for Servlet 5 upgrade

Closes gh-28786
pull/28862/head
Andy Wilkinson 3 years ago
parent c25890354b
commit b6ba46942b

@ -1,17 +0,0 @@
plugins {
id "java"
id "org.springframework.boot.conventions"
}
description = "Spring Boot Atmosphere smoke test"
dependencies {
implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-web"))
implementation("org.atmosphere:atmosphere-runtime:2.6.1")
runtimeOnly("org.webjars:atmosphere-javascript:3.0.4")
testImplementation(enforcedPlatform(project(":spring-boot-project:spring-boot-dependencies")))
testImplementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-test"))
testImplementation("org.springframework:spring-websocket")
}

@ -1,81 +0,0 @@
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed 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
*
* https://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.
*/
package smoketest.atmosphere;
import java.io.IOException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.atmosphere.config.managed.Decoder;
import org.atmosphere.config.managed.Encoder;
import org.atmosphere.config.service.Disconnect;
import org.atmosphere.config.service.ManagedService;
import org.atmosphere.config.service.Ready;
import org.atmosphere.cpr.AtmosphereResource;
import org.atmosphere.cpr.AtmosphereResourceEvent;
@ManagedService(path = "/chat")
public class ChatService {
private final Log logger = LogFactory.getLog(ChatService.class);
@Ready
public void onReady(AtmosphereResource resource) {
this.logger.info("Connected " + resource.uuid());
}
@Disconnect
public void onDisconnect(AtmosphereResourceEvent event) {
this.logger.info("Client " + event.getResource().uuid() + " disconnected ["
+ (event.isCancelled() ? "cancelled" : "closed") + "]");
}
@org.atmosphere.config.service.Message(encoders = JacksonEncoderDecoder.class,
decoders = JacksonEncoderDecoder.class)
public Message onMessage(Message message) throws IOException {
this.logger.info("Author " + message.getAuthor() + " sent message " + message.getMessage());
return message;
}
public static class JacksonEncoderDecoder implements Encoder<Message, String>, Decoder<String, Message> {
private final ObjectMapper mapper = new ObjectMapper();
@Override
public String encode(Message m) {
try {
return this.mapper.writeValueAsString(m);
}
catch (IOException ex) {
throw new IllegalStateException(ex);
}
}
@Override
public Message decode(String s) {
try {
return this.mapper.readValue(s, Message.class);
}
catch (IOException ex) {
throw new IllegalStateException(ex);
}
}
}
}

@ -1,53 +0,0 @@
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed 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
*
* https://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.
*/
package smoketest.atmosphere;
import java.util.Date;
public class Message {
private String message;
private String author;
private long time = new Date().getTime();
public String getMessage() {
return this.message;
}
public void setMessage(String message) {
this.message = message;
}
public String getAuthor() {
return this.author;
}
public void setAuthor(String author) {
this.author = author;
}
public long getTime() {
return this.time;
}
public void setTime(long time) {
this.time = time;
}
}

@ -1,88 +0,0 @@
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed 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
*
* https://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.
*/
package smoketest.atmosphere;
import java.util.Collections;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import org.atmosphere.cpr.AtmosphereServlet;
import org.atmosphere.cpr.ContainerInitializer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@SpringBootConfiguration
@EnableAutoConfiguration
public class SampleAtmosphereApplication {
@Bean
public EmbeddedAtmosphereInitializer atmosphereInitializer() {
return new EmbeddedAtmosphereInitializer();
}
@Bean
public ServletRegistrationBean<AtmosphereServlet> atmosphereServlet() {
// Dispatcher servlet is mapped to '/home' to allow the AtmosphereServlet
// to be mapped to '/chat'
AtmosphereServlet atmosphereServlet = new AtmosphereServlet();
atmosphereServlet.framework().setHandlersPath("/");
ServletRegistrationBean<AtmosphereServlet> registration = new ServletRegistrationBean<>(atmosphereServlet,
"/chat/*");
registration.addInitParameter("org.atmosphere.cpr.packages", "smoketest");
registration.addInitParameter(
"org.atmosphere.interceptor.HeartbeatInterceptor.clientHeartbeatFrequencyInSeconds", "10");
registration.setLoadOnStartup(0);
// Need to occur before the EmbeddedAtmosphereInitializer
registration.setOrder(Ordered.HIGHEST_PRECEDENCE);
return registration;
}
public static void main(String[] args) throws Exception {
SpringApplication.run(SampleAtmosphereApplication.class, args);
}
@Configuration(proxyBeanMethods = false)
static class MvcConfiguration implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("forward:/home/home.html");
}
}
private static class EmbeddedAtmosphereInitializer extends ContainerInitializer
implements ServletContextInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
onStartup(Collections.emptySet(), servletContext);
}
}
}

@ -1,72 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Atmosphere Chat</title>
<!-- Atmosphere -->
<script type="text/javascript" src="webjars/atmosphere-javascript/2.2.3/atmosphere.js"></script>
<!-- Application -->
<script type="text/javascript" src="javascript/jquery-1.9.0.js"></script>
<script type="text/javascript" src="javascript/application.js"></script>
<style>
* {
font-family: tahoma;
font-size: 12px;
padding: 0px;
margin: 0px;
}
p {
line-height: 18px;
}
div {
width: 500px;
margin-left: auto;
margin-right: auto;
}
#content {
padding: 5px;
background: #ddd;
border-radius: 5px;
border: 1px solid #CCC;
margin-top: 10px;
}
#header {
padding: 5px;
background: #f5deb3;
border-radius: 5px;
border: 1px solid #CCC;
margin-top: 10px;
}
#input {
border-radius: 2px;
border: 1px solid #ccc;
margin-top: 10px;
padding: 5px;
width: 400px;
}
#status {
width: 88px;
display: block;
float: left;
margin-top: 15px;
}
</style>
</head>
<body>
<div id="header">
<h3>Atmosphere Chat. Default transport is WebSocket, fallback is
long-polling</h3>
</div>
<div id="content"></div>
<div>
<span id="status">Connecting...</span> <input type="text" id="input"
disabled="disabled" />
</div>
</body>
</html>

@ -1,167 +0,0 @@
$(function() {
"use strict";
var header = $('#header');
var content = $('#content');
var input = $('#input');
var status = $('#status');
var myName = false;
var author = null;
var logged = false;
var socket = atmosphere;
var subSocket;
var transport = 'websocket';
// We are now ready to cut the request
var request = {
url : '/chat',
contentType : "application/json",
logLevel : 'debug',
transport : transport,
trackMessageLength : true,
reconnectInterval : 5000
};
request.onOpen = function(response) {
content.html($('<p>', {
text : 'Atmosphere connected using ' + response.transport
}));
input.removeAttr('disabled').focus();
status.text('Choose name:');
transport = response.transport;
// Carry the UUID. This is required if you want to call
// subscribe(request) again.
request.uuid = response.request.uuid;
};
request.onClientTimeout = function(r) {
content
.html($(
'<p>',
{
text : 'Client closed the connection after a timeout. Reconnecting in '
+ request.reconnectInterval
}));
subSocket
.push(JSON.stringify({
author : author,
message : 'is inactive and closed the connection. Will reconnect in '
+ request.reconnectInterval
}));
input.attr('disabled', 'disabled');
setTimeout(function() {
subSocket = socket.subscribe(request);
}, request.reconnectInterval);
};
request.onReopen = function(response) {
input.removeAttr('disabled').focus();
content.html($('<p>', {
text : 'Atmosphere re-connected using ' + response.transport
}));
};
// For demonstration of how you can customize the fallbackTransport using
// the onTransportFailure function
request.onTransportFailure = function(errorMsg, request) {
atmosphere.util.info(errorMsg);
request.fallbackTransport = "long-polling";
header
.html($(
'<h3>',
{
text : 'Atmosphere Chat. Default transport is WebSocket, fallback is '
+ request.fallbackTransport
}));
};
request.onMessage = function(response) {
var message = response.responseBody;
try {
var json = JSON.parse(message);
} catch (e) {
console.log('This doesn\'t look like a valid JSON: ', message);
return;
}
input.removeAttr('disabled').focus();
if (!logged && myName) {
logged = true;
status.text(myName + ': ').css('color', 'blue');
} else {
var me = json.author == author;
var date = typeof (json.time) == 'string' ? parseInt(json.time)
: json.time;
addMessage(json.author, json.message, me ? 'blue' : 'black',
new Date(date));
}
};
request.onClose = function(response) {
content.html($('<p>', {
text : 'Server closed the connection after a timeout'
}));
if (subSocket) {
subSocket.push(JSON.stringify({
author : author,
message : 'disconnecting'
}));
}
input.attr('disabled', 'disabled');
};
request.onError = function(response) {
content.html($('<p>', {
text : 'Sorry, but there\'s some problem with your '
+ 'socket or the server is down'
}));
logged = false;
};
request.onReconnect = function(request, response) {
content.html($('<p>', {
text : 'Connection lost, trying to reconnect. Trying to reconnect '
+ request.reconnectInterval
}));
input.attr('disabled', 'disabled');
};
subSocket = socket.subscribe(request);
input.keydown(function(e) {
if (e.keyCode === 13) {
var msg = $(this).val();
// First message is always the author's name
if (author == null) {
author = msg;
}
subSocket.push(JSON.stringify({
author : author,
message : msg
}));
$(this).val('');
input.attr('disabled', 'disabled');
if (myName === false) {
myName = msg;
}
}
});
function addMessage(author, message, color, datetime) {
content.append('<p><span style="color:'
+ color
+ '">'
+ author
+ '</span> @ '
+ +(datetime.getHours() < 10 ? '0' + datetime.getHours()
: datetime.getHours())
+ ':'
+ (datetime.getMinutes() < 10 ? '0' + datetime.getMinutes()
: datetime.getMinutes()) + ': ' + message + '</p>');
}
});

@ -1,120 +0,0 @@
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed 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
*
* https://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.
*/
package smoketest.atmosphere;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.client.WebSocketConnectionManager;
import org.springframework.web.socket.client.standard.StandardWebSocketClient;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = SampleAtmosphereApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT)
class SampleAtmosphereApplicationTests {
private static Log logger = LogFactory.getLog(SampleAtmosphereApplicationTests.class);
@LocalServerPort
private int port = 1234;
@Test
void chatEndpoint() {
ConfigurableApplicationContext context = new SpringApplicationBuilder(ClientConfiguration.class,
PropertyPlaceholderAutoConfiguration.class)
.properties("websocket.uri:ws://localhost:" + this.port + "/chat/websocket")
.run("--spring.main.web-application-type=none");
long count = context.getBean(ClientConfiguration.class).latch.getCount();
AtomicReference<String> messagePayloadReference = context.getBean(ClientConfiguration.class).messagePayload;
context.close();
assertThat(count).isEqualTo(0L);
assertThat(messagePayloadReference.get()).contains("{\"message\":\"test\",\"author\":\"test\",\"time\":");
}
@Configuration(proxyBeanMethods = false)
static class ClientConfiguration implements CommandLineRunner {
@Value("${websocket.uri}")
private String webSocketUri;
private final CountDownLatch latch = new CountDownLatch(1);
private final AtomicReference<String> messagePayload = new AtomicReference<>();
@Override
public void run(String... args) throws Exception {
logger.info("Waiting for response: latch=" + this.latch.getCount());
if (this.latch.await(10, TimeUnit.SECONDS)) {
logger.info("Got response: " + this.messagePayload.get());
}
else {
logger.info("Response not received: latch=" + this.latch.getCount());
}
}
@Bean
WebSocketConnectionManager wsConnectionManager() {
WebSocketConnectionManager manager = new WebSocketConnectionManager(client(), handler(), this.webSocketUri);
manager.setAutoStartup(true);
return manager;
}
@Bean
StandardWebSocketClient client() {
return new StandardWebSocketClient();
}
@Bean
TextWebSocketHandler handler() {
return new TextWebSocketHandler() {
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
session.sendMessage(new TextMessage("{\"author\":\"test\",\"message\":\"test\"}"));
}
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
logger.info("Received: " + message + " (" + ClientConfiguration.this.latch.getCount() + ")");
session.close();
ClientConfiguration.this.messagePayload.set(message.getPayload());
ClientConfiguration.this.latch.countDown();
}
};
}
}
}
Loading…
Cancel
Save