@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* 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.
|
||||
@@ -24,8 +24,6 @@ import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionStage;
|
||||
import java.util.function.Function;
|
||||
|
||||
import kotlinx.coroutines.CompletableDeferredKt;
|
||||
import kotlinx.coroutines.Deferred;
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.blockhound.BlockHound;
|
||||
import reactor.blockhound.integration.BlockHoundIntegration;
|
||||
@@ -39,13 +37,14 @@ import org.springframework.util.ConcurrentReferenceHashMap;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* A registry of adapters to adapt Reactive Streams {@link Publisher} to/from
|
||||
* various async/reactive types such as {@code CompletableFuture}, RxJava
|
||||
* {@code Flowable}, and others.
|
||||
* A registry of adapters to adapt Reactive Streams {@link Publisher} to/from various
|
||||
* async/reactive types such as {@code CompletableFuture}, RxJava {@code Flowable}, etc.
|
||||
* This is designed to complement Spring's Reactor {@code Mono}/{@code Flux} support while
|
||||
* also being usable without Reactor, e.g. just for {@code org.reactivestreams} bridging.
|
||||
*
|
||||
* <p>By default, depending on classpath availability, adapters are registered
|
||||
* for Reactor, RxJava 3, {@link CompletableFuture}, {@code Flow.Publisher},
|
||||
* and Kotlin Coroutines' {@code Deferred} and {@code Flow}.
|
||||
* <p>By default, depending on classpath availability, adapters are registered for Reactor
|
||||
* (including {@code CompletableFuture} and {@code Flow.Publisher} adapters), RxJava 3,
|
||||
* Kotlin Coroutines' {@code Deferred} (bridged via Reactor) and SmallRye Mutiny 1.x.
|
||||
*
|
||||
* <p><strong>Note:</strong> As of Spring Framework 5.3.11, support for
|
||||
* RxJava 1.x and 2.x is deprecated in favor of RxJava 3.
|
||||
@@ -401,9 +400,9 @@ public class ReactiveAdapterRegistry {
|
||||
@SuppressWarnings("KotlinInternalInJava")
|
||||
void registerAdapters(ReactiveAdapterRegistry registry) {
|
||||
registry.registerReactiveType(
|
||||
ReactiveTypeDescriptor.singleOptionalValue(Deferred.class,
|
||||
() -> CompletableDeferredKt.CompletableDeferred(null)),
|
||||
source -> CoroutinesUtils.deferredToMono((Deferred<?>) source),
|
||||
ReactiveTypeDescriptor.singleOptionalValue(kotlinx.coroutines.Deferred.class,
|
||||
() -> kotlinx.coroutines.CompletableDeferredKt.CompletableDeferred(null)),
|
||||
source -> CoroutinesUtils.deferredToMono((kotlinx.coroutines.Deferred<?>) source),
|
||||
source -> CoroutinesUtils.monoToDeferred(Mono.from(source)));
|
||||
|
||||
registry.registerReactiveType(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* 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.
|
||||
@@ -37,7 +37,7 @@ public final class ReactiveTypeDescriptor {
|
||||
private final boolean noValue;
|
||||
|
||||
@Nullable
|
||||
private final Supplier<?> emptyValueSupplier;
|
||||
private final Supplier<?> emptySupplier;
|
||||
|
||||
private final boolean deferred;
|
||||
|
||||
@@ -55,7 +55,7 @@ public final class ReactiveTypeDescriptor {
|
||||
this.reactiveType = reactiveType;
|
||||
this.multiValue = multiValue;
|
||||
this.noValue = noValue;
|
||||
this.emptyValueSupplier = emptySupplier;
|
||||
this.emptySupplier = emptySupplier;
|
||||
this.deferred = deferred;
|
||||
}
|
||||
|
||||
@@ -89,16 +89,16 @@ public final class ReactiveTypeDescriptor {
|
||||
* Return {@code true} if the reactive type can complete with no values.
|
||||
*/
|
||||
public boolean supportsEmpty() {
|
||||
return (this.emptyValueSupplier != null);
|
||||
return (this.emptySupplier != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an empty-value instance for the underlying reactive or async type.
|
||||
* Use of this type implies {@link #supportsEmpty()} is {@code true}.
|
||||
* <p>Use of this type implies {@link #supportsEmpty()} is {@code true}.
|
||||
*/
|
||||
public Object getEmptyValue() {
|
||||
Assert.state(this.emptyValueSupplier != null, "Empty values not supported");
|
||||
return this.emptyValueSupplier.get();
|
||||
Assert.state(this.emptySupplier != null, "Empty values not supported");
|
||||
return this.emptySupplier.get();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* 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.
|
||||
@@ -100,7 +100,7 @@ class ReactiveAdapterRegistryTests {
|
||||
List<Integer> sequence = Arrays.asList(1, 2, 3);
|
||||
Publisher<Integer> source = io.reactivex.rxjava3.core.Flowable.fromIterable(sequence);
|
||||
Object target = getAdapter(Flux.class).fromPublisher(source);
|
||||
assertThat(target instanceof Flux).isTrue();
|
||||
assertThat(target).isInstanceOf(Flux.class);
|
||||
assertThat(((Flux<Integer>) target).collectList().block(ONE_SECOND)).isEqualTo(sequence);
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ class ReactiveAdapterRegistryTests {
|
||||
void toMono() {
|
||||
Publisher<Integer> source = io.reactivex.rxjava3.core.Flowable.fromArray(1, 2, 3);
|
||||
Object target = getAdapter(Mono.class).fromPublisher(source);
|
||||
assertThat(target instanceof Mono).isTrue();
|
||||
assertThat(target).isInstanceOf(Mono.class);
|
||||
assertThat(((Mono<Integer>) target).block(ONE_SECOND)).isEqualTo(Integer.valueOf(1));
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ class ReactiveAdapterRegistryTests {
|
||||
void toCompletableFuture() throws Exception {
|
||||
Publisher<Integer> source = Flux.fromArray(new Integer[] {1, 2, 3});
|
||||
Object target = getAdapter(CompletableFuture.class).fromPublisher(source);
|
||||
assertThat(target instanceof CompletableFuture).isTrue();
|
||||
assertThat(target).isInstanceOf(CompletableFuture.class);
|
||||
assertThat(((CompletableFuture<Integer>) target).get()).isEqualTo(Integer.valueOf(1));
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@ class ReactiveAdapterRegistryTests {
|
||||
CompletableFuture<Integer> future = new CompletableFuture<>();
|
||||
future.complete(1);
|
||||
Object target = getAdapter(CompletableFuture.class).toPublisher(future);
|
||||
assertThat(target instanceof Mono).as("Expected Mono Publisher: " + target.getClass().getName()).isTrue();
|
||||
assertThat(target).as("Expected Mono Publisher: " + target.getClass().getName()).isInstanceOf(Mono.class);
|
||||
assertThat(((Mono<Integer>) target).block(ONE_SECOND)).isEqualTo(Integer.valueOf(1));
|
||||
}
|
||||
}
|
||||
@@ -294,7 +294,7 @@ class ReactiveAdapterRegistryTests {
|
||||
List<Integer> sequence = Arrays.asList(1, 2, 3);
|
||||
Publisher<Integer> source = Flux.fromIterable(sequence);
|
||||
Object target = getAdapter(io.reactivex.rxjava3.core.Flowable.class).fromPublisher(source);
|
||||
assertThat(target instanceof io.reactivex.rxjava3.core.Flowable).isTrue();
|
||||
assertThat(target).isInstanceOf(io.reactivex.rxjava3.core.Flowable.class);
|
||||
assertThat(((io.reactivex.rxjava3.core.Flowable<?>) target).toList().blockingGet()).isEqualTo(sequence);
|
||||
}
|
||||
|
||||
@@ -303,7 +303,7 @@ class ReactiveAdapterRegistryTests {
|
||||
List<Integer> sequence = Arrays.asList(1, 2, 3);
|
||||
Publisher<Integer> source = Flux.fromIterable(sequence);
|
||||
Object target = getAdapter(io.reactivex.rxjava3.core.Observable.class).fromPublisher(source);
|
||||
assertThat(target instanceof io.reactivex.rxjava3.core.Observable).isTrue();
|
||||
assertThat(target).isInstanceOf(io.reactivex.rxjava3.core.Observable.class);
|
||||
assertThat(((io.reactivex.rxjava3.core.Observable<?>) target).toList().blockingGet()).isEqualTo(sequence);
|
||||
}
|
||||
|
||||
@@ -311,7 +311,7 @@ class ReactiveAdapterRegistryTests {
|
||||
void toSingle() {
|
||||
Publisher<Integer> source = Flux.fromArray(new Integer[] {1});
|
||||
Object target = getAdapter(io.reactivex.rxjava3.core.Single.class).fromPublisher(source);
|
||||
assertThat(target instanceof io.reactivex.rxjava3.core.Single).isTrue();
|
||||
assertThat(target).isInstanceOf(io.reactivex.rxjava3.core.Single.class);
|
||||
assertThat(((io.reactivex.rxjava3.core.Single<Integer>) target).blockingGet()).isEqualTo(Integer.valueOf(1));
|
||||
}
|
||||
|
||||
@@ -319,7 +319,7 @@ class ReactiveAdapterRegistryTests {
|
||||
void toCompletable() {
|
||||
Publisher<Integer> source = Flux.fromArray(new Integer[] {1, 2, 3});
|
||||
Object target = getAdapter(io.reactivex.rxjava3.core.Completable.class).fromPublisher(source);
|
||||
assertThat(target instanceof io.reactivex.rxjava3.core.Completable).isTrue();
|
||||
assertThat(target).isInstanceOf(io.reactivex.rxjava3.core.Completable.class);
|
||||
((io.reactivex.rxjava3.core.Completable) target).blockingAwait();
|
||||
}
|
||||
|
||||
@@ -328,7 +328,7 @@ class ReactiveAdapterRegistryTests {
|
||||
List<Integer> sequence = Arrays.asList(1, 2, 3);
|
||||
Object source = io.reactivex.rxjava3.core.Flowable.fromIterable(sequence);
|
||||
Object target = getAdapter(io.reactivex.rxjava3.core.Flowable.class).toPublisher(source);
|
||||
assertThat(target instanceof Flux).as("Expected Flux Publisher: " + target.getClass().getName()).isTrue();
|
||||
assertThat(target).as("Expected Flux Publisher: " + target.getClass().getName()).isInstanceOf(Flux.class);
|
||||
assertThat(((Flux<Integer>) target).collectList().block(ONE_SECOND)).isEqualTo(sequence);
|
||||
}
|
||||
|
||||
@@ -337,7 +337,7 @@ class ReactiveAdapterRegistryTests {
|
||||
List<Integer> sequence = Arrays.asList(1, 2, 3);
|
||||
Object source = io.reactivex.rxjava3.core.Observable.fromIterable(sequence);
|
||||
Object target = getAdapter(io.reactivex.rxjava3.core.Observable.class).toPublisher(source);
|
||||
assertThat(target instanceof Flux).as("Expected Flux Publisher: " + target.getClass().getName()).isTrue();
|
||||
assertThat(target).as("Expected Flux Publisher: " + target.getClass().getName()).isInstanceOf(Flux.class);
|
||||
assertThat(((Flux<Integer>) target).collectList().block(ONE_SECOND)).isEqualTo(sequence);
|
||||
}
|
||||
|
||||
@@ -345,7 +345,7 @@ class ReactiveAdapterRegistryTests {
|
||||
void fromSingle() {
|
||||
Object source = io.reactivex.rxjava3.core.Single.just(1);
|
||||
Object target = getAdapter(io.reactivex.rxjava3.core.Single.class).toPublisher(source);
|
||||
assertThat(target instanceof Mono).as("Expected Mono Publisher: " + target.getClass().getName()).isTrue();
|
||||
assertThat(target).as("Expected Mono Publisher: " + target.getClass().getName()).isInstanceOf(Mono.class);
|
||||
assertThat(((Mono<Integer>) target).block(ONE_SECOND)).isEqualTo(Integer.valueOf(1));
|
||||
}
|
||||
|
||||
@@ -353,7 +353,7 @@ class ReactiveAdapterRegistryTests {
|
||||
void fromCompletable() {
|
||||
Object source = io.reactivex.rxjava3.core.Completable.complete();
|
||||
Object target = getAdapter(io.reactivex.rxjava3.core.Completable.class).toPublisher(source);
|
||||
assertThat(target instanceof Mono).as("Expected Mono Publisher: " + target.getClass().getName()).isTrue();
|
||||
assertThat(target).as("Expected Mono Publisher: " + target.getClass().getName()).isInstanceOf(Mono.class);
|
||||
((Mono<Void>) target).block(ONE_SECOND);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user