Browse Source

Defensively register default adapters behind Reactive Streams guard

See gh-31000
pull/31012/head
Juergen Hoeller 3 years ago
parent
commit
dedb58f7ed
  1. 26
      spring-core/src/main/java/org/springframework/core/ReactiveAdapterRegistry.java

26
spring-core/src/main/java/org/springframework/core/ReactiveAdapterRegistry.java

@ -60,6 +60,8 @@ public class ReactiveAdapterRegistry {
@Nullable @Nullable
private static volatile ReactiveAdapterRegistry sharedInstance; private static volatile ReactiveAdapterRegistry sharedInstance;
private static final boolean reactiveStreamsPresent;
private static final boolean reactorPresent; private static final boolean reactorPresent;
private static final boolean rxjava3Present; private static final boolean rxjava3Present;
@ -70,6 +72,7 @@ public class ReactiveAdapterRegistry {
static { static {
ClassLoader classLoader = ReactiveAdapterRegistry.class.getClassLoader(); ClassLoader classLoader = ReactiveAdapterRegistry.class.getClassLoader();
reactiveStreamsPresent = ClassUtils.isPresent("org.reactivestreams.Publisher", classLoader);
reactorPresent = ClassUtils.isPresent("reactor.core.publisher.Flux", classLoader); reactorPresent = ClassUtils.isPresent("reactor.core.publisher.Flux", classLoader);
rxjava3Present = ClassUtils.isPresent("io.reactivex.rxjava3.core.Flowable", classLoader); rxjava3Present = ClassUtils.isPresent("io.reactivex.rxjava3.core.Flowable", classLoader);
kotlinCoroutinesPresent = ClassUtils.isPresent("kotlinx.coroutines.reactor.MonoKt", classLoader); kotlinCoroutinesPresent = ClassUtils.isPresent("kotlinx.coroutines.reactor.MonoKt", classLoader);
@ -85,6 +88,11 @@ public class ReactiveAdapterRegistry {
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public ReactiveAdapterRegistry() { public ReactiveAdapterRegistry() {
// Defensive guard for the Reactive Streams API itself
if (!reactiveStreamsPresent) {
return;
}
// Reactor // Reactor
if (reactorPresent) { if (reactorPresent) {
new ReactorRegistrar().registerAdapters(this); new ReactorRegistrar().registerAdapters(this);
@ -107,21 +115,14 @@ public class ReactiveAdapterRegistry {
// Simple Flow.Publisher bridge if Reactor is not present // Simple Flow.Publisher bridge if Reactor is not present
if (!reactorPresent) { if (!reactorPresent) {
registerReactiveType( this.adapters.add(new ReactiveAdapter(
ReactiveTypeDescriptor.multiValue(Flow.Publisher.class, () -> PublisherToRS.EMPTY_FLOW), ReactiveTypeDescriptor.multiValue(Flow.Publisher.class, () -> PublisherToRS.EMPTY_FLOW),
source -> new PublisherToRS<>((Flow.Publisher<Object>) source), source -> new PublisherToRS<>((Flow.Publisher<Object>) source),
source -> new PublisherToFlow<>((Publisher<Object>) source)); source -> new PublisherToFlow<>((Publisher<Object>) source)));
} }
} }
/**
* Whether the registry has any adapters.
*/
public boolean hasAdapters() {
return !this.adapters.isEmpty();
}
/** /**
* Register a reactive type along with functions to adapt to and from a * Register a reactive type along with functions to adapt to and from a
* Reactive Streams {@link Publisher}. The function arguments assume that * Reactive Streams {@link Publisher}. The function arguments assume that
@ -138,6 +139,13 @@ public class ReactiveAdapterRegistry {
} }
} }
/**
* Return whether the registry has any adapters.
*/
public boolean hasAdapters() {
return !this.adapters.isEmpty();
}
/** /**
* Get the adapter for the given reactive type. * Get the adapter for the given reactive type.
* @return the corresponding adapter, or {@code null} if none available * @return the corresponding adapter, or {@code null} if none available

Loading…
Cancel
Save