Search in sources :

Example 31 with ReactiveAdapter

use of org.springframework.core.ReactiveAdapter in project spring-framework by spring-projects.

the class HandlerMethodArgumentResolverSupport method checkAnnotatedParamNoReactiveWrapper.

/**
 * Evaluate the {@code Predicate} on the method parameter type if it has the
 * given annotation, nesting within {@link java.util.Optional} if necessary,
 * but raise an {@code IllegalStateException} if the same matches the generic
 * type within a reactive type wrapper.
 */
protected <A extends Annotation> boolean checkAnnotatedParamNoReactiveWrapper(MethodParameter parameter, Class<A> annotationType, BiPredicate<A, Class<?>> typePredicate) {
    A annotation = parameter.getParameterAnnotation(annotationType);
    if (annotation == null) {
        return false;
    }
    parameter = parameter.nestedIfOptional();
    Class<?> type = parameter.getNestedParameterType();
    ReactiveAdapter adapter = getAdapterRegistry().getAdapter(type);
    if (adapter != null) {
        assertHasValues(adapter, parameter);
        parameter = parameter.nested();
        type = parameter.getNestedParameterType();
    }
    if (typePredicate.test(annotation, type)) {
        if (adapter == null) {
            return true;
        }
        throw buildReactiveWrapperException(parameter);
    }
    return false;
}
Also used : ReactiveAdapter(org.springframework.core.ReactiveAdapter)

Example 32 with ReactiveAdapter

use of org.springframework.core.ReactiveAdapter in project spring-framework by spring-projects.

the class HandlerMethodArgumentResolverSupport method checkParameterTypeNoReactiveWrapper.

/**
 * Evaluate the {@code Predicate} on the method parameter type but raise an
 * {@code IllegalStateException} if the same matches the generic type
 * within a reactive type wrapper.
 */
protected boolean checkParameterTypeNoReactiveWrapper(MethodParameter parameter, Predicate<Class<?>> predicate) {
    Class<?> type = parameter.getParameterType();
    ReactiveAdapter adapter = getAdapterRegistry().getAdapter(type);
    if (adapter != null) {
        assertHasValues(adapter, parameter);
        type = parameter.nested().getNestedParameterType();
    }
    if (predicate.test(type)) {
        if (adapter == null) {
            return true;
        }
        throw buildReactiveWrapperException(parameter);
    }
    return false;
}
Also used : ReactiveAdapter(org.springframework.core.ReactiveAdapter)

Example 33 with ReactiveAdapter

use of org.springframework.core.ReactiveAdapter in project spring-framework by spring-projects.

the class AbstractMessageReaderArgumentResolver method readBody.

/**
 * Read the body from a method argument with {@link HttpMessageReader}.
 * @param bodyParam represents the element type for the body
 * @param actualParam the actual method argument type; possibly different
 * from {@code bodyParam}, e.g. for an {@code HttpEntity} argument
 * @param isBodyRequired true if the body is required
 * @param bindingContext the binding context to use
 * @param exchange the current exchange
 * @return a Mono with the value to use for the method argument
 * @since 5.0.2
 */
protected Mono<Object> readBody(MethodParameter bodyParam, @Nullable MethodParameter actualParam, boolean isBodyRequired, BindingContext bindingContext, ServerWebExchange exchange) {
    ResolvableType bodyType = ResolvableType.forMethodParameter(bodyParam);
    ResolvableType actualType = (actualParam != null ? ResolvableType.forMethodParameter(actualParam) : bodyType);
    Class<?> resolvedType = bodyType.resolve();
    ReactiveAdapter adapter = (resolvedType != null ? getAdapterRegistry().getAdapter(resolvedType) : null);
    ResolvableType elementType = (adapter != null ? bodyType.getGeneric() : bodyType);
    isBodyRequired = isBodyRequired || (adapter != null && !adapter.supportsEmpty());
    ServerHttpRequest request = exchange.getRequest();
    ServerHttpResponse response = exchange.getResponse();
    MediaType contentType = request.getHeaders().getContentType();
    MediaType mediaType = (contentType != null ? contentType : MediaType.APPLICATION_OCTET_STREAM);
    Object[] hints = extractValidationHints(bodyParam);
    if (mediaType.isCompatibleWith(MediaType.APPLICATION_FORM_URLENCODED)) {
        if (logger.isDebugEnabled()) {
            logger.debug("Form data is accessed via ServerWebExchange.getFormData() in WebFlux.");
        }
        return Mono.error(new ResponseStatusException(HttpStatus.UNSUPPORTED_MEDIA_TYPE));
    }
    if (logger.isDebugEnabled()) {
        logger.debug(exchange.getLogPrefix() + (contentType != null ? "Content-Type:" + contentType : "No Content-Type, using " + MediaType.APPLICATION_OCTET_STREAM));
    }
    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)));
                }
                if (hints != null) {
                    flux = flux.doOnNext(target -> validate(target, hints, bodyParam, bindingContext, exchange));
                }
                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)));
                }
                if (hints != null) {
                    mono = mono.doOnNext(target -> validate(target, hints, bodyParam, bindingContext, exchange));
                }
                return (adapter != null ? Mono.just(adapter.fromPublisher(mono)) : Mono.from(mono));
            }
        }
    }
    // No compatible reader but body may be empty..
    HttpMethod method = request.getMethod();
    if (contentType == null && SUPPORTED_METHODS.contains(method)) {
        Flux<DataBuffer> body = request.getBody().doOnNext(buffer -> {
            DataBufferUtils.release(buffer);
            // Body not empty, back toy 415..
            throw new UnsupportedMediaTypeStatusException(mediaType, getSupportedMediaTypes(elementType), elementType);
        });
        if (isBodyRequired) {
            body = body.switchIfEmpty(Mono.error(() -> handleMissingBody(bodyParam)));
        }
        return (adapter != null ? Mono.just(adapter.fromPublisher(body)) : Mono.from(body));
    }
    return Mono.error(new UnsupportedMediaTypeStatusException(mediaType, getSupportedMediaTypes(elementType), elementType));
}
Also used : ServerHttpResponse(org.springframework.http.server.reactive.ServerHttpResponse) Validator(org.springframework.validation.Validator) Conventions(org.springframework.core.Conventions) WebExchangeDataBinder(org.springframework.web.bind.support.WebExchangeDataBinder) ServerWebInputException(org.springframework.web.server.ServerWebInputException) DecodingException(org.springframework.core.codec.DecodingException) Hints(org.springframework.core.codec.Hints) HttpMessageReader(org.springframework.http.codec.HttpMessageReader) BindingContext(org.springframework.web.reactive.BindingContext) ArrayList(java.util.ArrayList) ServerWebExchange(org.springframework.web.server.ServerWebExchange) HandlerMethodArgumentResolverSupport(org.springframework.web.reactive.result.method.HandlerMethodArgumentResolverSupport) UnsupportedMediaTypeStatusException(org.springframework.web.server.UnsupportedMediaTypeStatusException) Map(java.util.Map) MethodParameter(org.springframework.core.MethodParameter) DataBufferUtils(org.springframework.core.io.buffer.DataBufferUtils) Nullable(org.springframework.lang.Nullable) ResolvableType(org.springframework.core.ResolvableType) ReactiveAdapterRegistry(org.springframework.core.ReactiveAdapterRegistry) WebExchangeBindException(org.springframework.web.bind.support.WebExchangeBindException) ServerHttpRequest(org.springframework.http.server.reactive.ServerHttpRequest) ReactiveAdapter(org.springframework.core.ReactiveAdapter) ResponseStatusException(org.springframework.web.server.ResponseStatusException) MediaType(org.springframework.http.MediaType) HttpMethod(org.springframework.http.HttpMethod) ValidationAnnotationUtils(org.springframework.validation.annotation.ValidationAnnotationUtils) Set(java.util.Set) Mono(reactor.core.publisher.Mono) DataBuffer(org.springframework.core.io.buffer.DataBuffer) Flux(reactor.core.publisher.Flux) HttpStatus(org.springframework.http.HttpStatus) List(java.util.List) Annotation(java.lang.annotation.Annotation) Assert(org.springframework.util.Assert) ServerHttpRequest(org.springframework.http.server.reactive.ServerHttpRequest) ServerHttpResponse(org.springframework.http.server.reactive.ServerHttpResponse) UnsupportedMediaTypeStatusException(org.springframework.web.server.UnsupportedMediaTypeStatusException) MediaType(org.springframework.http.MediaType) ResolvableType(org.springframework.core.ResolvableType) ResponseStatusException(org.springframework.web.server.ResponseStatusException) ReactiveAdapter(org.springframework.core.ReactiveAdapter) HttpMethod(org.springframework.http.HttpMethod) DataBuffer(org.springframework.core.io.buffer.DataBuffer)

Example 34 with ReactiveAdapter

use of org.springframework.core.ReactiveAdapter in project spring-framework by spring-projects.

the class WebSessionMethodArgumentResolver method resolveArgument.

@Override
public Mono<Object> resolveArgument(MethodParameter parameter, BindingContext context, ServerWebExchange exchange) {
    Mono<WebSession> session = exchange.getSession();
    ReactiveAdapter adapter = getAdapterRegistry().getAdapter(parameter.getParameterType());
    return (adapter != null ? Mono.just(adapter.fromPublisher(session)) : Mono.from(session));
}
Also used : WebSession(org.springframework.web.server.WebSession) ReactiveAdapter(org.springframework.core.ReactiveAdapter)

Example 35 with ReactiveAdapter

use of org.springframework.core.ReactiveAdapter in project spring-framework by spring-projects.

the class ModelAttributeMethodArgumentResolver method prepareAttributeMono.

private Mono<?> prepareAttributeMono(String attributeName, ResolvableType attributeType, BindingContext context, ServerWebExchange exchange) {
    Object attribute = context.getModel().asMap().get(attributeName);
    if (attribute == null) {
        attribute = findAndRemoveReactiveAttribute(context.getModel(), attributeName);
    }
    if (attribute == null) {
        return createAttribute(attributeName, attributeType.toClass(), context, exchange);
    }
    ReactiveAdapter adapter = getAdapterRegistry().getAdapter(null, attribute);
    if (adapter != null) {
        Assert.isTrue(!adapter.isMultiValue(), "Data binding only supports single-value async types");
        return Mono.from(adapter.toPublisher(attribute));
    } else {
        return Mono.justOrEmpty(attribute);
    }
}
Also used : ReactiveAdapter(org.springframework.core.ReactiveAdapter)

Aggregations

ReactiveAdapter (org.springframework.core.ReactiveAdapter)41 ResolvableType (org.springframework.core.ResolvableType)16 Mono (reactor.core.publisher.Mono)14 ReactiveAdapterRegistry (org.springframework.core.ReactiveAdapterRegistry)13 List (java.util.List)12 Assert (org.springframework.util.Assert)12 MethodParameter (org.springframework.core.MethodParameter)11 Nullable (org.springframework.lang.Nullable)11 MediaType (org.springframework.http.MediaType)10 Map (java.util.Map)8 Publisher (org.reactivestreams.Publisher)8 Flux (reactor.core.publisher.Flux)8 DataBuffer (org.springframework.core.io.buffer.DataBuffer)7 ArrayList (java.util.ArrayList)6 Collections (java.util.Collections)6 BindingContext (org.springframework.web.reactive.BindingContext)6 ServerWebExchange (org.springframework.web.server.ServerWebExchange)6 Collectors (java.util.stream.Collectors)5 HttpEntity (org.springframework.http.HttpEntity)5 HttpMessageWriter (org.springframework.http.codec.HttpMessageWriter)5