Clean up warnings and polishing

This commit is contained in:
Sam Brannen 2022-07-31 14:14:56 +03:00
parent 9d1e9703ae
commit e4395f2f8b
55 changed files with 412 additions and 396 deletions

View File

@ -35,14 +35,12 @@ import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
import org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils; import org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils;
import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.EmbeddedValueResolver; import org.springframework.beans.factory.config.EmbeddedValueResolver;
import org.springframework.core.task.AsyncListenableTaskExecutor;
import org.springframework.core.task.AsyncTaskExecutor; import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.core.task.TaskExecutor; import org.springframework.core.task.TaskExecutor;
import org.springframework.core.task.support.TaskExecutorAdapter; import org.springframework.core.task.support.TaskExecutorAdapter;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.function.SingletonSupplier; import org.springframework.util.function.SingletonSupplier;
/** /**
@ -274,14 +272,14 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
* @param returnType the declared return type (potentially a {@link Future} variant) * @param returnType the declared return type (potentially a {@link Future} variant)
* @return the execution result (potentially a corresponding {@link Future} handle) * @return the execution result (potentially a corresponding {@link Future} handle)
*/ */
@SuppressWarnings("deprecation")
@Nullable @Nullable
@SuppressWarnings("deprecation")
protected Object doSubmit(Callable<Object> task, AsyncTaskExecutor executor, Class<?> returnType) { protected Object doSubmit(Callable<Object> task, AsyncTaskExecutor executor, Class<?> returnType) {
if (CompletableFuture.class.isAssignableFrom(returnType)) { if (CompletableFuture.class.isAssignableFrom(returnType)) {
return executor.submitCompletable(task); return executor.submitCompletable(task);
} }
else if (ListenableFuture.class.isAssignableFrom(returnType)) { else if (org.springframework.util.concurrent.ListenableFuture.class.isAssignableFrom(returnType)) {
return ((AsyncListenableTaskExecutor) executor).submitListenable(task); return ((org.springframework.core.task.AsyncListenableTaskExecutor) executor).submitListenable(task);
} }
else if (Future.class.isAssignableFrom(returnType)) { else if (Future.class.isAssignableFrom(returnType)) {
return executor.submit(task); return executor.submit(task);

View File

@ -50,7 +50,6 @@ import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.util.concurrent.ListenableFuture;
/** /**
* {@link GenericApplicationListener} adapter that delegates the processing of * {@link GenericApplicationListener} adapter that delegates the processing of
@ -253,8 +252,8 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe
} }
Class<?> declaredEventClass = declaredEventType.toClass(); Class<?> declaredEventClass = declaredEventType.toClass();
if (!ApplicationEvent.class.isAssignableFrom(declaredEventClass) && if (!ApplicationEvent.class.isAssignableFrom(declaredEventClass) &&
event instanceof PayloadApplicationEvent) { event instanceof PayloadApplicationEvent<?> payloadEvent) {
Object payload = ((PayloadApplicationEvent<?>) event).getPayload(); Object payload = payloadEvent.getPayload();
if (declaredEventClass.isInstance(payload)) { if (declaredEventClass.isInstance(payload)) {
return new Object[] {payload}; return new Object[] {payload};
} }
@ -262,15 +261,15 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe
return new Object[] {event}; return new Object[] {event};
} }
@SuppressWarnings("deprecation") @SuppressWarnings({ "deprecation", "unchecked" })
protected void handleResult(Object result) { protected void handleResult(Object result) {
if (reactiveStreamsPresent && new ReactiveResultHandler().subscribeToPublisher(result)) { if (reactiveStreamsPresent && new ReactiveResultHandler().subscribeToPublisher(result)) {
if (logger.isTraceEnabled()) { if (logger.isTraceEnabled()) {
logger.trace("Adapted to reactive result: " + result); logger.trace("Adapted to reactive result: " + result);
} }
} }
else if (result instanceof CompletionStage) { else if (result instanceof CompletionStage<?> completionStage) {
((CompletionStage<?>) result).whenComplete((event, ex) -> { completionStage.whenComplete((event, ex) -> {
if (ex != null) { if (ex != null) {
handleAsyncError(ex); handleAsyncError(ex);
} }
@ -279,8 +278,8 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe
} }
}); });
} }
else if (result instanceof ListenableFuture) { else if (result instanceof org.springframework.util.concurrent.ListenableFuture<?> listenableFuture) {
((ListenableFuture<?>) result).addCallback(this::publishEvents, this::handleAsyncError); listenableFuture.addCallback(this::publishEvents, this::handleAsyncError);
} }
else { else {
publishEvents(result); publishEvents(result);
@ -353,8 +352,8 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe
catch (InvocationTargetException ex) { catch (InvocationTargetException ex) {
// Throw underlying exception // Throw underlying exception
Throwable targetException = ex.getTargetException(); Throwable targetException = ex.getTargetException();
if (targetException instanceof RuntimeException) { if (targetException instanceof RuntimeException runtimeException) {
throw (RuntimeException) targetException; throw runtimeException;
} }
else { else {
String msg = getInvocationErrorMessage(bean, "Failed to invoke event listener method", args); String msg = getInvocationErrorMessage(bean, "Failed to invoke event listener method", args);
@ -441,8 +440,7 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe
@Nullable @Nullable
private ResolvableType getResolvableType(ApplicationEvent event) { private ResolvableType getResolvableType(ApplicationEvent event) {
ResolvableType payloadType = null; ResolvableType payloadType = null;
if (event instanceof PayloadApplicationEvent) { if (event instanceof PayloadApplicationEvent<?> payloadEvent) {
PayloadApplicationEvent<?> payloadEvent = (PayloadApplicationEvent<?>) event;
ResolvableType eventType = payloadEvent.getResolvableType(); ResolvableType eventType = payloadEvent.getResolvableType();
if (eventType != null) { if (eventType != null) {
payloadType = eventType.as(PayloadApplicationEvent.class).getGeneric(); payloadType = eventType.as(PayloadApplicationEvent.class).getGeneric();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed 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.
@ -23,7 +23,6 @@ import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.AsyncResult;
/** /**
* @author Mark Fisher * @author Mark Fisher
@ -52,8 +51,9 @@ public class AutowiredQualifierFooService implements FooService {
} }
@Override @Override
@SuppressWarnings("deprecation")
public Future<String> asyncFoo(int id) { public Future<String> asyncFoo(int id) {
return new AsyncResult<>(this.fooDao.findFoo(id)); return new org.springframework.scheduling.annotation.AsyncResult<>(this.fooDao.findFoo(id));
} }
@Override @Override

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2021 the original author or authors. * Copyright 2002-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed 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.
@ -35,7 +35,6 @@ import org.springframework.context.annotation.Lazy;
import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.core.io.ResourceLoader; import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.ResourcePatternResolver; import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.Assert; import org.springframework.util.Assert;
@ -92,10 +91,11 @@ public abstract class FooServiceImpl implements FooService {
} }
@Override @Override
@SuppressWarnings("deprecation")
public Future<String> asyncFoo(int id) { public Future<String> asyncFoo(int id) {
System.out.println(Thread.currentThread().getName()); System.out.println(Thread.currentThread().getName());
Assert.state(ServiceInvocationCounter.getThreadLocalCount() != null, "Thread-local counter not exposed"); Assert.state(ServiceInvocationCounter.getThreadLocalCount() != null, "Thread-local counter not exposed");
return new AsyncResult<>(fooDao().findFoo(id)); return new org.springframework.scheduling.annotation.AsyncResult<>(fooDao().findFoo(id));
} }
@Override @Override

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed 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.
@ -19,7 +19,6 @@ package example.scannable;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
import org.springframework.scheduling.annotation.AsyncResult;
/** /**
* @author Mark Fisher * @author Mark Fisher
@ -34,8 +33,9 @@ public class ScopedProxyTestBean implements FooService {
} }
@Override @Override
@SuppressWarnings("deprecation")
public Future<String> asyncFoo(int id) { public Future<String> asyncFoo(int id) {
return new AsyncResult<>("bar"); return new org.springframework.scheduling.annotation.AsyncResult<>("bar");
} }
@Override @Override

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2021 the original author or authors. * Copyright 2002-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed 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.
@ -66,7 +66,6 @@ import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.concurrent.SettableListenableFuture;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor; import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
@ -267,9 +266,11 @@ class AnnotationDrivenEventListenerTests {
} }
@Test @Test
@SuppressWarnings("deprecation")
void listenableFutureReply() { void listenableFutureReply() {
load(TestEventListener.class, ReplyEventListener.class); load(TestEventListener.class, ReplyEventListener.class);
SettableListenableFuture<String> future = new SettableListenableFuture<>(); org.springframework.util.concurrent.SettableListenableFuture<String> future =
new org.springframework.util.concurrent.SettableListenableFuture<>();
future.set("dummy"); future.set("dummy");
AnotherTestEvent event = new AnotherTestEvent(this, future); AnotherTestEvent event = new AnotherTestEvent(this, future);
ReplyEventListener replyEventListener = this.context.getBean(ReplyEventListener.class); ReplyEventListener replyEventListener = this.context.getBean(ReplyEventListener.class);

View File

@ -433,6 +433,7 @@ class GenericApplicationContextTests {
assertThat(context.getBeanFactory().getMergedBeanDefinition("test") assertThat(context.getBeanFactory().getMergedBeanDefinition("test")
.hasAttribute("mbdppCalled")).isTrue(); .hasAttribute("mbdppCalled")).isTrue();
assertThat(context.getBean("test")).isEqualTo("42"); assertThat(context.getBean("test")).isEqualTo("42");
context.close();
} }
@Test @Test

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2021 the original author or authors. * Copyright 2002-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed 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.
@ -40,7 +40,6 @@ import org.springframework.context.support.StaticApplicationContext;
import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils;
import org.springframework.util.concurrent.ListenableFuture;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
@ -276,7 +275,8 @@ public class AsyncAnnotationBeanPostProcessorTests {
Future<Object> failWithFuture(); Future<Object> failWithFuture();
ListenableFuture<Object> failWithListenableFuture(); @SuppressWarnings("deprecation")
org.springframework.util.concurrent.ListenableFuture<Object> failWithListenableFuture();
void failWithVoid(); void failWithVoid();
@ -310,7 +310,8 @@ public class AsyncAnnotationBeanPostProcessorTests {
@Async @Async
@Override @Override
public ListenableFuture<Object> failWithListenableFuture() { @SuppressWarnings("deprecation")
public org.springframework.util.concurrent.ListenableFuture<Object> failWithListenableFuture() {
throw new UnsupportedOperationException("failWithListenableFuture"); throw new UnsupportedOperationException("failWithListenableFuture");
} }

View File

@ -50,7 +50,7 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Chris Beams * @author Chris Beams
*/ */
@SuppressWarnings("resource") @SuppressWarnings({ "resource", "deprecation" })
public class AsyncExecutionTests { public class AsyncExecutionTests {
private static String originalThreadName; private static String originalThreadName;

View File

@ -23,9 +23,6 @@ import java.util.concurrent.ExecutionException;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureCallback;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
@ -35,11 +32,12 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
public class AsyncResultTests { public class AsyncResultTests {
@Test @Test
@SuppressWarnings("deprecation")
public void asyncResultWithCallbackAndValue() throws Exception { public void asyncResultWithCallbackAndValue() throws Exception {
String value = "val"; String value = "val";
final Set<String> values = new HashSet<>(1); final Set<String> values = new HashSet<>(1);
ListenableFuture<String> future = AsyncResult.forValue(value); org.springframework.util.concurrent.ListenableFuture<String> future = AsyncResult.forValue(value);
future.addCallback(new ListenableFutureCallback<String>() { future.addCallback(new org.springframework.util.concurrent.ListenableFutureCallback<String>() {
@Override @Override
public void onSuccess(String result) { public void onSuccess(String result) {
values.add(result); values.add(result);
@ -56,11 +54,12 @@ public class AsyncResultTests {
} }
@Test @Test
@SuppressWarnings("deprecation")
public void asyncResultWithCallbackAndException() throws Exception { public void asyncResultWithCallbackAndException() throws Exception {
IOException ex = new IOException(); IOException ex = new IOException();
final Set<Throwable> values = new HashSet<>(1); final Set<Throwable> values = new HashSet<>(1);
ListenableFuture<String> future = AsyncResult.forExecutionException(ex); org.springframework.util.concurrent.ListenableFuture<String> future = AsyncResult.forExecutionException(ex);
future.addCallback(new ListenableFutureCallback<String>() { future.addCallback(new org.springframework.util.concurrent.ListenableFutureCallback<String>() {
@Override @Override
public void onSuccess(String result) { public void onSuccess(String result) {
throw new AssertionError("Success callback not expected: " + result); throw new AssertionError("Success callback not expected: " + result);
@ -71,19 +70,20 @@ public class AsyncResultTests {
} }
}); });
assertThat(values.iterator().next()).isSameAs(ex); assertThat(values.iterator().next()).isSameAs(ex);
assertThatExceptionOfType(ExecutionException.class).isThrownBy( assertThatExceptionOfType(ExecutionException.class)
future::get) .isThrownBy(future::get)
.withCause(ex); .withCause(ex);
assertThatExceptionOfType(ExecutionException.class).isThrownBy( assertThatExceptionOfType(ExecutionException.class)
future.completable()::get) .isThrownBy(future.completable()::get)
.withCause(ex); .withCause(ex);
} }
@Test @Test
@SuppressWarnings("deprecation")
public void asyncResultWithSeparateCallbacksAndValue() throws Exception { public void asyncResultWithSeparateCallbacksAndValue() throws Exception {
String value = "val"; String value = "val";
final Set<String> values = new HashSet<>(1); final Set<String> values = new HashSet<>(1);
ListenableFuture<String> future = AsyncResult.forValue(value); org.springframework.util.concurrent.ListenableFuture<String> future = AsyncResult.forValue(value);
future.addCallback(values::add, ex -> new AssertionError("Failure callback not expected: " + ex)); future.addCallback(values::add, ex -> new AssertionError("Failure callback not expected: " + ex));
assertThat(values.iterator().next()).isSameAs(value); assertThat(values.iterator().next()).isSameAs(value);
assertThat(future.get()).isSameAs(value); assertThat(future.get()).isSameAs(value);
@ -92,17 +92,18 @@ public class AsyncResultTests {
} }
@Test @Test
@SuppressWarnings("deprecation")
public void asyncResultWithSeparateCallbacksAndException() throws Exception { public void asyncResultWithSeparateCallbacksAndException() throws Exception {
IOException ex = new IOException(); IOException ex = new IOException();
final Set<Throwable> values = new HashSet<>(1); final Set<Throwable> values = new HashSet<>(1);
ListenableFuture<String> future = AsyncResult.forExecutionException(ex); org.springframework.util.concurrent.ListenableFuture<String> future = AsyncResult.forExecutionException(ex);
future.addCallback(result -> new AssertionError("Success callback not expected: " + result), values::add); future.addCallback(result -> new AssertionError("Success callback not expected: " + result), values::add);
assertThat(values.iterator().next()).isSameAs(ex); assertThat(values.iterator().next()).isSameAs(ex);
assertThatExceptionOfType(ExecutionException.class).isThrownBy( assertThatExceptionOfType(ExecutionException.class)
future::get) .isThrownBy(future::get)
.withCause(ex); .withCause(ex);
assertThatExceptionOfType(ExecutionException.class).isThrownBy( assertThatExceptionOfType(ExecutionException.class)
future.completable()::get) .isThrownBy(future.completable()::get)
.withCause(ex); .withCause(ex);
} }

View File

@ -346,6 +346,7 @@ public class EnableAsyncTests {
} }
@SuppressWarnings("deprecation")
static class AsyncBeanWithExecutorQualifiedByName { static class AsyncBeanWithExecutorQualifiedByName {
@Async @Async
@ -369,6 +370,7 @@ public class EnableAsyncTests {
} }
} }
@SuppressWarnings("deprecation")
static class AsyncBeanWithExecutorQualifiedByExpressionOrPlaceholder { static class AsyncBeanWithExecutorQualifiedByExpressionOrPlaceholder {
@Async("#{environment['myExecutor']}") @Async("#{environment['myExecutor']}")

View File

@ -35,9 +35,7 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInfo; import org.junit.jupiter.api.TestInfo;
import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.DisposableBean;
import org.springframework.core.task.AsyncListenableTaskExecutor;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.util.concurrent.ListenableFuture;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
@ -49,7 +47,8 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
*/ */
abstract class AbstractSchedulingTaskExecutorTests { abstract class AbstractSchedulingTaskExecutorTests {
private AsyncListenableTaskExecutor executor; @SuppressWarnings("deprecation")
private org.springframework.core.task.AsyncListenableTaskExecutor executor;
protected String testName; protected String testName;
@ -65,7 +64,8 @@ abstract class AbstractSchedulingTaskExecutorTests {
this.executor = buildExecutor(); this.executor = buildExecutor();
} }
protected abstract AsyncListenableTaskExecutor buildExecutor(); @SuppressWarnings("deprecation")
protected abstract org.springframework.core.task.AsyncListenableTaskExecutor buildExecutor();
@AfterEach @AfterEach
void shutdownExecutor() throws Exception { void shutdownExecutor() throws Exception {
@ -125,10 +125,11 @@ abstract class AbstractSchedulingTaskExecutorTests {
} }
@Test @Test
@SuppressWarnings("deprecation")
void submitListenableRunnable() throws Exception { void submitListenableRunnable() throws Exception {
TestTask task = new TestTask(this.testName, 1); TestTask task = new TestTask(this.testName, 1);
// Act // Act
ListenableFuture<?> future = executor.submitListenable(task); org.springframework.util.concurrent.ListenableFuture<?> future = executor.submitListenable(task);
future.addCallback(result -> outcome = result, ex -> outcome = ex); future.addCallback(result -> outcome = result, ex -> outcome = ex);
// Assert // Assert
Awaitility.await() Awaitility.await()
@ -155,9 +156,10 @@ abstract class AbstractSchedulingTaskExecutorTests {
} }
@Test @Test
@SuppressWarnings("deprecation")
void submitFailingListenableRunnable() throws Exception { void submitFailingListenableRunnable() throws Exception {
TestTask task = new TestTask(this.testName, 0); TestTask task = new TestTask(this.testName, 0);
ListenableFuture<?> future = executor.submitListenable(task); org.springframework.util.concurrent.ListenableFuture<?> future = executor.submitListenable(task);
future.addCallback(result -> outcome = result, ex -> outcome = ex); future.addCallback(result -> outcome = result, ex -> outcome = ex);
Awaitility.await() Awaitility.await()
@ -183,9 +185,10 @@ abstract class AbstractSchedulingTaskExecutorTests {
} }
@Test @Test
@SuppressWarnings("deprecation")
void submitListenableRunnableWithGetAfterShutdown() throws Exception { void submitListenableRunnableWithGetAfterShutdown() throws Exception {
ListenableFuture<?> future1 = executor.submitListenable(new TestTask(this.testName, -1)); org.springframework.util.concurrent.ListenableFuture<?> future1 = executor.submitListenable(new TestTask(this.testName, -1));
ListenableFuture<?> future2 = executor.submitListenable(new TestTask(this.testName, -1)); org.springframework.util.concurrent.ListenableFuture<?> future2 = executor.submitListenable(new TestTask(this.testName, -1));
shutdownExecutor(); shutdownExecutor();
try { try {
@ -218,8 +221,8 @@ abstract class AbstractSchedulingTaskExecutorTests {
.atMost(4, TimeUnit.SECONDS) .atMost(4, TimeUnit.SECONDS)
.pollInterval(10, TimeUnit.MILLISECONDS) .pollInterval(10, TimeUnit.MILLISECONDS)
.untilAsserted(() -> .untilAsserted(() ->
assertThatExceptionOfType(TimeoutException.class).isThrownBy(() -> assertThatExceptionOfType(TimeoutException.class)
future2.get(1000, TimeUnit.MILLISECONDS))); .isThrownBy(() -> future2.get(1000, TimeUnit.MILLISECONDS)));
} }
@Test @Test
@ -234,8 +237,8 @@ abstract class AbstractSchedulingTaskExecutorTests {
void submitFailingCallable() throws Exception { void submitFailingCallable() throws Exception {
TestCallable task = new TestCallable(this.testName, 0); TestCallable task = new TestCallable(this.testName, 0);
Future<String> future = executor.submit(task); Future<String> future = executor.submit(task);
assertThatExceptionOfType(ExecutionException.class).isThrownBy(() -> assertThatExceptionOfType(ExecutionException.class)
future.get(1000, TimeUnit.MILLISECONDS)); .isThrownBy(() -> future.get(1000, TimeUnit.MILLISECONDS));
assertThat(future.isDone()).isTrue(); assertThat(future.isDone()).isTrue();
} }
@ -255,15 +258,16 @@ abstract class AbstractSchedulingTaskExecutorTests {
.atMost(4, TimeUnit.SECONDS) .atMost(4, TimeUnit.SECONDS)
.pollInterval(10, TimeUnit.MILLISECONDS) .pollInterval(10, TimeUnit.MILLISECONDS)
.untilAsserted(() -> .untilAsserted(() ->
assertThatExceptionOfType(CancellationException.class).isThrownBy(() -> assertThatExceptionOfType(CancellationException.class)
future2.get(1000, TimeUnit.MILLISECONDS))); .isThrownBy(() -> future2.get(1000, TimeUnit.MILLISECONDS)));
} }
@Test @Test
@SuppressWarnings("deprecation")
void submitListenableCallable() throws Exception { void submitListenableCallable() throws Exception {
TestCallable task = new TestCallable(this.testName, 1); TestCallable task = new TestCallable(this.testName, 1);
// Act // Act
ListenableFuture<String> future = executor.submitListenable(task); org.springframework.util.concurrent.ListenableFuture<String> future = executor.submitListenable(task);
future.addCallback(result -> outcome = result, ex -> outcome = ex); future.addCallback(result -> outcome = result, ex -> outcome = ex);
// Assert // Assert
Awaitility.await() Awaitility.await()
@ -274,10 +278,11 @@ abstract class AbstractSchedulingTaskExecutorTests {
} }
@Test @Test
@SuppressWarnings("deprecation")
void submitFailingListenableCallable() throws Exception { void submitFailingListenableCallable() throws Exception {
TestCallable task = new TestCallable(this.testName, 0); TestCallable task = new TestCallable(this.testName, 0);
// Act // Act
ListenableFuture<String> future = executor.submitListenable(task); org.springframework.util.concurrent.ListenableFuture<String> future = executor.submitListenable(task);
future.addCallback(result -> outcome = result, ex -> outcome = ex); future.addCallback(result -> outcome = result, ex -> outcome = ex);
// Assert // Assert
Awaitility.await() Awaitility.await()
@ -289,9 +294,10 @@ abstract class AbstractSchedulingTaskExecutorTests {
} }
@Test @Test
@SuppressWarnings("deprecation")
void submitListenableCallableWithGetAfterShutdown() throws Exception { void submitListenableCallableWithGetAfterShutdown() throws Exception {
ListenableFuture<?> future1 = executor.submitListenable(new TestCallable(this.testName, -1)); org.springframework.util.concurrent.ListenableFuture<?> future1 = executor.submitListenable(new TestCallable(this.testName, -1));
ListenableFuture<?> future2 = executor.submitListenable(new TestCallable(this.testName, -1)); org.springframework.util.concurrent.ListenableFuture<?> future2 = executor.submitListenable(new TestCallable(this.testName, -1));
shutdownExecutor(); shutdownExecutor();
assertThatExceptionOfType(CancellationException.class).isThrownBy(() -> { assertThatExceptionOfType(CancellationException.class).isThrownBy(() -> {
future1.get(1000, TimeUnit.MILLISECONDS); future1.get(1000, TimeUnit.MILLISECONDS);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2020 the original author or authors. * Copyright 2002-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed 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.
@ -24,7 +24,6 @@ import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.core.task.AsyncListenableTaskExecutor;
import org.springframework.core.task.NoOpRunnable; import org.springframework.core.task.NoOpRunnable;
import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatCode;
@ -40,7 +39,8 @@ class ConcurrentTaskExecutorTests extends AbstractSchedulingTaskExecutorTests {
@Override @Override
protected AsyncListenableTaskExecutor buildExecutor() { @SuppressWarnings("deprecation")
protected org.springframework.core.task.AsyncListenableTaskExecutor buildExecutor() {
concurrentExecutor.setThreadFactory(new CustomizableThreadFactory(this.threadNamePrefix)); concurrentExecutor.setThreadFactory(new CustomizableThreadFactory(this.threadNamePrefix));
return new ConcurrentTaskExecutor(concurrentExecutor); return new ConcurrentTaskExecutor(concurrentExecutor);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2020 the original author or authors. * Copyright 2002-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed 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.
@ -16,7 +16,6 @@
package org.springframework.scheduling.concurrent; package org.springframework.scheduling.concurrent;
import org.springframework.core.task.AsyncListenableTaskExecutor;
import org.springframework.scheduling.support.DelegatingErrorHandlingRunnable; import org.springframework.scheduling.support.DelegatingErrorHandlingRunnable;
import org.springframework.scheduling.support.TaskUtils; import org.springframework.scheduling.support.TaskUtils;
@ -27,7 +26,8 @@ import org.springframework.scheduling.support.TaskUtils;
class DecoratedThreadPoolTaskExecutorTests extends AbstractSchedulingTaskExecutorTests { class DecoratedThreadPoolTaskExecutorTests extends AbstractSchedulingTaskExecutorTests {
@Override @Override
protected AsyncListenableTaskExecutor buildExecutor() { @SuppressWarnings("deprecation")
protected org.springframework.core.task.AsyncListenableTaskExecutor buildExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setTaskDecorator(runnable -> executor.setTaskDecorator(runnable ->
new DelegatingErrorHandlingRunnable(runnable, TaskUtils.LOG_AND_PROPAGATE_ERROR_HANDLER)); new DelegatingErrorHandlingRunnable(runnable, TaskUtils.LOG_AND_PROPAGATE_ERROR_HANDLER));

View File

@ -23,8 +23,6 @@ import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.core.task.AsyncListenableTaskExecutor;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException; import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.assertThatThrownBy;
@ -43,7 +41,8 @@ class ThreadPoolTaskExecutorTests extends AbstractSchedulingTaskExecutorTests {
@Override @Override
protected AsyncListenableTaskExecutor buildExecutor() { @SuppressWarnings("deprecation")
protected org.springframework.core.task.AsyncListenableTaskExecutor buildExecutor() {
executor.setThreadNamePrefix(this.threadNamePrefix); executor.setThreadNamePrefix(this.threadNamePrefix);
executor.setMaxPoolSize(1); executor.setMaxPoolSize(1);
executor.afterPropertiesSet(); executor.afterPropertiesSet();

View File

@ -27,7 +27,6 @@ import java.util.concurrent.atomic.AtomicInteger;
import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.core.task.AsyncListenableTaskExecutor;
import org.springframework.scheduling.Trigger; import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext; import org.springframework.scheduling.TriggerContext;
import org.springframework.util.ErrorHandler; import org.springframework.util.ErrorHandler;
@ -46,8 +45,9 @@ class ThreadPoolTaskSchedulerTests extends AbstractSchedulingTaskExecutorTests {
private final ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler(); private final ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
@SuppressWarnings("deprecation")
@Override @Override
protected AsyncListenableTaskExecutor buildExecutor() { protected org.springframework.core.task.AsyncListenableTaskExecutor buildExecutor() {
scheduler.setThreadNamePrefix(this.threadNamePrefix); scheduler.setThreadNamePrefix(this.threadNamePrefix);
scheduler.afterPropertiesSet(); scheduler.afterPropertiesSet();
return scheduler; return scheduler;

View File

@ -33,11 +33,14 @@ import org.springframework.aot.hint.predicate.RuntimeHintsPredicates;
/** /**
* Java method that is instrumented by the {@link RuntimeHintsAgent}. * Java method that is instrumented by the {@link RuntimeHintsAgent}.
* <p>All their {@link RecordedInvocation invocations are recorded} by the agent at runtime. *
* We can then verify that the {@link RuntimeHints} configuration * <p>All {@linkplain RecordedInvocation invocations are recorded} by the agent
* {@link #matcher(RecordedInvocation) is matching} the runtime behavior of the codebase. * at runtime. We can then verify that the {@link RuntimeHints} configuration
* {@linkplain #matcher(RecordedInvocation) matches} the runtime behavior of the
* codebase.
* *
* @author Brian Clozel * @author Brian Clozel
* @since 6.0
* @see RuntimeHintsPredicates * @see RuntimeHintsPredicates
*/ */
enum InstrumentedMethod { enum InstrumentedMethod {
@ -390,8 +393,4 @@ enum InstrumentedMethod {
return this.hintsMatcherGenerator.apply(invocation); return this.hintsMatcherGenerator.apply(invocation);
} }
private static Predicate<RuntimeHints> hasReturnValue(RecordedInvocation invocation) {
return runtimeHints -> invocation.getReturnValue() != null;
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed 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.
@ -30,6 +30,7 @@ import static org.mockito.Mockito.mock;
/** /**
* @author Arjen Poutsma * @author Arjen Poutsma
*/ */
@SuppressWarnings("deprecation")
class FutureAdapterTests { class FutureAdapterTests {
private FutureAdapter<String, Integer> adapter; private FutureAdapter<String, Integer> adapter;
@ -50,7 +51,7 @@ class FutureAdapterTests {
} }
@Test @Test
void cancel() throws Exception { void cancel() {
given(adaptee.cancel(true)).willReturn(true); given(adaptee.cancel(true)).willReturn(true);
boolean result = adapter.cancel(true); boolean result = adapter.cancel(true);
assertThat(result).isTrue(); assertThat(result).isTrue();
@ -84,5 +85,4 @@ class FutureAdapterTests {
assertThat(result).isEqualTo("42"); assertThat(result).isEqualTo("42");
} }
} }

View File

@ -33,7 +33,7 @@ import static org.mockito.Mockito.verifyNoInteractions;
* @author Arjen Poutsma * @author Arjen Poutsma
* @author Sebastien Deleuze * @author Sebastien Deleuze
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings({ "unchecked", "deprecation" })
class ListenableFutureTaskTests { class ListenableFutureTaskTests {
@Test @Test

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2021 the original author or authors. * Copyright 2002-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed 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.
@ -27,8 +27,10 @@ import static org.assertj.core.api.Assertions.assertThat;
/** /**
* Unit tests for {@link MonoToListenableFutureAdapter}. * Unit tests for {@link MonoToListenableFutureAdapter}.
*
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
*/ */
@SuppressWarnings("deprecation")
class MonoToListenableFutureAdapterTests { class MonoToListenableFutureAdapterTests {
@Test @Test
@ -42,6 +44,7 @@ class MonoToListenableFutureAdapterTests {
} }
@Test @Test
@SuppressWarnings("deprecation")
void failure() { void failure() {
Throwable expected = new IllegalStateException("oops"); Throwable expected = new IllegalStateException("oops");
AtomicReference<Object> actual = new AtomicReference<>(); AtomicReference<Object> actual = new AtomicReference<>();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2021 the original author or authors. * Copyright 2002-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed 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.
@ -36,6 +36,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
* @author Mattias Severson * @author Mattias Severson
* @author Juergen Hoeller * @author Juergen Hoeller
*/ */
@SuppressWarnings("deprecation")
class SettableListenableFutureTests { class SettableListenableFutureTests {
private final SettableListenableFuture<String> settableListenableFuture = new SettableListenableFuture<>(); private final SettableListenableFuture<String> settableListenableFuture = new SettableListenableFuture<>();

View File

@ -20,13 +20,12 @@ import java.util.concurrent.CompletableFuture;
import org.springframework.core.MethodParameter; import org.springframework.core.MethodParameter;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.util.concurrent.CompletableToListenableFutureAdapter;
import org.springframework.util.concurrent.ListenableFuture;
/** /**
* An extension of {@link HandlerMethodReturnValueHandler} for handling async, * An extension of {@link HandlerMethodReturnValueHandler} for handling async,
* Future-like return value types that support success and error callbacks. * Future-like return value types that support success and error callbacks.
* Essentially anything that can be adapted to a {@link ListenableFuture}. * Essentially anything that can be adapted to a
* {@link org.springframework.util.concurrent.ListenableFuture ListenableFuture}.
* *
* <p>Implementations should consider extending the convenient base class * <p>Implementations should consider extending the convenient base class
* {@link AbstractAsyncReturnValueHandler}. * {@link AbstractAsyncReturnValueHandler}.
@ -52,8 +51,9 @@ public interface AsyncHandlerMethodReturnValueHandler extends HandlerMethodRetur
boolean isAsyncReturnValue(Object returnValue, MethodParameter returnType); boolean isAsyncReturnValue(Object returnValue, MethodParameter returnType);
/** /**
* Adapt the asynchronous return value to a {@link ListenableFuture}. * Adapt the asynchronous return value to a
* Implementations should consider returning an instance of * {@link org.springframework.util.concurrent.ListenableFuture ListenableFuture}.
* <p>Implementations should consider returning an instance of
* {@link org.springframework.util.concurrent.SettableListenableFuture * {@link org.springframework.util.concurrent.SettableListenableFuture
* SettableListenableFuture}. Return value handling will then continue when * SettableListenableFuture}. Return value handling will then continue when
* the ListenableFuture is completed with either success or error. * the ListenableFuture is completed with either success or error.
@ -69,14 +69,17 @@ public interface AsyncHandlerMethodReturnValueHandler extends HandlerMethodRetur
*/ */
@Deprecated @Deprecated
@Nullable @Nullable
default ListenableFuture<?> toListenableFuture(Object returnValue, MethodParameter returnType) { default org.springframework.util.concurrent.ListenableFuture<?> toListenableFuture(
Object returnValue, MethodParameter returnType) {
CompletableFuture<?> result = toCompletableFuture(returnValue, returnType); CompletableFuture<?> result = toCompletableFuture(returnValue, returnType);
return (result != null) ? new CompletableToListenableFutureAdapter<>(result) : null; return (result != null ?
new org.springframework.util.concurrent.CompletableToListenableFutureAdapter<>(result) :
null);
} }
/** /**
* Adapt the asynchronous return value to a {@link CompletableFuture}. * Adapt the asynchronous return value to a {@link CompletableFuture}.
* Return value handling will then continue when * <p>Return value handling will then continue when
* the CompletableFuture is completed with either success or error. * the CompletableFuture is completed with either success or error.
* <p><strong>Note:</strong> this method will only be invoked after * <p><strong>Note:</strong> this method will only be invoked after
* {@link #supportsReturnType(org.springframework.core.MethodParameter)} * {@link #supportsReturnType(org.springframework.core.MethodParameter)}

View File

@ -59,7 +59,6 @@ import org.springframework.messaging.handler.invocation.CompletableFutureReturnV
import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver; import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver;
import org.springframework.messaging.handler.invocation.HandlerMethodReturnValueHandler; import org.springframework.messaging.handler.invocation.HandlerMethodReturnValueHandler;
import org.springframework.messaging.handler.invocation.HandlerMethodReturnValueHandlerComposite; import org.springframework.messaging.handler.invocation.HandlerMethodReturnValueHandlerComposite;
import org.springframework.messaging.handler.invocation.ListenableFutureReturnValueHandler;
import org.springframework.messaging.handler.invocation.ReactiveReturnValueHandler; import org.springframework.messaging.handler.invocation.ReactiveReturnValueHandler;
import org.springframework.messaging.simp.SimpAttributesContextHolder; import org.springframework.messaging.simp.SimpAttributesContextHolder;
import org.springframework.messaging.simp.SimpLogging; import org.springframework.messaging.simp.SimpLogging;
@ -326,14 +325,14 @@ public class SimpAnnotationMethodMessageHandler extends AbstractMethodMessageHan
return resolvers; return resolvers;
} }
@SuppressWarnings("deprecation")
@Override @Override
@SuppressWarnings("deprecation")
protected List<? extends HandlerMethodReturnValueHandler> initReturnValueHandlers() { protected List<? extends HandlerMethodReturnValueHandler> initReturnValueHandlers() {
List<HandlerMethodReturnValueHandler> handlers = new ArrayList<>(); List<HandlerMethodReturnValueHandler> handlers = new ArrayList<>();
// Single-purpose return value types // Single-purpose return value types
handlers.add(new ListenableFutureReturnValueHandler()); handlers.add(new org.springframework.messaging.handler.invocation.ListenableFutureReturnValueHandler());
handlers.add(new CompletableFutureReturnValueHandler()); handlers.add(new CompletableFutureReturnValueHandler());
if (reactorPresent) { if (reactorPresent) {
handlers.add(new ReactiveReturnValueHandler()); handlers.add(new ReactiveReturnValueHandler());

View File

@ -18,9 +18,6 @@ package org.springframework.messaging.simp.stomp;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import org.springframework.util.concurrent.CompletableToListenableFutureAdapter;
import org.springframework.util.concurrent.ListenableFuture;
/** /**
* A {@link StompSession} that implements * A {@link StompSession} that implements
* {@link org.springframework.messaging.tcp.TcpConnectionHandler * {@link org.springframework.messaging.tcp.TcpConnectionHandler
@ -39,8 +36,9 @@ public interface ConnectionHandlingStompSession extends StompSession, StompTcpCo
* @deprecated as of 6.0, in favor of {@link #getSession()} * @deprecated as of 6.0, in favor of {@link #getSession()}
*/ */
@Deprecated @Deprecated
default ListenableFuture<StompSession> getSessionFuture() { default org.springframework.util.concurrent.ListenableFuture<StompSession> getSessionFuture() {
return new CompletableToListenableFutureAdapter<>(getSession()); return new org.springframework.util.concurrent.CompletableToListenableFutureAdapter<>(
getSession());
} }
/** /**

View File

@ -23,8 +23,6 @@ import org.springframework.messaging.simp.SimpLogging;
import org.springframework.messaging.tcp.TcpOperations; import org.springframework.messaging.tcp.TcpOperations;
import org.springframework.messaging.tcp.reactor.ReactorNettyTcpClient; import org.springframework.messaging.tcp.reactor.ReactorNettyTcpClient;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.concurrent.CompletableToListenableFutureAdapter;
import org.springframework.util.concurrent.ListenableFuture;
/** /**
* A STOMP over TCP client that uses {@link ReactorNettyTcpClient}. * A STOMP over TCP client that uses {@link ReactorNettyTcpClient}.
@ -77,15 +75,17 @@ public class ReactorNettyTcpStompClient extends StompClientSupport {
* @deprecated as of 6.0, in favor of {@link #connectAsync(StompSessionHandler)} * @deprecated as of 6.0, in favor of {@link #connectAsync(StompSessionHandler)}
*/ */
@Deprecated @Deprecated
public ListenableFuture<StompSession> connect(StompSessionHandler handler) { public org.springframework.util.concurrent.ListenableFuture<StompSession> connect(
return new CompletableToListenableFutureAdapter<>(connectAsync(handler)); StompSessionHandler handler) {
return new org.springframework.util.concurrent.CompletableToListenableFutureAdapter<>(
connectAsync(handler));
} }
/** /**
* Connect and notify the given {@link StompSessionHandler} when connected * Connect and notify the given {@link StompSessionHandler} when connected
* on the STOMP level. * on the STOMP level.
* @param handler the handler for the STOMP session * @param handler the handler for the STOMP session
* @return a ListenableFuture for access to the session when ready for use * @return a CompletableFuture for access to the session when ready for use
* @since 6.0 * @since 6.0
*/ */
public CompletableFuture<StompSession> connectAsync(StompSessionHandler handler) { public CompletableFuture<StompSession> connectAsync(StompSessionHandler handler) {
@ -101,7 +101,8 @@ public class ReactorNettyTcpStompClient extends StompClientSupport {
* @deprecated as of 6.0, in favor of {@link #connectAsync(StompHeaders, StompSessionHandler)} * @deprecated as of 6.0, in favor of {@link #connectAsync(StompHeaders, StompSessionHandler)}
*/ */
@Deprecated @Deprecated
public ListenableFuture<StompSession> connect(@Nullable StompHeaders connectHeaders, StompSessionHandler handler) { public org.springframework.util.concurrent.ListenableFuture<StompSession> connect(
@Nullable StompHeaders connectHeaders, StompSessionHandler handler) {
ConnectionHandlingStompSession session = createSession(connectHeaders, handler); ConnectionHandlingStompSession session = createSession(connectHeaders, handler);
this.tcpClient.connectAsync(session); this.tcpClient.connectAsync(session);
return session.getSessionFuture(); return session.getSessionFuture();
@ -131,4 +132,5 @@ public class ReactorNettyTcpStompClient extends StompClientSupport {
public String toString() { public String toString() {
return "ReactorNettyTcpStompClient[" + this.tcpClient + "]"; return "ReactorNettyTcpStompClient[" + this.tcpClient + "]";
} }
} }

View File

@ -21,7 +21,6 @@ import java.time.Duration;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -1110,16 +1109,6 @@ public class StompBrokerRelayMessageHandler extends AbstractBrokerMessageHandler
} }
private static class VoidCallable implements Callable<Void> {
@Override
public Void call() {
return null;
}
}
/** /**
* Contract for access to session counters. * Contract for access to session counters.
* @since 5.2 * @since 5.2

View File

@ -20,8 +20,6 @@ import java.io.Closeable;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import org.springframework.messaging.Message; import org.springframework.messaging.Message;
import org.springframework.util.concurrent.CompletableToListenableFutureAdapter;
import org.springframework.util.concurrent.ListenableFuture;
/** /**
* A contract for sending messages and managing a TCP connection. * A contract for sending messages and managing a TCP connection.
@ -40,8 +38,9 @@ public interface TcpConnection<P> extends Closeable {
* @deprecated as of 6.0, in favor of {@link #sendAsync(Message)} * @deprecated as of 6.0, in favor of {@link #sendAsync(Message)}
*/ */
@Deprecated @Deprecated
default ListenableFuture<Void> send(Message<P> message) { default org.springframework.util.concurrent.ListenableFuture<Void> send(Message<P> message) {
return new CompletableToListenableFutureAdapter<>(sendAsync(message)); return new org.springframework.util.concurrent.CompletableToListenableFutureAdapter<>(
sendAsync(message));
} }
/** /**

View File

@ -18,15 +18,12 @@ package org.springframework.messaging.tcp;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import org.springframework.util.concurrent.CompletableToListenableFutureAdapter;
import org.springframework.util.concurrent.ListenableFuture;
/** /**
* A contract for establishing TCP connections. * A contract for establishing TCP connections.
* *
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
* @since 4.0 * @since 4.0
* @param <P> the type of payload for in and outbound messages * @param <P> the type of payload for inbound and outbound messages
*/ */
public interface TcpOperations<P> { public interface TcpOperations<P> {
@ -38,8 +35,10 @@ public interface TcpOperations<P> {
* @deprecated as of 6.0, in favor of {@link #connectAsync(TcpConnectionHandler)} * @deprecated as of 6.0, in favor of {@link #connectAsync(TcpConnectionHandler)}
*/ */
@Deprecated @Deprecated
default ListenableFuture<Void> connect(TcpConnectionHandler<P> connectionHandler) { default org.springframework.util.concurrent.ListenableFuture<Void> connect(
return new CompletableToListenableFutureAdapter<>(connectAsync(connectionHandler)); TcpConnectionHandler<P> connectionHandler) {
return new org.springframework.util.concurrent.CompletableToListenableFutureAdapter<>(
connectAsync(connectionHandler));
} }
/** /**
@ -60,8 +59,10 @@ public interface TcpOperations<P> {
* @deprecated as of 6.0, in favor of {@link #connectAsync(TcpConnectionHandler, ReconnectStrategy)} * @deprecated as of 6.0, in favor of {@link #connectAsync(TcpConnectionHandler, ReconnectStrategy)}
*/ */
@Deprecated @Deprecated
default ListenableFuture<Void> connect(TcpConnectionHandler<P> connectionHandler, ReconnectStrategy reconnectStrategy) { default org.springframework.util.concurrent.ListenableFuture<Void> connect(
return new CompletableToListenableFutureAdapter<>(connectAsync(connectionHandler, reconnectStrategy)); TcpConnectionHandler<P> connectionHandler, ReconnectStrategy reconnectStrategy) {
return new org.springframework.util.concurrent.CompletableToListenableFutureAdapter<>(
connectAsync(connectionHandler, reconnectStrategy));
} }
/** /**
@ -81,13 +82,14 @@ public interface TcpOperations<P> {
* @deprecated as of 6.0, in favor of {@link #shutdownAsync()} * @deprecated as of 6.0, in favor of {@link #shutdownAsync()}
*/ */
@Deprecated @Deprecated
default ListenableFuture<Void> shutdown() { default org.springframework.util.concurrent.ListenableFuture<Void> shutdown() {
return new CompletableToListenableFutureAdapter<>(shutdownAsync()); return new org.springframework.util.concurrent.CompletableToListenableFutureAdapter<>(
shutdownAsync());
} }
/** /**
* Shut down and close any open connections. * Shut down and close any open connections.
* @return a ListenableFuture that can be used to determine when and if the * @return a CompletableFuture that can be used to determine when and if the
* connection is successfully closed * connection is successfully closed
* @since 6.0 * @since 6.0
*/ */

View File

@ -61,7 +61,6 @@ import org.springframework.messaging.simp.annotation.SubscribeMapping;
import org.springframework.messaging.support.MessageBuilder; import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.util.AntPathMatcher; import org.springframework.util.AntPathMatcher;
import org.springframework.util.concurrent.ListenableFutureTask;
import org.springframework.validation.Errors; import org.springframework.validation.Errors;
import org.springframework.validation.Validator; import org.springframework.validation.Validator;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@ -538,19 +537,19 @@ public class SimpAnnotationMethodMessageHandlerTests {
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
private static class ListenableFutureController { private static class ListenableFutureController {
private ListenableFutureTask<String> future; private org.springframework.util.concurrent.ListenableFutureTask<String> future;
private boolean exceptionCaught = false; private boolean exceptionCaught = false;
@MessageMapping("success") @MessageMapping("success")
public ListenableFutureTask<String> handleListenableFuture() { public org.springframework.util.concurrent.ListenableFutureTask<String> handleListenableFuture() {
this.future = new ListenableFutureTask<>(() -> "foo"); this.future = new org.springframework.util.concurrent.ListenableFutureTask<>(() -> "foo");
return this.future; return this.future;
} }
@MessageMapping("failure") @MessageMapping("failure")
public ListenableFutureTask<String> handleListenableFutureException() { public org.springframework.util.concurrent.ListenableFutureTask<String> handleListenableFutureException() {
this.future = new ListenableFutureTask<>(() -> { this.future = new org.springframework.util.concurrent.ListenableFutureTask<>(() -> {
throw new IllegalStateException(); throw new IllegalStateException();
}); });
return this.future; return this.future;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2021 the original author or authors. * Copyright 2002-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed 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.
@ -30,8 +30,6 @@ import org.springframework.http.ResponseEntity;
import org.springframework.test.web.Person; import org.springframework.test.web.Person;
import org.springframework.test.web.reactive.server.WebTestClient; import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.test.web.servlet.client.MockMvcWebTestClient; import org.springframework.test.web.servlet.client.MockMvcWebTestClient;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureTask;
import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
@ -46,14 +44,14 @@ import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBo
* *
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
*/ */
public class AsyncTests { class AsyncTests {
private final WebTestClient testClient = private final WebTestClient testClient =
MockMvcWebTestClient.bindToController(new AsyncController()).build(); MockMvcWebTestClient.bindToController(new AsyncController()).build();
@Test @Test
public void callable() { void callable() {
this.testClient.get() this.testClient.get()
.uri("/1?callable=true") .uri("/1?callable=true")
.exchange() .exchange()
@ -63,7 +61,7 @@ public class AsyncTests {
} }
@Test @Test
public void streaming() { void streaming() {
this.testClient.get() this.testClient.get()
.uri("/1?streaming=true") .uri("/1?streaming=true")
.exchange() .exchange()
@ -72,7 +70,7 @@ public class AsyncTests {
} }
@Test @Test
public void streamingSlow() { void streamingSlow() {
this.testClient.get() this.testClient.get()
.uri("/1?streamingSlow=true") .uri("/1?streamingSlow=true")
.exchange() .exchange()
@ -81,7 +79,7 @@ public class AsyncTests {
} }
@Test @Test
public void streamingJson() { void streamingJson() {
this.testClient.get() this.testClient.get()
.uri("/1?streamingJson=true") .uri("/1?streamingJson=true")
.exchange() .exchange()
@ -91,7 +89,7 @@ public class AsyncTests {
} }
@Test @Test
public void deferredResult() { void deferredResult() {
this.testClient.get() this.testClient.get()
.uri("/1?deferredResult=true") .uri("/1?deferredResult=true")
.exchange() .exchange()
@ -101,7 +99,7 @@ public class AsyncTests {
} }
@Test @Test
public void deferredResultWithImmediateValue() { void deferredResultWithImmediateValue() {
this.testClient.get() this.testClient.get()
.uri("/1?deferredResultWithImmediateValue=true") .uri("/1?deferredResultWithImmediateValue=true")
.exchange() .exchange()
@ -111,7 +109,7 @@ public class AsyncTests {
} }
@Test @Test
public void deferredResultWithDelayedError() { void deferredResultWithDelayedError() {
this.testClient.get() this.testClient.get()
.uri("/1?deferredResultWithDelayedError=true") .uri("/1?deferredResultWithDelayedError=true")
.exchange() .exchange()
@ -120,7 +118,7 @@ public class AsyncTests {
} }
@Test @Test
public void listenableFuture() { void listenableFuture() {
this.testClient.get() this.testClient.get()
.uri("/1?listenableFuture=true") .uri("/1?listenableFuture=true")
.exchange() .exchange()
@ -130,7 +128,7 @@ public class AsyncTests {
} }
@Test @Test
public void completableFutureWithImmediateValue() throws Exception { void completableFutureWithImmediateValue() throws Exception {
this.testClient.get() this.testClient.get()
.uri("/1?completableFutureWithImmediateValue=true") .uri("/1?completableFutureWithImmediateValue=true")
.exchange() .exchange()
@ -145,17 +143,17 @@ public class AsyncTests {
private static class AsyncController { private static class AsyncController {
@GetMapping(params = "callable") @GetMapping(params = "callable")
public Callable<Person> getCallable() { Callable<Person> getCallable() {
return () -> new Person("Joe"); return () -> new Person("Joe");
} }
@GetMapping(params = "streaming") @GetMapping(params = "streaming")
public StreamingResponseBody getStreaming() { StreamingResponseBody getStreaming() {
return os -> os.write("name=Joe".getBytes(StandardCharsets.UTF_8)); return os -> os.write("name=Joe".getBytes(StandardCharsets.UTF_8));
} }
@GetMapping(params = "streamingSlow") @GetMapping(params = "streamingSlow")
public StreamingResponseBody getStreamingSlow() { StreamingResponseBody getStreamingSlow() {
return os -> { return os -> {
os.write("name=Joe".getBytes()); os.write("name=Joe".getBytes());
try { try {
@ -169,41 +167,43 @@ public class AsyncTests {
} }
@GetMapping(params = "streamingJson") @GetMapping(params = "streamingJson")
public ResponseEntity<StreamingResponseBody> getStreamingJson() { ResponseEntity<StreamingResponseBody> getStreamingJson() {
return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON) return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON)
.body(os -> os.write("{\"name\":\"Joe\",\"someDouble\":0.5}".getBytes(StandardCharsets.UTF_8))); .body(os -> os.write("{\"name\":\"Joe\",\"someDouble\":0.5}".getBytes(StandardCharsets.UTF_8)));
} }
@GetMapping(params = "deferredResult") @GetMapping(params = "deferredResult")
public DeferredResult<Person> getDeferredResult() { DeferredResult<Person> getDeferredResult() {
DeferredResult<Person> result = new DeferredResult<>(); DeferredResult<Person> result = new DeferredResult<>();
delay(100, () -> result.setResult(new Person("Joe"))); delay(100, () -> result.setResult(new Person("Joe")));
return result; return result;
} }
@GetMapping(params = "deferredResultWithImmediateValue") @GetMapping(params = "deferredResultWithImmediateValue")
public DeferredResult<Person> getDeferredResultWithImmediateValue() { DeferredResult<Person> getDeferredResultWithImmediateValue() {
DeferredResult<Person> result = new DeferredResult<>(); DeferredResult<Person> result = new DeferredResult<>();
result.setResult(new Person("Joe")); result.setResult(new Person("Joe"));
return result; return result;
} }
@GetMapping(params = "deferredResultWithDelayedError") @GetMapping(params = "deferredResultWithDelayedError")
public DeferredResult<Person> getDeferredResultWithDelayedError() { DeferredResult<Person> getDeferredResultWithDelayedError() {
DeferredResult<Person> result = new DeferredResult<>(); DeferredResult<Person> result = new DeferredResult<>();
delay(100, () -> result.setErrorResult(new RuntimeException("Delayed Error"))); delay(100, () -> result.setErrorResult(new RuntimeException("Delayed Error")));
return result; return result;
} }
@GetMapping(params = "listenableFuture") @GetMapping(params = "listenableFuture")
public ListenableFuture<Person> getListenableFuture() { @SuppressWarnings("deprecation")
ListenableFutureTask<Person> futureTask = new ListenableFutureTask<>(() -> new Person("Joe")); org.springframework.util.concurrent.ListenableFuture<Person> getListenableFuture() {
org.springframework.util.concurrent.ListenableFutureTask<Person> futureTask =
new org.springframework.util.concurrent.ListenableFutureTask<>(() -> new Person("Joe"));
delay(100, futureTask); delay(100, futureTask);
return futureTask; return futureTask;
} }
@GetMapping(params = "completableFutureWithImmediateValue") @GetMapping(params = "completableFutureWithImmediateValue")
public CompletableFuture<Person> getCompletableFutureWithImmediateValue() { CompletableFuture<Person> getCompletableFutureWithImmediateValue() {
CompletableFuture<Person> future = new CompletableFuture<>(); CompletableFuture<Person> future = new CompletableFuture<>();
future.complete(new Person("Joe")); future.complete(new Person("Joe"));
return future; return future;
@ -211,7 +211,7 @@ public class AsyncTests {
@ExceptionHandler(Exception.class) @ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public String errorHandler(Exception ex) { String errorHandler(Exception ex) {
return ex.getMessage(); return ex.getMessage();
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2020 the original author or authors. * Copyright 2002-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed 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.
@ -31,8 +31,6 @@ import org.springframework.http.ResponseEntity;
import org.springframework.test.web.Person; import org.springframework.test.web.Person;
import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.MvcResult;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureTask;
import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.ResponseStatus;
@ -58,7 +56,7 @@ import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standal
* @author Sam Brannen * @author Sam Brannen
* @author Jacek Suchenia * @author Jacek Suchenia
*/ */
public class AsyncTests { class AsyncTests {
private final AsyncController asyncController = new AsyncController(); private final AsyncController asyncController = new AsyncController();
@ -66,7 +64,7 @@ public class AsyncTests {
@Test @Test
public void callable() throws Exception { void callable() throws Exception {
MvcResult mvcResult = this.mockMvc.perform(get("/1").param("callable", "true")) MvcResult mvcResult = this.mockMvc.perform(get("/1").param("callable", "true"))
.andExpect(request().asyncStarted()) .andExpect(request().asyncStarted())
.andExpect(request().asyncResult(equalTo(new Person("Joe")))) .andExpect(request().asyncResult(equalTo(new Person("Joe"))))
@ -80,7 +78,7 @@ public class AsyncTests {
} }
@Test @Test
public void streaming() throws Exception { void streaming() throws Exception {
this.mockMvc.perform(get("/1").param("streaming", "true")) this.mockMvc.perform(get("/1").param("streaming", "true"))
.andExpect(request().asyncStarted()) .andExpect(request().asyncStarted())
.andDo(MvcResult::getAsyncResult) // fetch async result similar to "asyncDispatch" builder .andDo(MvcResult::getAsyncResult) // fetch async result similar to "asyncDispatch" builder
@ -89,7 +87,7 @@ public class AsyncTests {
} }
@Test @Test
public void streamingSlow() throws Exception { void streamingSlow() throws Exception {
this.mockMvc.perform(get("/1").param("streamingSlow", "true")) this.mockMvc.perform(get("/1").param("streamingSlow", "true"))
.andExpect(request().asyncStarted()) .andExpect(request().asyncStarted())
.andDo(MvcResult::getAsyncResult) .andDo(MvcResult::getAsyncResult)
@ -98,7 +96,7 @@ public class AsyncTests {
} }
@Test @Test
public void streamingJson() throws Exception { void streamingJson() throws Exception {
this.mockMvc.perform(get("/1").param("streamingJson", "true")) this.mockMvc.perform(get("/1").param("streamingJson", "true"))
.andExpect(request().asyncStarted()) .andExpect(request().asyncStarted())
.andDo(MvcResult::getAsyncResult) .andDo(MvcResult::getAsyncResult)
@ -108,7 +106,7 @@ public class AsyncTests {
} }
@Test @Test
public void deferredResult() throws Exception { void deferredResult() throws Exception {
MvcResult mvcResult = this.mockMvc.perform(get("/1").param("deferredResult", "true")) MvcResult mvcResult = this.mockMvc.perform(get("/1").param("deferredResult", "true"))
.andExpect(request().asyncStarted()) .andExpect(request().asyncStarted())
.andReturn(); .andReturn();
@ -120,7 +118,7 @@ public class AsyncTests {
} }
@Test @Test
public void deferredResultWithImmediateValue() throws Exception { void deferredResultWithImmediateValue() throws Exception {
MvcResult mvcResult = this.mockMvc.perform(get("/1").param("deferredResultWithImmediateValue", "true")) MvcResult mvcResult = this.mockMvc.perform(get("/1").param("deferredResultWithImmediateValue", "true"))
.andExpect(request().asyncStarted()) .andExpect(request().asyncStarted())
.andExpect(request().asyncResult(new Person("Joe"))) .andExpect(request().asyncResult(new Person("Joe")))
@ -133,7 +131,7 @@ public class AsyncTests {
} }
@Test // SPR-13079 @Test // SPR-13079
public void deferredResultWithDelayedError() throws Exception { void deferredResultWithDelayedError() throws Exception {
MvcResult mvcResult = this.mockMvc.perform(get("/1").param("deferredResultWithDelayedError", "true")) MvcResult mvcResult = this.mockMvc.perform(get("/1").param("deferredResultWithDelayedError", "true"))
.andExpect(request().asyncStarted()) .andExpect(request().asyncStarted())
.andReturn(); .andReturn();
@ -144,7 +142,7 @@ public class AsyncTests {
} }
@Test @Test
public void listenableFuture() throws Exception { void listenableFuture() throws Exception {
MvcResult mvcResult = this.mockMvc.perform(get("/1").param("listenableFuture", "true")) MvcResult mvcResult = this.mockMvc.perform(get("/1").param("listenableFuture", "true"))
.andExpect(request().asyncStarted()) .andExpect(request().asyncStarted())
.andReturn(); .andReturn();
@ -156,7 +154,7 @@ public class AsyncTests {
} }
@Test // SPR-12597 @Test // SPR-12597
public void completableFutureWithImmediateValue() throws Exception { void completableFutureWithImmediateValue() throws Exception {
MvcResult mvcResult = this.mockMvc.perform(get("/1").param("completableFutureWithImmediateValue", "true")) MvcResult mvcResult = this.mockMvc.perform(get("/1").param("completableFutureWithImmediateValue", "true"))
.andExpect(request().asyncStarted()) .andExpect(request().asyncStarted())
.andReturn(); .andReturn();
@ -168,7 +166,7 @@ public class AsyncTests {
} }
@Test // SPR-12735 @Test // SPR-12735
public void printAsyncResult() throws Exception { void printAsyncResult() throws Exception {
StringWriter writer = new StringWriter(); StringWriter writer = new StringWriter();
MvcResult mvcResult = this.mockMvc.perform(get("/1").param("deferredResult", "true")) MvcResult mvcResult = this.mockMvc.perform(get("/1").param("deferredResult", "true"))
@ -194,17 +192,17 @@ public class AsyncTests {
private static class AsyncController { private static class AsyncController {
@RequestMapping(params = "callable") @RequestMapping(params = "callable")
public Callable<Person> getCallable() { Callable<Person> getCallable() {
return () -> new Person("Joe"); return () -> new Person("Joe");
} }
@RequestMapping(params = "streaming") @RequestMapping(params = "streaming")
public StreamingResponseBody getStreaming() { StreamingResponseBody getStreaming() {
return os -> os.write("name=Joe".getBytes(StandardCharsets.UTF_8)); return os -> os.write("name=Joe".getBytes(StandardCharsets.UTF_8));
} }
@RequestMapping(params = "streamingSlow") @RequestMapping(params = "streamingSlow")
public StreamingResponseBody getStreamingSlow() { StreamingResponseBody getStreamingSlow() {
return os -> { return os -> {
os.write("name=Joe".getBytes()); os.write("name=Joe".getBytes());
try { try {
@ -218,41 +216,43 @@ public class AsyncTests {
} }
@RequestMapping(params = "streamingJson") @RequestMapping(params = "streamingJson")
public ResponseEntity<StreamingResponseBody> getStreamingJson() { ResponseEntity<StreamingResponseBody> getStreamingJson() {
return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON) return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON)
.body(os -> os.write("{\"name\":\"Joe\",\"someDouble\":0.5}".getBytes(StandardCharsets.UTF_8))); .body(os -> os.write("{\"name\":\"Joe\",\"someDouble\":0.5}".getBytes(StandardCharsets.UTF_8)));
} }
@RequestMapping(params = "deferredResult") @RequestMapping(params = "deferredResult")
public DeferredResult<Person> getDeferredResult() { DeferredResult<Person> getDeferredResult() {
DeferredResult<Person> result = new DeferredResult<>(); DeferredResult<Person> result = new DeferredResult<>();
delay(100, () -> result.setResult(new Person("Joe"))); delay(100, () -> result.setResult(new Person("Joe")));
return result; return result;
} }
@RequestMapping(params = "deferredResultWithImmediateValue") @RequestMapping(params = "deferredResultWithImmediateValue")
public DeferredResult<Person> getDeferredResultWithImmediateValue() { DeferredResult<Person> getDeferredResultWithImmediateValue() {
DeferredResult<Person> deferredResult = new DeferredResult<>(); DeferredResult<Person> deferredResult = new DeferredResult<>();
deferredResult.setResult(new Person("Joe")); deferredResult.setResult(new Person("Joe"));
return deferredResult; return deferredResult;
} }
@RequestMapping(params = "deferredResultWithDelayedError") @RequestMapping(params = "deferredResultWithDelayedError")
public DeferredResult<Person> getDeferredResultWithDelayedError() { DeferredResult<Person> getDeferredResultWithDelayedError() {
DeferredResult<Person> result = new DeferredResult<>(); DeferredResult<Person> result = new DeferredResult<>();
delay(100, () -> result.setErrorResult(new RuntimeException("Delayed Error"))); delay(100, () -> result.setErrorResult(new RuntimeException("Delayed Error")));
return result; return result;
} }
@RequestMapping(params = "listenableFuture") @RequestMapping(params = "listenableFuture")
public ListenableFuture<Person> getListenableFuture() { @SuppressWarnings("deprecation")
ListenableFutureTask<Person> futureTask = new ListenableFutureTask<>(() -> new Person("Joe")); org.springframework.util.concurrent.ListenableFuture<Person> getListenableFuture() {
org.springframework.util.concurrent.ListenableFutureTask<Person> futureTask =
new org.springframework.util.concurrent.ListenableFutureTask<>(() -> new Person("Joe"));
delay(100, futureTask); delay(100, futureTask);
return futureTask; return futureTask;
} }
@RequestMapping(params = "completableFutureWithImmediateValue") @RequestMapping(params = "completableFutureWithImmediateValue")
public CompletableFuture<Person> getCompletableFutureWithImmediateValue() { CompletableFuture<Person> getCompletableFutureWithImmediateValue() {
CompletableFuture<Person> future = new CompletableFuture<>(); CompletableFuture<Person> future = new CompletableFuture<>();
future.complete(new Person("Joe")); future.complete(new Person("Joe"));
return future; return future;
@ -260,7 +260,7 @@ public class AsyncTests {
@ExceptionHandler(Exception.class) @ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public String errorHandler(Exception ex) { String errorHandler(Exception ex) {
return ex.getMessage(); return ex.getMessage();
} }

View File

@ -21,8 +21,6 @@ import java.util.concurrent.CompletionStage;
import org.springframework.core.MethodParameter; import org.springframework.core.MethodParameter;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureCallback;
import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.async.DeferredResult; import org.springframework.web.context.request.async.DeferredResult;
import org.springframework.web.context.request.async.WebAsyncUtils; import org.springframework.web.context.request.async.WebAsyncUtils;
@ -31,7 +29,8 @@ import org.springframework.web.method.support.ModelAndViewContainer;
/** /**
* Handler for return values of type {@link DeferredResult}, * Handler for return values of type {@link DeferredResult},
* {@link ListenableFuture}, and {@link CompletionStage}. * {@link org.springframework.util.concurrent.ListenableFuture}, and
* {@link CompletionStage}.
* *
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
* @since 3.2 * @since 3.2
@ -43,7 +42,7 @@ public class DeferredResultMethodReturnValueHandler implements HandlerMethodRetu
public boolean supportsReturnType(MethodParameter returnType) { public boolean supportsReturnType(MethodParameter returnType) {
Class<?> type = returnType.getParameterType(); Class<?> type = returnType.getParameterType();
return (DeferredResult.class.isAssignableFrom(type) || return (DeferredResult.class.isAssignableFrom(type) ||
ListenableFuture.class.isAssignableFrom(type) || org.springframework.util.concurrent.ListenableFuture.class.isAssignableFrom(type) ||
CompletionStage.class.isAssignableFrom(type)); CompletionStage.class.isAssignableFrom(type));
} }
@ -59,14 +58,14 @@ public class DeferredResultMethodReturnValueHandler implements HandlerMethodRetu
DeferredResult<?> result; DeferredResult<?> result;
if (returnValue instanceof DeferredResult) { if (returnValue instanceof DeferredResult<?> deferredResult) {
result = (DeferredResult<?>) returnValue; result = deferredResult;
} }
else if (returnValue instanceof ListenableFuture) { else if (returnValue instanceof org.springframework.util.concurrent.ListenableFuture<?> listenableFuture) {
result = adaptListenableFuture((ListenableFuture<?>) returnValue); result = adaptListenableFuture(listenableFuture);
} }
else if (returnValue instanceof CompletionStage) { else if (returnValue instanceof CompletionStage<?> completionStage) {
result = adaptCompletionStage((CompletionStage<?>) returnValue); result = adaptCompletionStage(completionStage);
} }
else { else {
// Should not happen... // Should not happen...
@ -77,9 +76,9 @@ public class DeferredResultMethodReturnValueHandler implements HandlerMethodRetu
} }
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
private DeferredResult<Object> adaptListenableFuture(ListenableFuture<?> future) { private DeferredResult<Object> adaptListenableFuture(org.springframework.util.concurrent.ListenableFuture<?> future) {
DeferredResult<Object> result = new DeferredResult<>(); DeferredResult<Object> result = new DeferredResult<>();
future.addCallback(new ListenableFutureCallback<Object>() { future.addCallback(new org.springframework.util.concurrent.ListenableFutureCallback<Object>() {
@Override @Override
public void onSuccess(@Nullable Object value) { public void onSuccess(@Nullable Object value) {
result.setResult(value); result.setResult(value);

View File

@ -22,8 +22,6 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.core.MethodParameter; import org.springframework.core.MethodParameter;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.SettableListenableFuture;
import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.ServletWebRequest; import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.context.request.async.AsyncWebRequest; import org.springframework.web.context.request.async.AsyncWebRequest;
@ -65,12 +63,13 @@ public class DeferredResultReturnValueHandlerTests {
@Test @Test
@SuppressWarnings("deprecation")
public void supportsReturnType() throws Exception { public void supportsReturnType() throws Exception {
assertThat(this.handler.supportsReturnType( assertThat(this.handler.supportsReturnType(
on(TestController.class).resolveReturnType(DeferredResult.class, String.class))).isTrue(); on(TestController.class).resolveReturnType(DeferredResult.class, String.class))).isTrue();
assertThat(this.handler.supportsReturnType( assertThat(this.handler.supportsReturnType(
on(TestController.class).resolveReturnType(ListenableFuture.class, String.class))).isTrue(); on(TestController.class).resolveReturnType(org.springframework.util.concurrent.ListenableFuture.class, String.class))).isTrue();
assertThat(this.handler.supportsReturnType( assertThat(this.handler.supportsReturnType(
on(TestController.class).resolveReturnType(CompletableFuture.class, String.class))).isTrue(); on(TestController.class).resolveReturnType(CompletableFuture.class, String.class))).isTrue();
@ -91,8 +90,10 @@ public class DeferredResultReturnValueHandlerTests {
@Test @Test
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public void listenableFuture() throws Exception { public void listenableFuture() throws Exception {
SettableListenableFuture<String> future = new SettableListenableFuture<>(); org.springframework.util.concurrent.SettableListenableFuture<String> future =
testHandle(future, ListenableFuture.class, () -> future.set("foo"), "foo"); new org.springframework.util.concurrent.SettableListenableFuture<>();
testHandle(future, org.springframework.util.concurrent.ListenableFuture.class,
() -> future.set("foo"), "foo");
} }
@Test @Test
@ -110,9 +111,11 @@ public class DeferredResultReturnValueHandlerTests {
@Test @Test
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public void listenableFutureWithError() throws Exception { public void listenableFutureWithError() throws Exception {
SettableListenableFuture<String> future = new SettableListenableFuture<>(); org.springframework.util.concurrent.SettableListenableFuture<String> future =
new org.springframework.util.concurrent.SettableListenableFuture<>();
IllegalStateException ex = new IllegalStateException(); IllegalStateException ex = new IllegalStateException();
testHandle(future, ListenableFuture.class, () -> future.setException(ex), ex); testHandle(future, org.springframework.util.concurrent.ListenableFuture.class,
() -> future.setException(ex), ex);
} }
@Test @Test
@ -147,7 +150,8 @@ public class DeferredResultReturnValueHandlerTests {
DeferredResult<String> handleDeferredResult() { return null; } DeferredResult<String> handleDeferredResult() { return null; }
ListenableFuture<String> handleListenableFuture() { return null; } @SuppressWarnings("deprecation")
org.springframework.util.concurrent.ListenableFuture<String> handleListenableFuture() { return null; }
CompletableFuture<String> handleCompletableFuture() { return null; } CompletableFuture<String> handleCompletableFuture() { return null; }
} }

View File

@ -18,7 +18,6 @@ package org.springframework.web.socket.client;
import java.net.URI; import java.net.URI;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -30,7 +29,6 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.web.socket.WebSocketExtension; import org.springframework.web.socket.WebSocketExtension;
import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketHttpHeaders; import org.springframework.web.socket.WebSocketHttpHeaders;
@ -45,19 +43,16 @@ import org.springframework.web.util.UriComponentsBuilder;
*/ */
public abstract class AbstractWebSocketClient implements WebSocketClient { public abstract class AbstractWebSocketClient implements WebSocketClient {
private static final Set<String> specialHeaders = new HashSet<>(); private static final Set<String> specialHeaders = Set.of(
"cache-control",
static { "connection",
specialHeaders.add("cache-control"); "host",
specialHeaders.add("connection"); "sec-websocket-extensions",
specialHeaders.add("host"); "sec-websocket-key",
specialHeaders.add("sec-websocket-extensions"); "sec-websocket-protocol",
specialHeaders.add("sec-websocket-key"); "sec-websocket-version",
specialHeaders.add("sec-websocket-protocol"); "pragma",
specialHeaders.add("sec-websocket-version"); "upgrade");
specialHeaders.add("pragma");
specialHeaders.add("upgrade");
}
protected final Log logger = LogFactory.getLog(getClass()); protected final Log logger = LogFactory.getLog(getClass());
@ -119,13 +114,14 @@ public abstract class AbstractWebSocketClient implements WebSocketClient {
* @param extensions requested WebSocket extensions, or an empty list * @param extensions requested WebSocket extensions, or an empty list
* @param attributes the attributes to associate with the WebSocketSession, i.e. via * @param attributes the attributes to associate with the WebSocketSession, i.e. via
* {@link WebSocketSession#getAttributes()}; currently always an empty map. * {@link WebSocketSession#getAttributes()}; currently always an empty map.
* @return the established WebSocket session wrapped in a ListenableFuture. * @return the established WebSocket session wrapped in a {@code ListenableFuture}.
* @deprecated as of 6.0, in favor of {@link #executeInternal(WebSocketHandler, HttpHeaders, URI, List, List, Map)} * @deprecated as of 6.0, in favor of {@link #executeInternal(WebSocketHandler, HttpHeaders, URI, List, List, Map)}
*/ */
@Deprecated @Deprecated
protected ListenableFuture<WebSocketSession> doHandshakeInternal(WebSocketHandler webSocketHandler, protected org.springframework.util.concurrent.ListenableFuture<WebSocketSession> doHandshakeInternal(
HttpHeaders headers, URI uri, List<String> subProtocols, List<WebSocketExtension> extensions, WebSocketHandler webSocketHandler, HttpHeaders headers, URI uri, List<String> subProtocols,
Map<String, Object> attributes) { List<WebSocketExtension> extensions, Map<String, Object> attributes) {
throw new UnsupportedOperationException("doHandshakeInternal is deprecated in favor of executeInternal"); throw new UnsupportedOperationException("doHandshakeInternal is deprecated in favor of executeInternal");
} }
@ -138,8 +134,8 @@ public abstract class AbstractWebSocketClient implements WebSocketClient {
* @param subProtocols requested sub-protocols, or an empty list * @param subProtocols requested sub-protocols, or an empty list
* @param extensions requested WebSocket extensions, or an empty list * @param extensions requested WebSocket extensions, or an empty list
* @param attributes the attributes to associate with the WebSocketSession, i.e. via * @param attributes the attributes to associate with the WebSocketSession, i.e. via
* {@link WebSocketSession#getAttributes()}; currently always an empty map. * {@link WebSocketSession#getAttributes()}; currently always an empty map
* @return the established WebSocket session wrapped in a ListenableFuture. * @return the established WebSocket session wrapped in a {@code CompletableFuture}.
*/ */
protected abstract CompletableFuture<WebSocketSession> executeInternal(WebSocketHandler webSocketHandler, protected abstract CompletableFuture<WebSocketSession> executeInternal(WebSocketHandler webSocketHandler,
HttpHeaders headers, URI uri, List<String> subProtocols, List<WebSocketExtension> extensions, HttpHeaders headers, URI uri, List<String> subProtocols, List<WebSocketExtension> extensions,

View File

@ -20,8 +20,6 @@ import java.net.URI;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.util.concurrent.CompletableToListenableFutureAdapter;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketHttpHeaders; import org.springframework.web.socket.WebSocketHttpHeaders;
import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.WebSocketSession;
@ -47,9 +45,10 @@ public interface WebSocketClient {
* @deprecated as of 6.0, in favor of {@link #execute(WebSocketHandler, String, Object...)} * @deprecated as of 6.0, in favor of {@link #execute(WebSocketHandler, String, Object...)}
*/ */
@Deprecated @Deprecated
default ListenableFuture<WebSocketSession> doHandshake(WebSocketHandler webSocketHandler, default org.springframework.util.concurrent.ListenableFuture<WebSocketSession> doHandshake(
String uriTemplate, Object... uriVariables) { WebSocketHandler webSocketHandler, String uriTemplate, Object... uriVariables) {
return new CompletableToListenableFutureAdapter<>(execute(webSocketHandler, uriTemplate, uriVariables)); return new org.springframework.util.concurrent.CompletableToListenableFutureAdapter<>(
execute(webSocketHandler, uriTemplate, uriVariables));
} }
/** /**
@ -73,9 +72,10 @@ public interface WebSocketClient {
* @deprecated as of 6.0, in favor of {@link #execute(WebSocketHandler, WebSocketHttpHeaders, URI)} * @deprecated as of 6.0, in favor of {@link #execute(WebSocketHandler, WebSocketHttpHeaders, URI)}
*/ */
@Deprecated @Deprecated
default ListenableFuture<WebSocketSession> doHandshake(WebSocketHandler webSocketHandler, default org.springframework.util.concurrent.ListenableFuture<WebSocketSession> doHandshake(
@Nullable WebSocketHttpHeaders headers, URI uri) { WebSocketHandler webSocketHandler, @Nullable WebSocketHttpHeaders headers, URI uri) {
return new CompletableToListenableFutureAdapter<>(execute(webSocketHandler, headers, uri)); return new org.springframework.util.concurrent.CompletableToListenableFutureAdapter<>(
execute(webSocketHandler, headers, uri));
} }
/** /**

View File

@ -30,10 +30,8 @@ import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
import org.eclipse.jetty.websocket.client.WebSocketClient; import org.eclipse.jetty.websocket.client.WebSocketClient;
import org.springframework.context.Lifecycle; import org.springframework.context.Lifecycle;
import org.springframework.core.task.AsyncListenableTaskExecutor;
import org.springframework.core.task.AsyncTaskExecutor; import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.core.task.SimpleAsyncTaskExecutor; import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.core.task.TaskExecutor;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.util.concurrent.FutureUtils; import org.springframework.util.concurrent.FutureUtils;
@ -84,8 +82,8 @@ public class JettyWebSocketClient extends AbstractWebSocketClient implements Lif
/** /**
* Set an {@link AsyncListenableTaskExecutor} to use when opening connections. * Set an {@link AsyncTaskExecutor} to use when opening connections.
* If this property is set to {@code null}, calls to any of the * <p>If this property is set to {@code null}, calls to any of the
* {@code doHandshake} methods will block until the connection is established. * {@code doHandshake} methods will block until the connection is established.
* <p>By default an instance of {@code SimpleAsyncTaskExecutor} is used. * <p>By default an instance of {@code SimpleAsyncTaskExecutor} is used.
*/ */
@ -94,7 +92,7 @@ public class JettyWebSocketClient extends AbstractWebSocketClient implements Lif
} }
/** /**
* Return the configured {@link TaskExecutor}. * Return the configured {@link AsyncTaskExecutor}.
*/ */
@Nullable @Nullable
public AsyncTaskExecutor getTaskExecutor() { public AsyncTaskExecutor getTaskExecutor() {

View File

@ -36,10 +36,8 @@ import jakarta.websocket.Extension;
import jakarta.websocket.HandshakeResponse; import jakarta.websocket.HandshakeResponse;
import jakarta.websocket.WebSocketContainer; import jakarta.websocket.WebSocketContainer;
import org.springframework.core.task.AsyncListenableTaskExecutor;
import org.springframework.core.task.AsyncTaskExecutor; import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.core.task.SimpleAsyncTaskExecutor; import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.core.task.TaskExecutor;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.util.Assert; import org.springframework.util.Assert;
@ -109,8 +107,8 @@ public class StandardWebSocketClient extends AbstractWebSocketClient {
} }
/** /**
* Set an {@link AsyncListenableTaskExecutor} to use when opening connections. * Set an {@link AsyncTaskExecutor} to use when opening connections.
* If this property is set to {@code null}, calls to any of the * <p>If this property is set to {@code null}, calls to any of the
* {@code doHandshake} methods will block until the connection is established. * {@code doHandshake} methods will block until the connection is established.
* <p>By default, an instance of {@code SimpleAsyncTaskExecutor} is used. * <p>By default, an instance of {@code SimpleAsyncTaskExecutor} is used.
*/ */
@ -119,7 +117,7 @@ public class StandardWebSocketClient extends AbstractWebSocketClient {
} }
/** /**
* Return the configured {@link TaskExecutor}. * Return the configured {@link AsyncTaskExecutor}.
*/ */
@Nullable @Nullable
public AsyncTaskExecutor getTaskExecutor() { public AsyncTaskExecutor getTaskExecutor() {

View File

@ -49,8 +49,6 @@ import org.springframework.messaging.tcp.TcpConnectionHandler;
import org.springframework.scheduling.TaskScheduler; import org.springframework.scheduling.TaskScheduler;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.MimeTypeUtils; import org.springframework.util.MimeTypeUtils;
import org.springframework.util.concurrent.CompletableToListenableFutureAdapter;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.web.socket.BinaryMessage; import org.springframework.web.socket.BinaryMessage;
import org.springframework.web.socket.CloseStatus; import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.TextMessage;
@ -210,12 +208,15 @@ public class WebSocketStompClient extends StompClientSupport implements SmartLif
* @param url the url to connect to * @param url the url to connect to
* @param handler the session handler * @param handler the session handler
* @param uriVars the URI variables to expand into the URL * @param uriVars the URI variables to expand into the URL
* @return a ListenableFuture for access to the session when ready for use * @return a {@code ListenableFuture} for access to the session when ready for use
* @deprecated as of 6.0, in favor of {@link #connectAsync(String, StompSessionHandler, Object...)} * @deprecated as of 6.0, in favor of {@link #connectAsync(String, StompSessionHandler, Object...)}
*/ */
@Deprecated @Deprecated
public ListenableFuture<StompSession> connect(String url, StompSessionHandler handler, Object... uriVars) { public org.springframework.util.concurrent.ListenableFuture<StompSession> connect(
return new CompletableToListenableFutureAdapter<>(connectAsync(url, handler, uriVars)); String url, StompSessionHandler handler, Object... uriVars) {
return new org.springframework.util.concurrent.CompletableToListenableFutureAdapter<>(
connectAsync(url, handler, uriVars));
} }
/** /**
@ -240,14 +241,15 @@ public class WebSocketStompClient extends StompClientSupport implements SmartLif
* @param handshakeHeaders the headers for the WebSocket handshake * @param handshakeHeaders the headers for the WebSocket handshake
* @param handler the session handler * @param handler the session handler
* @param uriVariables the URI variables to expand into the URL * @param uriVariables the URI variables to expand into the URL
* @return a ListenableFuture for access to the session when ready for use * @return a {@code ListenableFuture} for access to the session when ready for use
* @deprecated as of 6.0, in favor of {@link #connectAsync(String, WebSocketHttpHeaders, StompSessionHandler, Object...)} * @deprecated as of 6.0, in favor of {@link #connectAsync(String, WebSocketHttpHeaders, StompSessionHandler, Object...)}
*/ */
@Deprecated @Deprecated
public ListenableFuture<StompSession> connect(String url, @Nullable WebSocketHttpHeaders handshakeHeaders, public org.springframework.util.concurrent.ListenableFuture<StompSession> connect(
String url, @Nullable WebSocketHttpHeaders handshakeHeaders,
StompSessionHandler handler, Object... uriVariables) { StompSessionHandler handler, Object... uriVariables) {
return new CompletableToListenableFutureAdapter<>( return new org.springframework.util.concurrent.CompletableToListenableFutureAdapter<>(
connectAsync(url, handshakeHeaders, null, handler, uriVariables)); connectAsync(url, handshakeHeaders, null, handler, uriVariables));
} }
@ -259,7 +261,7 @@ public class WebSocketStompClient extends StompClientSupport implements SmartLif
* @param handshakeHeaders the headers for the WebSocket handshake * @param handshakeHeaders the headers for the WebSocket handshake
* @param handler the session handler * @param handler the session handler
* @param uriVariables the URI variables to expand into the URL * @param uriVariables the URI variables to expand into the URL
* @return a ListenableFuture for access to the session when ready for use * @return a {@code ListenableFuture} for access to the session when ready for use
* @since 6.0 * @since 6.0
*/ */
public CompletableFuture<StompSession> connectAsync(String url, @Nullable WebSocketHttpHeaders handshakeHeaders, public CompletableFuture<StompSession> connectAsync(String url, @Nullable WebSocketHttpHeaders handshakeHeaders,
@ -278,14 +280,15 @@ public class WebSocketStompClient extends StompClientSupport implements SmartLif
* @param connectHeaders headers for the STOMP CONNECT frame * @param connectHeaders headers for the STOMP CONNECT frame
* @param handler the session handler * @param handler the session handler
* @param uriVariables the URI variables to expand into the URL * @param uriVariables the URI variables to expand into the URL
* @return a ListenableFuture for access to the session when ready for use * @return a {@code ListenableFuture} for access to the session when ready for use
* @deprecated as of 6.0, in favor of {@link #connectAsync(String, WebSocketHttpHeaders, StompHeaders, StompSessionHandler, Object...)} * @deprecated as of 6.0, in favor of {@link #connectAsync(String, WebSocketHttpHeaders, StompHeaders, StompSessionHandler, Object...)}
*/ */
@Deprecated @Deprecated
public ListenableFuture<StompSession> connect(String url, @Nullable WebSocketHttpHeaders handshakeHeaders, public org.springframework.util.concurrent.ListenableFuture<StompSession> connect(
String url, @Nullable WebSocketHttpHeaders handshakeHeaders,
@Nullable StompHeaders connectHeaders, StompSessionHandler handler, Object... uriVariables) { @Nullable StompHeaders connectHeaders, StompSessionHandler handler, Object... uriVariables) {
return new CompletableToListenableFutureAdapter<>( return new org.springframework.util.concurrent.CompletableToListenableFutureAdapter<>(
connectAsync(url, handshakeHeaders, connectHeaders, handler, uriVariables)); connectAsync(url, handshakeHeaders, connectHeaders, handler, uriVariables));
} }
@ -318,14 +321,15 @@ public class WebSocketStompClient extends StompClientSupport implements SmartLif
* @param handshakeHeaders the headers for the WebSocket handshake * @param handshakeHeaders the headers for the WebSocket handshake
* @param connectHeaders headers for the STOMP CONNECT frame * @param connectHeaders headers for the STOMP CONNECT frame
* @param sessionHandler the STOMP session handler * @param sessionHandler the STOMP session handler
* @return a ListenableFuture for access to the session when ready for use * @return a {@code ListenableFuture} for access to the session when ready for use
* @deprecated as of 6.0, in favor of {@link #connectAsync(URI, WebSocketHttpHeaders, StompHeaders, StompSessionHandler)} * @deprecated as of 6.0, in favor of {@link #connectAsync(URI, WebSocketHttpHeaders, StompHeaders, StompSessionHandler)}
*/ */
@Deprecated @Deprecated
public ListenableFuture<StompSession> connect(URI url, @Nullable WebSocketHttpHeaders handshakeHeaders, public org.springframework.util.concurrent.ListenableFuture<StompSession> connect(
URI url, @Nullable WebSocketHttpHeaders handshakeHeaders,
@Nullable StompHeaders connectHeaders, StompSessionHandler sessionHandler) { @Nullable StompHeaders connectHeaders, StompSessionHandler sessionHandler) {
return new CompletableToListenableFutureAdapter<>( return new org.springframework.util.concurrent.CompletableToListenableFutureAdapter<>(
connectAsync(url, handshakeHeaders, connectHeaders, sessionHandler)); connectAsync(url, handshakeHeaders, connectHeaders, sessionHandler));
} }

View File

@ -29,7 +29,6 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.concurrent.SettableListenableFuture;
import org.springframework.web.socket.CloseStatus; import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.WebSocketHandler;
@ -40,9 +39,11 @@ import org.springframework.web.socket.sockjs.frame.SockJsMessageCodec;
/** /**
* Base class for SockJS client implementations of {@link WebSocketSession}. * Base class for SockJS client implementations of {@link WebSocketSession}.
* Provides processing of incoming SockJS message frames and delegates lifecycle *
* <p>Provides processing of incoming SockJS message frames and delegates lifecycle
* events and messages to the (application) {@link WebSocketHandler}. * events and messages to the (application) {@link WebSocketHandler}.
* Sub-classes implement actual send as well as disconnect logic. *
* <p>Subclasses implement actual send as well as disconnect logic.
* *
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
* @author Juergen Hoeller * @author Juergen Hoeller
@ -72,7 +73,7 @@ public abstract class AbstractClientSockJsSession implements WebSocketSession {
*/ */
@Deprecated @Deprecated
protected AbstractClientSockJsSession(TransportRequest request, WebSocketHandler handler, protected AbstractClientSockJsSession(TransportRequest request, WebSocketHandler handler,
SettableListenableFuture<WebSocketSession> connectFuture) { org.springframework.util.concurrent.SettableListenableFuture<WebSocketSession> connectFuture) {
this(request, handler, connectFuture.completable()); this(request, handler, connectFuture.completable());
} }

View File

@ -29,7 +29,6 @@ import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.util.concurrent.SettableListenableFuture;
import org.springframework.web.client.HttpServerErrorException; import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.WebSocketHandler;
@ -112,7 +111,7 @@ public abstract class AbstractXhrTransport implements XhrTransport {
@Deprecated @Deprecated
protected void connectInternal(TransportRequest request, WebSocketHandler handler, protected void connectInternal(TransportRequest request, WebSocketHandler handler,
URI receiveUrl, HttpHeaders handshakeHeaders, XhrClientSockJsSession session, URI receiveUrl, HttpHeaders handshakeHeaders, XhrClientSockJsSession session,
SettableListenableFuture<WebSocketSession> connectFuture) { org.springframework.util.concurrent.SettableListenableFuture<WebSocketSession> connectFuture) {
throw new UnsupportedOperationException("connectInternal has been deprecated in favor of connectInternal"); throw new UnsupportedOperationException("connectInternal has been deprecated in favor of connectInternal");
} }

View File

@ -33,8 +33,6 @@ import org.springframework.http.HttpHeaders;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.scheduling.TaskScheduler; import org.springframework.scheduling.TaskScheduler;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.concurrent.ListenableFutureCallback;
import org.springframework.util.concurrent.SettableListenableFuture;
import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.sockjs.SockJsTransportFailureException; import org.springframework.web.socket.sockjs.SockJsTransportFailureException;
@ -149,7 +147,9 @@ class DefaultTransportRequest implements TransportRequest {
@Deprecated @Deprecated
public void connect(WebSocketHandler handler, SettableListenableFuture<WebSocketSession> future) { public void connect(WebSocketHandler handler,
org.springframework.util.concurrent.SettableListenableFuture<WebSocketSession> future) {
if (logger.isTraceEnabled()) { if (logger.isTraceEnabled()) {
logger.trace("Starting " + this); logger.trace("Starting " + this);
} }
@ -208,15 +208,17 @@ class DefaultTransportRequest implements TransportRequest {
* callback. * callback.
*/ */
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
private class ListenableConnectCallback implements ListenableFutureCallback<WebSocketSession>, Runnable { private class ListenableConnectCallback implements
org.springframework.util.concurrent.ListenableFutureCallback<WebSocketSession>, Runnable {
private final WebSocketHandler handler; private final WebSocketHandler handler;
private final SettableListenableFuture<WebSocketSession> future; private final org.springframework.util.concurrent.SettableListenableFuture<WebSocketSession> future;
private final AtomicBoolean handled = new AtomicBoolean(); private final AtomicBoolean handled = new AtomicBoolean();
public ListenableConnectCallback(WebSocketHandler handler, SettableListenableFuture<WebSocketSession> future) { public ListenableConnectCallback(WebSocketHandler handler,
org.springframework.util.concurrent.SettableListenableFuture<WebSocketSession> future) {
this.handler = handler; this.handler = handler;
this.future = future; this.future = future;
} }

View File

@ -19,8 +19,6 @@ package org.springframework.web.socket.sockjs.client;
import java.util.List; import java.util.List;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import org.springframework.util.concurrent.CompletableToListenableFutureAdapter;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.sockjs.transport.TransportType; import org.springframework.web.socket.sockjs.transport.TransportType;
@ -34,29 +32,31 @@ import org.springframework.web.socket.sockjs.transport.TransportType;
public interface Transport { public interface Transport {
/** /**
* Return the SockJS transport types that this transport can be used for. * Get the SockJS transport types that this transport can be used for.
* In particular since from a client perspective there is no difference * <p>In particular since from a client perspective there is no difference
* between XHR and XHR streaming, an {@code XhrTransport} could do both. * between XHR and XHR streaming, an {@code XhrTransport} could do both.
*/ */
List<TransportType> getTransportTypes(); List<TransportType> getTransportTypes();
/** /**
* Connect the transport. * Connect the transport.
* @param request the transport request. * @param request the transport request
* @param webSocketHandler the application handler to delegate lifecycle events to. * @param webSocketHandler the application handler to delegate lifecycle events to
* @return a future to indicate success or failure to connect. * @return a future to indicate success or failure to connect
* @deprecated as of 6.0, in favor of {@link #connectAsync(TransportRequest, WebSocketHandler)} * @deprecated as of 6.0, in favor of {@link #connectAsync(TransportRequest, WebSocketHandler)}
*/ */
@Deprecated @Deprecated
default ListenableFuture<WebSocketSession> connect(TransportRequest request, WebSocketHandler webSocketHandler) { default org.springframework.util.concurrent.ListenableFuture<WebSocketSession> connect(
return new CompletableToListenableFutureAdapter<>(connectAsync(request, webSocketHandler)); TransportRequest request, WebSocketHandler webSocketHandler) {
return new org.springframework.util.concurrent.CompletableToListenableFutureAdapter<>(
connectAsync(request, webSocketHandler));
} }
/** /**
* Connect the transport. * Connect the transport.
* @param request the transport request. * @param request the transport request
* @param webSocketHandler the application handler to delegate lifecycle events to. * @param webSocketHandler the application handler to delegate lifecycle events to
* @return a future to indicate success or failure to connect. * @return a future to indicate success or failure to connect
* @since 6.0 * @since 6.0
*/ */
CompletableFuture<WebSocketSession> connectAsync(TransportRequest request, WebSocketHandler webSocketHandler); CompletableFuture<WebSocketSession> connectAsync(TransportRequest request, WebSocketHandler webSocketHandler);

View File

@ -23,7 +23,6 @@ import java.util.concurrent.CompletableFuture;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.concurrent.SettableListenableFuture;
import org.springframework.web.socket.CloseStatus; import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketExtension; import org.springframework.web.socket.WebSocketExtension;
@ -49,7 +48,7 @@ public class WebSocketClientSockJsSession extends AbstractClientSockJsSession im
*/ */
@Deprecated @Deprecated
public WebSocketClientSockJsSession(TransportRequest request, WebSocketHandler handler, public WebSocketClientSockJsSession(TransportRequest request, WebSocketHandler handler,
SettableListenableFuture<WebSocketSession> connectFuture) { org.springframework.util.concurrent.SettableListenableFuture<WebSocketSession> connectFuture) {
super(request, handler, connectFuture); super(request, handler, connectFuture);
} }

View File

@ -25,7 +25,6 @@ import java.util.concurrent.CompletableFuture;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.concurrent.SettableListenableFuture;
import org.springframework.web.socket.CloseStatus; import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketExtension; import org.springframework.web.socket.WebSocketExtension;
@ -56,11 +55,13 @@ public class XhrClientSockJsSession extends AbstractClientSockJsSession {
/** /**
* Create a new {@code XhrClientSockJsSession}. * Create a new {@code XhrClientSockJsSession}.
* @deprecated as of 6.0, in favor of {@link #XhrClientSockJsSession(TransportRequest, WebSocketHandler, XhrTransport, CompletableFuture)} * @deprecated as of 6.0, in favor of
* {@link #XhrClientSockJsSession(TransportRequest, WebSocketHandler, XhrTransport, CompletableFuture)}
*/ */
@Deprecated @Deprecated
public XhrClientSockJsSession(TransportRequest request, WebSocketHandler handler, public XhrClientSockJsSession(
XhrTransport transport, SettableListenableFuture<WebSocketSession> connectFuture) { TransportRequest request, WebSocketHandler handler, XhrTransport transport,
org.springframework.util.concurrent.SettableListenableFuture<WebSocketSession> connectFuture) {
super(request, handler, connectFuture); super(request, handler, connectFuture);
Assert.notNull(transport, "XhrTransport is required"); Assert.notNull(transport, "XhrTransport is required");
@ -72,6 +73,10 @@ public class XhrClientSockJsSession extends AbstractClientSockJsSession {
this.sendUrl = request.getSockJsUrlInfo().getTransportUrl(TransportType.XHR_SEND); this.sendUrl = request.getSockJsUrlInfo().getTransportUrl(TransportType.XHR_SEND);
} }
/**
* Create a new {@code XhrClientSockJsSession}.
* @since 6.0
*/
public XhrClientSockJsSession(TransportRequest request, WebSocketHandler handler, public XhrClientSockJsSession(TransportRequest request, WebSocketHandler handler,
XhrTransport transport, CompletableFuture<WebSocketSession> connectFuture) { XhrTransport transport, CompletableFuture<WebSocketSession> connectFuture) {

View File

@ -166,7 +166,7 @@ public abstract class AbstractWebSocketIntegrationTests {
} }
@Configuration @Configuration(proxyBeanMethods = false)
static class JettyUpgradeStrategyConfig extends AbstractRequestUpgradeStrategyConfig { static class JettyUpgradeStrategyConfig extends AbstractRequestUpgradeStrategyConfig {
@Override @Override
@ -177,7 +177,7 @@ public abstract class AbstractWebSocketIntegrationTests {
} }
@Configuration @Configuration(proxyBeanMethods = false)
static class TomcatUpgradeStrategyConfig extends AbstractRequestUpgradeStrategyConfig { static class TomcatUpgradeStrategyConfig extends AbstractRequestUpgradeStrategyConfig {
@Override @Override
@ -188,7 +188,7 @@ public abstract class AbstractWebSocketIntegrationTests {
} }
@Configuration @Configuration(proxyBeanMethods = false)
static class UndertowUpgradeStrategyConfig extends AbstractRequestUpgradeStrategyConfig { static class UndertowUpgradeStrategyConfig extends AbstractRequestUpgradeStrategyConfig {
@Override @Override

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed 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.
@ -53,6 +53,7 @@ class WebSocketHandshakeTests extends AbstractWebSocketIntegrationTests {
@ParameterizedWebSocketTest @ParameterizedWebSocketTest
@SuppressWarnings("deprecation")
void subProtocolNegotiation(WebSocketTestServer server, WebSocketClient webSocketClient, TestInfo testInfo) throws Exception { void subProtocolNegotiation(WebSocketTestServer server, WebSocketClient webSocketClient, TestInfo testInfo) throws Exception {
super.setup(server, webSocketClient, testInfo); super.setup(server, webSocketClient, testInfo);
@ -65,6 +66,7 @@ class WebSocketHandshakeTests extends AbstractWebSocketIntegrationTests {
} }
@ParameterizedWebSocketTest // SPR-12727 @ParameterizedWebSocketTest // SPR-12727
@SuppressWarnings("deprecation")
void unsolicitedPongWithEmptyPayload(WebSocketTestServer server, WebSocketClient webSocketClient, TestInfo testInfo) throws Exception { void unsolicitedPongWithEmptyPayload(WebSocketTestServer server, WebSocketClient webSocketClient, TestInfo testInfo) throws Exception {
super.setup(server, webSocketClient, testInfo); super.setup(server, webSocketClient, testInfo);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed 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.
@ -68,6 +68,7 @@ public class StandardWebSocketClientTests {
@Test @Test
@SuppressWarnings("deprecation")
public void testGetLocalAddress() throws Exception { public void testGetLocalAddress() throws Exception {
URI uri = new URI("ws://localhost/abc"); URI uri = new URI("ws://localhost/abc");
WebSocketSession session = this.wsClient.doHandshake(this.wsHandler, this.headers, uri).get(); WebSocketSession session = this.wsClient.doHandshake(this.wsHandler, this.headers, uri).get();
@ -77,6 +78,7 @@ public class StandardWebSocketClientTests {
} }
@Test @Test
@SuppressWarnings("deprecation")
public void testGetLocalAddressWss() throws Exception { public void testGetLocalAddressWss() throws Exception {
URI uri = new URI("wss://localhost/abc"); URI uri = new URI("wss://localhost/abc");
WebSocketSession session = this.wsClient.doHandshake(this.wsHandler, this.headers, uri).get(); WebSocketSession session = this.wsClient.doHandshake(this.wsHandler, this.headers, uri).get();
@ -86,6 +88,7 @@ public class StandardWebSocketClientTests {
} }
@Test @Test
@SuppressWarnings("deprecation")
public void testGetLocalAddressNoScheme() throws Exception { public void testGetLocalAddressNoScheme() throws Exception {
URI uri = new URI("localhost/abc"); URI uri = new URI("localhost/abc");
assertThatIllegalArgumentException().isThrownBy(() -> assertThatIllegalArgumentException().isThrownBy(() ->
@ -93,6 +96,7 @@ public class StandardWebSocketClientTests {
} }
@Test @Test
@SuppressWarnings("deprecation")
public void testGetRemoteAddress() throws Exception { public void testGetRemoteAddress() throws Exception {
URI uri = new URI("wss://localhost/abc"); URI uri = new URI("wss://localhost/abc");
WebSocketSession session = this.wsClient.doHandshake(this.wsHandler, this.headers, uri).get(); WebSocketSession session = this.wsClient.doHandshake(this.wsHandler, this.headers, uri).get();
@ -103,8 +107,8 @@ public class StandardWebSocketClientTests {
} }
@Test @Test
@SuppressWarnings("deprecation")
public void handshakeHeaders() throws Exception { public void handshakeHeaders() throws Exception {
URI uri = new URI("ws://localhost/abc"); URI uri = new URI("ws://localhost/abc");
List<String> protocols = Collections.singletonList("abc"); List<String> protocols = Collections.singletonList("abc");
this.headers.setSecWebSocketProtocol(protocols); this.headers.setSecWebSocketProtocol(protocols);
@ -117,8 +121,8 @@ public class StandardWebSocketClientTests {
} }
@Test @Test
@SuppressWarnings("deprecation")
public void clientEndpointConfig() throws Exception { public void clientEndpointConfig() throws Exception {
URI uri = new URI("ws://localhost/abc"); URI uri = new URI("ws://localhost/abc");
List<String> protocols = Collections.singletonList("abc"); List<String> protocols = Collections.singletonList("abc");
this.headers.setSecWebSocketProtocol(protocols); this.headers.setSecWebSocketProtocol(protocols);
@ -133,8 +137,8 @@ public class StandardWebSocketClientTests {
} }
@Test @Test
@SuppressWarnings("deprecation")
public void clientEndpointConfigWithUserProperties() throws Exception { public void clientEndpointConfigWithUserProperties() throws Exception {
Map<String,Object> userProperties = Collections.singletonMap("foo", "bar"); Map<String,Object> userProperties = Collections.singletonMap("foo", "bar");
URI uri = new URI("ws://localhost/abc"); URI uri = new URI("ws://localhost/abc");
@ -149,8 +153,8 @@ public class StandardWebSocketClientTests {
} }
@Test @Test
@SuppressWarnings("deprecation")
public void standardWebSocketClientConfiguratorInsertsHandshakeHeaders() throws Exception { public void standardWebSocketClientConfiguratorInsertsHandshakeHeaders() throws Exception {
URI uri = new URI("ws://localhost/abc"); URI uri = new URI("ws://localhost/abc");
this.headers.add("foo", "bar"); this.headers.add("foo", "bar");
@ -166,8 +170,8 @@ public class StandardWebSocketClientTests {
} }
@Test @Test
@SuppressWarnings("deprecation")
public void taskExecutor() throws Exception { public void taskExecutor() throws Exception {
URI uri = new URI("ws://localhost/abc"); URI uri = new URI("ws://localhost/abc");
this.wsClient.setTaskExecutor(new SimpleAsyncTaskExecutor()); this.wsClient.setTaskExecutor(new SimpleAsyncTaskExecutor());
WebSocketSession session = this.wsClient.doHandshake(this.wsHandler, this.headers, uri).get(); WebSocketSession session = this.wsClient.doHandshake(this.wsHandler, this.headers, uri).get();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed 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.
@ -49,6 +49,7 @@ class WebSocketConfigurationTests extends AbstractWebSocketIntegrationTests {
@ParameterizedWebSocketTest @ParameterizedWebSocketTest
@SuppressWarnings("deprecation")
void registerWebSocketHandler(WebSocketTestServer server, WebSocketClient webSocketClient, TestInfo testInfo) throws Exception { void registerWebSocketHandler(WebSocketTestServer server, WebSocketClient webSocketClient, TestInfo testInfo) throws Exception {
super.setup(server, webSocketClient, testInfo); super.setup(server, webSocketClient, testInfo);
@ -62,6 +63,7 @@ class WebSocketConfigurationTests extends AbstractWebSocketIntegrationTests {
} }
@ParameterizedWebSocketTest @ParameterizedWebSocketTest
@SuppressWarnings("deprecation")
void registerWebSocketHandlerWithSockJS(WebSocketTestServer server, WebSocketClient webSocketClient, TestInfo testInfo) throws Exception { void registerWebSocketHandlerWithSockJS(WebSocketTestServer server, WebSocketClient webSocketClient, TestInfo testInfo) throws Exception {
super.setup(server, webSocketClient, testInfo); super.setup(server, webSocketClient, testInfo);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed 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.
@ -109,8 +109,8 @@ class WebSocketStompClientIntegrationTests {
@Test @Test
@SuppressWarnings("deprecation")
void publishSubscribe() throws Exception { void publishSubscribe() throws Exception {
String url = "ws://127.0.0.1:" + this.server.getPort() + "/stomp"; String url = "ws://127.0.0.1:" + this.server.getPort() + "/stomp";
TestHandler testHandler = new TestHandler("/topic/foo", "payload"); TestHandler testHandler = new TestHandler("/topic/foo", "payload");
@ -121,7 +121,7 @@ class WebSocketStompClientIntegrationTests {
} }
@Configuration @Configuration(proxyBeanMethods = false)
static class TestConfig extends WebSocketMessageBrokerConfigurationSupport { static class TestConfig extends WebSocketMessageBrokerConfigurationSupport {
@Override @Override

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed 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.
@ -51,8 +51,6 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.core.testfixture.EnabledForTestGroups; import org.springframework.core.testfixture.EnabledForTestGroups;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.server.ServletServerHttpRequest; import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.util.concurrent.ListenableFutureCallback;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketHttpHeaders; import org.springframework.web.socket.WebSocketHttpHeaders;
@ -79,7 +77,7 @@ import static org.springframework.core.testfixture.TestGroup.LONG_RUNNING;
* @author Sam Brannen * @author Sam Brannen
*/ */
@EnabledForTestGroups(LONG_RUNNING) @EnabledForTestGroups(LONG_RUNNING)
public abstract class AbstractSockJsIntegrationTests { abstract class AbstractSockJsIntegrationTests {
protected Log logger = LogFactory.getLog(getClass()); protected Log logger = LogFactory.getLog(getClass());
@ -96,7 +94,7 @@ public abstract class AbstractSockJsIntegrationTests {
@BeforeEach @BeforeEach
public void setup(TestInfo testInfo) throws Exception { void setup(TestInfo testInfo) throws Exception {
logger.debug("Setting up '" + testInfo.getTestMethod().get().getName() + "'"); logger.debug("Setting up '" + testInfo.getTestMethod().get().getName() + "'");
this.testFilter = new TestFilter(); this.testFilter = new TestFilter();
@ -116,7 +114,7 @@ public abstract class AbstractSockJsIntegrationTests {
} }
@AfterEach @AfterEach
public void teardown() throws Exception { void teardown() throws Exception {
try { try {
this.sockJsClient.stop(); this.sockJsClient.stop();
} }
@ -157,17 +155,17 @@ public abstract class AbstractSockJsIntegrationTests {
} }
@Test @Test
public void echoWebSocket() throws Exception { void echoWebSocket() throws Exception {
testEcho(100, createWebSocketTransport(), null); testEcho(100, createWebSocketTransport(), null);
} }
@Test @Test
public void echoXhrStreaming() throws Exception { void echoXhrStreaming() throws Exception {
testEcho(100, createXhrTransport(), null); testEcho(100, createXhrTransport(), null);
} }
@Test @Test
public void echoXhr() throws Exception { void echoXhr() throws Exception {
AbstractXhrTransport xhrTransport = createXhrTransport(); AbstractXhrTransport xhrTransport = createXhrTransport();
xhrTransport.setXhrStreamingDisabled(true); xhrTransport.setXhrStreamingDisabled(true);
testEcho(100, xhrTransport, null); testEcho(100, xhrTransport, null);
@ -176,7 +174,7 @@ public abstract class AbstractSockJsIntegrationTests {
// SPR-13254 // SPR-13254
@Test @Test
public void echoXhrWithHeaders() throws Exception { void echoXhrWithHeaders() throws Exception {
AbstractXhrTransport xhrTransport = createXhrTransport(); AbstractXhrTransport xhrTransport = createXhrTransport();
xhrTransport.setXhrStreamingDisabled(true); xhrTransport.setXhrStreamingDisabled(true);
@ -191,30 +189,31 @@ public abstract class AbstractSockJsIntegrationTests {
} }
@Test @Test
public void receiveOneMessageWebSocket() throws Exception { void receiveOneMessageWebSocket() throws Exception {
testReceiveOneMessage(createWebSocketTransport(), null); testReceiveOneMessage(createWebSocketTransport(), null);
} }
@Test @Test
public void receiveOneMessageXhrStreaming() throws Exception { void receiveOneMessageXhrStreaming() throws Exception {
testReceiveOneMessage(createXhrTransport(), null); testReceiveOneMessage(createXhrTransport(), null);
} }
@Test @Test
public void receiveOneMessageXhr() throws Exception { void receiveOneMessageXhr() throws Exception {
AbstractXhrTransport xhrTransport = createXhrTransport(); AbstractXhrTransport xhrTransport = createXhrTransport();
xhrTransport.setXhrStreamingDisabled(true); xhrTransport.setXhrStreamingDisabled(true);
testReceiveOneMessage(xhrTransport, null); testReceiveOneMessage(xhrTransport, null);
} }
@Test @Test
public void infoRequestFailure() throws Exception { @SuppressWarnings("deprecation")
void infoRequestFailure() throws Exception {
TestClientHandler handler = new TestClientHandler(); TestClientHandler handler = new TestClientHandler();
this.testFilter.sendErrorMap.put("/info", 500); this.testFilter.sendErrorMap.put("/info", 500);
CountDownLatch latch = new CountDownLatch(1); CountDownLatch latch = new CountDownLatch(1);
initSockJsClient(createWebSocketTransport()); initSockJsClient(createWebSocketTransport());
this.sockJsClient.doHandshake(handler, this.baseUrl + "/echo").addCallback( this.sockJsClient.doHandshake(handler, this.baseUrl + "/echo").addCallback(
new ListenableFutureCallback<WebSocketSession>() { new org.springframework.util.concurrent.ListenableFutureCallback<WebSocketSession>() {
@Override @Override
public void onSuccess(WebSocketSession result) { public void onSuccess(WebSocketSession result) {
} }
@ -229,12 +228,12 @@ public abstract class AbstractSockJsIntegrationTests {
} }
@Test @Test
public void fallbackAfterTransportFailure() throws Exception { void fallbackAfterTransportFailure() throws Exception {
this.testFilter.sendErrorMap.put("/websocket", 200); this.testFilter.sendErrorMap.put("/websocket", 200);
this.testFilter.sendErrorMap.put("/xhr_streaming", 500); this.testFilter.sendErrorMap.put("/xhr_streaming", 500);
TestClientHandler handler = new TestClientHandler(); TestClientHandler handler = new TestClientHandler();
initSockJsClient(createWebSocketTransport(), createXhrTransport()); initSockJsClient(createWebSocketTransport(), createXhrTransport());
WebSocketSession session = this.sockJsClient.doHandshake(handler, this.baseUrl + "/echo").get(); WebSocketSession session = this.sockJsClient.execute(handler, this.baseUrl + "/echo").get();
assertThat(session.getClass()).as("Fallback didn't occur").isEqualTo(XhrClientSockJsSession.class); assertThat(session.getClass()).as("Fallback didn't occur").isEqualTo(XhrClientSockJsSession.class);
TextMessage message = new TextMessage("message1"); TextMessage message = new TextMessage("message1");
session.sendMessage(message); session.sendMessage(message);
@ -243,12 +242,13 @@ public abstract class AbstractSockJsIntegrationTests {
@Test @Test
@Timeout(5) @Timeout(5)
public void fallbackAfterConnectTimeout() throws Exception { @SuppressWarnings("deprecation")
void fallbackAfterConnectTimeout() throws Exception {
TestClientHandler clientHandler = new TestClientHandler(); TestClientHandler clientHandler = new TestClientHandler();
this.testFilter.sleepDelayMap.put("/xhr_streaming", 10000L); this.testFilter.sleepDelayMap.put("/xhr_streaming", 10000L);
this.testFilter.sendErrorMap.put("/xhr_streaming", 503); this.testFilter.sendErrorMap.put("/xhr_streaming", 503);
initSockJsClient(createXhrTransport()); initSockJsClient(createXhrTransport());
this.sockJsClient.setConnectTimeoutScheduler(this.wac.getBean(ThreadPoolTaskScheduler.class)); // this.sockJsClient.setConnectTimeoutScheduler(this.wac.getBean(ThreadPoolTaskScheduler.class));
WebSocketSession clientSession = sockJsClient.doHandshake(clientHandler, this.baseUrl + "/echo").get(); WebSocketSession clientSession = sockJsClient.doHandshake(clientHandler, this.baseUrl + "/echo").get();
assertThat(clientSession.getClass()).as("Fallback didn't occur").isEqualTo(XhrClientSockJsSession.class); assertThat(clientSession.getClass()).as("Fallback didn't occur").isEqualTo(XhrClientSockJsSession.class);
TextMessage message = new TextMessage("message1"); TextMessage message = new TextMessage("message1");
@ -258,6 +258,7 @@ public abstract class AbstractSockJsIntegrationTests {
} }
@SuppressWarnings("deprecation")
private void testEcho(int messageCount, Transport transport, WebSocketHttpHeaders headers) throws Exception { private void testEcho(int messageCount, Transport transport, WebSocketHttpHeaders headers) throws Exception {
List<TextMessage> messages = new ArrayList<>(); List<TextMessage> messages = new ArrayList<>();
for (int i = 0; i < messageCount; i++) { for (int i = 0; i < messageCount; i++) {
@ -278,6 +279,7 @@ public abstract class AbstractSockJsIntegrationTests {
session.close(); session.close();
} }
@SuppressWarnings("deprecation")
private void testReceiveOneMessage(Transport transport, WebSocketHttpHeaders headers) private void testReceiveOneMessage(Transport transport, WebSocketHttpHeaders headers)
throws Exception { throws Exception {
@ -311,7 +313,7 @@ public abstract class AbstractSockJsIntegrationTests {
} }
@Configuration @Configuration(proxyBeanMethods = false)
@EnableWebSocket @EnableWebSocket
static class TestConfig implements WebSocketConfigurer { static class TestConfig implements WebSocketConfigurer {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2015 the original author or authors. * Copyright 2002-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed 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.
@ -30,7 +30,7 @@ import org.springframework.web.socket.server.jetty.JettyRequestUpgradeStrategy;
* *
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
*/ */
public class JettySockJsIntegrationTests extends AbstractSockJsIntegrationTests { class JettySockJsIntegrationTests extends AbstractSockJsIntegrationTests {
@Override @Override
protected Class<?> upgradeStrategyConfigClass() { protected Class<?> upgradeStrategyConfigClass() {
@ -53,10 +53,10 @@ public class JettySockJsIntegrationTests extends AbstractSockJsIntegrationTests
} }
@Configuration @Configuration(proxyBeanMethods = false)
static class JettyTestConfig { static class JettyTestConfig {
@Bean @Bean
public RequestUpgradeStrategy upgradeStrategy() { RequestUpgradeStrategy upgradeStrategy() {
return new JettyRequestUpgradeStrategy(); return new JettyRequestUpgradeStrategy();
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed 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.
@ -40,8 +40,6 @@ import org.springframework.messaging.simp.stomp.StompCommand;
import org.springframework.messaging.simp.stomp.StompEncoder; import org.springframework.messaging.simp.stomp.StompEncoder;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor; import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.messaging.support.MessageBuilder; import org.springframework.messaging.support.MessageBuilder;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureCallback;
import org.springframework.web.client.HttpServerErrorException; import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.RequestCallback; import org.springframework.web.client.RequestCallback;
import org.springframework.web.client.ResponseExtractor; import org.springframework.web.client.ResponseExtractor;
@ -124,6 +122,7 @@ public class RestTemplateXhrTransportTests {
} }
@Test @Test
@SuppressWarnings("deprecation")
public void connectFailure() throws Exception { public void connectFailure() throws Exception {
final HttpServerErrorException expected = new HttpServerErrorException(HttpStatus.INTERNAL_SERVER_ERROR); final HttpServerErrorException expected = new HttpServerErrorException(HttpStatus.INTERNAL_SERVER_ERROR);
RestOperations restTemplate = mock(RestOperations.class); RestOperations restTemplate = mock(RestOperations.class);
@ -131,7 +130,7 @@ public class RestTemplateXhrTransportTests {
final CountDownLatch latch = new CountDownLatch(1); final CountDownLatch latch = new CountDownLatch(1);
connect(restTemplate).addCallback( connect(restTemplate).addCallback(
new ListenableFutureCallback<WebSocketSession>() { new org.springframework.util.concurrent.ListenableFutureCallback<WebSocketSession>() {
@Override @Override
public void onSuccess(WebSocketSession result) { public void onSuccess(WebSocketSession result) {
} }
@ -168,12 +167,15 @@ public class RestTemplateXhrTransportTests {
verify(response).close(); verify(response).close();
} }
private ListenableFuture<WebSocketSession> connect(ClientHttpResponse... responses) throws Exception { @SuppressWarnings("deprecation")
private org.springframework.util.concurrent.ListenableFuture<WebSocketSession> connect(
ClientHttpResponse... responses) throws Exception {
return connect(new TestRestTemplate(responses)); return connect(new TestRestTemplate(responses));
} }
private ListenableFuture<WebSocketSession> connect(RestOperations restTemplate, ClientHttpResponse... responses) @SuppressWarnings("deprecation")
throws Exception { private org.springframework.util.concurrent.ListenableFuture<WebSocketSession> connect(
RestOperations restTemplate, ClientHttpResponse... responses) throws Exception {
RestTemplateXhrTransport transport = new RestTemplateXhrTransport(restTemplate); RestTemplateXhrTransport transport = new RestTemplateXhrTransport(restTemplate);
transport.setTaskExecutor(new SyncTaskExecutor()); transport.setTaskExecutor(new SyncTaskExecutor());
@ -201,7 +203,6 @@ public class RestTemplateXhrTransportTests {
} }
private static class TestRestTemplate extends RestTemplate { private static class TestRestTemplate extends RestTemplate {
private Queue<ClientHttpResponse> responses = new LinkedBlockingDeque<>(); private Queue<ClientHttpResponse> responses = new LinkedBlockingDeque<>();
@ -225,5 +226,4 @@ public class RestTemplateXhrTransportTests {
} }
} }
} }

View File

@ -18,7 +18,6 @@ package org.springframework.web.socket.sockjs.client;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
@ -27,7 +26,6 @@ import org.mockito.ArgumentCaptor;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.util.concurrent.ListenableFutureCallback;
import org.springframework.web.client.HttpServerErrorException; import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketHttpHeaders; import org.springframework.web.socket.WebSocketHttpHeaders;
@ -43,46 +41,38 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions;
/** /**
* Unit tests for {@link org.springframework.web.socket.sockjs.client.SockJsClient}. * Unit tests for {@link SockJsClient}.
* *
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
*/ */
public class SockJsClientTests { class SockJsClientTests {
private static final String URL = "https://example.com"; private static final String URL = "https://example.com";
private static final WebSocketHandler handler = mock(WebSocketHandler.class); private static final WebSocketHandler handler = mock(WebSocketHandler.class);
private SockJsClient sockJsClient; private final InfoReceiver infoReceiver = mock(InfoReceiver.class);
private InfoReceiver infoReceiver; private final TestTransport webSocketTransport = new TestTransport("WebSocketTestTransport");
private TestTransport webSocketTransport; private final XhrTestTransport xhrTransport = new XhrTestTransport("XhrTestTransport");
private XhrTestTransport xhrTransport; @SuppressWarnings({ "deprecation", "unchecked" })
private org.springframework.util.concurrent.ListenableFutureCallback<WebSocketSession> connectCallback =
mock(org.springframework.util.concurrent.ListenableFutureCallback.class);
private ListenableFutureCallback<WebSocketSession> connectCallback; private SockJsClient sockJsClient = new SockJsClient(List.of(this.webSocketTransport, this.xhrTransport));
@BeforeEach @BeforeEach
@SuppressWarnings("unchecked") void setup() {
public void setup() {
this.infoReceiver = mock(InfoReceiver.class);
this.webSocketTransport = new TestTransport("WebSocketTestTransport");
this.xhrTransport = new XhrTestTransport("XhrTestTransport");
List<Transport> transports = new ArrayList<>();
transports.add(this.webSocketTransport);
transports.add(this.xhrTransport);
this.sockJsClient = new SockJsClient(transports);
this.sockJsClient.setInfoReceiver(this.infoReceiver); this.sockJsClient.setInfoReceiver(this.infoReceiver);
this.connectCallback = mock(ListenableFutureCallback.class);
} }
@Test @Test
public void connectWebSocket() throws Exception { @SuppressWarnings("deprecation")
void connectWebSocket() throws Exception {
setupInfoRequest(true); setupInfoRequest(true);
this.sockJsClient.doHandshake(handler, URL).addCallback(this.connectCallback); this.sockJsClient.doHandshake(handler, URL).addCallback(this.connectCallback);
assertThat(this.webSocketTransport.invoked()).isTrue(); assertThat(this.webSocketTransport.invoked()).isTrue();
@ -93,7 +83,8 @@ public class SockJsClientTests {
} }
@Test @Test
public void connectWebSocketDisabled() throws URISyntaxException { @SuppressWarnings("deprecation")
void connectWebSocketDisabled() throws URISyntaxException {
setupInfoRequest(false); setupInfoRequest(false);
this.sockJsClient.doHandshake(handler, URL); this.sockJsClient.doHandshake(handler, URL);
assertThat(this.webSocketTransport.invoked()).isFalse(); assertThat(this.webSocketTransport.invoked()).isFalse();
@ -102,7 +93,8 @@ public class SockJsClientTests {
} }
@Test @Test
public void connectXhrStreamingDisabled() throws Exception { @SuppressWarnings("deprecation")
void connectXhrStreamingDisabled() throws Exception {
setupInfoRequest(false); setupInfoRequest(false);
this.xhrTransport.setStreamingDisabled(true); this.xhrTransport.setStreamingDisabled(true);
this.sockJsClient.doHandshake(handler, URL).addCallback(this.connectCallback); this.sockJsClient.doHandshake(handler, URL).addCallback(this.connectCallback);
@ -111,10 +103,9 @@ public class SockJsClientTests {
assertThat(this.xhrTransport.getRequest().getTransportUrl().toString().endsWith("xhr")).isTrue(); assertThat(this.xhrTransport.getRequest().getTransportUrl().toString().endsWith("xhr")).isTrue();
} }
// SPR-13254 @Test // SPR-13254
@SuppressWarnings("deprecation")
@Test void connectWithHandshakeHeaders() throws Exception {
public void connectWithHandshakeHeaders() throws Exception {
ArgumentCaptor<HttpHeaders> headersCaptor = setupInfoRequest(false); ArgumentCaptor<HttpHeaders> headersCaptor = setupInfoRequest(false);
this.xhrTransport.setStreamingDisabled(true); this.xhrTransport.setStreamingDisabled(true);
@ -135,7 +126,8 @@ public class SockJsClientTests {
} }
@Test @Test
public void connectAndUseSubsetOfHandshakeHeadersForHttpRequests() throws Exception { @SuppressWarnings("deprecation")
void connectAndUseSubsetOfHandshakeHeadersForHttpRequests() throws Exception {
ArgumentCaptor<HttpHeaders> headersCaptor = setupInfoRequest(false); ArgumentCaptor<HttpHeaders> headersCaptor = setupInfoRequest(false);
this.xhrTransport.setStreamingDisabled(true); this.xhrTransport.setStreamingDisabled(true);
@ -152,14 +144,16 @@ public class SockJsClientTests {
} }
@Test @Test
public void connectSockJsInfo() throws Exception { @SuppressWarnings("deprecation")
void connectSockJsInfo() throws Exception {
setupInfoRequest(true); setupInfoRequest(true);
this.sockJsClient.doHandshake(handler, URL); this.sockJsClient.doHandshake(handler, URL);
verify(this.infoReceiver, times(1)).executeInfoRequest(any(), any()); verify(this.infoReceiver, times(1)).executeInfoRequest(any(), any());
} }
@Test @Test
public void connectSockJsInfoCached() throws Exception { @SuppressWarnings("deprecation")
void connectSockJsInfoCached() throws Exception {
setupInfoRequest(true); setupInfoRequest(true);
this.sockJsClient.doHandshake(handler, URL); this.sockJsClient.doHandshake(handler, URL);
this.sockJsClient.doHandshake(handler, URL); this.sockJsClient.doHandshake(handler, URL);
@ -168,7 +162,8 @@ public class SockJsClientTests {
} }
@Test @Test
public void connectInfoRequestFailure() throws URISyntaxException { @SuppressWarnings("deprecation")
void connectInfoRequestFailure() throws URISyntaxException {
HttpServerErrorException exception = new HttpServerErrorException(HttpStatus.SERVICE_UNAVAILABLE); HttpServerErrorException exception = new HttpServerErrorException(HttpStatus.SERVICE_UNAVAILABLE);
given(this.infoReceiver.executeInfoRequest(any(), any())).willThrow(exception); given(this.infoReceiver.executeInfoRequest(any(), any())).willThrow(exception);
this.sockJsClient.doHandshake(handler, URL).addCallback(this.connectCallback); this.sockJsClient.doHandshake(handler, URL).addCallback(this.connectCallback);
@ -178,12 +173,15 @@ public class SockJsClientTests {
} }
private ArgumentCaptor<HttpHeaders> setupInfoRequest(boolean webSocketEnabled) { private ArgumentCaptor<HttpHeaders> setupInfoRequest(boolean webSocketEnabled) {
String response = """
{
"entropy": 123,
"origins": ["*:*"],
"cookie_needed": true,
"websocket": %s
}""".formatted(webSocketEnabled).replace('\n', '\0');
ArgumentCaptor<HttpHeaders> headersCaptor = ArgumentCaptor.forClass(HttpHeaders.class); ArgumentCaptor<HttpHeaders> headersCaptor = ArgumentCaptor.forClass(HttpHeaders.class);
given(this.infoReceiver.executeInfoRequest(any(), headersCaptor.capture())).willReturn( given(this.infoReceiver.executeInfoRequest(any(), headersCaptor.capture())).willReturn(response);
"{\"entropy\":123," +
"\"origins\":[\"*:*\"]," +
"\"cookie_needed\":true," +
"\"websocket\":" + webSocketEnabled + "}");
return headersCaptor; return headersCaptor;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed 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.
@ -29,7 +29,7 @@ import org.springframework.web.socket.server.standard.UndertowRequestUpgradeStra
/** /**
* @author Brian Clozel * @author Brian Clozel
*/ */
public class UndertowSockJsIntegrationTests extends AbstractSockJsIntegrationTests { class UndertowSockJsIntegrationTests extends AbstractSockJsIntegrationTests {
@Override @Override
protected Class<?> upgradeStrategyConfigClass() { protected Class<?> upgradeStrategyConfigClass() {
@ -56,11 +56,13 @@ public class UndertowSockJsIntegrationTests extends AbstractSockJsIntegrationTes
} }
} }
@Configuration
@Configuration(proxyBeanMethods = false)
static class UndertowTestConfig { static class UndertowTestConfig {
@Bean @Bean
public RequestUpgradeStrategy upgradeStrategy() { RequestUpgradeStrategy upgradeStrategy() {
return new UndertowRequestUpgradeStrategy(); return new UndertowRequestUpgradeStrategy();
} }
} }
} }

View File

@ -39,22 +39,21 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions;
/** /**
* Unit tests for * Unit tests for {@link AbstractXhrTransport}.
* {@link org.springframework.web.socket.sockjs.client.AbstractXhrTransport}.
* *
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
*/ */
public class XhrTransportTests { class XhrTransportTests {
@Test @Test
public void infoResponse() throws Exception { void infoResponse() throws Exception {
TestXhrTransport transport = new TestXhrTransport(); TestXhrTransport transport = new TestXhrTransport();
transport.infoResponseToReturn = new ResponseEntity<>("body", HttpStatus.OK); transport.infoResponseToReturn = new ResponseEntity<>("body", HttpStatus.OK);
assertThat(transport.executeInfoRequest(new URI("https://example.com/info"), null)).isEqualTo("body"); assertThat(transport.executeInfoRequest(new URI("https://example.com/info"), null)).isEqualTo("body");
} }
@Test @Test
public void infoResponseError() throws Exception { void infoResponseError() throws Exception {
TestXhrTransport transport = new TestXhrTransport(); TestXhrTransport transport = new TestXhrTransport();
transport.infoResponseToReturn = new ResponseEntity<>("body", HttpStatus.BAD_REQUEST); transport.infoResponseToReturn = new ResponseEntity<>("body", HttpStatus.BAD_REQUEST);
assertThatExceptionOfType(HttpServerErrorException.class).isThrownBy(() -> assertThatExceptionOfType(HttpServerErrorException.class).isThrownBy(() ->
@ -62,7 +61,7 @@ public class XhrTransportTests {
} }
@Test @Test
public void sendMessage() throws Exception { void sendMessage() throws Exception {
HttpHeaders requestHeaders = new HttpHeaders(); HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.set("foo", "bar"); requestHeaders.set("foo", "bar");
requestHeaders.setContentType(MediaType.APPLICATION_JSON); requestHeaders.setContentType(MediaType.APPLICATION_JSON);
@ -76,7 +75,7 @@ public class XhrTransportTests {
} }
@Test @Test
public void sendMessageError() throws Exception { void sendMessageError() throws Exception {
TestXhrTransport transport = new TestXhrTransport(); TestXhrTransport transport = new TestXhrTransport();
transport.sendMessageResponseToReturn = new ResponseEntity<>(HttpStatus.BAD_REQUEST); transport.sendMessageResponseToReturn = new ResponseEntity<>(HttpStatus.BAD_REQUEST);
URI url = new URI("https://example.com"); URI url = new URI("https://example.com");
@ -85,7 +84,8 @@ public class XhrTransportTests {
} }
@Test @Test
public void connect() throws Exception { @SuppressWarnings("deprecation")
void connect() throws Exception {
HttpHeaders handshakeHeaders = new HttpHeaders(); HttpHeaders handshakeHeaders = new HttpHeaders();
handshakeHeaders.setOrigin("foo"); handshakeHeaders.setOrigin("foo");