Remove APIs marked as deprecated for removal

Closes gh-33809
This commit is contained in:
Juergen Hoeller 2024-12-04 13:19:39 +01:00
parent 078d683f47
commit 2b9010c2a2
150 changed files with 141 additions and 5922 deletions

View File

@ -647,13 +647,12 @@ For https://www.webjars.org/documentation[WebJars], versioned URLs like
`/webjars/jquery/1.2.0/jquery.min.js` are the recommended and most efficient way to use them. `/webjars/jquery/1.2.0/jquery.min.js` are the recommended and most efficient way to use them.
The related resource location is configured out of the box with Spring Boot (or can be configured The related resource location is configured out of the box with Spring Boot (or can be configured
manually via `ResourceHandlerRegistry`) and does not require to add the manually via `ResourceHandlerRegistry`) and does not require to add the
`org.webjars:webjars-locator-core` dependency. `org.webjars:webjars-locator-lite` dependency.
Version-less URLs like `/webjars/jquery/jquery.min.js` are supported through the Version-less URLs like `/webjars/jquery/jquery.min.js` are supported through the
`WebJarsResourceResolver` which is automatically registered when the `WebJarsResourceResolver` which is automatically registered when the
`org.webjars:webjars-locator-core` library is present on the classpath, at the cost of a `org.webjars:webjars-locator-lite` library is present on the classpath. The resolver can re-write
classpath scanning that could slow down application startup. The resolver can re-write URLs to URLs to include the version of the jar and can also match against incoming URLs without versions
include the version of the jar and can also match against incoming URLs without versions
-- for example, from `/webjars/jquery/jquery.min.js` to `/webjars/jquery/1.2.0/jquery.min.js`. -- for example, from `/webjars/jquery/jquery.min.js` to `/webjars/jquery/1.2.0/jquery.min.js`.
TIP: The Java configuration based on `ResourceHandlerRegistry` provides further options TIP: The Java configuration based on `ResourceHandlerRegistry` provides further options

View File

@ -48,13 +48,12 @@ For https://www.webjars.org/documentation[WebJars], versioned URLs like
`/webjars/jquery/1.2.0/jquery.min.js` are the recommended and most efficient way to use them. `/webjars/jquery/1.2.0/jquery.min.js` are the recommended and most efficient way to use them.
The related resource location is configured out of the box with Spring Boot (or can be configured The related resource location is configured out of the box with Spring Boot (or can be configured
manually via `ResourceHandlerRegistry`) and does not require to add the manually via `ResourceHandlerRegistry`) and does not require to add the
`org.webjars:webjars-locator-core` dependency. `org.webjars:webjars-locator-lite` dependency.
Version-less URLs like `/webjars/jquery/jquery.min.js` are supported through the Version-less URLs like `/webjars/jquery/jquery.min.js` are supported through the
`WebJarsResourceResolver` which is automatically registered when the `WebJarsResourceResolver` which is automatically registered when the
`org.webjars:webjars-locator-core` library is present on the classpath, at the cost of a `org.webjars:webjars-locator-lite` library is present on the classpath. The resolver can re-write
classpath scanning that could slow down application startup. The resolver can re-write URLs to URLs to include the version of the jar and can also match against incoming URLs without versions
include the version of the jar and can also match against incoming URLs without versions
-- for example, from `/webjars/jquery/jquery.min.js` to `/webjars/jquery/1.2.0/jquery.min.js`. -- for example, from `/webjars/jquery/jquery.min.js` to `/webjars/jquery/1.2.0/jquery.min.js`.
TIP: The Java configuration based on `ResourceHandlerRegistry` provides further options TIP: The Java configuration based on `ResourceHandlerRegistry` provides further options

View File

@ -38,7 +38,6 @@ dependencies {
api("com.oracle.database.jdbc:ojdbc11:21.9.0.0") api("com.oracle.database.jdbc:ojdbc11:21.9.0.0")
api("com.rometools:rome:1.19.0") api("com.rometools:rome:1.19.0")
api("com.squareup.okhttp3:mockwebserver:3.14.9") api("com.squareup.okhttp3:mockwebserver:3.14.9")
api("com.squareup.okhttp3:okhttp:3.14.9")
api("com.sun.activation:jakarta.activation:2.0.1") api("com.sun.activation:jakarta.activation:2.0.1")
api("com.sun.xml.bind:jaxb-core:3.0.2") api("com.sun.xml.bind:jaxb-core:3.0.2")
api("com.sun.xml.bind:jaxb-impl:3.0.2") api("com.sun.xml.bind:jaxb-impl:3.0.2")
@ -142,7 +141,6 @@ dependencies {
api("org.slf4j:slf4j-api:2.0.16") api("org.slf4j:slf4j-api:2.0.16")
api("org.testng:testng:7.10.2") api("org.testng:testng:7.10.2")
api("org.webjars:underscorejs:1.8.3") api("org.webjars:underscorejs:1.8.3")
api("org.webjars:webjars-locator-core:0.55")
api("org.webjars:webjars-locator-lite:1.0.0") api("org.webjars:webjars-locator-lite:1.0.0")
api("org.xmlunit:xmlunit-assertj:2.10.0") api("org.xmlunit:xmlunit-assertj:2.10.0")
api("org.xmlunit:xmlunit-matchers:2.10.0") api("org.xmlunit:xmlunit-matchers:2.10.0")

View File

@ -281,15 +281,11 @@ 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("removal")
@Nullable @Nullable
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 (org.springframework.util.concurrent.ListenableFuture.class.isAssignableFrom(returnType)) {
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

@ -35,7 +35,6 @@ import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult; import org.springframework.scheduling.annotation.AsyncResult;
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.springframework.core.testfixture.TestGroup.LONG_RUNNING; import static org.springframework.core.testfixture.TestGroup.LONG_RUNNING;
@ -136,10 +135,7 @@ public class AnnotationAsyncExecutionAspectTests {
assertThat(defaultThread.get()).isNotEqualTo(Thread.currentThread()); assertThat(defaultThread.get()).isNotEqualTo(Thread.currentThread());
assertThat(defaultThread.get().getName()).doesNotStartWith("e1-"); assertThat(defaultThread.get().getName()).doesNotStartWith("e1-");
ListenableFuture<Thread> e1Thread = obj.e1Work(); CompletableFuture<Thread> e1OtherThread = obj.e1Work();
assertThat(e1Thread.get().getName()).startsWith("e1-");
CompletableFuture<Thread> e1OtherThread = obj.e1OtherWork();
assertThat(e1OtherThread.get().getName()).startsWith("e1-"); assertThat(e1OtherThread.get().getName()).startsWith("e1-");
} }
@ -269,12 +265,7 @@ public class AnnotationAsyncExecutionAspectTests {
} }
@Async("e1") @Async("e1")
public ListenableFuture<Thread> e1Work() { public CompletableFuture<Thread> e1Work() {
return new AsyncResult<>(Thread.currentThread());
}
@Async("e1")
public CompletableFuture<Thread> e1OtherWork() {
return CompletableFuture.completedFuture(Thread.currentThread()); return CompletableFuture.completedFuture(Thread.currentThread());
} }
} }

View File

@ -171,30 +171,6 @@ public final class BeanInstanceSupplier<T> extends AutowiredElementResolver impl
return new BeanInstanceSupplier<>(this.lookup, generator, null, this.shortcutBeanNames); return new BeanInstanceSupplier<>(this.lookup, generator, null, this.shortcutBeanNames);
} }
/**
* Return a new {@link BeanInstanceSupplier} instance that uses the specified
* {@code generator} supplier to instantiate the underlying bean.
* @param generator a {@link ThrowingSupplier} to instantiate the underlying bean
* @return a new {@link BeanInstanceSupplier} instance with the specified generator
* @deprecated in favor of {@link #withGenerator(ThrowingFunction)}
*/
@Deprecated(since = "6.0.11", forRemoval = true)
public BeanInstanceSupplier<T> withGenerator(ThrowingSupplier<T> generator) {
Assert.notNull(generator, "'generator' must not be null");
return new BeanInstanceSupplier<>(this.lookup, registeredBean -> generator.get(),
null, this.shortcutBeanNames);
}
/**
* Return a new {@link BeanInstanceSupplier} instance
* that uses direct bean name injection shortcuts for specific parameters.
* @deprecated in favor of {@link #withShortcut(String...)}
*/
@Deprecated(since = "6.2", forRemoval = true)
public BeanInstanceSupplier<T> withShortcuts(String... beanNames) {
return withShortcut(beanNames);
}
/** /**
* Return a new {@link BeanInstanceSupplier} instance that uses * Return a new {@link BeanInstanceSupplier} instance that uses
* direct bean name injection shortcuts for specific parameters. * direct bean name injection shortcuts for specific parameters.

View File

@ -55,23 +55,6 @@ public class SimpleInstantiationStrategy implements InstantiationStrategy {
return currentlyInvokedFactoryMethod.get(); return currentlyInvokedFactoryMethod.get();
} }
/**
* Set the factory method currently being invoked or {@code null} to remove
* the current value, if any.
* @param method the factory method currently being invoked or {@code null}
* @since 6.0
* @deprecated in favor of {@link #instantiateWithFactoryMethod(Method, Supplier)}
*/
@Deprecated(since = "6.2", forRemoval = true)
public static void setCurrentlyInvokedFactoryMethod(@Nullable Method method) {
if (method != null) {
currentlyInvokedFactoryMethod.set(method);
}
else {
currentlyInvokedFactoryMethod.remove();
}
}
/** /**
* Invoke the given {@code instanceSupplier} with the factory method exposed * Invoke the given {@code instanceSupplier} with the factory method exposed
* as being invoked. * as being invoked.

View File

@ -62,7 +62,6 @@ import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils;
import org.springframework.util.function.ThrowingBiFunction; import org.springframework.util.function.ThrowingBiFunction;
import org.springframework.util.function.ThrowingFunction; import org.springframework.util.function.ThrowingFunction;
import org.springframework.util.function.ThrowingSupplier;
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;
@ -180,16 +179,6 @@ class BeanInstanceSupplierTests {
.withMessage("'generator' must not be null"); .withMessage("'generator' must not be null");
} }
@Test
@Deprecated
@SuppressWarnings("removal")
void withGeneratorWhenSupplierIsNullThrowsException() {
BeanInstanceSupplier<Object> resolver = BeanInstanceSupplier.forConstructor();
assertThatIllegalArgumentException()
.isThrownBy(() -> resolver.withGenerator((ThrowingSupplier<Object>) null))
.withMessage("'generator' must not be null");
}
@Test @Test
void getWithConstructorDoesNotSetResolvedFactoryMethod() { void getWithConstructorDoesNotSetResolvedFactoryMethod() {
BeanInstanceSupplier<SingleArgConstructor> resolver = BeanInstanceSupplier.forConstructor(String.class); BeanInstanceSupplier<SingleArgConstructor> resolver = BeanInstanceSupplier.forConstructor(String.class);
@ -236,18 +225,6 @@ class BeanInstanceSupplierTests {
assertThat(resolver.get(registerBean)).isInstanceOf(String.class).isEqualTo("1"); assertThat(resolver.get(registerBean)).isInstanceOf(String.class).isEqualTo("1");
} }
@Test
@Deprecated
@SuppressWarnings("removal")
void getWithGeneratorCallsSupplier() {
BeanRegistrar registrar = new BeanRegistrar(SingleArgConstructor.class);
this.beanFactory.registerSingleton("one", "1");
RegisteredBean registerBean = registrar.registerBean(this.beanFactory);
BeanInstanceSupplier<String> resolver = BeanInstanceSupplier.<String>forConstructor(String.class)
.withGenerator(() -> "1");
assertThat(resolver.get(registerBean)).isInstanceOf(String.class).isEqualTo("1");
}
@Test @Test
void getWhenRegisteredBeanIsNullThrowsException() { void getWhenRegisteredBeanIsNullThrowsException() {
BeanInstanceSupplier<Object> resolver = BeanInstanceSupplier.forConstructor(String.class); BeanInstanceSupplier<Object> resolver = BeanInstanceSupplier.forConstructor(String.class);

View File

@ -25,12 +25,10 @@ import org.quartz.simpl.SimpleThreadPool;
import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.task.AsyncListenableTaskExecutor; import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.scheduling.SchedulingException; import org.springframework.scheduling.SchedulingException;
import org.springframework.scheduling.SchedulingTaskExecutor; import org.springframework.scheduling.SchedulingTaskExecutor;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureTask;
/** /**
* Subclass of Quartz's SimpleThreadPool that implements Spring's * Subclass of Quartz's SimpleThreadPool that implements Spring's
@ -47,9 +45,9 @@ import org.springframework.util.concurrent.ListenableFutureTask;
* @see org.springframework.core.task.TaskExecutor * @see org.springframework.core.task.TaskExecutor
* @see SchedulerFactoryBean#setTaskExecutor * @see SchedulerFactoryBean#setTaskExecutor
*/ */
@SuppressWarnings({"deprecation", "removal"}) @SuppressWarnings("deprecation")
public class SimpleThreadPoolTaskExecutor extends SimpleThreadPool public class SimpleThreadPoolTaskExecutor extends SimpleThreadPool
implements AsyncListenableTaskExecutor, SchedulingTaskExecutor, InitializingBean, DisposableBean { implements AsyncTaskExecutor, SchedulingTaskExecutor, InitializingBean, DisposableBean {
private boolean waitForJobsToCompleteOnShutdown = false; private boolean waitForJobsToCompleteOnShutdown = false;
@ -91,20 +89,6 @@ public class SimpleThreadPoolTaskExecutor extends SimpleThreadPool
return future; return future;
} }
@Override
public ListenableFuture<?> submitListenable(Runnable task) {
ListenableFutureTask<Object> future = new ListenableFutureTask<>(task, null);
execute(future);
return future;
}
@Override
public <T> ListenableFuture<T> submitListenable(Callable<T> task) {
ListenableFutureTask<T> future = new ListenableFutureTask<>(task);
execute(future);
return future;
}
@Override @Override
public void destroy() { public void destroy() {

View File

@ -310,7 +310,6 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe
return new Object[] {event}; return new Object[] {event};
} }
@SuppressWarnings({"removal", "unchecked", "deprecation"})
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()) {
@ -327,9 +326,6 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe
} }
}); });
} }
else if (result instanceof org.springframework.util.concurrent.ListenableFuture<?> listenableFuture) {
listenableFuture.addCallback(this::publishEvents, this::handleAsyncError);
}
else { else {
publishEvents(result); publishEvents(result);
} }

View File

@ -22,10 +22,6 @@ import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.util.concurrent.FailureCallback;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureCallback;
import org.springframework.util.concurrent.SuccessCallback;
/** /**
* A pass-through {@code Future} handle that can be used for method signatures * A pass-through {@code Future} handle that can be used for method signatures
@ -46,8 +42,7 @@ import org.springframework.util.concurrent.SuccessCallback;
* @deprecated as of 6.0, in favor of {@link CompletableFuture} * @deprecated as of 6.0, in favor of {@link CompletableFuture}
*/ */
@Deprecated(since = "6.0") @Deprecated(since = "6.0")
@SuppressWarnings("removal") public class AsyncResult<V> implements Future<V> {
public class AsyncResult<V> implements ListenableFuture<V> {
@Nullable @Nullable
private final V value; private final V value;
@ -105,38 +100,6 @@ public class AsyncResult<V> implements ListenableFuture<V> {
return get(); return get();
} }
@Override
public void addCallback(ListenableFutureCallback<? super V> callback) {
addCallback(callback, callback);
}
@Override
public void addCallback(SuccessCallback<? super V> successCallback, FailureCallback failureCallback) {
try {
if (this.executionException != null) {
failureCallback.onFailure(exposedException(this.executionException));
}
else {
successCallback.onSuccess(this.value);
}
}
catch (Throwable ex) {
// Ignore
}
}
@Override
public CompletableFuture<V> completable() {
if (this.executionException != null) {
CompletableFuture<V> completable = new CompletableFuture<>();
completable.completeExceptionally(exposedException(this.executionException));
return completable;
}
else {
return CompletableFuture.completedFuture(this.value);
}
}
/** /**
* Create a new async result which exposes the given value from {@link Future#get()}. * Create a new async result which exposes the given value from {@link Future#get()}.
@ -144,7 +107,7 @@ public class AsyncResult<V> implements ListenableFuture<V> {
* @since 4.2 * @since 4.2
* @see Future#get() * @see Future#get()
*/ */
public static <V> org.springframework.util.concurrent.ListenableFuture<V> forValue(V value) { public static <V> Future<V> forValue(V value) {
return new AsyncResult<>(value, null); return new AsyncResult<>(value, null);
} }
@ -156,7 +119,7 @@ public class AsyncResult<V> implements ListenableFuture<V> {
* @since 4.2 * @since 4.2
* @see ExecutionException * @see ExecutionException
*/ */
public static <V> org.springframework.util.concurrent.ListenableFuture<V> forExecutionException(Throwable ex) { public static <V> Future<V> forExecutionException(Throwable ex) {
return new AsyncResult<>(null, ex); return new AsyncResult<>(null, ex);
} }

View File

@ -26,14 +26,13 @@ import java.util.concurrent.Future;
import jakarta.enterprise.concurrent.ManagedExecutors; import jakarta.enterprise.concurrent.ManagedExecutors;
import jakarta.enterprise.concurrent.ManagedTask; import jakarta.enterprise.concurrent.ManagedTask;
import org.springframework.core.task.AsyncListenableTaskExecutor; import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.core.task.TaskDecorator; import org.springframework.core.task.TaskDecorator;
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.scheduling.SchedulingAwareRunnable; import org.springframework.scheduling.SchedulingAwareRunnable;
import org.springframework.scheduling.SchedulingTaskExecutor; import org.springframework.scheduling.SchedulingTaskExecutor;
import org.springframework.util.ClassUtils; import org.springframework.util.ClassUtils;
import org.springframework.util.concurrent.ListenableFuture;
/** /**
* Adapter that takes a {@code java.util.concurrent.Executor} and exposes * Adapter that takes a {@code java.util.concurrent.Executor} and exposes
@ -62,8 +61,8 @@ import org.springframework.util.concurrent.ListenableFuture;
* @see DefaultManagedTaskExecutor * @see DefaultManagedTaskExecutor
* @see ThreadPoolTaskExecutor * @see ThreadPoolTaskExecutor
*/ */
@SuppressWarnings({"deprecation", "removal"}) @SuppressWarnings("deprecation")
public class ConcurrentTaskExecutor implements AsyncListenableTaskExecutor, SchedulingTaskExecutor { public class ConcurrentTaskExecutor implements AsyncTaskExecutor, SchedulingTaskExecutor {
private static final Executor STUB_EXECUTOR = (task -> { private static final Executor STUB_EXECUTOR = (task -> {
throw new IllegalStateException("Executor not configured"); throw new IllegalStateException("Executor not configured");
@ -172,16 +171,6 @@ public class ConcurrentTaskExecutor implements AsyncListenableTaskExecutor, Sche
return this.adaptedExecutor.submit(task); return this.adaptedExecutor.submit(task);
} }
@Override
public ListenableFuture<?> submitListenable(Runnable task) {
return this.adaptedExecutor.submitListenable(task);
}
@Override
public <T> ListenableFuture<T> submitListenable(Callable<T> task) {
return this.adaptedExecutor.submitListenable(task);
}
private TaskExecutorAdapter getAdaptedExecutor(Executor originalExecutor) { private TaskExecutorAdapter getAdaptedExecutor(Executor originalExecutor) {
TaskExecutorAdapter adapter = TaskExecutorAdapter adapter =
@ -224,16 +213,6 @@ public class ConcurrentTaskExecutor implements AsyncListenableTaskExecutor, Sche
public <T> Future<T> submit(Callable<T> task) { public <T> Future<T> submit(Callable<T> task) {
return super.submit(ManagedTaskBuilder.buildManagedTask(task, task.toString())); return super.submit(ManagedTaskBuilder.buildManagedTask(task, task.toString()));
} }
@Override
public ListenableFuture<?> submitListenable(Runnable task) {
return super.submitListenable(ManagedTaskBuilder.buildManagedTask(task, task.toString()));
}
@Override
public <T> ListenableFuture<T> submitListenable(Callable<T> task) {
return super.submitListenable(ManagedTaskBuilder.buildManagedTask(task, task.toString()));
}
} }

View File

@ -218,18 +218,6 @@ public class ConcurrentTaskScheduler extends ConcurrentTaskExecutor implements T
return super.submit(new DelegatingErrorHandlingCallable<>(task, this.errorHandler)); return super.submit(new DelegatingErrorHandlingCallable<>(task, this.errorHandler));
} }
@SuppressWarnings({"deprecation", "removal"})
@Override
public org.springframework.util.concurrent.ListenableFuture<?> submitListenable(Runnable task) {
return super.submitListenable(TaskUtils.decorateTaskWithErrorHandler(task, this.errorHandler, false));
}
@SuppressWarnings({"deprecation", "removal"})
@Override
public <T> org.springframework.util.concurrent.ListenableFuture<T> submitListenable(Callable<T> task) {
return super.submitListenable(new DelegatingErrorHandlingCallable<>(task, this.errorHandler));
}
@Override @Override
@Nullable @Nullable
public ScheduledFuture<?> schedule(Runnable task, Trigger trigger) { public ScheduledFuture<?> schedule(Runnable task, Trigger trigger) {

View File

@ -269,18 +269,6 @@ public class SimpleAsyncTaskScheduler extends SimpleAsyncTaskExecutor implements
return super.submit(new DelegatingErrorHandlingCallable<>(task, this.errorHandler)); return super.submit(new DelegatingErrorHandlingCallable<>(task, this.errorHandler));
} }
@SuppressWarnings({"deprecation", "removal"})
@Override
public org.springframework.util.concurrent.ListenableFuture<?> submitListenable(Runnable task) {
return super.submitListenable(TaskUtils.decorateTaskWithErrorHandler(task, this.errorHandler, false));
}
@SuppressWarnings({"deprecation", "removal"})
@Override
public <T> org.springframework.util.concurrent.ListenableFuture<T> submitListenable(Callable<T> task) {
return super.submitListenable(new DelegatingErrorHandlingCallable<>(task, this.errorHandler));
}
@Override @Override
@Nullable @Nullable
public ScheduledFuture<?> schedule(Runnable task, Trigger trigger) { public ScheduledFuture<?> schedule(Runnable task, Trigger trigger) {

View File

@ -30,15 +30,13 @@ import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.springframework.core.task.AsyncListenableTaskExecutor; import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.core.task.TaskDecorator; import org.springframework.core.task.TaskDecorator;
import org.springframework.core.task.TaskRejectedException; import org.springframework.core.task.TaskRejectedException;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.scheduling.SchedulingTaskExecutor; import org.springframework.scheduling.SchedulingTaskExecutor;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.ConcurrentReferenceHashMap; import org.springframework.util.ConcurrentReferenceHashMap;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureTask;
/** /**
* JavaBean that allows for configuring a {@link java.util.concurrent.ThreadPoolExecutor} * JavaBean that allows for configuring a {@link java.util.concurrent.ThreadPoolExecutor}
@ -80,9 +78,9 @@ import org.springframework.util.concurrent.ListenableFutureTask;
* @see ThreadPoolExecutorFactoryBean * @see ThreadPoolExecutorFactoryBean
* @see ConcurrentTaskExecutor * @see ConcurrentTaskExecutor
*/ */
@SuppressWarnings({"serial", "deprecation", "removal"}) @SuppressWarnings({"serial", "deprecation"})
public class ThreadPoolTaskExecutor extends ExecutorConfigurationSupport public class ThreadPoolTaskExecutor extends ExecutorConfigurationSupport
implements AsyncListenableTaskExecutor, SchedulingTaskExecutor { implements AsyncTaskExecutor, SchedulingTaskExecutor {
private final Object poolSizeMonitor = new Object(); private final Object poolSizeMonitor = new Object();
@ -414,32 +412,6 @@ public class ThreadPoolTaskExecutor extends ExecutorConfigurationSupport
} }
} }
@Override
public ListenableFuture<?> submitListenable(Runnable task) {
ExecutorService executor = getThreadPoolExecutor();
try {
ListenableFutureTask<Object> future = new ListenableFutureTask<>(task, null);
executor.execute(future);
return future;
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException(executor, task, ex);
}
}
@Override
public <T> ListenableFuture<T> submitListenable(Callable<T> task) {
ExecutorService executor = getThreadPoolExecutor();
try {
ListenableFutureTask<T> future = new ListenableFutureTask<>(task);
executor.execute(future);
return future;
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException(executor, task, ex);
}
}
@Override @Override
protected void cancelRemainingTask(Runnable task) { protected void cancelRemainingTask(Runnable task) {
super.cancelRemainingTask(task); super.cancelRemainingTask(task);

View File

@ -19,7 +19,6 @@ package org.springframework.scheduling.concurrent;
import java.time.Clock; import java.time.Clock;
import java.time.Duration; import java.time.Duration;
import java.time.Instant; import java.time.Instant;
import java.util.Map;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.Delayed; import java.util.concurrent.Delayed;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
@ -36,7 +35,7 @@ import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import org.springframework.core.task.AsyncListenableTaskExecutor; import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.core.task.TaskDecorator; import org.springframework.core.task.TaskDecorator;
import org.springframework.core.task.TaskRejectedException; import org.springframework.core.task.TaskRejectedException;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
@ -45,10 +44,7 @@ import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.Trigger; import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.support.TaskUtils; import org.springframework.scheduling.support.TaskUtils;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.ConcurrentReferenceHashMap;
import org.springframework.util.ErrorHandler; import org.springframework.util.ErrorHandler;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureTask;
/** /**
* A standard implementation of Spring's {@link TaskScheduler} interface, wrapping * A standard implementation of Spring's {@link TaskScheduler} interface, wrapping
@ -74,9 +70,9 @@ import org.springframework.util.concurrent.ListenableFutureTask;
* @see ThreadPoolTaskExecutor * @see ThreadPoolTaskExecutor
* @see SimpleAsyncTaskScheduler * @see SimpleAsyncTaskScheduler
*/ */
@SuppressWarnings({"serial", "deprecation", "removal"}) @SuppressWarnings({"serial", "deprecation"})
public class ThreadPoolTaskScheduler extends ExecutorConfigurationSupport public class ThreadPoolTaskScheduler extends ExecutorConfigurationSupport
implements AsyncListenableTaskExecutor, SchedulingTaskExecutor, TaskScheduler { implements AsyncTaskExecutor, SchedulingTaskExecutor, TaskScheduler {
private static final TimeUnit NANO = TimeUnit.NANOSECONDS; private static final TimeUnit NANO = TimeUnit.NANOSECONDS;
@ -100,10 +96,6 @@ public class ThreadPoolTaskScheduler extends ExecutorConfigurationSupport
@Nullable @Nullable
private ScheduledExecutorService scheduledExecutor; private ScheduledExecutorService scheduledExecutor;
// Underlying ScheduledFutureTask to user-level ListenableFuture handle, if any
private final Map<Object, ListenableFuture<?>> listenableFutureMap =
new ConcurrentReferenceHashMap<>(16, ConcurrentReferenceHashMap.ReferenceType.WEAK);
/** /**
* Set the ScheduledExecutorService's pool size. * Set the ScheduledExecutorService's pool size.
@ -357,49 +349,6 @@ public class ThreadPoolTaskScheduler extends ExecutorConfigurationSupport
} }
} }
@Override
public ListenableFuture<?> submitListenable(Runnable task) {
ExecutorService executor = getScheduledExecutor();
try {
ListenableFutureTask<Object> listenableFuture = new ListenableFutureTask<>(task, null);
executeAndTrack(executor, listenableFuture);
return listenableFuture;
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException(executor, task, ex);
}
}
@Override
public <T> ListenableFuture<T> submitListenable(Callable<T> task) {
ExecutorService executor = getScheduledExecutor();
try {
ListenableFutureTask<T> listenableFuture = new ListenableFutureTask<>(task);
executeAndTrack(executor, listenableFuture);
return listenableFuture;
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException(executor, task, ex);
}
}
private void executeAndTrack(ExecutorService executor, ListenableFutureTask<?> listenableFuture) {
Future<?> scheduledFuture = executor.submit(errorHandlingTask(listenableFuture, false));
this.listenableFutureMap.put(scheduledFuture, listenableFuture);
listenableFuture.addCallback(result -> this.listenableFutureMap.remove(scheduledFuture),
ex -> this.listenableFutureMap.remove(scheduledFuture));
}
@Override
protected void cancelRemainingTask(Runnable task) {
super.cancelRemainingTask(task);
// Cancel associated user-level ListenableFuture handle as well
ListenableFuture<?> listenableFuture = this.listenableFutureMap.get(task);
if (listenableFuture != null) {
listenableFuture.cancel(true);
}
}
// TaskScheduler implementation // TaskScheduler implementation

View File

@ -81,19 +81,6 @@ public interface MethodValidationResult {
*/ */
List<ParameterValidationResult> getParameterValidationResults(); List<ParameterValidationResult> getParameterValidationResults();
/**
* Return all validation results. This includes both method parameters with
* errors directly on them, and Object method parameters with nested errors
* on their fields and properties.
* @see #getValueResults()
* @see #getBeanResults()
* @deprecated deprecated in favor of {@link #getParameterValidationResults()}
*/
@Deprecated(since = "6.2", forRemoval = true)
default List<ParameterValidationResult> getAllValidationResults() {
return getParameterValidationResults();
}
/** /**
* Return the subset of {@link #getParameterValidationResults() allValidationResults} * Return the subset of {@link #getParameterValidationResults() allValidationResults}
* that includes method parameters with validation errors directly on method * that includes method parameters with validation errors directly on method

View File

@ -85,35 +85,6 @@ public class ParameterValidationResult {
this.sourceLookup = sourceLookup; this.sourceLookup = sourceLookup;
} }
/**
* Create a {@code ParameterValidationResult}.
* @deprecated in favor of
* {@link ParameterValidationResult#ParameterValidationResult(MethodParameter, Object, Collection, Object, Integer, Object, BiFunction)}
*/
@Deprecated(since = "6.2", forRemoval = true)
public ParameterValidationResult(
MethodParameter param, @Nullable Object arg, Collection<? extends MessageSourceResolvable> errors,
@Nullable Object container, @Nullable Integer index, @Nullable Object key) {
this(param, arg, errors, container, index, key, (error, sourceType) -> {
throw new IllegalArgumentException("No source object of the given type");
});
}
/**
* Create a {@code ParameterValidationResult}.
* @deprecated in favor of
* {@link ParameterValidationResult#ParameterValidationResult(MethodParameter, Object, Collection, Object, Integer, Object, BiFunction)}
*/
@Deprecated(since = "6.1.3", forRemoval = true)
public ParameterValidationResult(
MethodParameter param, @Nullable Object arg, Collection<? extends MessageSourceResolvable> errors) {
this(param, arg, errors, null, null, null, (error, sourceType) -> {
throw new IllegalArgumentException("No source object of the given type");
});
}
/** /**
* The method parameter the validation results are for. * The method parameter the validation results are for.

View File

@ -279,25 +279,6 @@ class AnnotationDrivenEventListenerTests {
this.eventCollector.assertTotalEventsCount(2); this.eventCollector.assertTotalEventsCount(2);
} }
@Test
@SuppressWarnings({"deprecation", "removal"})
void listenableFutureReply() {
load(TestEventListener.class, ReplyEventListener.class);
org.springframework.util.concurrent.SettableListenableFuture<String> future =
new org.springframework.util.concurrent.SettableListenableFuture<>();
future.set("dummy");
AnotherTestEvent event = new AnotherTestEvent(this, future);
ReplyEventListener replyEventListener = this.context.getBean(ReplyEventListener.class);
TestEventListener listener = this.context.getBean(TestEventListener.class);
this.eventCollector.assertNoEventReceived(listener);
this.eventCollector.assertNoEventReceived(replyEventListener);
this.context.publishEvent(event);
this.eventCollector.assertEvent(replyEventListener, event);
this.eventCollector.assertEvent(listener, "dummy"); // reply
this.eventCollector.assertTotalEventsCount(2);
}
@Test @Test
void completableFutureReply() { void completableFutureReply() {
load(TestEventListener.class, ReplyEventListener.class); load(TestEventListener.class, ReplyEventListener.class);

View File

@ -200,20 +200,6 @@ class AsyncAnnotationBeanPostProcessorTests {
assertFutureWithException(result, exceptionHandler); assertFutureWithException(result, exceptionHandler);
} }
@Test
@SuppressWarnings("resource")
public void handleExceptionWithListenableFuture() {
ConfigurableApplicationContext context =
new AnnotationConfigApplicationContext(ConfigWithExceptionHandler.class);
ITestBean testBean = context.getBean("target", ITestBean.class);
TestableAsyncUncaughtExceptionHandler exceptionHandler =
context.getBean("exceptionHandler", TestableAsyncUncaughtExceptionHandler.class);
assertThat(exceptionHandler.isCalled()).as("handler should not have been called yet").isFalse();
Future<Object> result = testBean.failWithListenableFuture();
assertFutureWithException(result, exceptionHandler);
}
private void assertFutureWithException(Future<Object> result, private void assertFutureWithException(Future<Object> result,
TestableAsyncUncaughtExceptionHandler exceptionHandler) { TestableAsyncUncaughtExceptionHandler exceptionHandler) {
assertThatExceptionOfType(ExecutionException.class).isThrownBy( assertThatExceptionOfType(ExecutionException.class).isThrownBy(
@ -275,9 +261,6 @@ class AsyncAnnotationBeanPostProcessorTests {
Future<Object> failWithFuture(); Future<Object> failWithFuture();
@SuppressWarnings({"deprecation", "removal"})
org.springframework.util.concurrent.ListenableFuture<Object> failWithListenableFuture();
void failWithVoid(); void failWithVoid();
void await(long timeout); void await(long timeout);
@ -308,13 +291,6 @@ class AsyncAnnotationBeanPostProcessorTests {
throw new UnsupportedOperationException("failWithFuture"); throw new UnsupportedOperationException("failWithFuture");
} }
@Async
@Override
@SuppressWarnings({"deprecation", "removal"})
public org.springframework.util.concurrent.ListenableFuture<Object> failWithListenableFuture() {
throw new UnsupportedOperationException("failWithListenableFuture");
}
@Async @Async
@Override @Override
public void failWithVoid() { public void failWithVoid() {

View File

@ -42,7 +42,6 @@ import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener; import org.springframework.context.ApplicationListener;
import org.springframework.context.support.GenericApplicationContext; import org.springframework.context.support.GenericApplicationContext;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
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;
@ -51,7 +50,6 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Chris Beams * @author Chris Beams
*/ */
@SuppressWarnings({"resource", "deprecation", "removal"})
class AsyncExecutionTests { class AsyncExecutionTests {
private static String originalThreadName; private static String originalThreadName;
@ -81,8 +79,6 @@ class AsyncExecutionTests {
asyncTest.doSomething(10); asyncTest.doSomething(10);
Future<String> future = asyncTest.returnSomething(20); Future<String> future = asyncTest.returnSomething(20);
assertThat(future.get()).isEqualTo("20"); assertThat(future.get()).isEqualTo("20");
ListenableFuture<String> listenableFuture = asyncTest.returnSomethingListenable(20);
assertThat(listenableFuture.get()).isEqualTo("20");
CompletableFuture<String> completableFuture = asyncTest.returnSomethingCompletable(20); CompletableFuture<String> completableFuture = asyncTest.returnSomethingCompletable(20);
assertThat(completableFuture.get()).isEqualTo("20"); assertThat(completableFuture.get()).isEqualTo("20");
@ -94,14 +90,6 @@ class AsyncExecutionTests {
asyncTest.returnSomething(-1).get()) asyncTest.returnSomething(-1).get())
.withCauseInstanceOf(IOException.class); .withCauseInstanceOf(IOException.class);
assertThatExceptionOfType(ExecutionException.class).isThrownBy(() ->
asyncTest.returnSomethingListenable(0).get())
.withCauseInstanceOf(IllegalArgumentException.class);
assertThatExceptionOfType(ExecutionException.class).isThrownBy(() ->
asyncTest.returnSomethingListenable(-1).get())
.withCauseInstanceOf(IOException.class);
assertThatExceptionOfType(ExecutionException.class).isThrownBy(() -> assertThatExceptionOfType(ExecutionException.class).isThrownBy(() ->
asyncTest.returnSomethingCompletable(0).get()) asyncTest.returnSomethingCompletable(0).get())
.withCauseInstanceOf(IllegalArgumentException.class); .withCauseInstanceOf(IllegalArgumentException.class);
@ -174,8 +162,6 @@ class AsyncExecutionTests {
asyncTest.doSomething(10); asyncTest.doSomething(10);
Future<String> future = asyncTest.returnSomething(20); Future<String> future = asyncTest.returnSomething(20);
assertThat(future.get()).isEqualTo("20"); assertThat(future.get()).isEqualTo("20");
ListenableFuture<String> listenableFuture = asyncTest.returnSomethingListenable(20);
assertThat(listenableFuture.get()).isEqualTo("20");
CompletableFuture<String> completableFuture = asyncTest.returnSomethingCompletable(20); CompletableFuture<String> completableFuture = asyncTest.returnSomethingCompletable(20);
assertThat(completableFuture.get()).isEqualTo("20"); assertThat(completableFuture.get()).isEqualTo("20");
@ -183,10 +169,6 @@ class AsyncExecutionTests {
asyncTest.returnSomething(0).get()) asyncTest.returnSomething(0).get())
.withCauseInstanceOf(IllegalArgumentException.class); .withCauseInstanceOf(IllegalArgumentException.class);
assertThatExceptionOfType(ExecutionException.class).isThrownBy(() ->
asyncTest.returnSomethingListenable(0).get())
.withCauseInstanceOf(IllegalArgumentException.class);
assertThatExceptionOfType(ExecutionException.class).isThrownBy(() -> assertThatExceptionOfType(ExecutionException.class).isThrownBy(() ->
asyncTest.returnSomethingCompletable(0).get()) asyncTest.returnSomethingCompletable(0).get())
.withCauseInstanceOf(IllegalArgumentException.class); .withCauseInstanceOf(IllegalArgumentException.class);
@ -419,18 +401,6 @@ class AsyncExecutionTests {
return AsyncResult.forValue(Integer.toString(i)); return AsyncResult.forValue(Integer.toString(i));
} }
@Async
public ListenableFuture<String> returnSomethingListenable(int i) {
assertThat(Thread.currentThread().getName()).isNotEqualTo(originalThreadName);
if (i == 0) {
throw new IllegalArgumentException();
}
else if (i < 0) {
return AsyncResult.forExecutionException(new IOException());
}
return new AsyncResult<>(Integer.toString(i));
}
@Async @Async
public CompletableFuture<String> returnSomethingCompletable(int i) { public CompletableFuture<String> returnSomethingCompletable(int i) {
assertThat(Thread.currentThread().getName()).isNotEqualTo(originalThreadName); assertThat(Thread.currentThread().getName()).isNotEqualTo(originalThreadName);
@ -505,14 +475,6 @@ class AsyncExecutionTests {
return new AsyncResult<>(Integer.toString(i)); return new AsyncResult<>(Integer.toString(i));
} }
public ListenableFuture<String> returnSomethingListenable(int i) {
assertThat(Thread.currentThread().getName()).isNotEqualTo(originalThreadName);
if (i == 0) {
throw new IllegalArgumentException();
}
return new AsyncResult<>(Integer.toString(i));
}
@Async @Async
public CompletableFuture<String> returnSomethingCompletable(int i) { public CompletableFuture<String> returnSomethingCompletable(int i) {
assertThat(Thread.currentThread().getName()).isNotEqualTo(originalThreadName); assertThat(Thread.currentThread().getName()).isNotEqualTo(originalThreadName);

View File

@ -1,110 +0,0 @@
/*
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.scheduling.annotation;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
/**
* @author Juergen Hoeller
*/
class AsyncResultTests {
@Test
@SuppressWarnings({ "deprecation", "removal" })
public void asyncResultWithCallbackAndValue() throws Exception {
String value = "val";
final Set<String> values = new HashSet<>(1);
org.springframework.util.concurrent.ListenableFuture<String> future = AsyncResult.forValue(value);
future.addCallback(new org.springframework.util.concurrent.ListenableFutureCallback<>() {
@Override
public void onSuccess(String result) {
values.add(result);
}
@Override
public void onFailure(Throwable ex) {
throw new AssertionError("Failure callback not expected: " + ex, ex);
}
});
assertThat(values).singleElement().isSameAs(value);
assertThat(future.get()).isSameAs(value);
assertThat(future.completable().get()).isSameAs(value);
future.completable().thenAccept(v -> assertThat(v).isSameAs(value));
}
@Test
@SuppressWarnings({ "deprecation", "removal" })
public void asyncResultWithCallbackAndException() {
IOException ex = new IOException();
final Set<Throwable> values = new HashSet<>(1);
org.springframework.util.concurrent.ListenableFuture<String> future = AsyncResult.forExecutionException(ex);
future.addCallback(new org.springframework.util.concurrent.ListenableFutureCallback<>() {
@Override
public void onSuccess(String result) {
throw new AssertionError("Success callback not expected: " + result);
}
@Override
public void onFailure(Throwable ex) {
values.add(ex);
}
});
assertThat(values).singleElement().isSameAs(ex);
assertThatExceptionOfType(ExecutionException.class)
.isThrownBy(future::get)
.withCause(ex);
assertThatExceptionOfType(ExecutionException.class)
.isThrownBy(future.completable()::get)
.withCause(ex);
}
@Test
@SuppressWarnings({ "deprecation", "removal" })
public void asyncResultWithSeparateCallbacksAndValue() throws Exception {
String value = "val";
final Set<String> values = new HashSet<>(1);
org.springframework.util.concurrent.ListenableFuture<String> future = AsyncResult.forValue(value);
future.addCallback(values::add, ex -> new AssertionError("Failure callback not expected: " + ex));
assertThat(values).singleElement().isSameAs(value);
assertThat(future.get()).isSameAs(value);
assertThat(future.completable().get()).isSameAs(value);
future.completable().thenAccept(v -> assertThat(v).isSameAs(value));
}
@Test
@SuppressWarnings({ "deprecation", "removal" })
public void asyncResultWithSeparateCallbacksAndException() {
IOException ex = new IOException();
final Set<Throwable> values = new HashSet<>(1);
org.springframework.util.concurrent.ListenableFuture<String> future = AsyncResult.forExecutionException(ex);
future.addCallback(result -> new AssertionError("Success callback not expected: " + result), values::add);
assertThat(values).singleElement().isSameAs(ex);
assertThatExceptionOfType(ExecutionException.class)
.isThrownBy(future::get)
.withCause(ex);
assertThatExceptionOfType(ExecutionException.class)
.isThrownBy(future.completable()::get)
.withCause(ex);
}
}

View File

@ -35,6 +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.AsyncTaskExecutor;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -47,8 +48,7 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
*/ */
abstract class AbstractSchedulingTaskExecutorTests { abstract class AbstractSchedulingTaskExecutorTests {
@SuppressWarnings("removal") private AsyncTaskExecutor executor;
private org.springframework.core.task.AsyncListenableTaskExecutor executor;
protected String testName; protected String testName;
@ -64,8 +64,7 @@ abstract class AbstractSchedulingTaskExecutorTests {
this.executor = buildExecutor(); this.executor = buildExecutor();
} }
@SuppressWarnings("removal") protected abstract AsyncTaskExecutor buildExecutor();
protected abstract org.springframework.core.task.AsyncListenableTaskExecutor buildExecutor();
@AfterEach @AfterEach
void shutdownExecutor() throws Exception { void shutdownExecutor() throws Exception {
@ -124,22 +123,6 @@ abstract class AbstractSchedulingTaskExecutorTests {
}); });
} }
@Test
@SuppressWarnings({ "deprecation", "removal" })
void submitListenableRunnable() {
TestTask task = new TestTask(this.testName, 1);
// Act
org.springframework.util.concurrent.ListenableFuture<?> future = executor.submitListenable(task);
future.addCallback(result -> outcome = result, ex -> outcome = ex);
// Assert
Awaitility.await()
.atMost(5, TimeUnit.SECONDS)
.pollInterval(10, TimeUnit.MILLISECONDS)
.until(future::isDone);
assertThat(outcome).isNull();
assertThreadNamePrefix(task);
}
@Test @Test
void submitCompletableRunnable() { void submitCompletableRunnable() {
TestTask task = new TestTask(this.testName, 1); TestTask task = new TestTask(this.testName, 1);
@ -155,21 +138,6 @@ abstract class AbstractSchedulingTaskExecutorTests {
assertThreadNamePrefix(task); assertThreadNamePrefix(task);
} }
@Test
@SuppressWarnings({ "deprecation", "removal" })
void submitFailingListenableRunnable() {
TestTask task = new TestTask(this.testName, 0);
org.springframework.util.concurrent.ListenableFuture<?> future = executor.submitListenable(task);
future.addCallback(result -> outcome = result, ex -> outcome = ex);
Awaitility.await()
.dontCatchUncaughtExceptions()
.atMost(5, TimeUnit.SECONDS)
.pollInterval(10, TimeUnit.MILLISECONDS)
.until(() -> future.isDone() && outcome != null);
assertThat(outcome.getClass()).isSameAs(RuntimeException.class);
}
@Test @Test
void submitFailingCompletableRunnable() { void submitFailingCompletableRunnable() {
TestTask task = new TestTask(this.testName, 0); TestTask task = new TestTask(this.testName, 0);
@ -184,43 +152,15 @@ abstract class AbstractSchedulingTaskExecutorTests {
assertThat(outcome.getClass()).isSameAs(CompletionException.class); assertThat(outcome.getClass()).isSameAs(CompletionException.class);
} }
@Test
@SuppressWarnings({ "deprecation", "removal" })
void submitListenableRunnableWithGetAfterShutdown() throws Exception {
org.springframework.util.concurrent.ListenableFuture<?> future1 = executor.submitListenable(new TestTask(this.testName, -1));
org.springframework.util.concurrent.ListenableFuture<?> future2 = executor.submitListenable(new TestTask(this.testName, -1));
shutdownExecutor();
try {
future1.get(1000, TimeUnit.MILLISECONDS);
}
catch (Exception ex) {
// ignore
}
Awaitility.await()
.atMost(5, TimeUnit.SECONDS)
.pollInterval(10, TimeUnit.MILLISECONDS)
.untilAsserted(() -> assertThatExceptionOfType(CancellationException.class)
.isThrownBy(() -> future2.get(1000, TimeUnit.MILLISECONDS)));
}
@Test @Test
void submitCompletableRunnableWithGetAfterShutdown() throws Exception { void submitCompletableRunnableWithGetAfterShutdown() throws Exception {
CompletableFuture<?> future1 = executor.submitCompletable(new TestTask(this.testName, -1)); CompletableFuture<?> future1 = executor.submitCompletable(new TestTask(this.testName, -1));
CompletableFuture<?> future2 = executor.submitCompletable(new TestTask(this.testName, -1)); CompletableFuture<?> future2 = executor.submitCompletable(new TestTask(this.testName, -1));
shutdownExecutor(); shutdownExecutor();
assertThatExceptionOfType(TimeoutException.class).isThrownBy(() -> {
try {
future1.get(1000, TimeUnit.MILLISECONDS); future1.get(1000, TimeUnit.MILLISECONDS);
} future2.get(1000, TimeUnit.MILLISECONDS);
catch (Exception ex) { });
// ignore
}
Awaitility.await()
.atMost(5, TimeUnit.SECONDS)
.pollInterval(10, TimeUnit.MILLISECONDS)
.untilAsserted(() -> assertThatExceptionOfType(TimeoutException.class)
.isThrownBy(() -> future2.get(1000, TimeUnit.MILLISECONDS)));
} }
@Test @Test
@ -245,57 +185,6 @@ abstract class AbstractSchedulingTaskExecutorTests {
Future<?> future1 = executor.submit(new TestCallable(this.testName, -1)); Future<?> future1 = executor.submit(new TestCallable(this.testName, -1));
Future<?> future2 = executor.submit(new TestCallable(this.testName, -1)); Future<?> future2 = executor.submit(new TestCallable(this.testName, -1));
shutdownExecutor(); shutdownExecutor();
try {
future1.get(1000, TimeUnit.MILLISECONDS);
}
catch (Exception ex) {
// ignore
}
Awaitility.await()
.atMost(5, TimeUnit.SECONDS)
.pollInterval(10, TimeUnit.MILLISECONDS)
.untilAsserted(() -> assertThatExceptionOfType(CancellationException.class)
.isThrownBy(() -> future2.get(1000, TimeUnit.MILLISECONDS)));
}
@Test
@SuppressWarnings({ "deprecation", "removal" })
void submitListenableCallable() {
TestCallable task = new TestCallable(this.testName, 1);
// Act
org.springframework.util.concurrent.ListenableFuture<String> future = executor.submitListenable(task);
future.addCallback(result -> outcome = result, ex -> outcome = ex);
// Assert
Awaitility.await()
.atMost(5, TimeUnit.SECONDS)
.pollInterval(10, TimeUnit.MILLISECONDS)
.until(() -> future.isDone() && outcome != null);
assertThat(outcome.toString().substring(0, this.threadNamePrefix.length())).isEqualTo(this.threadNamePrefix);
}
@Test
@SuppressWarnings({ "deprecation", "removal" })
void submitFailingListenableCallable() {
TestCallable task = new TestCallable(this.testName, 0);
// Act
org.springframework.util.concurrent.ListenableFuture<String> future = executor.submitListenable(task);
future.addCallback(result -> outcome = result, ex -> outcome = ex);
// Assert
Awaitility.await()
.dontCatchUncaughtExceptions()
.atMost(5, TimeUnit.SECONDS)
.pollInterval(10, TimeUnit.MILLISECONDS)
.until(() -> future.isDone() && outcome != null);
assertThat(outcome.getClass()).isSameAs(RuntimeException.class);
}
@Test
@SuppressWarnings({ "deprecation", "removal" })
void submitListenableCallableWithGetAfterShutdown() throws Exception {
org.springframework.util.concurrent.ListenableFuture<?> future1 = executor.submitListenable(new TestCallable(this.testName, -1));
org.springframework.util.concurrent.ListenableFuture<?> future2 = executor.submitListenable(new TestCallable(this.testName, -1));
shutdownExecutor();
assertThatExceptionOfType(CancellationException.class).isThrownBy(() -> { assertThatExceptionOfType(CancellationException.class).isThrownBy(() -> {
future1.get(1000, TimeUnit.MILLISECONDS); future1.get(1000, TimeUnit.MILLISECONDS);
future2.get(1000, TimeUnit.MILLISECONDS); future2.get(1000, TimeUnit.MILLISECONDS);

View File

@ -25,6 +25,7 @@ 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.AsyncTaskExecutor;
import org.springframework.core.task.NoOpRunnable; import org.springframework.core.task.NoOpRunnable;
import org.springframework.core.task.TaskDecorator; import org.springframework.core.task.TaskDecorator;
import org.springframework.util.Assert; import org.springframework.util.Assert;
@ -42,8 +43,7 @@ class ConcurrentTaskExecutorTests extends AbstractSchedulingTaskExecutorTests {
@Override @Override
@SuppressWarnings("removal") protected AsyncTaskExecutor buildExecutor() {
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

@ -31,6 +31,7 @@ import org.junit.jupiter.api.AfterEach;
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.AsyncTaskExecutor;
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;
@ -52,8 +53,7 @@ class ConcurrentTaskSchedulerTests extends AbstractSchedulingTaskExecutorTests {
@Override @Override
@SuppressWarnings("removal") protected AsyncTaskExecutor buildExecutor() {
protected org.springframework.core.task.AsyncListenableTaskExecutor buildExecutor() {
threadFactory.setThreadNamePrefix(this.threadNamePrefix); threadFactory.setThreadNamePrefix(this.threadNamePrefix);
scheduler.setTaskDecorator(runnable -> () -> { scheduler.setTaskDecorator(runnable -> () -> {
taskRun.set(true); taskRun.set(true);
@ -79,26 +79,12 @@ class ConcurrentTaskSchedulerTests extends AbstractSchedulingTaskExecutorTests {
// decorated Future cannot be cancelled on shutdown with ConcurrentTaskScheduler (see above) // decorated Future cannot be cancelled on shutdown with ConcurrentTaskScheduler (see above)
} }
@Test
@SuppressWarnings("deprecation")
@Override
void submitListenableRunnableWithGetAfterShutdown() {
// decorated Future cannot be cancelled on shutdown with ConcurrentTaskScheduler (see above)
}
@Test @Test
@Override @Override
void submitCallableWithGetAfterShutdown() { void submitCallableWithGetAfterShutdown() {
// decorated Future cannot be cancelled on shutdown with ConcurrentTaskScheduler (see above) // decorated Future cannot be cancelled on shutdown with ConcurrentTaskScheduler (see above)
} }
@Test
@SuppressWarnings("deprecation")
@Override
void submitListenableCallableWithGetAfterShutdown() {
// decorated Future cannot be cancelled on shutdown with ConcurrentTaskScheduler (see above)
}
@Test @Test
void executeFailingRunnableWithErrorHandler() { void executeFailingRunnableWithErrorHandler() {

View File

@ -16,6 +16,7 @@
package org.springframework.scheduling.concurrent; package org.springframework.scheduling.concurrent;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.scheduling.support.DelegatingErrorHandlingRunnable; import org.springframework.scheduling.support.DelegatingErrorHandlingRunnable;
import org.springframework.scheduling.support.TaskUtils; import org.springframework.scheduling.support.TaskUtils;
@ -26,8 +27,7 @@ import org.springframework.scheduling.support.TaskUtils;
class DecoratedThreadPoolTaskExecutorTests extends AbstractSchedulingTaskExecutorTests { class DecoratedThreadPoolTaskExecutorTests extends AbstractSchedulingTaskExecutorTests {
@Override @Override
@SuppressWarnings("removal") protected AsyncTaskExecutor buildExecutor() {
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

@ -27,6 +27,7 @@ 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.AsyncTaskExecutor;
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;
@ -45,8 +46,7 @@ class SimpleAsyncTaskSchedulerTests extends AbstractSchedulingTaskExecutorTests
@Override @Override
@SuppressWarnings("removal") protected AsyncTaskExecutor buildExecutor() {
protected org.springframework.core.task.AsyncListenableTaskExecutor buildExecutor() {
scheduler.setTaskDecorator(runnable -> () -> { scheduler.setTaskDecorator(runnable -> () -> {
taskRun.set(true); taskRun.set(true);
runnable.run(); runnable.run();
@ -62,12 +62,6 @@ class SimpleAsyncTaskSchedulerTests extends AbstractSchedulingTaskExecutorTests
// decorated Future cannot be cancelled on shutdown with SimpleAsyncTaskScheduler // decorated Future cannot be cancelled on shutdown with SimpleAsyncTaskScheduler
} }
@Test
@Override
void submitListenableRunnableWithGetAfterShutdown() {
// decorated Future cannot be cancelled on shutdown with SimpleAsyncTaskScheduler
}
@Test @Test
@Override @Override
void submitCompletableRunnableWithGetAfterShutdown() { void submitCompletableRunnableWithGetAfterShutdown() {
@ -80,13 +74,6 @@ class SimpleAsyncTaskSchedulerTests extends AbstractSchedulingTaskExecutorTests
// decorated Future cannot be cancelled on shutdown with SimpleAsyncTaskScheduler // decorated Future cannot be cancelled on shutdown with SimpleAsyncTaskScheduler
} }
@Test
@SuppressWarnings("deprecation")
@Override
void submitListenableCallableWithGetAfterShutdown() {
// decorated Future cannot be cancelled on shutdown with SimpleAsyncTaskScheduler
}
@Test @Test
@Override @Override
void submitCompletableCallableWithGetAfterShutdown() { void submitCompletableCallableWithGetAfterShutdown() {

View File

@ -23,6 +23,8 @@ import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.core.task.AsyncTaskExecutor;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException; import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
@ -41,8 +43,7 @@ class ThreadPoolTaskExecutorTests extends AbstractSchedulingTaskExecutorTests {
@Override @Override
@SuppressWarnings("removal") protected AsyncTaskExecutor buildExecutor() {
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

@ -28,6 +28,7 @@ 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.AsyncTaskExecutor;
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;
@ -49,8 +50,7 @@ class ThreadPoolTaskSchedulerTests extends AbstractSchedulingTaskExecutorTests {
@Override @Override
@SuppressWarnings("removal") protected AsyncTaskExecutor buildExecutor() {
protected org.springframework.core.task.AsyncListenableTaskExecutor buildExecutor() {
scheduler.setTaskDecorator(runnable -> () -> { scheduler.setTaskDecorator(runnable -> () -> {
taskRun.set(true); taskRun.set(true);
runnable.run(); runnable.run();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2023 the original author or authors. * Copyright 2002-2024 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,9 +35,10 @@ import org.springframework.util.ResourceUtils;
* *
* @author Stephane Nicoll * @author Stephane Nicoll
* @author Sam Brannen * @author Sam Brannen
* @author Juergen Hoeller
* @since 6.0 * @since 6.0
*/ */
public class FilePatternResourceHintsRegistrar { public final class FilePatternResourceHintsRegistrar {
private final List<String> classpathLocations; private final List<String> classpathLocations;
@ -46,26 +47,16 @@ public class FilePatternResourceHintsRegistrar {
private final List<String> fileExtensions; private final List<String> fileExtensions;
/** private FilePatternResourceHintsRegistrar(List<String> filePrefixes, List<String> classpathLocations,
* Create a new instance for the specified file prefixes, classpath locations,
* and file extensions.
* @param filePrefixes the file prefixes
* @param classpathLocations the classpath locations
* @param fileExtensions the file extensions (starting with a dot)
* @deprecated as of 6.0.12 in favor of {@linkplain #forClassPathLocations(String...) the builder}
*/
@Deprecated(since = "6.0.12", forRemoval = true)
public FilePatternResourceHintsRegistrar(List<String> filePrefixes, List<String> classpathLocations,
List<String> fileExtensions) { List<String> fileExtensions) {
this.classpathLocations = validateClasspathLocations(classpathLocations); this.classpathLocations = validateClassPathLocations(classpathLocations);
this.filePrefixes = validateFilePrefixes(filePrefixes); this.filePrefixes = validateFilePrefixes(filePrefixes);
this.fileExtensions = validateFileExtensions(fileExtensions); this.fileExtensions = validateFileExtensions(fileExtensions);
} }
@Deprecated(since = "6.0.12", forRemoval = true) private void registerHints(ResourceHints hints, @Nullable ClassLoader classLoader) {
public void registerHints(ResourceHints hints, @Nullable ClassLoader classLoader) {
ClassLoader classLoaderToUse = (classLoader != null ? classLoader : getClass().getClassLoader()); ClassLoader classLoaderToUse = (classLoader != null ? classLoader : getClass().getClassLoader());
List<String> includes = new ArrayList<>(); List<String> includes = new ArrayList<>();
for (String location : this.classpathLocations) { for (String location : this.classpathLocations) {
@ -85,7 +76,7 @@ public class FilePatternResourceHintsRegistrar {
/** /**
* Configure the registrar with the specified * Configure the registrar with the specified
* {@linkplain Builder#withClasspathLocations(String...) classpath locations}. * {@linkplain Builder#withClassPathLocations(String...) classpath locations}.
* @param classpathLocations the classpath locations * @param classpathLocations the classpath locations
* @return a {@link Builder} to further configure the registrar * @return a {@link Builder} to further configure the registrar
* @since 6.0.12 * @since 6.0.12
@ -97,17 +88,17 @@ public class FilePatternResourceHintsRegistrar {
/** /**
* Configure the registrar with the specified * Configure the registrar with the specified
* {@linkplain Builder#withClasspathLocations(List) classpath locations}. * {@linkplain Builder#withClassPathLocations(List) classpath locations}.
* @param classpathLocations the classpath locations * @param classpathLocations the classpath locations
* @return a {@link Builder} to further configure the registrar * @return a {@link Builder} to further configure the registrar
* @since 6.0.12 * @since 6.0.12
* @see #forClassPathLocations(String...) * @see #forClassPathLocations(String...)
*/ */
public static Builder forClassPathLocations(List<String> classpathLocations) { public static Builder forClassPathLocations(List<String> classpathLocations) {
return new Builder().withClasspathLocations(classpathLocations); return new Builder().withClassPathLocations(classpathLocations);
} }
private static List<String> validateClasspathLocations(List<String> classpathLocations) { private static List<String> validateClassPathLocations(List<String> classpathLocations) {
Assert.notEmpty(classpathLocations, "At least one classpath location must be specified"); Assert.notEmpty(classpathLocations, "At least one classpath location must be specified");
List<String> parsedLocations = new ArrayList<>(); List<String> parsedLocations = new ArrayList<>();
for (String location : classpathLocations) { for (String location : classpathLocations) {
@ -162,15 +153,20 @@ public class FilePatternResourceHintsRegistrar {
/** /**
* Consider the specified classpath locations. * Consider the specified classpath locations.
* <p>A location can either be a special {@value ResourceUtils#CLASSPATH_URL_PREFIX} * @deprecated in favor of {@link #withClassPathLocations(String...)}
* pseudo location or a standard location, such as {@code com/example/resources}.
* An empty String represents the root of the classpath.
* @param classpathLocations the classpath locations to consider
* @return this builder
* @see #withClasspathLocations(List)
*/ */
@Deprecated(since = "7.0", forRemoval = true)
public Builder withClasspathLocations(String... classpathLocations) { public Builder withClasspathLocations(String... classpathLocations) {
return withClasspathLocations(Arrays.asList(classpathLocations)); return withClassPathLocations(Arrays.asList(classpathLocations));
}
/**
* Consider the specified classpath locations.
* @deprecated in favor of {@link #withClassPathLocations(List)}
*/
@Deprecated(since = "7.0", forRemoval = true)
public Builder withClasspathLocations(List<String> classpathLocations) {
return withClassPathLocations(classpathLocations);
} }
/** /**
@ -180,10 +176,25 @@ public class FilePatternResourceHintsRegistrar {
* An empty String represents the root of the classpath. * An empty String represents the root of the classpath.
* @param classpathLocations the classpath locations to consider * @param classpathLocations the classpath locations to consider
* @return this builder * @return this builder
* @see #withClasspathLocations(String...) * @since 7.0
* @see #withClassPathLocations(List)
*/ */
public Builder withClasspathLocations(List<String> classpathLocations) { public Builder withClassPathLocations(String... classpathLocations) {
this.classpathLocations.addAll(validateClasspathLocations(classpathLocations)); return withClassPathLocations(Arrays.asList(classpathLocations));
}
/**
* Consider the specified classpath locations.
* <p>A location can either be a special {@value ResourceUtils#CLASSPATH_URL_PREFIX}
* pseudo location or a standard location, such as {@code com/example/resources}.
* An empty String represents the root of the classpath.
* @param classpathLocations the classpath locations to consider
* @return this builder
* @since 7.0
* @see #withClassPathLocations(String...)
*/
public Builder withClassPathLocations(List<String> classpathLocations) {
this.classpathLocations.addAll(validateClassPathLocations(classpathLocations));
return this; return this;
} }
@ -235,7 +246,6 @@ public class FilePatternResourceHintsRegistrar {
return this; return this;
} }
private FilePatternResourceHintsRegistrar build() { private FilePatternResourceHintsRegistrar build() {
return new FilePatternResourceHintsRegistrar(this.filePrefixes, return new FilePatternResourceHintsRegistrar(this.filePrefixes,
this.classpathLocations, this.fileExtensions); this.classpathLocations, this.fileExtensions);

View File

@ -1,58 +0,0 @@
/*
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.task;
import java.util.concurrent.Callable;
/**
* Extension of the {@link AsyncTaskExecutor} interface, adding the capability to submit
* tasks for {@code ListenableFutures}.
*
* @author Arjen Poutsma
* @since 4.0
* @deprecated as of 6.0, in favor of
* {@link AsyncTaskExecutor#submitCompletable(Runnable)} and
* {@link AsyncTaskExecutor#submitCompletable(Callable)}
*/
@Deprecated(since = "6.0", forRemoval = true)
@SuppressWarnings("removal")
public interface AsyncListenableTaskExecutor extends AsyncTaskExecutor {
/**
* Submit a {@code Runnable} task for execution, receiving a {@code ListenableFuture}
* representing that task. The Future will return a {@code null} result upon completion.
* @param task the {@code Runnable} to execute (never {@code null})
* @return a {@code ListenableFuture} representing pending completion of the task
* @throws TaskRejectedException if the given task was not accepted
* @deprecated in favor of {@link AsyncTaskExecutor#submitCompletable(Runnable)}
*/
@Deprecated(since = "6.0", forRemoval = true)
org.springframework.util.concurrent.ListenableFuture<?> submitListenable(Runnable task);
/**
* Submit a {@code Callable} task for execution, receiving a {@code ListenableFuture}
* representing that task. The Future will return the Callable's result upon
* completion.
* @param task the {@code Callable} to execute (never {@code null})
* @return a {@code ListenableFuture} representing pending completion of the task
* @throws TaskRejectedException if the given task was not accepted
* @deprecated in favor of {@link AsyncTaskExecutor#submitCompletable(Callable)}
*/
@Deprecated(since = "6.0", forRemoval = true)
<T> org.springframework.util.concurrent.ListenableFuture<T> submitListenable(Callable<T> task);
}

View File

@ -28,8 +28,6 @@ import org.springframework.lang.Nullable;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.ConcurrencyThrottleSupport; import org.springframework.util.ConcurrencyThrottleSupport;
import org.springframework.util.CustomizableThreadCreator; import org.springframework.util.CustomizableThreadCreator;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureTask;
/** /**
* {@link TaskExecutor} implementation that fires up a new Thread for each task, * {@link TaskExecutor} implementation that fires up a new Thread for each task,
@ -58,9 +56,9 @@ import org.springframework.util.concurrent.ListenableFutureTask;
* @see org.springframework.scheduling.concurrent.SimpleAsyncTaskScheduler * @see org.springframework.scheduling.concurrent.SimpleAsyncTaskScheduler
* @see org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor * @see org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor
*/ */
@SuppressWarnings({"serial", "removal"}) @SuppressWarnings("serial")
public class SimpleAsyncTaskExecutor extends CustomizableThreadCreator public class SimpleAsyncTaskExecutor extends CustomizableThreadCreator
implements AsyncListenableTaskExecutor, Serializable, AutoCloseable { implements AsyncTaskExecutor, Serializable, AutoCloseable {
/** /**
* Permit any number of concurrent invocations: that is, don't throttle concurrency. * Permit any number of concurrent invocations: that is, don't throttle concurrency.
@ -294,22 +292,6 @@ public class SimpleAsyncTaskExecutor extends CustomizableThreadCreator
return future; return future;
} }
@SuppressWarnings("deprecation")
@Override
public ListenableFuture<?> submitListenable(Runnable task) {
ListenableFutureTask<Object> future = new ListenableFutureTask<>(task, null);
execute(future, TIMEOUT_INDEFINITE);
return future;
}
@SuppressWarnings("deprecation")
@Override
public <T> ListenableFuture<T> submitListenable(Callable<T> task) {
ListenableFutureTask<T> future = new ListenableFutureTask<>(task);
execute(future, TIMEOUT_INDEFINITE);
return future;
}
/** /**
* Template method for the actual execution of a task. * Template method for the actual execution of a task.
* <p>The default implementation creates a new Thread and starts it. * <p>The default implementation creates a new Thread and starts it.

View File

@ -23,13 +23,11 @@ import java.util.concurrent.Future;
import java.util.concurrent.FutureTask; import java.util.concurrent.FutureTask;
import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.RejectedExecutionException;
import org.springframework.core.task.AsyncListenableTaskExecutor; import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.core.task.TaskDecorator; import org.springframework.core.task.TaskDecorator;
import org.springframework.core.task.TaskRejectedException; import org.springframework.core.task.TaskRejectedException;
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.util.concurrent.ListenableFutureTask;
/** /**
* Adapter that takes a JDK {@code java.util.concurrent.Executor} and * Adapter that takes a JDK {@code java.util.concurrent.Executor} and
@ -43,8 +41,8 @@ import org.springframework.util.concurrent.ListenableFutureTask;
* @see java.util.concurrent.ExecutorService * @see java.util.concurrent.ExecutorService
* @see java.util.concurrent.Executors * @see java.util.concurrent.Executors
*/ */
@SuppressWarnings({"deprecation", "removal"}) @SuppressWarnings("deprecation")
public class TaskExecutorAdapter implements AsyncListenableTaskExecutor { public class TaskExecutorAdapter implements AsyncTaskExecutor {
private final Executor concurrentExecutor; private final Executor concurrentExecutor;
@ -133,30 +131,6 @@ public class TaskExecutorAdapter implements AsyncListenableTaskExecutor {
} }
} }
@Override
public ListenableFuture<?> submitListenable(Runnable task) {
try {
ListenableFutureTask<Object> future = new ListenableFutureTask<>(task, null);
doExecute(this.concurrentExecutor, this.taskDecorator, future);
return future;
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException(this.concurrentExecutor, task, ex);
}
}
@Override
public <T> ListenableFuture<T> submitListenable(Callable<T> task) {
try {
ListenableFutureTask<T> future = new ListenableFutureTask<>(task);
doExecute(this.concurrentExecutor, this.taskDecorator, future);
return future;
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException(this.concurrentExecutor, task, ex);
}
}
/** /**
* Actually execute the given {@code Runnable} (which may be a user-supplied task * Actually execute the given {@code Runnable} (which may be a user-supplied task

View File

@ -23,7 +23,6 @@ import java.nio.charset.Charset;
import java.util.BitSet; import java.util.BitSet;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Locale; import java.util.Locale;
@ -695,48 +694,4 @@ public class MimeType implements Comparable<MimeType>, Serializable {
return map; return map;
} }
/**
* Comparator to sort {@link MimeType MimeTypes} in order of specificity.
*
* @param <T> the type of mime types that may be compared by this comparator
* @deprecated As of 6.0, with no direct replacement
*/
@Deprecated(since = "6.0", forRemoval = true)
public static class SpecificityComparator<T extends MimeType> implements Comparator<T> {
@Override
public int compare(T mimeType1, T mimeType2) {
if (mimeType1.isWildcardType() && !mimeType2.isWildcardType()) { // */* < audio/*
return 1;
}
else if (mimeType2.isWildcardType() && !mimeType1.isWildcardType()) { // audio/* > */*
return -1;
}
else if (!mimeType1.getType().equals(mimeType2.getType())) { // audio/basic == text/html
return 0;
}
else { // mediaType1.getType().equals(mediaType2.getType())
if (mimeType1.isWildcardSubtype() && !mimeType2.isWildcardSubtype()) { // audio/* < audio/basic
return 1;
}
else if (mimeType2.isWildcardSubtype() && !mimeType1.isWildcardSubtype()) { // audio/basic > audio/*
return -1;
}
else if (!mimeType1.getSubtype().equals(mimeType2.getSubtype())) { // audio/basic == audio/wave
return 0;
}
else { // mediaType2.getSubtype().equals(mediaType2.getSubtype())
return compareParameters(mimeType1, mimeType2);
}
}
}
protected int compareParameters(T mimeType1, T mimeType2) {
int paramsSize1 = mimeType1.getParameters().size();
int paramsSize2 = mimeType2.getParameters().size();
return Integer.compare(paramsSize2, paramsSize1); // audio/basic;level=1 < audio/basic
}
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2023 the original author or authors. * Copyright 2002-2024 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.
@ -22,7 +22,6 @@ import java.security.SecureRandom;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
@ -51,14 +50,6 @@ public abstract class MimeTypeUtils {
'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
'V', 'W', 'X', 'Y', 'Z'}; 'V', 'W', 'X', 'Y', 'Z'};
/**
* Comparator formally used by {@link #sortBySpecificity(List)}.
* @deprecated As of 6.0, with no direct replacement
*/
@SuppressWarnings("removal")
@Deprecated(since = "6.0", forRemoval = true)
public static final Comparator<MimeType> SPECIFICITY_COMPARATOR = new MimeType.SpecificityComparator<>();
/** /**
* Public constant mime type that includes all media ranges (i.e. "&#42;/&#42;"). * Public constant mime type that includes all media ranges (i.e. "&#42;/&#42;").
*/ */

View File

@ -49,24 +49,6 @@ public class PropertyPlaceholderHelper {
this(placeholderPrefix, placeholderSuffix, null, null, true); this(placeholderPrefix, placeholderSuffix, null, null, true);
} }
/**
* Create a new {@code PropertyPlaceholderHelper} that uses the supplied prefix and suffix.
* @param placeholderPrefix the prefix that denotes the start of a placeholder
* @param placeholderSuffix the suffix that denotes the end of a placeholder
* @param valueSeparator the separating character between the placeholder variable
* and the associated default value, if any
* @param ignoreUnresolvablePlaceholders indicates whether unresolvable placeholders should
* be ignored ({@code true}) or cause an exception ({@code false})
* @deprecated as of 6.2, in favor of
* {@link PropertyPlaceholderHelper#PropertyPlaceholderHelper(String, String, String, Character, boolean)}
*/
@Deprecated(since = "6.2", forRemoval = true)
public PropertyPlaceholderHelper(String placeholderPrefix, String placeholderSuffix,
@Nullable String valueSeparator, boolean ignoreUnresolvablePlaceholders) {
this(placeholderPrefix, placeholderSuffix, valueSeparator, null, ignoreUnresolvablePlaceholders);
}
/** /**
* Create a new {@code PropertyPlaceholderHelper} that uses the supplied prefix and suffix. * Create a new {@code PropertyPlaceholderHelper} that uses the supplied prefix and suffix.
* @param placeholderPrefix the prefix that denotes the start of a placeholder * @param placeholderPrefix the prefix that denotes the start of a placeholder

View File

@ -1,110 +0,0 @@
/*
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.util.concurrent;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* Adapts a {@link CompletableFuture} or {@link CompletionStage} into a
* Spring {@link ListenableFuture}.
*
* @author Sebastien Deleuze
* @author Juergen Hoeller
* @since 4.2
* @param <T> the result type returned by this Future's {@code get} method
* @deprecated as of 6.0, with no concrete replacement
*/
@Deprecated(since = "6.0", forRemoval = true)
@SuppressWarnings("removal")
public class CompletableToListenableFutureAdapter<T> implements ListenableFuture<T> {
private final CompletableFuture<T> completableFuture;
private final ListenableFutureCallbackRegistry<T> callbacks = new ListenableFutureCallbackRegistry<>();
/**
* Create a new adapter for the given {@link CompletionStage}.
* @since 4.3.7
*/
public CompletableToListenableFutureAdapter(CompletionStage<T> completionStage) {
this(completionStage.toCompletableFuture());
}
/**
* Create a new adapter for the given {@link CompletableFuture}.
*/
public CompletableToListenableFutureAdapter(CompletableFuture<T> completableFuture) {
this.completableFuture = completableFuture;
this.completableFuture.whenComplete((result, ex) -> {
if (ex != null) {
this.callbacks.failure(ex);
}
else {
this.callbacks.success(result);
}
});
}
@Override
public void addCallback(ListenableFutureCallback<? super T> callback) {
this.callbacks.addCallback(callback);
}
@Override
public void addCallback(SuccessCallback<? super T> successCallback, FailureCallback failureCallback) {
this.callbacks.addSuccessCallback(successCallback);
this.callbacks.addFailureCallback(failureCallback);
}
@Override
public CompletableFuture<T> completable() {
return this.completableFuture;
}
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
return this.completableFuture.cancel(mayInterruptIfRunning);
}
@Override
public boolean isCancelled() {
return this.completableFuture.isCancelled();
}
@Override
public boolean isDone() {
return this.completableFuture.isDone();
}
@Override
public T get() throws InterruptedException, ExecutionException {
return this.completableFuture.get();
}
@Override
public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
return this.completableFuture.get(timeout, unit);
}
}

View File

@ -1,40 +0,0 @@
/*
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.util.concurrent;
import java.util.function.BiConsumer;
/**
* Failure callback for a {@link ListenableFuture}.
*
* @author Sebastien Deleuze
* @since 4.1
* @deprecated as of 6.0, in favor of
* {@link java.util.concurrent.CompletableFuture#whenComplete(BiConsumer)}
*/
@Deprecated(since = "6.0", forRemoval = true)
@FunctionalInterface
public interface FailureCallback {
/**
* Called when the {@link ListenableFuture} completes with failure.
* <p>Note that Exceptions raised by this method are ignored.
* @param ex the failure
*/
void onFailure(Throwable ex);
}

View File

@ -1,74 +0,0 @@
/*
* Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.util.concurrent;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
import java.util.function.BiConsumer;
/**
* Extend {@link Future} with the capability to accept completion callbacks.
* If the future has completed when the callback is added, the callback is
* triggered immediately.
*
* <p>Inspired by {@code com.google.common.util.concurrent.ListenableFuture}.
*
* @author Arjen Poutsma
* @author Sebastien Deleuze
* @author Juergen Hoeller
* @since 4.0
* @param <T> the result type returned by this Future's {@code get} method
* @deprecated as of 6.0, in favor of {@link CompletableFuture}
*/
@Deprecated(since = "6.0", forRemoval = true)
public interface ListenableFuture<T> extends Future<T> {
/**
* Register the given {@code ListenableFutureCallback}.
* @param callback the callback to register
* @deprecated as of 6.0, in favor of
* {@link CompletableFuture#whenComplete(BiConsumer)}
*/
@Deprecated(since = "6.0", forRemoval = true)
@SuppressWarnings("removal")
void addCallback(ListenableFutureCallback<? super T> callback);
/**
* Java 8 lambda-friendly alternative with success and failure callbacks.
* @param successCallback the success callback
* @param failureCallback the failure callback
* @since 4.1
* @deprecated as of 6.0, in favor of
* {@link CompletableFuture#whenComplete(BiConsumer)}
*/
@Deprecated(since = "6.0", forRemoval = true)
@SuppressWarnings("removal")
void addCallback(SuccessCallback<? super T> successCallback, FailureCallback failureCallback);
/**
* Expose this {@link ListenableFuture} as a JDK {@link CompletableFuture}.
* @since 5.0
*/
@SuppressWarnings("NullAway")
default CompletableFuture<T> completable() {
CompletableFuture<T> completable = new DelegatingCompletableFuture<>(this);
addCallback(completable::complete, completable::completeExceptionally);
return completable;
}
}

View File

@ -1,86 +0,0 @@
/*
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.util.concurrent;
import java.util.concurrent.ExecutionException;
import org.springframework.lang.Nullable;
/**
* Abstract class that adapts a {@link ListenableFuture} parameterized over S into a
* {@code ListenableFuture} parameterized over T. All methods are delegated to the
* adaptee, where {@link #get()}, {@link #get(long, java.util.concurrent.TimeUnit)},
* and {@link ListenableFutureCallback#onSuccess(Object)} call {@link #adapt(Object)}
* on the adaptee's result.
*
* @author Arjen Poutsma
* @since 4.0
* @param <T> the type of this {@code Future}
* @param <S> the type of the adaptee's {@code Future}
* @deprecated as of 6.0, in favor of
* {@link java.util.concurrent.CompletableFuture}
*/
@Deprecated(since = "6.0", forRemoval = true)
@SuppressWarnings("removal")
public abstract class ListenableFutureAdapter<T, S> extends FutureAdapter<T, S> implements ListenableFuture<T> {
/**
* Construct a new {@code ListenableFutureAdapter} with the given adaptee.
* @param adaptee the future to adapt to
*/
protected ListenableFutureAdapter(ListenableFuture<S> adaptee) {
super(adaptee);
}
@Override
public void addCallback(final ListenableFutureCallback<? super T> callback) {
addCallback(callback, callback);
}
@Override
public void addCallback(final SuccessCallback<? super T> successCallback, final FailureCallback failureCallback) {
ListenableFuture<S> listenableAdaptee = (ListenableFuture<S>) getAdaptee();
listenableAdaptee.addCallback(new ListenableFutureCallback<>() {
@Override
public void onSuccess(@Nullable S result) {
T adapted = null;
if (result != null) {
try {
adapted = adaptInternal(result);
}
catch (ExecutionException ex) {
Throwable cause = ex.getCause();
onFailure(cause != null ? cause : ex);
return;
}
catch (Throwable ex) {
onFailure(ex);
return;
}
}
successCallback.onSuccess(adapted);
}
@Override
public void onFailure(Throwable ex) {
failureCallback.onFailure(ex);
}
});
}
}

View File

@ -1,36 +0,0 @@
/*
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.util.concurrent;
import java.util.function.BiConsumer;
/**
* Callback mechanism for the outcome, success or failure, from a
* {@link ListenableFuture}.
*
* @author Arjen Poutsma
* @author Sebastien Deleuze
* @since 4.0
* @param <T> the result type
* @deprecated as of 6.0, in favor of
* {@link java.util.concurrent.CompletableFuture#whenComplete(BiConsumer)}
*/
@Deprecated(since = "6.0", forRemoval = true)
@SuppressWarnings("removal")
public interface ListenableFutureCallback<T> extends SuccessCallback<T>, FailureCallback {
}

View File

@ -1,157 +0,0 @@
/*
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.util.concurrent;
import java.util.ArrayDeque;
import java.util.Queue;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* Helper class for {@link ListenableFuture} implementations that maintains a queue
* of success and failure callbacks and helps to notify them.
*
* <p>Inspired by {@code com.google.common.util.concurrent.ExecutionList}.
*
* @author Arjen Poutsma
* @author Sebastien Deleuze
* @author Rossen Stoyanchev
* @since 4.0
* @param <T> the callback result type
* @deprecated as of 6.0, with no concrete replacement
*/
@Deprecated(since = "6.0", forRemoval = true)
@SuppressWarnings("removal")
public class ListenableFutureCallbackRegistry<T> {
private final Queue<SuccessCallback<? super T>> successCallbacks = new ArrayDeque<>(1);
private final Queue<FailureCallback> failureCallbacks = new ArrayDeque<>(1);
private State state = State.NEW;
@Nullable
private Object result;
private final Object mutex = new Object();
/**
* Add the given callback to this registry.
* @param callback the callback to add
*/
public void addCallback(ListenableFutureCallback<? super T> callback) {
Assert.notNull(callback, "'callback' must not be null");
synchronized (this.mutex) {
switch (this.state) {
case NEW -> {
this.successCallbacks.add(callback);
this.failureCallbacks.add(callback);
}
case SUCCESS -> notifySuccess(callback);
case FAILURE -> notifyFailure(callback);
}
}
}
@SuppressWarnings("unchecked")
private void notifySuccess(SuccessCallback<? super T> callback) {
try {
callback.onSuccess((T) this.result);
}
catch (Throwable ex) {
// Ignore
}
}
private void notifyFailure(FailureCallback callback) {
Assert.state(this.result instanceof Throwable, "No Throwable result for failure state");
try {
callback.onFailure((Throwable) this.result);
}
catch (Throwable ex) {
// Ignore
}
}
/**
* Add the given success callback to this registry.
* @param callback the success callback to add
* @since 4.1
*/
public void addSuccessCallback(SuccessCallback<? super T> callback) {
Assert.notNull(callback, "'callback' must not be null");
synchronized (this.mutex) {
switch (this.state) {
case NEW -> this.successCallbacks.add(callback);
case SUCCESS -> notifySuccess(callback);
}
}
}
/**
* Add the given failure callback to this registry.
* @param callback the failure callback to add
* @since 4.1
*/
public void addFailureCallback(FailureCallback callback) {
Assert.notNull(callback, "'callback' must not be null");
synchronized (this.mutex) {
switch (this.state) {
case NEW -> this.failureCallbacks.add(callback);
case FAILURE -> notifyFailure(callback);
}
}
}
/**
* Trigger a {@link ListenableFutureCallback#onSuccess(Object)} call on all
* added callbacks with the given result.
* @param result the result to trigger the callbacks with
*/
public void success(@Nullable T result) {
synchronized (this.mutex) {
this.state = State.SUCCESS;
this.result = result;
SuccessCallback<? super T> callback;
while ((callback = this.successCallbacks.poll()) != null) {
notifySuccess(callback);
}
}
}
/**
* Trigger a {@link ListenableFutureCallback#onFailure(Throwable)} call on all
* added callbacks with the given {@code Throwable}.
* @param ex the exception to trigger the callbacks with
*/
public void failure(Throwable ex) {
synchronized (this.mutex) {
this.state = State.FAILURE;
this.result = ex;
FailureCallback callback;
while ((callback = this.failureCallbacks.poll()) != null) {
notifyFailure(callback);
}
}
}
private enum State {NEW, SUCCESS, FAILURE}
}

View File

@ -1,107 +0,0 @@
/*
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.util.concurrent;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import org.springframework.lang.Nullable;
/**
* Extension of {@link FutureTask} that implements {@link ListenableFuture}.
*
* @author Arjen Poutsma
* @since 4.0
* @param <T> the result type returned by this Future's {@code get} method
* @deprecated as of 6.0, with no concrete replacement
*/
@Deprecated(since = "6.0", forRemoval = true)
@SuppressWarnings("removal")
public class ListenableFutureTask<T> extends FutureTask<T> implements ListenableFuture<T> {
private final ListenableFutureCallbackRegistry<T> callbacks = new ListenableFutureCallbackRegistry<>();
/**
* Create a new {@code ListenableFutureTask} that will, upon running,
* execute the given {@link Callable}.
* @param callable the callable task
*/
public ListenableFutureTask(Callable<T> callable) {
super(callable);
}
/**
* Create a {@code ListenableFutureTask} that will, upon running,
* execute the given {@link Runnable}, and arrange that {@link #get()}
* will return the given result on successful completion.
* @param runnable the runnable task
* @param result the result to return on successful completion
*/
public ListenableFutureTask(Runnable runnable, @Nullable T result) {
super(runnable, result);
}
@Override
public void addCallback(ListenableFutureCallback<? super T> callback) {
this.callbacks.addCallback(callback);
}
@Override
public void addCallback(SuccessCallback<? super T> successCallback, FailureCallback failureCallback) {
this.callbacks.addSuccessCallback(successCallback);
this.callbacks.addFailureCallback(failureCallback);
}
@Override
@SuppressWarnings("NullAway")
public CompletableFuture<T> completable() {
CompletableFuture<T> completable = new DelegatingCompletableFuture<>(this);
this.callbacks.addSuccessCallback(completable::complete);
this.callbacks.addFailureCallback(completable::completeExceptionally);
return completable;
}
@Override
protected void done() {
Throwable cause;
try {
T result = get();
this.callbacks.success(result);
return;
}
catch (InterruptedException ex) {
Thread.currentThread().interrupt();
return;
}
catch (ExecutionException ex) {
cause = ex.getCause();
if (cause == null) {
cause = ex;
}
}
catch (Throwable ex) {
cause = ex;
}
this.callbacks.failure(cause);
}
}

View File

@ -1,40 +0,0 @@
/*
* Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.util.concurrent;
import reactor.core.publisher.Mono;
/**
* Adapts a {@link Mono} into a {@link ListenableFuture} by obtaining a
* {@code CompletableFuture} from the {@code Mono} via {@link Mono#toFuture()}
* and then adapting it with {@link CompletableToListenableFutureAdapter}.
*
* @author Rossen Stoyanchev
* @author Stephane Maldini
* @since 5.1
* @param <T> the object type
* @deprecated as of 6.0, in favor of {@link Mono#toFuture()}
*/
@Deprecated(since = "6.0")
@SuppressWarnings("removal")
public class MonoToListenableFutureAdapter<T> extends CompletableToListenableFutureAdapter<T> {
public MonoToListenableFutureAdapter(Mono<T> mono) {
super(mono.toFuture());
}
}

View File

@ -1,192 +0,0 @@
/*
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.util.concurrent;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* A {@link ListenableFuture} whose value can be set via {@link #set(Object)}
* or {@link #setException(Throwable)}. It may also get cancelled.
*
* <p>Inspired by {@code com.google.common.util.concurrent.SettableFuture}.
*
* @author Mattias Severson
* @author Rossen Stoyanchev
* @author Juergen Hoeller
* @since 4.1
* @param <T> the result type returned by this Future's {@code get} method
* @deprecated as of 6.0, in favor of {@link CompletableFuture}
*/
@Deprecated(since = "6.0", forRemoval = true)
@SuppressWarnings("removal")
public class SettableListenableFuture<T> implements ListenableFuture<T> {
private static final Callable<Object> DUMMY_CALLABLE = () -> {
throw new IllegalStateException("Should never be called");
};
private final SettableTask<T> settableTask = new SettableTask<>();
/**
* Set the value of this future. This method will return {@code true} if the
* value was set successfully, or {@code false} if the future has already been
* set or cancelled.
* @param value the value that will be set
* @return {@code true} if the value was successfully set, else {@code false}
*/
public boolean set(@Nullable T value) {
return this.settableTask.setResultValue(value);
}
/**
* Set the exception of this future. This method will return {@code true} if the
* exception was set successfully, or {@code false} if the future has already been
* set or cancelled.
* @param exception the value that will be set
* @return {@code true} if the exception was successfully set, else {@code false}
*/
public boolean setException(Throwable exception) {
Assert.notNull(exception, "Exception must not be null");
return this.settableTask.setExceptionResult(exception);
}
@Override
public void addCallback(ListenableFutureCallback<? super T> callback) {
this.settableTask.addCallback(callback);
}
@Override
public void addCallback(SuccessCallback<? super T> successCallback, FailureCallback failureCallback) {
this.settableTask.addCallback(successCallback, failureCallback);
}
@Override
public CompletableFuture<T> completable() {
return this.settableTask.completable();
}
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
boolean cancelled = this.settableTask.cancel(mayInterruptIfRunning);
if (cancelled && mayInterruptIfRunning) {
interruptTask();
}
return cancelled;
}
@Override
public boolean isCancelled() {
return this.settableTask.isCancelled();
}
@Override
public boolean isDone() {
return this.settableTask.isDone();
}
/**
* Retrieve the value.
* <p>This method returns the value if it has been set via {@link #set(Object)},
* throws an {@link java.util.concurrent.ExecutionException} if an exception has
* been set via {@link #setException(Throwable)}, or throws a
* {@link java.util.concurrent.CancellationException} if the future has been cancelled.
* @return the value associated with this future
*/
@Nullable
@Override
public T get() throws InterruptedException, ExecutionException {
return this.settableTask.get();
}
/**
* Retrieve the value.
* <p>This method returns the value if it has been set via {@link #set(Object)},
* throws an {@link java.util.concurrent.ExecutionException} if an exception has
* been set via {@link #setException(Throwable)}, or throws a
* {@link java.util.concurrent.CancellationException} if the future has been cancelled.
* @param timeout the maximum time to wait
* @param unit the unit of the timeout argument
* @return the value associated with this future
*/
@Nullable
@Override
public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
return this.settableTask.get(timeout, unit);
}
/**
* Subclasses can override this method to implement interruption of the future's
* computation. The method is invoked automatically by a successful call to
* {@link #cancel(boolean) cancel(true)}.
* <p>The default implementation is empty.
*/
protected void interruptTask() {
}
private static class SettableTask<T> extends ListenableFutureTask<T> {
@Nullable
private volatile Thread completingThread;
@SuppressWarnings("unchecked")
public SettableTask() {
super((Callable<T>) DUMMY_CALLABLE);
}
public boolean setResultValue(@Nullable T value) {
set(value);
return checkCompletingThread();
}
public boolean setExceptionResult(Throwable exception) {
setException(exception);
return checkCompletingThread();
}
@Override
protected void done() {
if (!isCancelled()) {
// Implicitly invoked by set/setException: store current thread for
// determining whether the given result has actually triggered completion
// (since FutureTask.set/setException unfortunately don't expose that)
this.completingThread = Thread.currentThread();
}
super.done();
}
private boolean checkCompletingThread() {
boolean check = (this.completingThread == Thread.currentThread());
if (check) {
this.completingThread = null; // only first match actually counts
}
return check;
}
}
}

View File

@ -1,43 +0,0 @@
/*
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.util.concurrent;
import java.util.function.BiConsumer;
import org.springframework.lang.Nullable;
/**
* Success callback for a {@link ListenableFuture}.
*
* @author Sebastien Deleuze
* @since 4.1
* @param <T> the result type
* @deprecated as of 6.0, in favor of
* {@link java.util.concurrent.CompletableFuture#whenComplete(BiConsumer)}
*/
@Deprecated(since = "6.0", forRemoval = true)
@FunctionalInterface
public interface SuccessCallback<T> {
/**
* Called when the {@link ListenableFuture} completes with success.
* <p>Note that Exceptions raised by this method are ignored.
* @param result the result
*/
void onSuccess(@Nullable T result);
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2023 the original author or authors. * Copyright 2002-2024 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.
@ -78,7 +78,7 @@ class FilePatternResourceHintsRegistrarTests {
@Test @Test
void registerWithMultipleClasspathLocations() { void registerWithMultipleClasspathLocations() {
FilePatternResourceHintsRegistrar.forClassPathLocations("").withClasspathLocations("META-INF") FilePatternResourceHintsRegistrar.forClassPathLocations("").withClassPathLocations("META-INF")
.withFilePrefixes("test").withFileExtensions(".txt") .withFilePrefixes("test").withFileExtensions(".txt")
.registerHints(this.hints, null); .registerHints(this.hints, null);
assertThat(this.hints.resourcePatternHints()).singleElement() assertThat(this.hints.resourcePatternHints()).singleElement()
@ -133,7 +133,7 @@ class FilePatternResourceHintsRegistrarTests {
@Test @Test
void registerWithNonExistingLocationDoesNotRegisterHint() { void registerWithNonExistingLocationDoesNotRegisterHint() {
FilePatternResourceHintsRegistrar.forClassPathLocations("does-not-exist/") FilePatternResourceHintsRegistrar.forClassPathLocations("does-not-exist/")
.withClasspathLocations("another-does-not-exist/") .withClassPathLocations("another-does-not-exist/")
.withFilePrefixes("test").withFileExtensions(".txt") .withFilePrefixes("test").withFileExtensions(".txt")
.registerHints(this.hints, null); .registerHints(this.hints, null);
assertThat(this.hints.resourcePatternHints()).isEmpty(); assertThat(this.hints.resourcePatternHints()).isEmpty();

View File

@ -1,138 +0,0 @@
/*
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.util.concurrent;
import java.io.IOException;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.fail;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
/**
* @author Arjen Poutsma
* @author Sebastien Deleuze
*/
@SuppressWarnings({"deprecation", "removal"})
class ListenableFutureTaskTests {
@Test
void success() throws Exception {
final String s = "Hello World";
Callable<String> callable = () -> s;
ListenableFutureTask<String> task = new ListenableFutureTask<>(callable);
task.addCallback(new ListenableFutureCallback<>() {
@Override
public void onSuccess(String result) {
assertThat(result).isEqualTo(s);
}
@Override
public void onFailure(Throwable ex) {
throw new AssertionError(ex.getMessage(), ex);
}
});
task.run();
assertThat(task.get()).isSameAs(s);
assertThat(task.completable().get()).isSameAs(s);
task.completable().thenAccept(v -> assertThat(v).isSameAs(s));
}
@Test
void failure() {
final String s = "Hello World";
Callable<String> callable = () -> {
throw new IOException(s);
};
ListenableFutureTask<String> task = new ListenableFutureTask<>(callable);
task.addCallback(new ListenableFutureCallback<>() {
@Override
public void onSuccess(String result) {
fail("onSuccess not expected");
}
@Override
public void onFailure(Throwable ex) {
assertThat(ex.getMessage()).isEqualTo(s);
}
});
task.run();
assertThatExceptionOfType(ExecutionException.class)
.isThrownBy(task::get)
.havingCause()
.withMessage(s);
assertThatExceptionOfType(ExecutionException.class)
.isThrownBy(task.completable()::get)
.havingCause()
.withMessage(s);
}
@Test
void successWithLambdas() throws Exception {
final String s = "Hello World";
Callable<String> callable = () -> s;
SuccessCallback<String> successCallback = mock();
FailureCallback failureCallback = mock();
ListenableFutureTask<String> task = new ListenableFutureTask<>(callable);
task.addCallback(successCallback, failureCallback);
task.run();
verify(successCallback).onSuccess(s);
verifyNoInteractions(failureCallback);
assertThat(task.get()).isSameAs(s);
assertThat(task.completable().get()).isSameAs(s);
task.completable().thenAccept(v -> assertThat(v).isSameAs(s));
}
@Test
void failureWithLambdas() {
final String s = "Hello World";
IOException ex = new IOException(s);
Callable<String> callable = () -> {
throw ex;
};
SuccessCallback<String> successCallback = mock();
FailureCallback failureCallback = mock();
ListenableFutureTask<String> task = new ListenableFutureTask<>(callable);
task.addCallback(successCallback, failureCallback);
task.run();
verify(failureCallback).onFailure(ex);
verifyNoInteractions(successCallback);
assertThatExceptionOfType(ExecutionException.class)
.isThrownBy(task::get)
.havingCause()
.withMessage(s);
assertThatExceptionOfType(ExecutionException.class)
.isThrownBy(task.completable()::get)
.havingCause()
.withMessage(s);
}
}

View File

@ -1,74 +0,0 @@
/*
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.util.concurrent;
import java.time.Duration;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.jupiter.api.Test;
import reactor.core.publisher.Mono;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link MonoToListenableFutureAdapter}.
*
* @author Rossen Stoyanchev
*/
@SuppressWarnings({"deprecation", "removal"})
class MonoToListenableFutureAdapterTests {
@Test
void success() {
String expected = "one";
AtomicReference<Object> actual = new AtomicReference<>();
ListenableFuture<String> future = new MonoToListenableFutureAdapter<>(Mono.just(expected));
future.addCallback(actual::set, actual::set);
assertThat(actual.get()).isEqualTo(expected);
}
@Test
@SuppressWarnings("deprecation")
void failure() {
Throwable expected = new IllegalStateException("oops");
AtomicReference<Object> actual = new AtomicReference<>();
ListenableFuture<String> future = new MonoToListenableFutureAdapter<>(Mono.error(expected));
future.addCallback(actual::set, actual::set);
assertThat(actual.get()).isEqualTo(expected);
}
@Test
void cancellation() {
Mono<Long> mono = Mono.delay(Duration.ofSeconds(60));
Future<Long> future = new MonoToListenableFutureAdapter<>(mono);
assertThat(future.cancel(true)).isTrue();
assertThat(future.isCancelled()).isTrue();
}
@Test
void cancellationAfterTerminated() {
Future<Void> future = new MonoToListenableFutureAdapter<>(Mono.empty());
assertThat(future.cancel(true)).as("Should return false if task already completed").isFalse();
assertThat(future.isCancelled()).isFalse();
}
}

View File

@ -1,414 +0,0 @@
/*
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.util.concurrent;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
/**
* @author Mattias Severson
* @author Juergen Hoeller
*/
@SuppressWarnings({"deprecation", "removal"})
class SettableListenableFutureTests {
private final SettableListenableFuture<String> settableListenableFuture = new SettableListenableFuture<>();
@Test
void validateInitialValues() {
assertThat(settableListenableFuture.isCancelled()).isFalse();
assertThat(settableListenableFuture.isDone()).isFalse();
}
@Test
void returnsSetValue() throws ExecutionException, InterruptedException {
String string = "hello";
assertThat(settableListenableFuture.set(string)).isTrue();
assertThat(settableListenableFuture.get()).isEqualTo(string);
assertThat(settableListenableFuture.isCancelled()).isFalse();
assertThat(settableListenableFuture.isDone()).isTrue();
}
@Test
void returnsSetValueFromCompletable() throws ExecutionException, InterruptedException {
String string = "hello";
assertThat(settableListenableFuture.set(string)).isTrue();
Future<String> completable = settableListenableFuture.completable();
assertThat(completable.get()).isEqualTo(string);
assertThat(completable.isCancelled()).isFalse();
assertThat(completable.isDone()).isTrue();
}
@Test
void setValueUpdatesDoneStatus() {
settableListenableFuture.set("hello");
assertThat(settableListenableFuture.isCancelled()).isFalse();
assertThat(settableListenableFuture.isDone()).isTrue();
}
@Test
void throwsSetExceptionWrappedInExecutionException() {
Throwable exception = new RuntimeException();
assertThat(settableListenableFuture.setException(exception)).isTrue();
assertThatExceptionOfType(ExecutionException.class).isThrownBy(
settableListenableFuture::get)
.withCause(exception);
assertThat(settableListenableFuture.isCancelled()).isFalse();
assertThat(settableListenableFuture.isDone()).isTrue();
}
@Test
void throwsSetExceptionWrappedInExecutionExceptionFromCompletable() {
Throwable exception = new RuntimeException();
assertThat(settableListenableFuture.setException(exception)).isTrue();
Future<String> completable = settableListenableFuture.completable();
assertThatExceptionOfType(ExecutionException.class).isThrownBy(
completable::get)
.withCause(exception);
assertThat(completable.isCancelled()).isFalse();
assertThat(completable.isDone()).isTrue();
}
@Test
void throwsSetErrorWrappedInExecutionException() {
Throwable exception = new OutOfMemoryError();
assertThat(settableListenableFuture.setException(exception)).isTrue();
assertThatExceptionOfType(ExecutionException.class).isThrownBy(
settableListenableFuture::get)
.withCause(exception);
assertThat(settableListenableFuture.isCancelled()).isFalse();
assertThat(settableListenableFuture.isDone()).isTrue();
}
@Test
void throwsSetErrorWrappedInExecutionExceptionFromCompletable() {
Throwable exception = new OutOfMemoryError();
assertThat(settableListenableFuture.setException(exception)).isTrue();
Future<String> completable = settableListenableFuture.completable();
assertThatExceptionOfType(ExecutionException.class).isThrownBy(
completable::get)
.withCause(exception);
assertThat(completable.isCancelled()).isFalse();
assertThat(completable.isDone()).isTrue();
}
@Test
void setValueTriggersCallback() {
String string = "hello";
final String[] callbackHolder = new String[1];
settableListenableFuture.addCallback(new ListenableFutureCallback<>() {
@Override
public void onSuccess(String result) {
callbackHolder[0] = result;
}
@Override
public void onFailure(Throwable ex) {
throw new AssertionError("Expected onSuccess() to be called", ex);
}
});
settableListenableFuture.set(string);
assertThat(callbackHolder[0]).isEqualTo(string);
assertThat(settableListenableFuture.isCancelled()).isFalse();
assertThat(settableListenableFuture.isDone()).isTrue();
}
@Test
void setValueTriggersCallbackOnlyOnce() {
String string = "hello";
final String[] callbackHolder = new String[1];
settableListenableFuture.addCallback(new ListenableFutureCallback<>() {
@Override
public void onSuccess(String result) {
callbackHolder[0] = result;
}
@Override
public void onFailure(Throwable ex) {
throw new AssertionError("Expected onSuccess() to be called", ex);
}
});
settableListenableFuture.set(string);
assertThat(settableListenableFuture.set("good bye")).isFalse();
assertThat(callbackHolder[0]).isEqualTo(string);
assertThat(settableListenableFuture.isCancelled()).isFalse();
assertThat(settableListenableFuture.isDone()).isTrue();
}
@Test
void setExceptionTriggersCallback() {
Throwable exception = new RuntimeException();
final Throwable[] callbackHolder = new Throwable[1];
settableListenableFuture.addCallback(new ListenableFutureCallback<>() {
@Override
public void onSuccess(String result) {
fail("Expected onFailure() to be called");
}
@Override
public void onFailure(Throwable ex) {
callbackHolder[0] = ex;
}
});
settableListenableFuture.setException(exception);
assertThat(callbackHolder[0]).isEqualTo(exception);
assertThat(settableListenableFuture.isCancelled()).isFalse();
assertThat(settableListenableFuture.isDone()).isTrue();
}
@Test
void setExceptionTriggersCallbackOnlyOnce() {
Throwable exception = new RuntimeException();
final Throwable[] callbackHolder = new Throwable[1];
settableListenableFuture.addCallback(new ListenableFutureCallback<>() {
@Override
public void onSuccess(String result) {
fail("Expected onFailure() to be called");
}
@Override
public void onFailure(Throwable ex) {
callbackHolder[0] = ex;
}
});
settableListenableFuture.setException(exception);
assertThat(settableListenableFuture.setException(new IllegalArgumentException())).isFalse();
assertThat(callbackHolder[0]).isEqualTo(exception);
assertThat(settableListenableFuture.isCancelled()).isFalse();
assertThat(settableListenableFuture.isDone()).isTrue();
}
@Test
void nullIsAcceptedAsValueToSet() throws ExecutionException, InterruptedException {
settableListenableFuture.set(null);
assertThat(settableListenableFuture.get()).isNull();
assertThat(settableListenableFuture.isCancelled()).isFalse();
assertThat(settableListenableFuture.isDone()).isTrue();
}
@Test
void getWaitsForCompletion() throws ExecutionException, InterruptedException {
final String string = "hello";
new Thread(() -> {
try {
Thread.sleep(20L);
settableListenableFuture.set(string);
}
catch (InterruptedException ex) {
throw new RuntimeException(ex);
}
}).start();
String value = settableListenableFuture.get();
assertThat(value).isEqualTo(string);
assertThat(settableListenableFuture.isCancelled()).isFalse();
assertThat(settableListenableFuture.isDone()).isTrue();
}
@Test
void getWithTimeoutThrowsTimeoutException() {
assertThatExceptionOfType(TimeoutException.class).isThrownBy(() ->
settableListenableFuture.get(1L, TimeUnit.MILLISECONDS));
}
@Test
void getWithTimeoutWaitsForCompletion() throws ExecutionException, InterruptedException, TimeoutException {
final String string = "hello";
new Thread(() -> {
try {
Thread.sleep(20L);
settableListenableFuture.set(string);
}
catch (InterruptedException ex) {
throw new RuntimeException(ex);
}
}).start();
String value = settableListenableFuture.get(500L, TimeUnit.MILLISECONDS);
assertThat(value).isEqualTo(string);
assertThat(settableListenableFuture.isCancelled()).isFalse();
assertThat(settableListenableFuture.isDone()).isTrue();
}
@Test
void cancelPreventsValueFromBeingSet() {
assertThat(settableListenableFuture.cancel(true)).isTrue();
assertThat(settableListenableFuture.set("hello")).isFalse();
assertThat(settableListenableFuture.isCancelled()).isTrue();
assertThat(settableListenableFuture.isDone()).isTrue();
}
@Test
void cancelSetsFutureToDone() {
settableListenableFuture.cancel(true);
assertThat(settableListenableFuture.isCancelled()).isTrue();
assertThat(settableListenableFuture.isDone()).isTrue();
}
@Test
void cancelWithMayInterruptIfRunningTrueCallsOverriddenMethod() {
InterruptibleSettableListenableFuture interruptibleFuture = new InterruptibleSettableListenableFuture();
assertThat(interruptibleFuture.cancel(true)).isTrue();
assertThat(interruptibleFuture.calledInterruptTask()).isTrue();
assertThat(interruptibleFuture.isCancelled()).isTrue();
assertThat(interruptibleFuture.isDone()).isTrue();
}
@Test
void cancelWithMayInterruptIfRunningFalseDoesNotCallOverriddenMethod() {
InterruptibleSettableListenableFuture interruptibleFuture = new InterruptibleSettableListenableFuture();
assertThat(interruptibleFuture.cancel(false)).isTrue();
assertThat(interruptibleFuture.calledInterruptTask()).isFalse();
assertThat(interruptibleFuture.isCancelled()).isTrue();
assertThat(interruptibleFuture.isDone()).isTrue();
}
@Test
void setPreventsCancel() {
assertThat(settableListenableFuture.set("hello")).isTrue();
assertThat(settableListenableFuture.cancel(true)).isFalse();
assertThat(settableListenableFuture.isCancelled()).isFalse();
assertThat(settableListenableFuture.isDone()).isTrue();
}
@Test
void cancelPreventsExceptionFromBeingSet() {
assertThat(settableListenableFuture.cancel(true)).isTrue();
assertThat(settableListenableFuture.setException(new RuntimeException())).isFalse();
assertThat(settableListenableFuture.isCancelled()).isTrue();
assertThat(settableListenableFuture.isDone()).isTrue();
}
@Test
void setExceptionPreventsCancel() {
assertThat(settableListenableFuture.setException(new RuntimeException())).isTrue();
assertThat(settableListenableFuture.cancel(true)).isFalse();
assertThat(settableListenableFuture.isCancelled()).isFalse();
assertThat(settableListenableFuture.isDone()).isTrue();
}
@Test
void cancelStateThrowsExceptionWhenCallingGet() {
settableListenableFuture.cancel(true);
assertThatExceptionOfType(CancellationException.class).isThrownBy(settableListenableFuture::get);
assertThat(settableListenableFuture.isCancelled()).isTrue();
assertThat(settableListenableFuture.isDone()).isTrue();
}
@Test
void cancelStateThrowsExceptionWhenCallingGetWithTimeout() {
new Thread(() -> {
try {
Thread.sleep(20L);
settableListenableFuture.cancel(true);
}
catch (InterruptedException ex) {
throw new RuntimeException(ex);
}
}).start();
assertThatExceptionOfType(CancellationException.class).isThrownBy(() ->
settableListenableFuture.get(500L, TimeUnit.MILLISECONDS));
assertThat(settableListenableFuture.isCancelled()).isTrue();
assertThat(settableListenableFuture.isDone()).isTrue();
}
@Test
@SuppressWarnings({"rawtypes", "unchecked"})
public void cancelDoesNotNotifyCallbacksOnSet() {
ListenableFutureCallback callback = mock();
settableListenableFuture.addCallback(callback);
settableListenableFuture.cancel(true);
verify(callback).onFailure(any(CancellationException.class));
verifyNoMoreInteractions(callback);
settableListenableFuture.set("hello");
verifyNoMoreInteractions(callback);
assertThat(settableListenableFuture.isCancelled()).isTrue();
assertThat(settableListenableFuture.isDone()).isTrue();
}
@Test
@SuppressWarnings({"rawtypes", "unchecked"})
public void cancelDoesNotNotifyCallbacksOnSetException() {
ListenableFutureCallback callback = mock();
settableListenableFuture.addCallback(callback);
settableListenableFuture.cancel(true);
verify(callback).onFailure(any(CancellationException.class));
verifyNoMoreInteractions(callback);
settableListenableFuture.setException(new RuntimeException());
verifyNoMoreInteractions(callback);
assertThat(settableListenableFuture.isCancelled()).isTrue();
assertThat(settableListenableFuture.isDone()).isTrue();
}
private static class InterruptibleSettableListenableFuture extends SettableListenableFuture<String> {
private boolean interrupted = false;
@Override
protected void interruptTask() {
interrupted = true;
}
boolean calledInterruptTask() {
return interrupted;
}
}
}

View File

@ -211,69 +211,11 @@ public class ExpressionState {
initScopeRootObjects().push(getActiveContextObject()); initScopeRootObjects().push(getActiveContextObject());
} }
/**
* Enter a new scope with a new {@linkplain #getActiveContextObject() root
* context object} and a new local variable scope containing the supplied
* name/value pair.
* @param name the name of the local variable
* @param value the value of the local variable
* @deprecated as of 6.2 with no replacement; to be removed in 7.0
*/
@Deprecated(since = "6.2", forRemoval = true)
public void enterScope(String name, Object value) {
initVariableScopes().push(new VariableScope(name, value));
initScopeRootObjects().push(getActiveContextObject());
}
/**
* Enter a new scope with a new {@linkplain #getActiveContextObject() root
* context object} and a new local variable scope containing the supplied
* name/value pairs.
* @param variables a map containing name/value pairs for local variables
* @deprecated as of 6.2 with no replacement; to be removed in 7.0
*/
@Deprecated(since = "6.2", forRemoval = true)
public void enterScope(@Nullable Map<String, Object> variables) {
initVariableScopes().push(new VariableScope(variables));
initScopeRootObjects().push(getActiveContextObject());
}
public void exitScope() { public void exitScope() {
initVariableScopes().pop(); initVariableScopes().pop();
initScopeRootObjects().pop(); initScopeRootObjects().pop();
} }
/**
* Set a local variable with the given name to the supplied value within the
* current scope.
* <p>If a local variable with the given name already exists, it will be
* overwritten.
* @param name the name of the local variable
* @param value the value of the local variable
* @deprecated as of 6.2 with no replacement; to be removed in 7.0
*/
@Deprecated(since = "6.2", forRemoval = true)
public void setLocalVariable(String name, Object value) {
initVariableScopes().element().setVariable(name, value);
}
/**
* Look up the value of the local variable with the given name.
* @param name the name of the local variable
* @return the value of the local variable, or {@code null} if the variable
* does not exist in the current scope
* @deprecated as of 6.2 with no replacement; to be removed in 7.0
*/
@Deprecated(since = "6.2", forRemoval = true)
@Nullable
public Object lookupLocalVariable(String name) {
for (VariableScope scope : initVariableScopes()) {
if (scope.definesVariable(name)) {
return scope.lookupVariable(name);
}
}
return null;
}
private Deque<TypedValue> initContextObjects() { private Deque<TypedValue> initContextObjects() {
if (this.contextObjects == null) { if (this.contextObjects == null) {

View File

@ -123,17 +123,6 @@ public class Indexer extends SpelNodeImpl {
private volatile CachedIndexState cachedIndexWriteState; private volatile CachedIndexState cachedIndexWriteState;
/**
* Create an {@code Indexer} with the given start position, end position, and
* index expression.
* @see #Indexer(boolean, int, int, SpelNodeImpl)
* @deprecated as of 6.2, in favor of {@link #Indexer(boolean, int, int, SpelNodeImpl)}
*/
@Deprecated(since = "6.2", forRemoval = true)
public Indexer(int startPos, int endPos, SpelNodeImpl indexExpression) {
this(false, startPos, endPos, indexExpression);
}
/** /**
* Create an {@code Indexer} with the given null-safe flag, start position, * Create an {@code Indexer} with the given null-safe flag, start position,
* end position, and index expression. * end position, and index expression.

View File

@ -16,8 +16,6 @@
package org.springframework.expression.spel; package org.springframework.expression.spel;
import java.util.Map;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.TypeDescriptor;
@ -55,21 +53,6 @@ class ExpressionStateTests extends AbstractExpressionTests {
assertThat(state.getEvaluationContext()).isEqualTo(context); assertThat(state.getEvaluationContext()).isEqualTo(context);
} }
@Test
@SuppressWarnings("removal")
void localVariables() {
Object value = state.lookupLocalVariable("foo");
assertThat(value).isNull();
state.setLocalVariable("foo",34);
value = state.lookupLocalVariable("foo");
assertThat(value).isEqualTo(34);
state.setLocalVariable("foo", null);
value = state.lookupLocalVariable("foo");
assertThat(value).isNull();
}
@Test @Test
void globalVariables() { void globalVariables() {
TypedValue typedValue = state.lookupVariable("foo"); TypedValue typedValue = state.lookupVariable("foo");
@ -86,41 +69,6 @@ class ExpressionStateTests extends AbstractExpressionTests {
assertThat(typedValue.getTypeDescriptor().getType()).isEqualTo(String.class); assertThat(typedValue.getTypeDescriptor().getType()).isEqualTo(String.class);
} }
@Test
@SuppressWarnings("removal")
void noVariableInterference() {
TypedValue typedValue = state.lookupVariable("foo");
assertThat(typedValue).isEqualTo(TypedValue.NULL);
state.setLocalVariable("foo",34);
typedValue = state.lookupVariable("foo");
assertThat(typedValue).isEqualTo(TypedValue.NULL);
state.setVariable("goo", "hello");
assertThat(state.lookupLocalVariable("goo")).isNull();
}
@Test
@SuppressWarnings("removal")
void localVariableNestedScopes() {
assertThat(state.lookupLocalVariable("foo")).isNull();
state.setLocalVariable("foo",12);
assertThat(state.lookupLocalVariable("foo")).isEqualTo(12);
state.enterScope(null);
// found in upper scope
assertThat(state.lookupLocalVariable("foo")).isEqualTo(12);
state.setLocalVariable("foo","abc");
// found in nested scope
assertThat(state.lookupLocalVariable("foo")).isEqualTo("abc");
state.exitScope();
// found in nested scope
assertThat(state.lookupLocalVariable("foo")).isEqualTo(12);
}
@Test @Test
void rootContextObject() { void rootContextObject() {
assertThat(state.getRootContextObject().getValue().getClass()).isEqualTo(Inventor.class); assertThat(state.getRootContextObject().getValue().getClass()).isEqualTo(Inventor.class);
@ -159,25 +107,6 @@ class ExpressionStateTests extends AbstractExpressionTests {
assertThat(state.getActiveContextObject()).isEqualTo(TypedValue.NULL); assertThat(state.getActiveContextObject()).isEqualTo(TypedValue.NULL);
} }
@Test
@SuppressWarnings("removal")
void populatedNestedScopes() {
assertThat(state.lookupLocalVariable("foo")).isNull();
state.enterScope("foo",34);
assertThat(state.lookupLocalVariable("foo")).isEqualTo(34);
state.enterScope(null);
state.setLocalVariable("foo", 12);
assertThat(state.lookupLocalVariable("foo")).isEqualTo(12);
state.exitScope();
assertThat(state.lookupLocalVariable("foo")).isEqualTo(34);
state.exitScope();
assertThat(state.lookupLocalVariable("goo")).isNull();
}
@Test @Test
void rootObjectConstructor() { void rootObjectConstructor() {
EvaluationContext ctx = TestScenarioCreator.getTestEvaluationContext(); EvaluationContext ctx = TestScenarioCreator.getTestEvaluationContext();
@ -189,27 +118,6 @@ class ExpressionStateTests extends AbstractExpressionTests {
assertThat(stateRoot.getValue()).isEqualTo("i am a string"); assertThat(stateRoot.getValue()).isEqualTo("i am a string");
} }
@Test
@SuppressWarnings("removal")
void populatedNestedScopesMap() {
assertThat(state.lookupLocalVariable("foo")).isNull();
assertThat(state.lookupLocalVariable("goo")).isNull();
state.enterScope(Map.of("foo", 34, "goo", "abc"));
assertThat(state.lookupLocalVariable("foo")).isEqualTo(34);
assertThat(state.lookupLocalVariable("goo")).isEqualTo("abc");
state.enterScope(null);
state.setLocalVariable("foo",12);
assertThat(state.lookupLocalVariable("foo")).isEqualTo(12);
assertThat(state.lookupLocalVariable("goo")).isEqualTo("abc");
state.exitScope();
state.exitScope();
assertThat(state.lookupLocalVariable("foo")).isNull();
assertThat(state.lookupLocalVariable("goo")).isNull();
}
@Test @Test
void operators() { void operators() {
assertThatExceptionOfType(SpelEvaluationException.class) assertThatExceptionOfType(SpelEvaluationException.class)

View File

@ -50,35 +50,6 @@ 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 org.springframework.util.concurrent.ListenableFuture ListenableFuture}.
* <p>Implementations should consider returning an instance of
* {@link org.springframework.util.concurrent.SettableListenableFuture
* SettableListenableFuture}. Return value handling will then continue when
* the ListenableFuture is completed with either success or error.
* <p><strong>Note:</strong> this method will only be invoked after
* {@link #supportsReturnType(org.springframework.core.MethodParameter)}
* is called and it returns {@code true}.
* @param returnValue the value returned from the handler method
* @param returnType the type of the return value
* @return the resulting ListenableFuture, or {@code null} in which case
* no further handling will be performed
* @deprecated as of 6.0, in favor of
* {@link #toCompletableFuture(Object, MethodParameter)}
*/
@Deprecated(since = "6.0", forRemoval = true)
@SuppressWarnings("removal")
@Nullable
default org.springframework.util.concurrent.ListenableFuture<?> toListenableFuture(
Object returnValue, MethodParameter returnType) {
CompletableFuture<?> result = toCompletableFuture(returnValue, returnType);
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}.
* <p>Return value handling will then continue when * <p>Return value handling will then continue when

View File

@ -1,49 +0,0 @@
/*
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.messaging.handler.invocation;
import java.util.concurrent.CompletableFuture;
import org.springframework.core.MethodParameter;
/**
* Support for {@link org.springframework.util.concurrent.ListenableFuture} as a return value type.
*
* @author Sebastien Deleuze
* @since 4.2
* @deprecated as of 6.0, in favor of {@link CompletableFutureReturnValueHandler}
*/
@Deprecated(since = "6.0", forRemoval = true)
@SuppressWarnings("removal")
public class ListenableFutureReturnValueHandler extends AbstractAsyncReturnValueHandler {
@Override
public boolean supportsReturnType(MethodParameter returnType) {
return org.springframework.util.concurrent.ListenableFuture.class.isAssignableFrom(returnType.getParameterType());
}
@Override
public org.springframework.util.concurrent.ListenableFuture<?> toListenableFuture(Object returnValue, MethodParameter returnType) {
return (org.springframework.util.concurrent.ListenableFuture<?>) returnValue;
}
@Override
public CompletableFuture<?> toCompletableFuture(Object returnValue, MethodParameter returnType) {
return ((org.springframework.util.concurrent.ListenableFuture<?>) returnValue).completable();
}
}

View File

@ -344,13 +344,11 @@ public class SimpAnnotationMethodMessageHandler extends AbstractMethodMessageHan
} }
@Override @Override
@SuppressWarnings("removal")
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 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

@ -31,17 +31,6 @@ import java.util.concurrent.CompletableFuture;
*/ */
public interface ConnectionHandlingStompSession extends StompSession, StompTcpConnectionHandler<byte[]> { public interface ConnectionHandlingStompSession extends StompSession, StompTcpConnectionHandler<byte[]> {
/**
* Return a future that will complete when the session is ready for use.
* @deprecated as of 6.0, in favor of {@link #getSession()}
*/
@Deprecated(since = "6.0", forRemoval = true)
@SuppressWarnings("removal")
default org.springframework.util.concurrent.ListenableFuture<StompSession> getSessionFuture() {
return new org.springframework.util.concurrent.CompletableToListenableFutureAdapter<>(
getSession());
}
/** /**
* Return a future that will complete when the session is ready for use. * Return a future that will complete when the session is ready for use.
* @since 6.0 * @since 6.0

View File

@ -89,22 +89,6 @@ public class ReactorNettyTcpStompClient extends StompClientSupport {
} }
/**
* Connect and notify the given {@link StompSessionHandler} when connected
* on the STOMP level.
* @param handler the handler for the STOMP session
* @return a ListenableFuture for access to the session when ready for use
* @deprecated as of 6.0, in favor of {@link #connectAsync(StompSessionHandler)}
*/
@Deprecated(since = "6.0", forRemoval = true)
@SuppressWarnings("removal")
public org.springframework.util.concurrent.ListenableFuture<StompSession> connect(
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.
@ -116,24 +100,6 @@ public class ReactorNettyTcpStompClient extends StompClientSupport {
return connectAsync(null, handler); return connectAsync(null, handler);
} }
/**
* An overloaded version of {@link #connect(StompSessionHandler)} that
* accepts headers to use for the STOMP CONNECT frame.
* @param connectHeaders headers to add to the CONNECT frame
* @param handler the handler for the STOMP session
* @return a ListenableFuture for access to the session when ready for use
* @deprecated as of 6.0, in favor of {@link #connectAsync(StompHeaders, StompSessionHandler)}
*/
@Deprecated(since = "6.0", forRemoval = true)
@SuppressWarnings("removal")
public org.springframework.util.concurrent.ListenableFuture<StompSession> connect(
@Nullable StompHeaders connectHeaders, StompSessionHandler handler) {
ConnectionHandlingStompSession session = createSession(connectHeaders, handler);
this.tcpClient.connectAsync(session);
return session.getSessionFuture();
}
/** /**
* An overloaded version of {@link #connectAsync(StompSessionHandler)} that * An overloaded version of {@link #connectAsync(StompSessionHandler)} that
* accepts headers to use for the STOMP CONNECT frame. * accepts headers to use for the STOMP CONNECT frame.

View File

@ -30,20 +30,6 @@ import org.springframework.messaging.Message;
*/ */
public interface TcpConnection<P> extends Closeable { public interface TcpConnection<P> extends Closeable {
/**
* Send the given message.
* @param message the message
* @return a ListenableFuture that can be used to determine when and if the
* message was successfully sent
* @deprecated as of 6.0, in favor of {@link #sendAsync(Message)}
*/
@Deprecated(since = "6.0", forRemoval = true)
@SuppressWarnings("removal")
default org.springframework.util.concurrent.ListenableFuture<Void> send(Message<P> message) {
return new org.springframework.util.concurrent.CompletableToListenableFutureAdapter<>(
sendAsync(message));
}
/** /**
* Send the given message. * Send the given message.
* @param message the message * @param message the message

View File

@ -27,22 +27,6 @@ import java.util.concurrent.CompletableFuture;
*/ */
public interface TcpOperations<P> { public interface TcpOperations<P> {
/**
* Open a new connection.
* @param connectionHandler a handler to manage the connection
* @return a ListenableFuture that can be used to determine when and if the
* connection is successfully established
* @deprecated as of 6.0, in favor of {@link #connectAsync(TcpConnectionHandler)}
*/
@Deprecated(since = "6.0", forRemoval = true)
@SuppressWarnings("removal")
default org.springframework.util.concurrent.ListenableFuture<Void> connect(
TcpConnectionHandler<P> connectionHandler) {
return new org.springframework.util.concurrent.CompletableToListenableFutureAdapter<>(
connectAsync(connectionHandler));
}
/** /**
* Open a new connection. * Open a new connection.
* @param connectionHandler a handler to manage the connection * @param connectionHandler a handler to manage the connection
@ -52,23 +36,6 @@ public interface TcpOperations<P> {
*/ */
CompletableFuture<Void> connectAsync(TcpConnectionHandler<P> connectionHandler); CompletableFuture<Void> connectAsync(TcpConnectionHandler<P> connectionHandler);
/**
* Open a new connection and a strategy for reconnecting if the connection fails.
* @param connectionHandler a handler to manage the connection
* @param reconnectStrategy a strategy for reconnecting
* @return a ListenableFuture that can be used to determine when and if the
* initial connection is successfully established
* @deprecated as of 6.0, in favor of {@link #connectAsync(TcpConnectionHandler, ReconnectStrategy)}
*/
@Deprecated(since = "6.0", forRemoval = true)
@SuppressWarnings("removal")
default org.springframework.util.concurrent.ListenableFuture<Void> connect(
TcpConnectionHandler<P> connectionHandler, ReconnectStrategy reconnectStrategy) {
return new org.springframework.util.concurrent.CompletableToListenableFutureAdapter<>(
connectAsync(connectionHandler, reconnectStrategy));
}
/** /**
* Open a new connection and a strategy for reconnecting if the connection fails. * Open a new connection and a strategy for reconnecting if the connection fails.
* @param connectionHandler a handler to manage the connection * @param connectionHandler a handler to manage the connection
@ -79,18 +46,6 @@ public interface TcpOperations<P> {
*/ */
CompletableFuture<Void> connectAsync(TcpConnectionHandler<P> connectionHandler, ReconnectStrategy reconnectStrategy); CompletableFuture<Void> connectAsync(TcpConnectionHandler<P> connectionHandler, ReconnectStrategy reconnectStrategy);
/**
* Shut down and close any open connections.
* @return a ListenableFuture that can be used to determine when and if the
* connection is successfully closed
* @deprecated as of 6.0, in favor of {@link #shutdownAsync()}
*/
@Deprecated(since = "6.0", forRemoval = true)
@SuppressWarnings("removal")
default org.springframework.util.concurrent.ListenableFuture<Void> shutdown() {
return new org.springframework.util.concurrent.CompletableToListenableFutureAdapter<>(shutdownAsync());
}
/** /**
* Shut down and close any open connections. * Shut down and close any open connections.
* @return a CompletableFuture that can be used to determine when and if the * @return a CompletableFuture that can be used to determine when and if the

View File

@ -273,39 +273,6 @@ public class SimpAnnotationMethodMessageHandlerTests {
assertThat(controller.method).isEqualTo("handleFoo"); assertThat(controller.method).isEqualTo("handleFoo");
} }
@Test
@SuppressWarnings({ "unchecked", "rawtypes" })
public void listenableFutureSuccess() {
Message emptyMessage = MessageBuilder.withPayload(new byte[0]).build();
given(this.channel.send(any(Message.class))).willReturn(true);
given(this.converter.toMessage(any(), any(MessageHeaders.class))).willReturn(emptyMessage);
ListenableFutureController controller = new ListenableFutureController();
this.messageHandler.registerHandler(controller);
this.messageHandler.setDestinationPrefixes(Arrays.asList("/app1", "/app2/"));
Message<?> message = createMessage("/app1/listenable-future/success");
this.messageHandler.handleMessage(message);
assertThat(controller.future).isNotNull();
controller.future.run();
verify(this.converter).toMessage(this.payloadCaptor.capture(), any(MessageHeaders.class));
assertThat(this.payloadCaptor.getValue()).isEqualTo("foo");
}
@Test
void listenableFutureFailure() {
ListenableFutureController controller = new ListenableFutureController();
this.messageHandler.registerHandler(controller);
this.messageHandler.setDestinationPrefixes(Arrays.asList("/app1", "/app2/"));
Message<?> message = createMessage("/app1/listenable-future/failure");
this.messageHandler.handleMessage(message);
controller.future.run();
assertThat(controller.exceptionCaught).isTrue();
}
@Test @Test
@SuppressWarnings({ "unchecked", "rawtypes" }) @SuppressWarnings({ "unchecked", "rawtypes" })
public void completableFutureSuccess() { public void completableFutureSuccess() {
@ -569,36 +536,6 @@ public class SimpAnnotationMethodMessageHandlerTests {
} }
@Controller
@MessageMapping("listenable-future")
@SuppressWarnings({"deprecation", "removal"})
private static class ListenableFutureController {
org.springframework.util.concurrent.ListenableFutureTask<String> future;
boolean exceptionCaught = false;
@MessageMapping("success")
public org.springframework.util.concurrent.ListenableFutureTask<String> handleListenableFuture() {
this.future = new org.springframework.util.concurrent.ListenableFutureTask<>(() -> "foo");
return this.future;
}
@MessageMapping("failure")
public org.springframework.util.concurrent.ListenableFutureTask<String> handleListenableFutureException() {
this.future = new org.springframework.util.concurrent.ListenableFutureTask<>(() -> {
throw new IllegalStateException();
});
return this.future;
}
@MessageExceptionHandler(IllegalStateException.class)
public void handleValidationException() {
this.exceptionCaught = true;
}
}
@Controller @Controller
private static class CompletableFutureController { private static class CompletableFutureController {

View File

@ -82,18 +82,6 @@ public class JsonPathExpectationsHelper {
this.configuration = (configuration != null) ? configuration : Configuration.defaultConfiguration(); this.configuration = (configuration != null) ? configuration : Configuration.defaultConfiguration();
} }
/**
* Construct a new {@code JsonPathExpectationsHelper}.
* @param expression the {@link JsonPath} expression; never {@code null} or empty
* @param args arguments to parameterize the {@code JsonPath} expression with,
* using formatting specifiers defined in {@link String#format(String, Object...)}
* @deprecated in favor of calling {@link String#formatted(Object...)} upfront
*/
@Deprecated(since = "6.2", forRemoval = true)
public JsonPathExpectationsHelper(String expression, Object... args) {
this(expression.formatted(args), (Configuration) null);
}
/** /**
* Evaluate the JSON path expression against the supplied {@code content} * Evaluate the JSON path expression against the supplied {@code content}

View File

@ -711,13 +711,6 @@ class DefaultWebTestClient implements WebTestClient {
JsonPathConfigurationProvider.getConfiguration(this.jsonEncoderDecoder)); JsonPathConfigurationProvider.getConfiguration(this.jsonEncoderDecoder));
} }
@Override
@SuppressWarnings("removal")
public JsonPathAssertions jsonPath(String expression, Object... args) {
Assert.hasText(expression, "expression must not be null or empty");
return jsonPath(expression.formatted(args));
}
@Override @Override
public XpathAssertions xpath(String expression, @Nullable Map<String, String> namespaces, Object... args) { public XpathAssertions xpath(String expression, @Nullable Map<String, String> namespaces, Object... args) {
return new XpathAssertions(this, expression, namespaces, args); return new XpathAssertions(this, expression, namespaces, args);

View File

@ -176,16 +176,6 @@ public class ExchangeResult {
return this.response.getStatusCode(); return this.response.getStatusCode();
} }
/**
* Return the HTTP status code as an integer.
* @since 5.1.10
* @deprecated in favor of {@link #getStatus()}, for removal in 7.0
*/
@Deprecated(since = "6.0", forRemoval = true)
public int getRawStatusCode() {
return getStatus().value();
}
/** /**
* Return the response headers received from the server. * Return the response headers received from the server.
*/ */

View File

@ -161,17 +161,6 @@ public class JsonPathAssertions {
return this.bodySpec; return this.bodySpec;
} }
/**
* Delegates to {@link JsonPathExpectationsHelper#assertValue(String, Matcher, Class)}.
* @since 5.1
* @deprecated in favor of {@link #value(Class, Matcher)}
*/
@Deprecated(since = "6.2", forRemoval = true)
public <T> WebTestClient.BodyContentSpec value(Matcher<? super T> matcher, Class<T> targetType) {
this.pathHelper.assertValue(this.content, matcher, targetType);
return this.bodySpec;
}
/** /**
* Delegates to {@link JsonPathExpectationsHelper#assertValue(String, Matcher, ParameterizedTypeReference)}. * Delegates to {@link JsonPathExpectationsHelper#assertValue(String, Matcher, ParameterizedTypeReference)}.
* @since 6.2 * @since 6.2
@ -202,16 +191,6 @@ public class JsonPathAssertions {
return this.bodySpec; return this.bodySpec;
} }
/**
* Consume the result of the JSONPath evaluation and provide a target class.
* @since 5.1
* @deprecated in favor of {@link #value(Class, Consumer)}
*/
@Deprecated(since = "6.2", forRemoval = true)
public <T> WebTestClient.BodyContentSpec value(Consumer<T> consumer, Class<T> targetType) {
return value(targetType, consumer);
}
/** /**
* Consume the result of the JSONPath evaluation and provide a parameterized type. * Consume the result of the JSONPath evaluation and provide a parameterized type.
* @since 6.2 * @since 6.2

View File

@ -1075,19 +1075,6 @@ public interface WebTestClient {
*/ */
JsonPathAssertions jsonPath(String expression); JsonPathAssertions jsonPath(String expression);
/**
* Access to response body assertions using a
* <a href="https://github.com/jayway/JsonPath">JsonPath</a> expression
* to inspect a specific subset of the body.
* <p>The JSON path expression can be a parameterized string using
* formatting specifiers as defined in {@link String#format}.
* @param expression the JsonPath expression
* @param args arguments to parameterize the expression
* @deprecated in favor of calling {@link String#formatted(Object...)} upfront
*/
@Deprecated(since = "6.2", forRemoval = true)
JsonPathAssertions jsonPath(String expression, Object... args);
/** /**
* Access to response body assertions using an XPath expression to * Access to response body assertions using an XPath expression to
* inspect a specific subset of the body. * inspect a specific subset of the body.

View File

@ -117,16 +117,6 @@ class AsyncTests {
.expectBody(String.class).isEqualTo("Delayed Error"); .expectBody(String.class).isEqualTo("Delayed Error");
} }
@Test
void listenableFuture() {
this.testClient.get()
.uri("/1?listenableFuture=true")
.exchange()
.expectStatus().isOk()
.expectHeader().contentType(MediaType.APPLICATION_JSON)
.expectBody().json("{\"name\":\"Joe\",\"someDouble\":0.0,\"someBoolean\":false}");
}
@Test @Test
void completableFutureWithImmediateValue() { void completableFutureWithImmediateValue() {
this.testClient.get() this.testClient.get()
@ -193,15 +183,6 @@ class AsyncTests {
return result; return result;
} }
@GetMapping(params = "listenableFuture")
@SuppressWarnings({ "deprecation", "removal" })
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);
return futureTask;
}
@GetMapping(params = "completableFutureWithImmediateValue") @GetMapping(params = "completableFutureWithImmediateValue")
CompletableFuture<Person> getCompletableFutureWithImmediateValue() { CompletableFuture<Person> getCompletableFutureWithImmediateValue() {
CompletableFuture<Person> future = new CompletableFuture<>(); CompletableFuture<Person> future = new CompletableFuture<>();

View File

@ -144,18 +144,6 @@ class AsyncTests {
.andExpect(content().string("Delayed Error")); .andExpect(content().string("Delayed Error"));
} }
@Test
void listenableFuture() throws Exception {
MvcResult mvcResult = this.mockMvc.perform(get("/1").param("listenableFuture", "true"))
.andExpect(request().asyncStarted())
.andReturn();
this.mockMvc.perform(asyncDispatch(mvcResult))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(content().string("{\"name\":\"Joe\",\"someDouble\":0.0,\"someBoolean\":false}"));
}
@Test // SPR-12597 @Test // SPR-12597
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"))
@ -245,13 +233,6 @@ class AsyncTests {
.hasStatus5xxServerError().hasBodyTextEqualTo("Delayed Error"); .hasStatus5xxServerError().hasBodyTextEqualTo("Delayed Error");
} }
@Test
void listenableFuture() {
assertThat(this.mockMvc.get().uri("/1").param("listenableFuture", "true"))
.hasStatusOk().hasContentTypeCompatibleWith(MediaType.APPLICATION_JSON)
.hasBodyTextEqualTo("{\"name\":\"Joe\",\"someDouble\":0.0,\"someBoolean\":false}");
}
@Test // SPR-12597 @Test // SPR-12597
void completableFutureWithImmediateValue() { void completableFutureWithImmediateValue() {
assertThat(this.mockMvc.get().uri("/1").param("completableFutureWithImmediateValue", "true")) assertThat(this.mockMvc.get().uri("/1").param("completableFutureWithImmediateValue", "true"))
@ -333,15 +314,6 @@ class AsyncTests {
return result; return result;
} }
@RequestMapping(params = "listenableFuture")
@SuppressWarnings({"deprecation", "removal"})
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);
return futureTask;
}
@RequestMapping(params = "completableFutureWithImmediateValue") @RequestMapping(params = "completableFutureWithImmediateValue")
CompletableFuture<Person> getCompletableFutureWithImmediateValue() { CompletableFuture<Person> getCompletableFutureWithImmediateValue() {
CompletableFuture<Person> future = new CompletableFuture<>(); CompletableFuture<Person> future = new CompletableFuture<>();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2023 the original author or authors. * Copyright 2002-2024 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.
@ -96,13 +96,6 @@ public class GenericReactiveTransaction implements ReactiveTransaction {
this.suspendedResources = suspendedResources; this.suspendedResources = suspendedResources;
} }
@Deprecated(since = "6.1", forRemoval = true)
public GenericReactiveTransaction(@Nullable Object transaction, boolean newTransaction,
boolean newSynchronization, boolean readOnly, boolean debug, @Nullable Object suspendedResources) {
this(null, transaction, newTransaction, newSynchronization, false, readOnly, debug, suspendedResources);
}
@Override @Override
public String getTransactionName() { public String getTransactionName() {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2023 the original author or authors. * Copyright 2002-2024 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.
@ -102,13 +102,6 @@ public class DefaultTransactionStatus extends AbstractTransactionStatus {
this.suspendedResources = suspendedResources; this.suspendedResources = suspendedResources;
} }
@Deprecated(since = "6.1", forRemoval = true)
public DefaultTransactionStatus(@Nullable Object transaction, boolean newTransaction,
boolean newSynchronization, boolean readOnly, boolean debug, @Nullable Object suspendedResources) {
this(null, transaction, newTransaction, newSynchronization, false, readOnly, debug, suspendedResources);
}
@Override @Override
public String getTransactionName() { public String getTransactionName() {

View File

@ -20,7 +20,6 @@ dependencies {
optional("com.google.code.gson:gson") optional("com.google.code.gson:gson")
optional("com.google.protobuf:protobuf-java-util") optional("com.google.protobuf:protobuf-java-util")
optional("com.rometools:rome") optional("com.rometools:rome")
optional("com.squareup.okhttp3:okhttp")
optional("io.micrometer:context-propagation") optional("io.micrometer:context-propagation")
optional("io.netty:netty-buffer") optional("io.netty:netty-buffer")
optional("io.netty:netty-handler") optional("io.netty:netty-handler")

View File

@ -1961,21 +1961,6 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
return (headers instanceof ReadOnlyHttpHeaders ? headers : new ReadOnlyHttpHeaders(headers.headers)); return (headers instanceof ReadOnlyHttpHeaders ? headers : new ReadOnlyHttpHeaders(headers.headers));
} }
/**
* Remove any read-only wrapper that may have been previously applied around
* the given headers via {@link #readOnlyHttpHeaders(HttpHeaders)}.
* <p>Once the writable instance is mutated, the read-only instance is likely
* to be out of sync and should be discarded.
* @param headers the headers to expose
* @return a writable variant of the headers, or the original headers as-is
* @since 5.1.1
* @deprecated as of 6.2 in favor of {@link #HttpHeaders(MultiValueMap)}.
*/
@Deprecated(since = "6.2", forRemoval = true)
public static HttpHeaders writableHttpHeaders(HttpHeaders headers) {
return new HttpHeaders(headers);
}
/** /**
* Helps to format HTTP header values, as HTTP header values themselves can * Helps to format HTTP header values, as HTTP header values themselves can
* contain comma-separated values, can become confusing with regular * contain comma-separated values, can become confusing with regular

View File

@ -22,7 +22,6 @@ import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -100,23 +99,6 @@ public class MediaType extends MimeType implements Serializable {
*/ */
public static final String APPLICATION_FORM_URLENCODED_VALUE = "application/x-www-form-urlencoded"; public static final String APPLICATION_FORM_URLENCODED_VALUE = "application/x-www-form-urlencoded";
/**
* Public constant media type for {@code application/graphql+json}.
* @since 5.3.19
* @see <a href="https://github.com/graphql/graphql-over-http/pull/215">GraphQL over HTTP spec change</a>
* @deprecated as of 6.0.3, in favor of {@link MediaType#APPLICATION_GRAPHQL_RESPONSE}
*/
@Deprecated(since = "6.0.3", forRemoval = true)
public static final MediaType APPLICATION_GRAPHQL;
/**
* A String equivalent of {@link MediaType#APPLICATION_GRAPHQL}.
* @since 5.3.19
* @deprecated as of 6.0.3, in favor of {@link MediaType#APPLICATION_GRAPHQL_RESPONSE_VALUE}
*/
@Deprecated(since = "6.0.3", forRemoval = true)
public static final String APPLICATION_GRAPHQL_VALUE = "application/graphql+json";
/** /**
* Public constant media type for {@code application/graphql-response+json}. * Public constant media type for {@code application/graphql-response+json}.
* @since 6.0.3 * @since 6.0.3
@ -456,7 +438,6 @@ public class MediaType extends MimeType implements Serializable {
APPLICATION_ATOM_XML = new MediaType("application", "atom+xml"); APPLICATION_ATOM_XML = new MediaType("application", "atom+xml");
APPLICATION_CBOR = new MediaType("application", "cbor"); APPLICATION_CBOR = new MediaType("application", "cbor");
APPLICATION_FORM_URLENCODED = new MediaType("application", "x-www-form-urlencoded"); APPLICATION_FORM_URLENCODED = new MediaType("application", "x-www-form-urlencoded");
APPLICATION_GRAPHQL = new MediaType("application", "graphql+json");
APPLICATION_GRAPHQL_RESPONSE = new MediaType("application", "graphql-response+json"); APPLICATION_GRAPHQL_RESPONSE = new MediaType("application", "graphql-response+json");
APPLICATION_JSON = new MediaType("application", "json"); APPLICATION_JSON = new MediaType("application", "json");
APPLICATION_JSON_UTF8 = new MediaType("application", "json", StandardCharsets.UTF_8); APPLICATION_JSON_UTF8 = new MediaType("application", "json", StandardCharsets.UTF_8);
@ -847,141 +828,4 @@ public class MediaType extends MimeType implements Serializable {
return MimeTypeUtils.toString(mediaTypes); return MimeTypeUtils.toString(mediaTypes);
} }
/**
* Sorts the given list of {@code MediaType} objects by specificity.
* <p>Given two media types:
* <ol>
* <li>if either media type has a {@linkplain #isWildcardType() wildcard type}, then the media type without the
* wildcard is ordered before the other.</li>
* <li>if the two media types have different {@linkplain #getType() types}, then they are considered equal and
* remain their current order.</li>
* <li>if either media type has a {@linkplain #isWildcardSubtype() wildcard subtype}, then the media type without
* the wildcard is sorted before the other.</li>
* <li>if the two media types have different {@linkplain #getSubtype() subtypes}, then they are considered equal
* and remain their current order.</li>
* <li>if the two media types have different {@linkplain #getQualityValue() quality value}, then the media type
* with the highest quality value is ordered before the other.</li>
* <li>if the two media types have a different amount of {@linkplain #getParameter(String) parameters}, then the
* media type with the most parameters is ordered before the other.</li>
* </ol>
* <p>For example:
* <blockquote>audio/basic &lt; audio/* &lt; *&#047;*</blockquote>
* <blockquote>audio/* &lt; audio/*;q=0.7; audio/*;q=0.3</blockquote>
* <blockquote>audio/basic;level=1 &lt; audio/basic</blockquote>
* <blockquote>audio/basic == text/html</blockquote>
* <blockquote>audio/basic == audio/wave</blockquote>
* @param mediaTypes the list of media types to be sorted
* @deprecated As of 6.0, in favor of {@link MimeTypeUtils#sortBySpecificity(List)}
*/
@Deprecated(since = "6.0", forRemoval = true)
public static void sortBySpecificity(List<MediaType> mediaTypes) {
Assert.notNull(mediaTypes, "'mediaTypes' must not be null");
if (mediaTypes.size() > 1) {
mediaTypes.sort(SPECIFICITY_COMPARATOR);
}
}
/**
* Sorts the given list of {@code MediaType} objects by quality value.
* <p>Given two media types:
* <ol>
* <li>if the two media types have different {@linkplain #getQualityValue() quality value}, then the media type
* with the highest quality value is ordered before the other.</li>
* <li>if either media type has a {@linkplain #isWildcardType() wildcard type}, then the media type without the
* wildcard is ordered before the other.</li>
* <li>if the two media types have different {@linkplain #getType() types}, then they are considered equal and
* remain their current order.</li>
* <li>if either media type has a {@linkplain #isWildcardSubtype() wildcard subtype}, then the media type without
* the wildcard is sorted before the other.</li>
* <li>if the two media types have different {@linkplain #getSubtype() subtypes}, then they are considered equal
* and remain their current order.</li>
* <li>if the two media types have a different amount of {@linkplain #getParameter(String) parameters}, then the
* media type with the most parameters is ordered before the other.</li>
* </ol>
* @param mediaTypes the list of media types to be sorted
* @see #getQualityValue()
* @deprecated As of 6.0, with no direct replacement
*/
@Deprecated(since = "6.0", forRemoval = true)
public static void sortByQualityValue(List<MediaType> mediaTypes) {
Assert.notNull(mediaTypes, "'mediaTypes' must not be null");
if (mediaTypes.size() > 1) {
mediaTypes.sort(QUALITY_VALUE_COMPARATOR);
}
}
/**
* Sorts the given list of {@code MediaType} objects by specificity as the
* primary criteria and quality value the secondary.
* @deprecated As of 6.0, in favor of {@link MimeTypeUtils#sortBySpecificity(List)}
*/
@Deprecated(since = "6.0")
public static void sortBySpecificityAndQuality(List<MediaType> mediaTypes) {
Assert.notNull(mediaTypes, "'mediaTypes' must not be null");
if (mediaTypes.size() > 1) {
mediaTypes.sort(MediaType.SPECIFICITY_COMPARATOR.thenComparing(MediaType.QUALITY_VALUE_COMPARATOR));
}
}
/**
* Comparator used by {@link #sortByQualityValue(List)}.
* @deprecated As of 6.0, with no direct replacement
*/
@Deprecated(since = "6.0", forRemoval = true)
public static final Comparator<MediaType> QUALITY_VALUE_COMPARATOR = (mediaType1, mediaType2) -> {
double quality1 = mediaType1.getQualityValue();
double quality2 = mediaType2.getQualityValue();
int qualityComparison = Double.compare(quality2, quality1);
if (qualityComparison != 0) {
return qualityComparison; // audio/*;q=0.7 < audio/*;q=0.3
}
else if (mediaType1.isWildcardType() && !mediaType2.isWildcardType()) { // */* < audio/*
return 1;
}
else if (mediaType2.isWildcardType() && !mediaType1.isWildcardType()) { // audio/* > */*
return -1;
}
else if (!mediaType1.getType().equals(mediaType2.getType())) { // audio/basic == text/html
return 0;
}
else { // mediaType1.getType().equals(mediaType2.getType())
if (mediaType1.isWildcardSubtype() && !mediaType2.isWildcardSubtype()) { // audio/* < audio/basic
return 1;
}
else if (mediaType2.isWildcardSubtype() && !mediaType1.isWildcardSubtype()) { // audio/basic > audio/*
return -1;
}
else if (!mediaType1.getSubtype().equals(mediaType2.getSubtype())) { // audio/basic == audio/wave
return 0;
}
else {
int paramsSize1 = mediaType1.getParameters().size();
int paramsSize2 = mediaType2.getParameters().size();
return Integer.compare(paramsSize2, paramsSize1); // audio/basic;level=1 < audio/basic
}
}
};
/**
* Comparator used by {@link #sortBySpecificity(List)}.
* @deprecated As of 6.0, with no direct replacement
*/
@Deprecated(since = "6.0", forRemoval = true)
@SuppressWarnings("removal")
public static final Comparator<MediaType> SPECIFICITY_COMPARATOR = new SpecificityComparator<>() {
@Override
protected int compareParameters(MediaType mediaType1, MediaType mediaType2) {
double quality1 = mediaType1.getQualityValue();
double quality2 = mediaType2.getQualityValue();
int qualityComparison = Double.compare(quality2, quality1);
if (qualityComparison != 0) {
return qualityComparison; // audio/*;q=0.7 < audio/*;q=0.3
}
return super.compareParameters(mediaType1, mediaType2);
}
};
} }

View File

@ -42,19 +42,6 @@ public interface ClientHttpResponse extends HttpInputMessage, Closeable {
*/ */
HttpStatusCode getStatusCode() throws IOException; HttpStatusCode getStatusCode() throws IOException;
/**
* Get the HTTP status code as an integer.
* @return the HTTP status as an integer value
* @throws IOException in case of I/O errors
* @since 3.1.1
* @see #getStatusCode()
* @deprecated in favor of {@link #getStatusCode()}, for removal in 7.0
*/
@Deprecated(since = "6.0", forRemoval = true)
default int getRawStatusCode() throws IOException {
return getStatusCode().value();
}
/** /**
* Get the HTTP status text of the response. * Get the HTTP status text of the response.
* @return the HTTP status text * @return the HTTP status text

View File

@ -209,18 +209,6 @@ public class HttpComponentsClientHttpRequestFactory implements ClientHttpRequest
this.readTimeout = readTimeout.toMillis(); this.readTimeout = readTimeout.toMillis();
} }
/**
* Indicates whether this request factory should buffer the request body internally.
* <p>Default is {@code true}. When sending large amounts of data via POST or PUT, it is
* recommended to change this property to {@code false}, so as not to run out of memory.
* @since 4.0
* @deprecated since 6.1 requests are never buffered, as if this property is {@code false}
*/
@Deprecated(since = "6.1", forRemoval = true)
public void setBufferRequestBody(boolean bufferRequestBody) {
// no-op
}
/** /**
* Configure a factory to pre-create the {@link HttpContext} for each request. * Configure a factory to pre-create the {@link HttpContext} for each request.
* <p>This may be useful for example in mutual TLS authentication where a * <p>This may be useful for example in mutual TLS authentication where a

View File

@ -1,142 +0,0 @@
/*
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.http.client;
import java.io.IOException;
import java.net.URI;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okio.BufferedSink;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;
/**
* {@link ClientHttpRequest} implementation based on OkHttp 3.x.
*
* <p>Created via the {@link OkHttp3ClientHttpRequestFactory}.
*
* @author Luciano Leggieri
* @author Arjen Poutsma
* @author Roy Clarkson
* @since 4.3
* @deprecated since 6.1, in favor of other HTTP client libraries;
* scheduled for removal in 7.0
*/
@Deprecated(since = "6.1", forRemoval = true)
class OkHttp3ClientHttpRequest extends AbstractStreamingClientHttpRequest {
private final OkHttpClient client;
private final URI uri;
private final HttpMethod method;
public OkHttp3ClientHttpRequest(OkHttpClient client, URI uri, HttpMethod method) {
this.client = client;
this.uri = uri;
this.method = method;
}
@Override
public HttpMethod getMethod() {
return this.method;
}
@Override
public URI getURI() {
return this.uri;
}
@Override
@SuppressWarnings("removal")
protected ClientHttpResponse executeInternal(HttpHeaders headers, @Nullable Body body) throws IOException {
RequestBody requestBody;
if (body != null) {
requestBody = new BodyRequestBody(headers, body);
}
else if (okhttp3.internal.http.HttpMethod.requiresRequestBody(getMethod().name())) {
String header = headers.getFirst(HttpHeaders.CONTENT_TYPE);
MediaType contentType = (header != null) ? MediaType.parse(header) : null;
requestBody = RequestBody.create(contentType, new byte[0]);
}
else {
requestBody = null;
}
Request.Builder builder = new Request.Builder()
.url(this.uri.toURL());
builder.method(this.method.name(), requestBody);
headers.forEach((headerName, headerValues) -> {
for (String headerValue : headerValues) {
builder.addHeader(headerName, headerValue);
}
});
Request request = builder.build();
return new OkHttp3ClientHttpResponse(this.client.newCall(request).execute());
}
private static class BodyRequestBody extends RequestBody {
private final HttpHeaders headers;
private final Body body;
public BodyRequestBody(HttpHeaders headers, Body body) {
this.headers = headers;
this.body = body;
}
@Override
public long contentLength() {
return this.headers.getContentLength();
}
@Nullable
@Override
public MediaType contentType() {
String contentType = this.headers.getFirst(HttpHeaders.CONTENT_TYPE);
if (StringUtils.hasText(contentType)) {
return MediaType.parse(contentType);
}
else {
return null;
}
}
@Override
public void writeTo(BufferedSink sink) throws IOException {
this.body.writeTo(sink.outputStream());
}
@Override
public boolean isOneShot() {
return !this.body.repeatable();
}
}
}

View File

@ -1,153 +0,0 @@
/*
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.http.client;
import java.io.IOException;
import java.net.URI;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
import okhttp3.Cache;
import okhttp3.OkHttpClient;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.http.HttpMethod;
import org.springframework.util.Assert;
/**
* {@link ClientHttpRequestFactory} implementation that uses
* <a href="https://square.github.io/okhttp/">OkHttp</a> 3.x to create requests.
*
* @author Luciano Leggieri
* @author Arjen Poutsma
* @author Roy Clarkson
* @since 4.3
* @deprecated since 6.1, in favor of other {@link ClientHttpRequestFactory} implementations;
* scheduled for removal in 7.0
*/
@Deprecated(since = "6.1", forRemoval = true)
public class OkHttp3ClientHttpRequestFactory implements ClientHttpRequestFactory, DisposableBean {
private OkHttpClient client;
private final boolean defaultClient;
/**
* Create a factory with a default {@link OkHttpClient} instance.
*/
public OkHttp3ClientHttpRequestFactory() {
this.client = new OkHttpClient();
this.defaultClient = true;
}
/**
* Create a factory with the given {@link OkHttpClient} instance.
* @param client the client to use
*/
public OkHttp3ClientHttpRequestFactory(OkHttpClient client) {
Assert.notNull(client, "OkHttpClient must not be null");
this.client = client;
this.defaultClient = false;
}
/**
* Set the underlying read timeout in milliseconds.
* A value of 0 specifies an infinite timeout.
*/
public void setReadTimeout(int readTimeout) {
this.client = this.client.newBuilder()
.readTimeout(readTimeout, TimeUnit.MILLISECONDS)
.build();
}
/**
* Set the underlying read timeout in milliseconds.
* A value of 0 specifies an infinite timeout.
* @since 6.1
*/
public void setReadTimeout(Duration readTimeout) {
this.client = this.client.newBuilder()
.readTimeout(readTimeout)
.build();
}
/**
* Set the underlying write timeout in milliseconds.
* A value of 0 specifies an infinite timeout.
*/
public void setWriteTimeout(int writeTimeout) {
this.client = this.client.newBuilder()
.writeTimeout(writeTimeout, TimeUnit.MILLISECONDS)
.build();
}
/**
* Set the underlying write timeout in milliseconds.
* A value of 0 specifies an infinite timeout.
* @since 6.1
*/
public void setWriteTimeout(Duration writeTimeout) {
this.client = this.client.newBuilder()
.writeTimeout(writeTimeout)
.build();
}
/**
* Set the underlying connect timeout in milliseconds.
* A value of 0 specifies an infinite timeout.
*/
public void setConnectTimeout(int connectTimeout) {
this.client = this.client.newBuilder()
.connectTimeout(connectTimeout, TimeUnit.MILLISECONDS)
.build();
}
/**
* Set the underlying connect timeout in milliseconds.
* A value of 0 specifies an infinite timeout.
* @since 6.1
*/
public void setConnectTimeout(Duration connectTimeout) {
this.client = this.client.newBuilder()
.connectTimeout(connectTimeout)
.build();
}
@Override
@SuppressWarnings("removal")
public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) {
return new OkHttp3ClientHttpRequest(this.client, uri, httpMethod);
}
@Override
public void destroy() throws IOException {
if (this.defaultClient) {
// Clean up the client if we created it in the constructor
Cache cache = this.client.cache();
if (cache != null) {
cache.close();
}
this.client.dispatcher().executorService().shutdown();
this.client.connectionPool().evictAll();
}
}
}

View File

@ -1,94 +0,0 @@
/*
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.http.client;
import java.io.IOException;
import java.io.InputStream;
import okhttp3.Response;
import okhttp3.ResponseBody;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatusCode;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* {@link ClientHttpResponse} implementation based on OkHttp 3.x.
*
* @author Luciano Leggieri
* @author Arjen Poutsma
* @author Roy Clarkson
* @since 4.3
* @deprecated since 6.1, in favor of other HTTP client libraries;
* scheduled for removal in 7.0
*/
@Deprecated(since = "6.1", forRemoval = true)
class OkHttp3ClientHttpResponse implements ClientHttpResponse {
private final Response response;
@Nullable
private volatile HttpHeaders headers;
public OkHttp3ClientHttpResponse(Response response) {
Assert.notNull(response, "Response must not be null");
this.response = response;
}
@Override
public HttpStatusCode getStatusCode() throws IOException {
return HttpStatusCode.valueOf(this.response.code());
}
@Override
public String getStatusText() {
return this.response.message();
}
@Override
public InputStream getBody() throws IOException {
ResponseBody body = this.response.body();
return (body != null ? body.byteStream() : InputStream.nullInputStream());
}
@Override
public HttpHeaders getHeaders() {
HttpHeaders headers = this.headers;
if (headers == null) {
headers = new HttpHeaders();
for (String headerName : this.response.headers().names()) {
for (String headerValue : this.response.headers(headerName)) {
headers.add(headerName, headerValue);
}
}
this.headers = headers;
}
return headers;
}
@Override
public void close() {
ResponseBody body = this.response.body();
if (body != null) {
body.close();
}
}
}

View File

@ -81,24 +81,6 @@ final class ReactorClientHttpRequest extends AbstractStreamingClientHttpRequest
this.exchangeTimeout = exchangeTimeout; this.exchangeTimeout = exchangeTimeout;
} }
/**
* Original constructor with timeout values.
* @deprecated without a replacement; readTimeout is now applied to the
* underlying client via {@link HttpClient#responseTimeout(Duration)}, and the
* value passed here is not used; exchangeTimeout is deprecated and superseded
* by Reactor Netty timeout configuration, but applied if set.
*/
@Deprecated(since = "6.2", forRemoval = true)
public ReactorClientHttpRequest(
HttpClient httpClient, URI uri, HttpMethod method,
@Nullable Duration exchangeTimeout, @Nullable Duration readTimeout) {
this.httpClient = httpClient;
this.method = method;
this.uri = uri;
this.exchangeTimeout = exchangeTimeout;
}
@Override @Override
public HttpMethod getMethod() { public HttpMethod getMethod() {

View File

@ -180,36 +180,6 @@ public class ReactorClientHttpRequestFactory implements ClientHttpRequestFactory
setReadTimeout(Duration.ofMillis(readTimeout)); setReadTimeout(Duration.ofMillis(readTimeout));
} }
/**
* Set the timeout for the HTTP exchange in milliseconds.
* <p>By default, as of 6.2 this is no longer set.
* @see #setConnectTimeout(int)
* @see #setReadTimeout(Duration)
* @see <a href="https://projectreactor.io/docs/netty/release/reference/index.html#timeout-configuration">Timeout Configuration</a>
* @deprecated as of 6.2 and no longer set by default (previously 5 seconds)
* in favor of using Reactor Netty HttpClient timeout configuration.
*/
@Deprecated(since = "6.2", forRemoval = true)
public void setExchangeTimeout(long exchangeTimeout) {
Assert.isTrue(exchangeTimeout > 0, "Timeout must be a positive value");
this.exchangeTimeout = Duration.ofMillis(exchangeTimeout);
}
/**
* Variant of {@link #setExchangeTimeout(long)} with a Duration value.
* <p>By default, as of 6.2 this is no longer set.
* @see #setConnectTimeout(int)
* @see #setReadTimeout(Duration)
* @see <a href="https://projectreactor.io/docs/netty/release/reference/index.html#timeout-configuration">Timeout Configuration</a>
* @deprecated as of 6.2 and no longer set by default (previously 5 seconds)
* in favor of using Reactor Netty HttpClient timeout configuration.
*/
@Deprecated(since = "6.2", forRemoval = true)
public void setExchangeTimeout(Duration exchangeTimeout) {
Assert.notNull(exchangeTimeout, "ExchangeTimeout must not be null");
setExchangeTimeout((int) exchangeTimeout.toMillis());
}
@Override @Override
public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException { public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {

View File

@ -18,12 +18,10 @@ package org.springframework.http.client;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.time.Duration;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import org.reactivestreams.FlowAdapters; import org.reactivestreams.FlowAdapters;
import reactor.netty.Connection; import reactor.netty.Connection;
import reactor.netty.http.client.HttpClient;
import reactor.netty.http.client.HttpClientResponse; import reactor.netty.http.client.HttpClientResponse;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
@ -64,21 +62,6 @@ final class ReactorClientHttpResponse implements ClientHttpResponse {
new Netty4HeadersAdapter(response.responseHeaders())); new Netty4HeadersAdapter(response.responseHeaders()));
} }
/**
* Original constructor.
* @deprecated without a replacement; readTimeout is now applied to the
* underlying client via {@link HttpClient#responseTimeout(Duration)}, and the
* value passed here is not used.
*/
@Deprecated(since = "6.2", forRemoval = true)
public ReactorClientHttpResponse(
HttpClientResponse response, Connection connection, @Nullable Duration readTimeout) {
this.response = response;
this.connection = connection;
this.headers = HttpHeaders.readOnlyHttpHeaders(new Netty4HeadersAdapter(response.responseHeaders()));
}
@Override @Override
public HttpStatusCode getStatusCode() { public HttpStatusCode getStatusCode() {

View File

@ -1,58 +0,0 @@
/*
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.http.client;
import java.util.function.Function;
import reactor.netty.http.client.HttpClient;
/**
* Reactor-Netty implementation of {@link ClientHttpRequestFactory}.
*
* @author Arjen Poutsma
* @author Juergen Hoeller
* @since 6.1
* @deprecated in favor of the renamed {@link ReactorClientHttpRequestFactory}
*/
@Deprecated(since = "6.2", forRemoval = true)
public class ReactorNettyClientRequestFactory extends ReactorClientHttpRequestFactory {
/**
* Superseded by {@link ReactorClientHttpRequestFactory}.
* @see ReactorClientHttpRequestFactory#ReactorClientHttpRequestFactory()
*/
public ReactorNettyClientRequestFactory() {
super();
}
/**
* Superseded by {@link ReactorClientHttpRequestFactory}.
* @see ReactorClientHttpRequestFactory#ReactorClientHttpRequestFactory(HttpClient)
*/
public ReactorNettyClientRequestFactory(HttpClient httpClient) {
super(httpClient);
}
/**
* Superseded by {@link ReactorClientHttpRequestFactory}.
* @see ReactorClientHttpRequestFactory#ReactorClientHttpRequestFactory(ReactorResourceFactory, Function)
*/
public ReactorNettyClientRequestFactory(ReactorResourceFactory resourceFactory, Function<HttpClient, HttpClient> mapper) {
super(resourceFactory, mapper);
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2023 the original author or authors. * Copyright 2002-2024 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.
@ -59,24 +59,6 @@ public class SimpleClientHttpRequestFactory implements ClientHttpRequestFactory
this.proxy = proxy; this.proxy = proxy;
} }
/**
* Indicate whether this request factory should buffer the
* {@linkplain ClientHttpRequest#getBody() request body} internally.
* <p>Default is {@code true}. When sending large amounts of data via POST or PUT,
* it is recommended to change this property to {@code false}, so as not to run
* out of memory. This will result in a {@link ClientHttpRequest} that either
* streams directly to the underlying {@link HttpURLConnection} (if the
* {@link org.springframework.http.HttpHeaders#getContentLength() Content-Length}
* is known in advance), or that will use "Chunked transfer encoding"
* (if the {@code Content-Length} is not known in advance).
* @see #setChunkSize(int)
* @see HttpURLConnection#setFixedLengthStreamingMode(int)
* @deprecated since 6.1 requests are never buffered, as if this property is {@code false}
*/
@Deprecated(since = "6.1", forRemoval = true)
public void setBufferRequestBody(boolean bufferRequestBody) {
}
/** /**
* Set the number of bytes to write in each chunk when not buffering request * Set the number of bytes to write in each chunk when not buffering request
* bodies locally. * bodies locally.
@ -134,20 +116,6 @@ public class SimpleClientHttpRequestFactory implements ClientHttpRequestFactory
this.readTimeout = (int) readTimeout.toMillis(); this.readTimeout = (int) readTimeout.toMillis();
} }
/**
* Set if the underlying URLConnection can be set to 'output streaming' mode.
* Default is {@code true}.
* <p>When output streaming is enabled, authentication and redirection cannot be handled automatically.
* If output streaming is disabled, the {@link HttpURLConnection#setFixedLengthStreamingMode} and
* {@link HttpURLConnection#setChunkedStreamingMode} methods of the underlying connection will never
* be called.
* @param outputStreaming if output streaming is enabled
* @deprecated as of 6.1 requests are always streamed, as if this property is {@code true}
*/
@Deprecated(since = "6.1", forRemoval = true)
public void setOutputStreaming(boolean outputStreaming) {
}
@Override @Override
public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException { public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {

View File

@ -46,18 +46,6 @@ public interface ClientHttpResponse extends ReactiveHttpInputMessage {
*/ */
HttpStatusCode getStatusCode(); HttpStatusCode getStatusCode();
/**
* Return the HTTP status code as an integer.
* @return the HTTP status as an integer value
* @since 5.0.6
* @see #getStatusCode()
* @deprecated in favor of {@link #getStatusCode()}, for removal in 7.0
*/
@Deprecated(since = "6.0", forRemoval = true)
default int getRawStatusCode() {
return getStatusCode().value();
}
/** /**
* Return a read-only map of response cookies received from the server. * Return a read-only map of response cookies received from the server.
*/ */

View File

@ -76,14 +76,6 @@ class ReactorNetty2ServerHttpResponse extends AbstractServerHttpResponse impleme
return (status != null ? status : HttpStatusCode.valueOf(this.response.status().code())); return (status != null ? status : HttpStatusCode.valueOf(this.response.status().code()));
} }
@Override
@Deprecated
@SuppressWarnings("removal")
public Integer getRawStatusCode() {
Integer status = super.getRawStatusCode();
return (status != null ? status : this.response.status().code());
}
@Override @Override
protected void applyStatusCode() { protected void applyStatusCode() {
HttpStatusCode status = super.getStatusCode(); HttpStatusCode status = super.getStatusCode();

View File

@ -75,14 +75,6 @@ class ReactorServerHttpResponse extends AbstractServerHttpResponse implements Ze
return (status != null ? status : HttpStatusCode.valueOf(this.response.status().code())); return (status != null ? status : HttpStatusCode.valueOf(this.response.status().code()));
} }
@Override
@Deprecated
@SuppressWarnings("removal")
public Integer getRawStatusCode() {
Integer status = super.getRawStatusCode();
return (status != null ? status : this.response.status().code());
}
@Override @Override
protected void applyStatusCode() { protected void applyStatusCode() {
HttpStatusCode status = super.getStatusCode(); HttpStatusCode status = super.getStatusCode();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2022 the original author or authors. * Copyright 2002-2024 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.
@ -60,20 +60,6 @@ public interface ServerHttpResponse extends ReactiveHttpOutputMessage {
return setStatusCode(value != null ? HttpStatusCode.valueOf(value) : null); return setStatusCode(value != null ? HttpStatusCode.valueOf(value) : null);
} }
/**
* Return the status code that has been set, or otherwise fall back on the
* status of the response from the underlying server. The return value may
* be {@code null} if there is no default value from the underlying server.
* @since 5.2.4
* @deprecated in favor of {@link #getStatusCode()}, for removal in 7.0
*/
@Deprecated(since = "6.0", forRemoval = true)
@Nullable
default Integer getRawStatusCode() {
HttpStatusCode httpStatus = getStatusCode();
return (httpStatus != null ? httpStatus.value() : null);
}
/** /**
* Return a mutable map with the cookies to send to the server. * Return a mutable map with the cookies to send to the server.
*/ */

View File

@ -71,14 +71,6 @@ public class ServerHttpResponseDecorator implements ServerHttpResponse {
return getDelegate().setRawStatusCode(value); return getDelegate().setRawStatusCode(value);
} }
@Override
@Nullable
@Deprecated
@SuppressWarnings("removal")
public Integer getRawStatusCode() {
return getDelegate().getRawStatusCode();
}
@Override @Override
public HttpHeaders getHeaders() { public HttpHeaders getHeaders() {
return getDelegate().getHeaders(); return getDelegate().getHeaders();

View File

@ -104,14 +104,6 @@ class ServletServerHttpResponse extends AbstractListenerServerHttpResponse {
return (status != null ? status : HttpStatusCode.valueOf(this.response.getStatus())); return (status != null ? status : HttpStatusCode.valueOf(this.response.getStatus()));
} }
@Override
@Deprecated
@SuppressWarnings("removal")
public Integer getRawStatusCode() {
Integer status = super.getRawStatusCode();
return (status != null ? status : this.response.getStatus());
}
@Override @Override
protected void applyStatusCode() { protected void applyStatusCode() {
HttpStatusCode status = super.getStatusCode(); HttpStatusCode status = super.getStatusCode();

View File

@ -87,14 +87,6 @@ class UndertowServerHttpResponse extends AbstractListenerServerHttpResponse impl
return (status != null ? status : HttpStatusCode.valueOf(this.exchange.getStatusCode())); return (status != null ? status : HttpStatusCode.valueOf(this.exchange.getStatusCode()));
} }
@Override
@Deprecated
@SuppressWarnings("removal")
public Integer getRawStatusCode() {
Integer status = super.getRawStatusCode();
return (status != null ? status : this.exchange.getStatusCode());
}
@Override @Override
protected void applyStatusCode() { protected void applyStatusCode() {
HttpStatusCode status = super.getStatusCode(); HttpStatusCode status = super.getStatusCode();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2023 the original author or authors. * Copyright 2002-2024 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,25 +66,6 @@ public class MissingServletRequestParameterException extends MissingRequestValue
getBody().setDetail(initBodyDetail(this.parameterName)); getBody().setDetail(initBodyDetail(this.parameterName));
} }
/**
* Constructor for use when a value was present but converted to {@code null}.
* @param parameterName the name of the missing parameter
* @param parameterType the expected type of the missing parameter
* @param missingAfterConversion whether the value became null after conversion
* @since 5.3.6
* @deprecated in favor of {@link #MissingServletRequestParameterException(String, MethodParameter, boolean)}
*/
@Deprecated(since = "6.1", forRemoval = true)
public MissingServletRequestParameterException(
String parameterName, String parameterType, boolean missingAfterConversion) {
super("", missingAfterConversion, null, new Object[] {parameterName});
this.parameterName = parameterName;
this.parameterType = parameterType;
this.parameter = null;
getBody().setDetail(initBodyDetail(this.parameterName));
}
private static String initBodyDetail(String name) { private static String initBodyDetail(String name) {
return "Required parameter '" + name + "' is not present."; return "Required parameter '" + name + "' is not present.";
} }

View File

@ -136,31 +136,9 @@ public class DefaultResponseErrorHandler implements ResponseErrorHandler {
*/ */
@Override @Override
public void handleError(URI url, HttpMethod method, ClientHttpResponse response) throws IOException { public void handleError(URI url, HttpMethod method, ClientHttpResponse response) throws IOException {
// For backwards compatibility try handle(response) first
HandleErrorResponseDecorator decorator = new HandleErrorResponseDecorator(response);
handleError(decorator);
if (decorator.isHandled()) {
return;
}
handleError(response, response.getStatusCode(), url, method); handleError(response, response.getStatusCode(), url, method);
} }
@SuppressWarnings("removal")
@Override
public void handleError(ClientHttpResponse response) throws IOException {
// Called via handleError(url, method, response)
if (response instanceof HandleErrorResponseDecorator decorator) {
decorator.setNotHandled();
return;
}
// Called directly, so do handle
handleError(response, response.getStatusCode(), null, null);
}
/** /**
* Handle the error based on the resolved status code. * Handle the error based on the resolved status code.
* <p>The default implementation delegates to * <p>The default implementation delegates to
@ -288,22 +266,4 @@ public class DefaultResponseErrorHandler implements ResponseErrorHandler {
}; };
} }
private static class HandleErrorResponseDecorator extends ClientHttpResponseDecorator {
private boolean handled = true;
public HandleErrorResponseDecorator(ClientHttpResponse delegate) {
super(delegate);
}
public void setNotHandled() {
this.handled = false;
}
public boolean isHandled() {
return this.handled;
}
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2018 the original author or authors. * Copyright 2002-2024 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.
@ -52,19 +52,6 @@ public interface ResponseErrorHandler {
* @since 5.0 * @since 5.0
*/ */
default void handleError(URI url, HttpMethod method, ClientHttpResponse response) throws IOException { default void handleError(URI url, HttpMethod method, ClientHttpResponse response) throws IOException {
handleError(response);
}
/**
* Handle the error in the given response.
* <p>This method is only called when {@link #hasError(ClientHttpResponse)}
* has returned {@code true}.
* @param response the response with the error
* @throws IOException in case of I/O errors
* @deprecated in favor of {@link #handleError(URI, HttpMethod, ClientHttpResponse)}
*/
@Deprecated(since = "6.2.1", forRemoval = true)
default void handleError(ClientHttpResponse response) throws IOException {
} }
} }

View File

@ -1,176 +0,0 @@
/*
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.filter.reactive;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import io.micrometer.observation.Observation;
import io.micrometer.observation.ObservationRegistry;
import io.micrometer.observation.contextpropagation.ObservationThreadLocalAccessor;
import reactor.core.observability.DefaultSignalListener;
import reactor.core.publisher.Mono;
import reactor.util.context.Context;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.observation.DefaultServerRequestObservationConvention;
import org.springframework.http.server.reactive.observation.ServerHttpObservationDocumentation;
import org.springframework.http.server.reactive.observation.ServerRequestObservationContext;
import org.springframework.http.server.reactive.observation.ServerRequestObservationConvention;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
/**
* {@link org.springframework.web.server.WebFilter} that creates {@link Observation observations}
* for HTTP exchanges. This collects information about the execution time and
* information gathered from the {@link ServerRequestObservationContext}.
* <p>Web Frameworks can fetch the current {@link ServerRequestObservationContext context}
* as a {@link #CURRENT_OBSERVATION_CONTEXT_ATTRIBUTE request attribute} and contribute
* additional information to it.
* The configured {@link ServerRequestObservationConvention} will use this context to collect
* {@link io.micrometer.common.KeyValue metadata} and attach it to the observation.
*
* @author Brian Clozel
* @since 6.0
* @deprecated since 6.1 in favor of {@link WebHttpHandlerBuilder}.
*/
@Deprecated(since = "6.1", forRemoval = true)
public class ServerHttpObservationFilter implements WebFilter {
/**
* Name of the request attribute holding the {@link ServerRequestObservationContext context} for the current observation.
*/
public static final String CURRENT_OBSERVATION_CONTEXT_ATTRIBUTE = ServerHttpObservationFilter.class.getName() + ".context";
private static final ServerRequestObservationConvention DEFAULT_OBSERVATION_CONVENTION = new DefaultServerRequestObservationConvention();
private final ObservationRegistry observationRegistry;
private final ServerRequestObservationConvention observationConvention;
/**
* Create an {@code HttpRequestsObservationWebFilter} that records observations
* against the given {@link ObservationRegistry}. The default
* {@link DefaultServerRequestObservationConvention convention} will be used.
* @param observationRegistry the registry to use for recording observations
*/
public ServerHttpObservationFilter(ObservationRegistry observationRegistry) {
this(observationRegistry, DEFAULT_OBSERVATION_CONVENTION);
}
/**
* Create an {@code HttpRequestsObservationWebFilter} that records observations
* against the given {@link ObservationRegistry} with a custom convention.
* @param observationRegistry the registry to use for recording observations
* @param observationConvention the convention to use for all recorded observations
*/
public ServerHttpObservationFilter(ObservationRegistry observationRegistry, ServerRequestObservationConvention observationConvention) {
this.observationRegistry = observationRegistry;
this.observationConvention = observationConvention;
}
/**
* Get the current {@link ServerRequestObservationContext observation context} from the given request, if available.
* @param exchange the current exchange
* @return the current observation context
*/
public static Optional<ServerRequestObservationContext> findObservationContext(ServerWebExchange exchange) {
return Optional.ofNullable(exchange.getAttribute(CURRENT_OBSERVATION_CONTEXT_ATTRIBUTE));
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
ServerRequestObservationContext observationContext = new ServerRequestObservationContext(exchange.getRequest(),
exchange.getResponse(), exchange.getAttributes());
exchange.getAttributes().put(CURRENT_OBSERVATION_CONTEXT_ATTRIBUTE, observationContext);
return chain.filter(exchange).tap(() -> new ObservationSignalListener(observationContext));
}
private final class ObservationSignalListener extends DefaultSignalListener<Void> {
private static final Set<String> DISCONNECTED_CLIENT_EXCEPTIONS = Set.of("AbortedException",
"ClientAbortException", "EOFException", "EofException");
private final ServerRequestObservationContext observationContext;
private final Observation observation;
private final AtomicBoolean observationRecorded = new AtomicBoolean();
ObservationSignalListener(ServerRequestObservationContext observationContext) {
this.observationContext = observationContext;
this.observation = ServerHttpObservationDocumentation.HTTP_REACTIVE_SERVER_REQUESTS.observation(observationConvention,
DEFAULT_OBSERVATION_CONVENTION, () -> observationContext, observationRegistry);
}
@Override
public Context addToContext(Context originalContext) {
return originalContext.put(ObservationThreadLocalAccessor.KEY, this.observation);
}
@Override
public void doFirst() throws Throwable {
this.observation.start();
}
@Override
public void doOnCancel() throws Throwable {
if (this.observationRecorded.compareAndSet(false, true)) {
this.observationContext.setConnectionAborted(true);
this.observation.stop();
}
}
@Override
public void doOnComplete() throws Throwable {
if (this.observationRecorded.compareAndSet(false, true)) {
doOnTerminate(this.observationContext);
}
}
@Override
public void doOnError(Throwable error) throws Throwable {
if (this.observationRecorded.compareAndSet(false, true)) {
if (DISCONNECTED_CLIENT_EXCEPTIONS.contains(error.getClass().getSimpleName())) {
this.observationContext.setConnectionAborted(true);
}
this.observationContext.setError(error);
doOnTerminate(this.observationContext);
}
}
private void doOnTerminate(ServerRequestObservationContext context) {
ServerHttpResponse response = context.getResponse();
if (response != null) {
if (response.isCommitted()) {
this.observation.stop();
}
else {
response.beforeCommit(() -> {
this.observation.stop();
return Mono.empty();
});
}
}
}
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2022 the original author or authors. * Copyright 2002-2024 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.
@ -88,11 +88,10 @@ public class ResponseStatusExceptionHandler implements WebExceptionHandler {
return "Resolved [" + className + ": " + message + "] for HTTP " + request.getMethod() + " " + path; return "Resolved [" + className + ": " + message + "] for HTTP " + request.getMethod() + " " + path;
} }
@SuppressWarnings("deprecation")
private boolean updateResponse(ServerHttpResponse response, Throwable ex) { private boolean updateResponse(ServerHttpResponse response, Throwable ex) {
boolean result = false; boolean result = false;
HttpStatusCode statusCode = determineStatus(ex); HttpStatusCode statusCode = determineStatus(ex);
int code = (statusCode != null ? statusCode.value() : determineRawStatusCode(ex)); int code = (statusCode != null ? statusCode.value() : -1);
if (code != -1) { if (code != -1) {
if (response.setStatusCode(statusCode)) { if (response.setStatusCode(statusCode)) {
if (ex instanceof ResponseStatusException responseStatusException) { if (ex instanceof ResponseStatusException responseStatusException) {
@ -127,19 +126,4 @@ public class ResponseStatusExceptionHandler implements WebExceptionHandler {
} }
} }
/**
* Determine the raw status code for the given exception.
* @param ex the exception to check
* @return the associated HTTP status code, or -1 if it can't be derived.
* @since 5.3
* @deprecated in favor of {@link #determineStatus(Throwable)}, for removal in 7.0
*/
@Deprecated(since = "6.0", forRemoval = true)
protected int determineRawStatusCode(Throwable ex) {
if (ex instanceof ResponseStatusException responseStatusException) {
return responseStatusException.getStatusCode().value();
}
return -1;
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2023 the original author or authors. * Copyright 2002-2024 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.
@ -18,9 +18,6 @@ package org.springframework.web.service.invoker;
import java.time.Duration; import java.time.Duration;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import org.springframework.core.ParameterizedTypeReference; import org.springframework.core.ParameterizedTypeReference;
import org.springframework.core.ReactiveAdapterRegistry; import org.springframework.core.ReactiveAdapterRegistry;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
@ -35,9 +32,7 @@ import org.springframework.util.Assert;
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
* @since 6.1 * @since 6.1
*/ */
@SuppressWarnings("removal") public abstract class AbstractReactorHttpExchangeAdapter implements ReactorHttpExchangeAdapter {
public abstract class AbstractReactorHttpExchangeAdapter
implements ReactorHttpExchangeAdapter, org.springframework.web.service.invoker.HttpClientAdapter {
private ReactiveAdapterRegistry reactiveAdapterRegistry = ReactiveAdapterRegistry.getSharedInstance(); private ReactiveAdapterRegistry reactiveAdapterRegistry = ReactiveAdapterRegistry.getSharedInstance();
@ -126,46 +121,4 @@ public abstract class AbstractReactorHttpExchangeAdapter
return entity; return entity;
} }
// HttpClientAdapter implementation
@Override
public Mono<Void> requestToVoid(HttpRequestValues requestValues) {
return exchangeForMono(requestValues);
}
@Override
public Mono<HttpHeaders> requestToHeaders(HttpRequestValues requestValues) {
return exchangeForHeadersMono(requestValues);
}
@Override
public <T> Mono<T> requestToBody(HttpRequestValues requestValues, ParameterizedTypeReference<T> bodyType) {
return exchangeForBodyMono(requestValues, bodyType);
}
@Override
public <T> Flux<T> requestToBodyFlux(HttpRequestValues requestValues, ParameterizedTypeReference<T> bodyType) {
return exchangeForBodyFlux(requestValues, bodyType);
}
@Override
public Mono<ResponseEntity<Void>> requestToBodilessEntity(HttpRequestValues requestValues) {
return exchangeForBodilessEntityMono(requestValues);
}
@Override
public <T> Mono<ResponseEntity<T>> requestToEntity(
HttpRequestValues requestValues, ParameterizedTypeReference<T> bodyType) {
return exchangeForEntityMono(requestValues, bodyType);
}
@Override
public <T> Mono<ResponseEntity<Flux<T>>> requestToEntityFlux(
HttpRequestValues requestValues, ParameterizedTypeReference<T> bodyType) {
return exchangeForEntityFlux(requestValues, bodyType);
}
} }

View File

@ -1,147 +0,0 @@
/*
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.service.invoker;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
/**
* Contract to abstract the underlying HTTP client and decouple it from the
* {@linkplain HttpServiceProxyFactory#createClient(Class) HTTP service proxy}.
*
* @author Rossen Stoyanchev
* @author Olga Maciaszek-Sharma
* @since 6.0
* @deprecated in favor of {@link ReactorHttpExchangeAdapter}
*/
@Deprecated(since = "6.1", forRemoval = true)
public interface HttpClientAdapter {
/**
* Perform the given request, and release the response content, if any.
* @param requestValues the request to perform
* @return {@code Mono} that completes when the request is fully executed
* and the response content is released.
*/
Mono<Void> requestToVoid(HttpRequestValues requestValues);
/**
* Perform the given request, release the response content, and return the
* response headers.
* @param requestValues the request to perform
* @return {@code Mono} that returns the response headers the request is
* fully executed and the response content released.
*/
Mono<HttpHeaders> requestToHeaders(HttpRequestValues requestValues);
/**
* Perform the given request and decode the response content to the given type.
* @param requestValues the request to perform
* @param bodyType the target type to decode to
* @return {@code Mono} that returns the decoded response.
* @param <T> the type the response is decoded to
*/
<T> Mono<T> requestToBody(HttpRequestValues requestValues, ParameterizedTypeReference<T> bodyType);
/**
* Perform the given request and decode the response content to a stream with
* elements of the given type.
* @param requestValues the request to perform
* @param bodyType the target stream element type to decode to
* @return {@code Flux} with decoded stream elements.
* @param <T> the type the response is decoded to
*/
<T> Flux<T> requestToBodyFlux(HttpRequestValues requestValues, ParameterizedTypeReference<T> bodyType);
/**
* Variant of {@link #requestToVoid(HttpRequestValues)} with additional
* access to the response status and headers.
*/
Mono<ResponseEntity<Void>> requestToBodilessEntity(HttpRequestValues requestValues);
/**
* Variant of {@link #requestToBody(HttpRequestValues, ParameterizedTypeReference)}
* with additional access to the response status and headers.
*/
<T> Mono<ResponseEntity<T>> requestToEntity(HttpRequestValues requestValues, ParameterizedTypeReference<T> bodyType);
/**
* Variant of {@link #requestToBodyFlux(HttpRequestValues, ParameterizedTypeReference)}
* with additional access to the response status and headers.
*/
<T> Mono<ResponseEntity<Flux<T>>> requestToEntityFlux(HttpRequestValues requestValues, ParameterizedTypeReference<T> bodyType);
/**
* Adapt this instance to {@link ReactorHttpExchangeAdapter}.
* @since 6.1
*/
default ReactorHttpExchangeAdapter asReactorExchangeAdapter() {
return new AbstractReactorHttpExchangeAdapter() {
@Override
public boolean supportsRequestAttributes() {
return true;
}
@Override
public Mono<Void> exchangeForMono(HttpRequestValues values) {
return HttpClientAdapter.this.requestToVoid(values);
}
@Override
public Mono<HttpHeaders> exchangeForHeadersMono(HttpRequestValues values) {
return HttpClientAdapter.this.requestToHeaders(values);
}
@Override
public <T> Mono<T> exchangeForBodyMono(HttpRequestValues values, ParameterizedTypeReference<T> bodyType) {
return HttpClientAdapter.this.requestToBody(values, bodyType);
}
@Override
public <T> Flux<T> exchangeForBodyFlux(HttpRequestValues values, ParameterizedTypeReference<T> bodyType) {
return HttpClientAdapter.this.requestToBodyFlux(values, bodyType);
}
@Override
public Mono<ResponseEntity<Void>> exchangeForBodilessEntityMono(HttpRequestValues values) {
return HttpClientAdapter.this.requestToBodilessEntity(values);
}
@Override
public <T> Mono<ResponseEntity<T>> exchangeForEntityMono(
HttpRequestValues requestValues, ParameterizedTypeReference<T> bodyType) {
return HttpClientAdapter.this.requestToEntity(requestValues, bodyType);
}
@Override
public <T> Mono<ResponseEntity<Flux<T>>> exchangeForEntityFlux(
HttpRequestValues requestValues, ParameterizedTypeReference<T> bodyType) {
return HttpClientAdapter.this.requestToEntityFlux(requestValues, bodyType);
}
};
}
}

View File

@ -86,21 +86,6 @@ public class ContentCachingRequestWrapper extends HttpServletRequestWrapper {
this.contentCacheLimit = (cacheLimit > 0 ? cacheLimit : null); this.contentCacheLimit = (cacheLimit > 0 ? cacheLimit : null);
} }
/**
* Create a new ContentCachingRequestWrapper for the given servlet request.
* @param request the original servlet request
* @deprecated in favor of {@link #ContentCachingRequestWrapper(HttpServletRequest, int)}
* in order to explicitly choose the cache limit
*/
@Deprecated(since = "6.2.1", forRemoval = true)
public ContentCachingRequestWrapper(HttpServletRequest request) {
super(request);
int contentLength = request.getContentLength();
this.cachedContent = (contentLength > 0 ?
new FastByteArrayOutputStream(contentLength) : new FastByteArrayOutputStream());
this.contentCacheLimit = null;
}
@Override @Override
public ServletInputStream getInputStream() throws IOException { public ServletInputStream getInputStream() throws IOException {

View File

@ -30,7 +30,6 @@ import java.util.Optional;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.springframework.http.HttpRequest;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
@ -243,34 +242,6 @@ public class UriComponentsBuilder implements UriBuilder, Cloneable {
return fromUriString(httpUrl); return fromUriString(httpUrl);
} }
/**
* Create a new {@code UriComponents} object from the URI associated with
* the given HttpRequest while also overlaying with values from the headers
* "Forwarded" (<a href="https://tools.ietf.org/html/rfc7239">RFC 7239</a>),
* or "X-Forwarded-Host", "X-Forwarded-Port", and "X-Forwarded-Proto" if
* "Forwarded" is not found.
* @param request the source request
* @return the URI components of the URI
* @since 4.1.5
* @deprecated in favor of {@link ForwardedHeaderUtils#adaptFromForwardedHeaders};
* to be removed in 7.0
*/
@Deprecated(since = "6.1", forRemoval = true)
public static UriComponentsBuilder fromHttpRequest(HttpRequest request) {
return ForwardedHeaderUtils.adaptFromForwardedHeaders(request.getURI(), request.getHeaders());
}
/**
* Create an instance by parsing the "Origin" header of an HTTP request.
* @see <a href="https://tools.ietf.org/html/rfc6454">RFC 6454</a>
* @deprecated in favor of {@link UriComponentsBuilder#fromUriString(String)};
* to be removed in 7.0
*/
@Deprecated(since = "6.2", forRemoval = true)
public static UriComponentsBuilder fromOriginHeader(String origin) {
return fromUriString(origin);
}
// Encode methods // Encode methods

View File

@ -19,7 +19,6 @@ package org.springframework.http;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
@ -279,221 +278,6 @@ class MediaTypeTests {
assertThat(audioBasic.isLessSpecific(MediaType.TEXT_HTML)).isFalse(); assertThat(audioBasic.isLessSpecific(MediaType.TEXT_HTML)).isFalse();
} }
@Test
void specificityComparator() {
MediaType audioBasic = new MediaType("audio", "basic");
MediaType audioWave = new MediaType("audio", "wave");
MediaType audio = new MediaType("audio");
MediaType audio03 = new MediaType("audio", "*", 0.3);
MediaType audio07 = new MediaType("audio", "*", 0.7);
MediaType audioBasicLevel = new MediaType("audio", "basic", Collections.singletonMap("level", "1"));
MediaType textHtml = new MediaType("text", "html");
MediaType allXml = new MediaType("application", "*+xml");
MediaType all = MediaType.ALL;
@SuppressWarnings("removal")
Comparator<MediaType> comp = MediaType.SPECIFICITY_COMPARATOR;
// equal
assertThat(comp.compare(audioBasic, audioBasic)).as("Invalid comparison result").isEqualTo(0);
assertThat(comp.compare(audio, audio)).as("Invalid comparison result").isEqualTo(0);
assertThat(comp.compare(audio07, audio07)).as("Invalid comparison result").isEqualTo(0);
assertThat(comp.compare(audio03, audio03)).as("Invalid comparison result").isEqualTo(0);
assertThat(comp.compare(audioBasicLevel, audioBasicLevel)).as("Invalid comparison result").isEqualTo(0);
// specific to unspecific
assertThat(comp.compare(audioBasic, audio)).as("Invalid comparison result").isLessThan(0);
assertThat(comp.compare(audioBasic, all)).as("Invalid comparison result").isLessThan(0);
assertThat(comp.compare(audio, all)).as("Invalid comparison result").isLessThan(0);
assertThat(comp.compare(MediaType.APPLICATION_XHTML_XML, allXml)).as("Invalid comparison result").isLessThan(0);
// unspecific to specific
assertThat(comp.compare(audio, audioBasic)).as("Invalid comparison result").isGreaterThan(0);
assertThat(comp.compare(allXml, MediaType.APPLICATION_XHTML_XML)).as("Invalid comparison result")
.isGreaterThan(0);
assertThat(comp.compare(all, audioBasic)).as("Invalid comparison result").isGreaterThan(0);
assertThat(comp.compare(all, audio)).as("Invalid comparison result").isGreaterThan(0);
// qualifiers
assertThat(comp.compare(audio, audio07)).as("Invalid comparison result").isLessThan(0);
assertThat(comp.compare(audio07, audio)).as("Invalid comparison result").isGreaterThan(0);
assertThat(comp.compare(audio07, audio03)).as("Invalid comparison result").isLessThan(0);
assertThat(comp.compare(audio03, audio07)).as("Invalid comparison result").isGreaterThan(0);
assertThat(comp.compare(audio03, all)).as("Invalid comparison result").isLessThan(0);
assertThat(comp.compare(all, audio03)).as("Invalid comparison result").isGreaterThan(0);
// other parameters
assertThat(comp.compare(audioBasic, audioBasicLevel)).as("Invalid comparison result").isGreaterThan(0);
assertThat(comp.compare(audioBasicLevel, audioBasic)).as("Invalid comparison result").isLessThan(0);
// different types
assertThat(comp.compare(audioBasic, textHtml)).as("Invalid comparison result").isEqualTo(0);
assertThat(comp.compare(textHtml, audioBasic)).as("Invalid comparison result").isEqualTo(0);
// different subtypes
assertThat(comp.compare(audioBasic, audioWave)).as("Invalid comparison result").isEqualTo(0);
assertThat(comp.compare(audioWave, audioBasic)).as("Invalid comparison result").isEqualTo(0);
}
@Test
@SuppressWarnings("removal")
public void sortBySpecificityRelated() {
MediaType audioBasic = new MediaType("audio", "basic");
MediaType audio = new MediaType("audio");
MediaType audio03 = new MediaType("audio", "*", 0.3);
MediaType audio07 = new MediaType("audio", "*", 0.7);
MediaType audioBasicLevel = new MediaType("audio", "basic", Collections.singletonMap("level", "1"));
MediaType all = MediaType.ALL;
List<MediaType> expected = new ArrayList<>();
expected.add(audioBasicLevel);
expected.add(audioBasic);
expected.add(audio);
expected.add(audio07);
expected.add(audio03);
expected.add(all);
List<MediaType> result = new ArrayList<>(expected);
Random rnd = new Random();
// shuffle & sort 10 times
for (int i = 0; i < 10; i++) {
Collections.shuffle(result, rnd);
MediaType.sortBySpecificity(result);
for (int j = 0; j < result.size(); j++) {
assertThat(result.get(j)).as("Invalid media type at " + j).isSameAs(expected.get(j));
}
}
}
@Test
@SuppressWarnings("removal")
public void sortBySpecificityUnrelated() {
MediaType audioBasic = new MediaType("audio", "basic");
MediaType audioWave = new MediaType("audio", "wave");
MediaType textHtml = new MediaType("text", "html");
List<MediaType> expected = new ArrayList<>();
expected.add(textHtml);
expected.add(audioBasic);
expected.add(audioWave);
List<MediaType> result = new ArrayList<>(expected);
MediaType.sortBySpecificity(result);
for (int i = 0; i < result.size(); i++) {
assertThat(result.get(i)).as("Invalid media type at " + i).isSameAs(expected.get(i));
}
}
@Test
void qualityComparator() {
MediaType audioBasic = new MediaType("audio", "basic");
MediaType audioWave = new MediaType("audio", "wave");
MediaType audio = new MediaType("audio");
MediaType audio03 = new MediaType("audio", "*", 0.3);
MediaType audio07 = new MediaType("audio", "*", 0.7);
MediaType audioBasicLevel = new MediaType("audio", "basic", Collections.singletonMap("level", "1"));
MediaType textHtml = new MediaType("text", "html");
MediaType allXml = new MediaType("application", "*+xml");
MediaType all = MediaType.ALL;
@SuppressWarnings("removal")
Comparator<MediaType> comp = MediaType.QUALITY_VALUE_COMPARATOR;
// equal
assertThat(comp.compare(audioBasic, audioBasic)).as("Invalid comparison result").isEqualTo(0);
assertThat(comp.compare(audio, audio)).as("Invalid comparison result").isEqualTo(0);
assertThat(comp.compare(audio07, audio07)).as("Invalid comparison result").isEqualTo(0);
assertThat(comp.compare(audio03, audio03)).as("Invalid comparison result").isEqualTo(0);
assertThat(comp.compare(audioBasicLevel, audioBasicLevel)).as("Invalid comparison result").isEqualTo(0);
// specific to unspecific
assertThat(comp.compare(audioBasic, audio)).as("Invalid comparison result").isLessThan(0);
assertThat(comp.compare(audioBasic, all)).as("Invalid comparison result").isLessThan(0);
assertThat(comp.compare(audio, all)).as("Invalid comparison result").isLessThan(0);
assertThat(comp.compare(MediaType.APPLICATION_XHTML_XML, allXml)).as("Invalid comparison result").isLessThan(0);
// unspecific to specific
assertThat(comp.compare(audio, audioBasic)).as("Invalid comparison result").isGreaterThan(0);
assertThat(comp.compare(all, audioBasic)).as("Invalid comparison result").isGreaterThan(0);
assertThat(comp.compare(all, audio)).as("Invalid comparison result").isGreaterThan(0);
assertThat(comp.compare(allXml, MediaType.APPLICATION_XHTML_XML)).as("Invalid comparison result")
.isGreaterThan(0);
// qualifiers
assertThat(comp.compare(audio, audio07)).as("Invalid comparison result").isLessThan(0);
assertThat(comp.compare(audio07, audio)).as("Invalid comparison result").isGreaterThan(0);
assertThat(comp.compare(audio07, audio03)).as("Invalid comparison result").isLessThan(0);
assertThat(comp.compare(audio03, audio07)).as("Invalid comparison result").isGreaterThan(0);
assertThat(comp.compare(audio03, all)).as("Invalid comparison result").isGreaterThan(0);
assertThat(comp.compare(all, audio03)).as("Invalid comparison result").isLessThan(0);
// other parameters
assertThat(comp.compare(audioBasic, audioBasicLevel)).as("Invalid comparison result").isGreaterThan(0);
assertThat(comp.compare(audioBasicLevel, audioBasic)).as("Invalid comparison result").isLessThan(0);
// different types
assertThat(comp.compare(audioBasic, textHtml)).as("Invalid comparison result").isEqualTo(0);
assertThat(comp.compare(textHtml, audioBasic)).as("Invalid comparison result").isEqualTo(0);
// different subtypes
assertThat(comp.compare(audioBasic, audioWave)).as("Invalid comparison result").isEqualTo(0);
assertThat(comp.compare(audioWave, audioBasic)).as("Invalid comparison result").isEqualTo(0);
}
@Test
@SuppressWarnings("removal")
public void sortByQualityRelated() {
MediaType audioBasic = new MediaType("audio", "basic");
MediaType audio = new MediaType("audio");
MediaType audio03 = new MediaType("audio", "*", 0.3);
MediaType audio07 = new MediaType("audio", "*", 0.7);
MediaType audioBasicLevel = new MediaType("audio", "basic", Collections.singletonMap("level", "1"));
MediaType all = MediaType.ALL;
List<MediaType> expected = new ArrayList<>();
expected.add(audioBasicLevel);
expected.add(audioBasic);
expected.add(audio);
expected.add(all);
expected.add(audio07);
expected.add(audio03);
List<MediaType> result = new ArrayList<>(expected);
Random rnd = new Random();
// shuffle & sort 10 times
for (int i = 0; i < 10; i++) {
Collections.shuffle(result, rnd);
MediaType.sortByQualityValue(result);
for (int j = 0; j < result.size(); j++) {
assertThat(result.get(j)).as("Invalid media type at " + j).isSameAs(expected.get(j));
}
}
}
@Test
@SuppressWarnings("removal")
public void sortByQualityUnrelated() {
MediaType audioBasic = new MediaType("audio", "basic");
MediaType audioWave = new MediaType("audio", "wave");
MediaType textHtml = new MediaType("text", "html");
List<MediaType> expected = new ArrayList<>();
expected.add(textHtml);
expected.add(audioBasic);
expected.add(audioWave);
List<MediaType> result = new ArrayList<>(expected);
MediaType.sortBySpecificity(result);
for (int i = 0; i < result.size(); i++) {
assertThat(result.get(i)).as("Invalid media type at " + i).isSameAs(expected.get(i));
}
}
@Test @Test
void testWithConversionService() { void testWithConversionService() {
ConversionService conversionService = new DefaultConversionService(); ConversionService conversionService = new DefaultConversionService();

Some files were not shown because too many files have changed in this diff Show More