Example usage for org.springframework.core ReactiveAdapter isMultiValue

List of usage examples for org.springframework.core ReactiveAdapter isMultiValue

Introduction

In this page you can find the example usage for org.springframework.core ReactiveAdapter isMultiValue.

Prototype

public boolean isMultiValue() 

Source Link

Document

Shortcut for getDescriptor().isMultiValue() .

Usage

From source file:org.springframework.cloud.function.web.RequestProcessor.java

private Publisher<?> body(Object handler, ServerWebExchange exchange) {
    ResolvableType elementType = ResolvableType.forClass(this.inspector.getInputType(handler));
    ResolvableType actualType = elementType;
    Class<?> resolvedType = elementType.resolve();
    ReactiveAdapter adapter = (resolvedType != null ? getAdapterRegistry().getAdapter(resolvedType) : null);

    ServerHttpRequest request = exchange.getRequest();
    ServerHttpResponse response = exchange.getResponse();

    MediaType contentType = request.getHeaders().getContentType();
    MediaType mediaType = (contentType != null ? contentType : MediaType.APPLICATION_OCTET_STREAM);

    if (logger.isDebugEnabled()) {
        logger.debug(exchange.getLogPrefix() + (contentType != null ? "Content-Type:" + contentType
                : "No Content-Type, using " + MediaType.APPLICATION_OCTET_STREAM));
    }//from www. j av  a2s  . c  om
    boolean isBodyRequired = (adapter != null && !adapter.supportsEmpty());

    MethodParameter bodyParam = new MethodParameter(handlerMethod(handler), 0);
    for (HttpMessageReader<?> reader : getMessageReaders()) {
        if (reader.canRead(elementType, mediaType)) {
            Map<String, Object> readHints = Hints.from(Hints.LOG_PREFIX_HINT, exchange.getLogPrefix());
            if (adapter != null && adapter.isMultiValue()) {
                if (logger.isDebugEnabled()) {
                    logger.debug(exchange.getLogPrefix() + "0..N [" + elementType + "]");
                }
                Flux<?> flux = reader.read(actualType, elementType, request, response, readHints);
                flux = flux.onErrorResume(ex -> Flux.error(handleReadError(bodyParam, ex)));
                if (isBodyRequired) {
                    flux = flux.switchIfEmpty(Flux.error(() -> handleMissingBody(bodyParam)));
                }
                return Mono.just(adapter.fromPublisher(flux));
            } else {
                // Single-value (with or without reactive type wrapper)
                if (logger.isDebugEnabled()) {
                    logger.debug(exchange.getLogPrefix() + "0..1 [" + elementType + "]");
                }
                Mono<?> mono = reader.readMono(actualType, elementType, request, response, readHints);
                mono = mono.onErrorResume(ex -> Mono.error(handleReadError(bodyParam, ex)));
                if (isBodyRequired) {
                    mono = mono.switchIfEmpty(Mono.error(() -> handleMissingBody(bodyParam)));
                }
                return (adapter != null ? Mono.just(adapter.fromPublisher(mono)) : Mono.from(mono));
            }
        }
    }

    return Mono.error(new UnsupportedMediaTypeStatusException(mediaType,
            Arrays.asList(MediaType.APPLICATION_JSON), elementType));
}

From source file:org.springframework.messaging.handler.annotation.reactive.PayloadMethodArgumentResolver.java

private Mono<Object> decodeContent(MethodParameter parameter, Message<?> message, boolean isContentRequired,
        Flux<DataBuffer> content, MimeType mimeType) {

    ResolvableType targetType = ResolvableType.forMethodParameter(parameter);
    Class<?> resolvedType = targetType.resolve();
    ReactiveAdapter adapter = (resolvedType != null ? getAdapterRegistry().getAdapter(resolvedType) : null);
    ResolvableType elementType = (adapter != null ? targetType.getGeneric() : targetType);
    isContentRequired = isContentRequired || (adapter != null && !adapter.supportsEmpty());
    Consumer<Object> validator = getValidator(message, parameter);

    Map<String, Object> hints = Collections.emptyMap();

    for (Decoder<?> decoder : this.decoders) {
        if (decoder.canDecode(elementType, mimeType)) {
            if (adapter != null && adapter.isMultiValue()) {
                Flux<?> flux = content.map(buffer -> decoder.decode(buffer, elementType, mimeType, hints))
                        .onErrorResume(ex -> Flux.error(handleReadError(parameter, message, ex)));
                if (isContentRequired) {
                    flux = flux.switchIfEmpty(Flux.error(() -> handleMissingBody(parameter, message)));
                }/*from w  w w .  j a v  a 2  s.  c om*/
                if (validator != null) {
                    flux = flux.doOnNext(validator);
                }
                return Mono.just(adapter.fromPublisher(flux));
            } else {
                // Single-value (with or without reactive type wrapper)
                Mono<?> mono = content.next()
                        .map(buffer -> decoder.decode(buffer, elementType, mimeType, hints))
                        .onErrorResume(ex -> Mono.error(handleReadError(parameter, message, ex)));
                if (isContentRequired) {
                    mono = mono.switchIfEmpty(Mono.error(() -> handleMissingBody(parameter, message)));
                }
                if (validator != null) {
                    mono = mono.doOnNext(validator);
                }
                return (adapter != null ? Mono.just(adapter.fromPublisher(mono)) : Mono.from(mono));
            }
        }
    }

    return Mono.error(new MethodArgumentResolutionException(message, parameter,
            "Cannot decode to [" + targetType + "]" + message));
}

From source file:org.springframework.messaging.handler.annotation.support.reactive.PayloadMethodArgumentResolver.java

private Mono<Object> decodeContent(MethodParameter parameter, Message<?> message, boolean isContentRequired,
        Flux<DataBuffer> content, MimeType mimeType) {

    ResolvableType targetType = ResolvableType.forMethodParameter(parameter);
    Class<?> resolvedType = targetType.resolve();
    ReactiveAdapter adapter = (resolvedType != null ? getAdapterRegistry().getAdapter(resolvedType) : null);
    ResolvableType elementType = (adapter != null ? targetType.getGeneric() : targetType);
    isContentRequired = isContentRequired || (adapter != null && !adapter.supportsEmpty());
    Consumer<Object> validator = getValidator(message, parameter);

    Map<String, Object> hints = Collections.emptyMap();

    for (Decoder<?> decoder : this.decoders) {
        if (decoder.canDecode(elementType, mimeType)) {
            if (adapter != null && adapter.isMultiValue()) {
                Flux<?> flux = content
                        .concatMap(buffer -> decoder.decode(Mono.just(buffer), elementType, mimeType, hints))
                        .onErrorResume(ex -> Flux.error(handleReadError(parameter, message, ex)));
                if (isContentRequired) {
                    flux = flux.switchIfEmpty(Flux.error(() -> handleMissingBody(parameter, message)));
                }/*from   w  w w .j  a v  a 2  s.  c  o m*/
                if (validator != null) {
                    flux = flux.doOnNext(validator::accept);
                }
                return Mono.just(adapter.fromPublisher(flux));
            } else {
                // Single-value (with or without reactive type wrapper)
                Mono<?> mono = decoder.decodeToMono(content.next(), targetType, mimeType, hints)
                        .onErrorResume(ex -> Mono.error(handleReadError(parameter, message, ex)));
                if (isContentRequired) {
                    mono = mono.switchIfEmpty(Mono.error(() -> handleMissingBody(parameter, message)));
                }
                if (validator != null) {
                    mono = mono.doOnNext(validator::accept);
                }
                return (adapter != null ? Mono.just(adapter.fromPublisher(mono)) : Mono.from(mono));
            }
        }
    }

    return Mono.error(new MethodArgumentResolutionException(message, parameter,
            "Cannot decode to [" + targetType + "]" + message));
}

From source file:org.springframework.web.reactive.result.view.AbstractView.java

/**
 * By default, resolve async attributes supported by the
 * {@link ReactiveAdapterRegistry} to their blocking counterparts.
 * <p>View implementations capable of taking advantage of reactive types
 * can override this method if needed.// w  w w  .  j  a v a 2  s .  com
 * @return {@code Mono} for the completion of async attributes resolution
 */
protected Mono<Void> resolveAsyncAttributes(Map<String, Object> model) {

    List<String> names = new ArrayList<>();
    List<Mono<?>> valueMonos = new ArrayList<>();

    for (Map.Entry<String, ?> entry : model.entrySet()) {
        Object value = entry.getValue();
        if (value == null) {
            continue;
        }
        ReactiveAdapter adapter = this.adapterRegistry.getAdapter(null, value);
        if (adapter != null) {
            names.add(entry.getKey());
            if (adapter.isMultiValue()) {
                Flux<Object> fluxValue = Flux.from(adapter.toPublisher(value));
                valueMonos.add(fluxValue.collectList().defaultIfEmpty(Collections.emptyList()));
            } else {
                Mono<Object> monoValue = Mono.from(adapter.toPublisher(value));
                valueMonos.add(monoValue.defaultIfEmpty(NO_VALUE));
            }
        }
    }

    if (names.isEmpty()) {
        return Mono.empty();
    }

    return Mono.zip(valueMonos, values -> {
        for (int i = 0; i < values.length; i++) {
            if (values[i] != NO_VALUE) {
                model.put(names.get(i), values[i]);
            } else {
                model.remove(names.get(i));
            }
        }
        return NO_VALUE;
    }).then();
}

From source file:org.springframework.web.servlet.mvc.method.annotation.ReactiveTypeHandler.java

/**
 * Process the given reactive return value and decide whether to adapt it
 * to a {@link ResponseBodyEmitter} or a {@link DeferredResult}.
 * @return an emitter for streaming or {@code null} if handled internally
 * with a {@link DeferredResult}.// w  ww.j  a va2  s.com
 */
@Nullable
public ResponseBodyEmitter handleValue(Object returnValue, MethodParameter returnType,
        ModelAndViewContainer mav, NativeWebRequest request) throws Exception {

    Assert.notNull(returnValue, "Expected return value");
    ReactiveAdapter adapter = this.reactiveRegistry.getAdapter(returnValue.getClass());
    Assert.state(adapter != null, "Unexpected return value: " + returnValue);

    ResolvableType elementType = ResolvableType.forMethodParameter(returnType).getGeneric(0);
    Class<?> elementClass = elementType.resolve(Object.class);

    Collection<MediaType> mediaTypes = getMediaTypes(request);
    Optional<MediaType> mediaType = mediaTypes.stream().filter(MimeType::isConcrete).findFirst();

    if (adapter.isMultiValue()) {
        if (mediaTypes.stream().anyMatch(MediaType.TEXT_EVENT_STREAM::includes)
                || ServerSentEvent.class.isAssignableFrom(elementClass)) {
            SseEmitter emitter = new SseEmitter(STREAMING_TIMEOUT_VALUE);
            new SseEmitterSubscriber(emitter, this.taskExecutor).connect(adapter, returnValue);
            return emitter;
        }
        if (CharSequence.class.isAssignableFrom(elementClass)) {
            ResponseBodyEmitter emitter = getEmitter(mediaType.orElse(MediaType.TEXT_PLAIN));
            new TextEmitterSubscriber(emitter, this.taskExecutor).connect(adapter, returnValue);
            return emitter;
        }
        if (mediaTypes.stream().anyMatch(MediaType.APPLICATION_STREAM_JSON::includes)) {
            ResponseBodyEmitter emitter = getEmitter(MediaType.APPLICATION_STREAM_JSON);
            new JsonEmitterSubscriber(emitter, this.taskExecutor).connect(adapter, returnValue);
            return emitter;
        }
    }

    // Not streaming...
    DeferredResult<Object> result = new DeferredResult<>();
    new DeferredResultSubscriber(result, adapter, elementType).connect(adapter, returnValue);
    WebAsyncUtils.getAsyncManager(request).startDeferredResultProcessing(result, mav);

    return null;
}