/** * Get the adapter for the given reactive type. */ @Nullable public ReactiveAdapter getAdapter(Class<?> reactiveType) { return getAdapter(reactiveType, null); }
/** * Basic constructor with a default {@link ReactiveAdapterRegistry}. * @param writers writers for serializing to the response body * @param resolver to determine the requested content type */ public ResponseBodyResultHandler(List<HttpMessageWriter<?>> writers, RequestedContentTypeResolver resolver) { this(writers, resolver, ReactiveAdapterRegistry.getSharedInstance()); }
/** * Whether the type can be adapted to a Reactive Streams {@link Publisher}. */ public boolean isReactiveType(Class<?> type) { return (this.reactiveRegistry.hasAdapters() && this.reactiveRegistry.getAdapter(type) != null); }
ReactiveAdapterRegistry reactiveAdapterRegistry = ReactiveAdapterRegistry.getSharedInstance(); if (reactiveAdapterRegistry.hasAdapters()) { ReactiveAdapter adapter = reactiveAdapterRegistry.getAdapter(valueClass); if (adapter != null && !adapter.getDescriptor().isNoValue()) { reactiveSuffix = ClassUtils.getShortName(valueClass);
/** * Return a {@link ReactiveAdapterRegistry} to adapting reactive types. */ @Bean public ReactiveAdapterRegistry webFluxAdapterRegistry() { return new ReactiveAdapterRegistry(); }
void registerAdapter(ReactiveAdapterRegistry registry) { // TODO: remove reflection when build requires JDK 9+ try { String publisherName = "java.util.concurrent.Flow.Publisher"; Class<?> publisherClass = ClassUtils.forName(publisherName, getClass().getClassLoader()); String adapterName = "reactor.adapter.JdkFlowAdapter"; Class<?> flowAdapterClass = ClassUtils.forName(adapterName, getClass().getClassLoader()); Method toFluxMethod = flowAdapterClass.getMethod("flowPublisherToFlux", publisherClass); Method toFlowMethod = flowAdapterClass.getMethod("publisherToFlowPublisher", Publisher.class); Object emptyFlow = ReflectionUtils.invokeMethod(toFlowMethod, null, Flux.empty()); registry.registerReactiveType( ReactiveTypeDescriptor.multiValue(publisherClass, () -> emptyFlow), source -> (Publisher<?>) ReflectionUtils.invokeMethod(toFluxMethod, null, source), publisher -> ReflectionUtils.invokeMethod(toFlowMethod, null, publisher) ); } catch (Throwable ex) { // Ignore } } }
ReactiveAdapterRegistry reactiveAdapterRegistry = ReactiveAdapterRegistry.getSharedInstance(); if (reactiveAdapterRegistry.hasAdapters()) { ReactiveAdapter adapter = reactiveAdapterRegistry.getAdapter(valueClass); if (adapter != null && !adapter.getDescriptor().isNoValue()) { reactiveSuffix = ClassUtils.getShortName(valueClass);
/** * Return a shared default {@code ReactiveAdapterRegistry} instance, lazily * building it once needed. * <p><b>NOTE:</b> We highly recommend passing a long-lived, pre-configured * {@code ReactiveAdapterRegistry} instance for customization purposes. * This accessor is only meant as a fallback for code paths that want to * fall back on a default instance if one isn't provided. * @return the shared {@code ReactiveAdapterRegistry} instance (never {@code null}) * @since 5.0.2 */ public static ReactiveAdapterRegistry getSharedInstance() { ReactiveAdapterRegistry registry = sharedInstance; if (registry == null) { synchronized (ReactiveAdapterRegistry.class) { registry = sharedInstance; if (registry == null) { registry = new ReactiveAdapterRegistry(); sharedInstance = registry; } } } return registry; }
void registerAdapters(ReactiveAdapterRegistry registry) { // Register Flux and Mono before Publisher... registry.registerReactiveType( ReactiveTypeDescriptor.singleOptionalValue(Mono.class, Mono::empty), source -> (Mono<?>) source, Mono::from ); registry.registerReactiveType( ReactiveTypeDescriptor.multiValue(Flux.class, Flux::empty), source -> (Flux<?>) source, Flux::from); registry.registerReactiveType( ReactiveTypeDescriptor.multiValue(Publisher.class, Flux::empty), source -> (Publisher<?>) source, source -> source); registry.registerReactiveType( ReactiveTypeDescriptor.singleOptionalValue(CompletableFuture.class, () -> { CompletableFuture<?> empty = new CompletableFuture<>(); empty.complete(null); return empty; }), source -> Mono.fromFuture((CompletableFuture<?>) source), source -> Mono.from(source).toFuture() ); } }
@Override public boolean supportsReturnType(MethodParameter returnType) { return this.adapterRegistry.getAdapter(returnType.getParameterType()) != null; }
ReactiveAdapterRegistry reactiveAdapterRegistry = ReactiveAdapterRegistry.getSharedInstance(); if (reactiveAdapterRegistry.hasAdapters()) { ReactiveAdapter adapter = reactiveAdapterRegistry.getAdapter(valueClass); if (adapter != null && !adapter.getDescriptor().isNoValue()) { reactiveSuffix = ClassUtils.getShortName(valueClass);
/** * Basic constructor with a default {@link ReactiveAdapterRegistry}. * @param writers writers for serializing to the response body * @param resolver to determine the requested content type */ public ResponseEntityResultHandler(List<HttpMessageWriter<?>> writers, RequestedContentTypeResolver resolver) { this(writers, resolver, ReactiveAdapterRegistry.getSharedInstance()); }
/** * Whether the type can be adapted to a Reactive Streams {@link Publisher}. */ public boolean isReactiveType(Class<?> type) { return (this.reactiveRegistry.hasAdapters() && this.reactiveRegistry.getAdapter(type) != null); }
/** * Return a shared default {@code ReactiveAdapterRegistry} instance, lazily * building it once needed. * <p><b>NOTE:</b> We highly recommend passing a long-lived, pre-configured * {@code ReactiveAdapterRegistry} instance for customization purposes. * This accessor is only meant as a fallback for code paths that want to * fall back on a default instance if one isn't provided. * @return the shared {@code ReactiveAdapterRegistry} instance (never {@code null}) * @since 5.0.2 */ public static ReactiveAdapterRegistry getSharedInstance() { ReactiveAdapterRegistry registry = sharedInstance; if (registry == null) { synchronized (ReactiveAdapterRegistry.class) { registry = sharedInstance; if (registry == null) { registry = new ReactiveAdapterRegistry(); sharedInstance = registry; } } } return registry; }
void registerAdapters(ReactiveAdapterRegistry registry) { registry.registerReactiveType( ReactiveTypeDescriptor.multiValue(rx.Observable.class, rx.Observable::empty), source -> RxReactiveStreams.toPublisher((rx.Observable<?>) source), RxReactiveStreams::toObservable ); registry.registerReactiveType( ReactiveTypeDescriptor.singleRequiredValue(rx.Single.class), source -> RxReactiveStreams.toPublisher((rx.Single<?>) source), RxReactiveStreams::toSingle ); registry.registerReactiveType( ReactiveTypeDescriptor.noValue(rx.Completable.class, rx.Completable::complete), source -> RxReactiveStreams.toPublisher((rx.Completable) source), RxReactiveStreams::toCompletable ); } }
/** * Get the adapter for the given reactive type. */ @Nullable public ReactiveAdapter getAdapter(Class<?> reactiveType) { return getAdapter(reactiveType, null); }
ReactiveAdapterRegistry reactiveAdapterRegistry = ReactiveAdapterRegistry.getSharedInstance(); if (reactiveAdapterRegistry.hasAdapters()) { ReactiveAdapter adapter = reactiveAdapterRegistry.getAdapter(valueClass); if (adapter != null && !adapter.getDescriptor().isNoValue()) { reactiveSuffix = ClassUtils.getShortName(valueClass);
/** * Constructor with {@link HttpMessageWriter HttpMessageWriters} and a * {@code RequestedContentTypeResolver}. * @param messageWriters for serializing Objects to the response body stream * @param contentTypeResolver for resolving the requested content type */ protected AbstractMessageWriterResultHandler(List<HttpMessageWriter<?>> messageWriters, RequestedContentTypeResolver contentTypeResolver) { this(messageWriters, contentTypeResolver, ReactiveAdapterRegistry.getSharedInstance()); }
/** * Whether the type can be adapted to a Reactive Streams {@link Publisher}. */ public boolean isReactiveType(Class<?> type) { return (this.reactiveRegistry.hasAdapters() && this.reactiveRegistry.getAdapter(type) != null); }
/** * Constructor with {@link ViewResolver}s and a {@link RequestedContentTypeResolver}. * @param resolvers the resolver to use * @param contentTypeResolver for resolving the requested content type */ public ViewResolutionResultHandler(List<ViewResolver> resolvers, RequestedContentTypeResolver contentTypeResolver) { this(resolvers, contentTypeResolver, new ReactiveAdapterRegistry()); }