Search in sources :

Example 21 with ReactiveAdapter

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

the class RSocketMessageHandler method getCardinality.

private int getCardinality(MethodParameter parameter) {
    Class<?> clazz = parameter.getParameterType();
    ReactiveAdapter adapter = getReactiveAdapterRegistry().getAdapter(clazz);
    if (adapter == null) {
        return clazz.equals(void.class) ? 0 : 1;
    } else if (parameter.nested().getNestedParameterType().equals(Void.class)) {
        return 0;
    } else {
        return adapter.isMultiValue() ? 2 : 1;
    }
}
Also used : ReactiveAdapter(org.springframework.core.ReactiveAdapter)

Example 22 with ReactiveAdapter

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

the class AbstractEncoderMethodReturnValueHandler method encodeContent.

private Flux<DataBuffer> encodeContent(@Nullable Object content, MethodParameter returnType, DataBufferFactory bufferFactory, @Nullable MimeType mimeType, Map<String, Object> hints) {
    ResolvableType returnValueType = ResolvableType.forMethodParameter(returnType);
    ReactiveAdapter adapter = getAdapterRegistry().getAdapter(returnValueType.resolve(), content);
    Publisher<?> publisher;
    ResolvableType elementType;
    if (adapter != null) {
        publisher = adapter.toPublisher(content);
        Method method = returnType.getMethod();
        boolean isUnwrapped = (method != null && KotlinDetector.isSuspendingFunction(method) && !COROUTINES_FLOW_CLASS_NAME.equals(returnValueType.toClass().getName()));
        ResolvableType genericType = (isUnwrapped ? returnValueType : returnValueType.getGeneric());
        elementType = getElementType(adapter, genericType);
    } else {
        publisher = Mono.justOrEmpty(content);
        elementType = (returnValueType.toClass() == Object.class && content != null ? ResolvableType.forInstance(content) : returnValueType);
    }
    if (elementType.resolve() == void.class || elementType.resolve() == Void.class) {
        return Flux.from(publisher).cast(DataBuffer.class);
    }
    Encoder<?> encoder = getEncoder(elementType, mimeType);
    return Flux.from(publisher).map(value -> encodeValue(value, elementType, encoder, bufferFactory, mimeType, hints));
}
Also used : Method(java.lang.reflect.Method) ResolvableType(org.springframework.core.ResolvableType) ReactiveAdapter(org.springframework.core.ReactiveAdapter)

Example 23 with ReactiveAdapter

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

the class MetadataEncoder method metadata.

/**
 * Add a metadata entry. If called more than once or in addition to route,
 * composite metadata must be in use.
 */
public MetadataEncoder metadata(Object metadata, @Nullable MimeType mimeType) {
    if (this.isComposite) {
        Assert.notNull(mimeType, "MimeType is required for composite metadata entries.");
    } else if (mimeType == null) {
        mimeType = this.metadataMimeType;
    } else if (!this.metadataMimeType.equals(mimeType)) {
        throw new IllegalArgumentException("Mime type is optional when not using composite metadata, but it was provided " + "and does not match the connection metadata mime type '" + this.metadataMimeType + "'.");
    }
    ReactiveAdapter adapter = this.strategies.reactiveAdapterRegistry().getAdapter(metadata.getClass());
    if (adapter != null) {
        Assert.isTrue(!adapter.isMultiValue(), "Expected single value: " + metadata);
        metadata = Mono.from(adapter.toPublisher(metadata)).defaultIfEmpty(NO_VALUE);
        this.hasAsyncValues = true;
    }
    this.metadataEntries.add(new MetadataEntry(metadata, mimeType));
    assertMetadataEntryCount();
    return this;
}
Also used : ReactiveAdapter(org.springframework.core.ReactiveAdapter)

Example 24 with ReactiveAdapter

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

the class TransactionAspectSupport method invokeWithinTransaction.

/**
 * General delegate for around-advice-based subclasses, delegating to several other template
 * methods on this class. Able to handle {@link CallbackPreferringPlatformTransactionManager}
 * as well as regular {@link PlatformTransactionManager} implementations and
 * {@link ReactiveTransactionManager} implementations for reactive return types.
 * @param method the Method being invoked
 * @param targetClass the target class that we're invoking the method on
 * @param invocation the callback to use for proceeding with the target invocation
 * @return the return value of the method, if any
 * @throws Throwable propagated from the target invocation
 */
@Nullable
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass, final InvocationCallback invocation) throws Throwable {
    // If the transaction attribute is null, the method is non-transactional.
    TransactionAttributeSource tas = getTransactionAttributeSource();
    final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
    final TransactionManager tm = determineTransactionManager(txAttr);
    if (this.reactiveAdapterRegistry != null && tm instanceof ReactiveTransactionManager) {
        boolean isSuspendingFunction = KotlinDetector.isSuspendingFunction(method);
        boolean hasSuspendingFlowReturnType = isSuspendingFunction && COROUTINES_FLOW_CLASS_NAME.equals(new MethodParameter(method, -1).getParameterType().getName());
        if (isSuspendingFunction && !(invocation instanceof CoroutinesInvocationCallback)) {
            throw new IllegalStateException("Coroutines invocation not supported: " + method);
        }
        CoroutinesInvocationCallback corInv = (isSuspendingFunction ? (CoroutinesInvocationCallback) invocation : null);
        ReactiveTransactionSupport txSupport = this.transactionSupportCache.computeIfAbsent(method, key -> {
            Class<?> reactiveType = (isSuspendingFunction ? (hasSuspendingFlowReturnType ? Flux.class : Mono.class) : method.getReturnType());
            ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(reactiveType);
            if (adapter == null) {
                throw new IllegalStateException("Cannot apply reactive transaction to non-reactive return type: " + method.getReturnType());
            }
            return new ReactiveTransactionSupport(adapter);
        });
        InvocationCallback callback = invocation;
        if (corInv != null) {
            callback = () -> CoroutinesUtils.invokeSuspendingFunction(method, corInv.getTarget(), corInv.getArguments());
        }
        Object result = txSupport.invokeWithinTransaction(method, targetClass, callback, txAttr, (ReactiveTransactionManager) tm);
        if (corInv != null) {
            Publisher<?> pr = (Publisher<?>) result;
            return (hasSuspendingFlowReturnType ? KotlinDelegate.asFlow(pr) : KotlinDelegate.awaitSingleOrNull(pr, corInv.getContinuation()));
        }
        return result;
    }
    PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
    final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
    if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
        // Standard transaction demarcation with getTransaction and commit/rollback calls.
        TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);
        Object retVal;
        try {
            // This is an around advice: Invoke the next interceptor in the chain.
            // This will normally result in a target object being invoked.
            retVal = invocation.proceedWithInvocation();
        } catch (Throwable ex) {
            // target invocation exception
            completeTransactionAfterThrowing(txInfo, ex);
            throw ex;
        } finally {
            cleanupTransactionInfo(txInfo);
        }
        if (retVal != null && vavrPresent && VavrDelegate.isVavrTry(retVal)) {
            // Set rollback-only in case of Vavr failure matching our rollback rules...
            TransactionStatus status = txInfo.getTransactionStatus();
            if (status != null && txAttr != null) {
                retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
            }
        }
        commitTransactionAfterReturning(txInfo);
        return retVal;
    } else {
        Object result;
        final ThrowableHolder throwableHolder = new ThrowableHolder();
        // It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
        try {
            result = ((CallbackPreferringPlatformTransactionManager) ptm).execute(txAttr, status -> {
                TransactionInfo txInfo = prepareTransactionInfo(ptm, txAttr, joinpointIdentification, status);
                try {
                    Object retVal = invocation.proceedWithInvocation();
                    if (retVal != null && vavrPresent && VavrDelegate.isVavrTry(retVal)) {
                        // Set rollback-only in case of Vavr failure matching our rollback rules...
                        retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
                    }
                    return retVal;
                } catch (Throwable ex) {
                    if (txAttr.rollbackOn(ex)) {
                        // A RuntimeException: will lead to a rollback.
                        if (ex instanceof RuntimeException) {
                            throw (RuntimeException) ex;
                        } else {
                            throw new ThrowableHolderException(ex);
                        }
                    } else {
                        // A normal return value: will lead to a commit.
                        throwableHolder.throwable = ex;
                        return null;
                    }
                } finally {
                    cleanupTransactionInfo(txInfo);
                }
            });
        } catch (ThrowableHolderException ex) {
            throw ex.getCause();
        } catch (TransactionSystemException ex2) {
            if (throwableHolder.throwable != null) {
                logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
                ex2.initApplicationException(throwableHolder.throwable);
            }
            throw ex2;
        } catch (Throwable ex2) {
            if (throwableHolder.throwable != null) {
                logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
            }
            throw ex2;
        }
        // Check result state: It might indicate a Throwable to rethrow.
        if (throwableHolder.throwable != null) {
            throw throwableHolder.throwable;
        }
        return result;
    }
}
Also used : Continuation(kotlin.coroutines.Continuation) AwaitKt(kotlinx.coroutines.reactive.AwaitKt) ReactiveTransaction(org.springframework.transaction.ReactiveTransaction) InitializingBean(org.springframework.beans.factory.InitializingBean) ConcurrentMap(java.util.concurrent.ConcurrentMap) ConcurrentReferenceHashMap(org.springframework.util.ConcurrentReferenceHashMap) KotlinDetector(org.springframework.core.KotlinDetector) TransactionManager(org.springframework.transaction.TransactionManager) TransactionSystemException(org.springframework.transaction.TransactionSystemException) BeanFactoryAware(org.springframework.beans.factory.BeanFactoryAware) MethodParameter(org.springframework.core.MethodParameter) Nullable(org.springframework.lang.Nullable) Method(java.lang.reflect.Method) BeanFactoryAnnotationUtils(org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils) ReactiveAdapterRegistry(org.springframework.core.ReactiveAdapterRegistry) ReactiveFlowKt(kotlinx.coroutines.reactive.ReactiveFlowKt) CoroutinesUtils(org.springframework.core.CoroutinesUtils) TransactionContextManager(org.springframework.transaction.reactive.TransactionContextManager) ReactiveAdapter(org.springframework.core.ReactiveAdapter) Properties(java.util.Properties) ClassUtils(org.springframework.util.ClassUtils) CallbackPreferringPlatformTransactionManager(org.springframework.transaction.support.CallbackPreferringPlatformTransactionManager) Publisher(org.reactivestreams.Publisher) Mono(reactor.core.publisher.Mono) ReactiveTransactionManager(org.springframework.transaction.ReactiveTransactionManager) NamedThreadLocal(org.springframework.core.NamedThreadLocal) Flux(reactor.core.publisher.Flux) Try(io.vavr.control.Try) NoTransactionException(org.springframework.transaction.NoTransactionException) PlatformTransactionManager(org.springframework.transaction.PlatformTransactionManager) BeanFactory(org.springframework.beans.factory.BeanFactory) TransactionStatus(org.springframework.transaction.TransactionStatus) Log(org.apache.commons.logging.Log) LogFactory(org.apache.commons.logging.LogFactory) Assert(org.springframework.util.Assert) StringUtils(org.springframework.util.StringUtils) TransactionStatus(org.springframework.transaction.TransactionStatus) TransactionSystemException(org.springframework.transaction.TransactionSystemException) CallbackPreferringPlatformTransactionManager(org.springframework.transaction.support.CallbackPreferringPlatformTransactionManager) ReactiveAdapter(org.springframework.core.ReactiveAdapter) Mono(reactor.core.publisher.Mono) Flux(reactor.core.publisher.Flux) Publisher(org.reactivestreams.Publisher) CallbackPreferringPlatformTransactionManager(org.springframework.transaction.support.CallbackPreferringPlatformTransactionManager) PlatformTransactionManager(org.springframework.transaction.PlatformTransactionManager) TransactionManager(org.springframework.transaction.TransactionManager) CallbackPreferringPlatformTransactionManager(org.springframework.transaction.support.CallbackPreferringPlatformTransactionManager) ReactiveTransactionManager(org.springframework.transaction.ReactiveTransactionManager) PlatformTransactionManager(org.springframework.transaction.PlatformTransactionManager) ReactiveTransactionManager(org.springframework.transaction.ReactiveTransactionManager) MethodParameter(org.springframework.core.MethodParameter) Nullable(org.springframework.lang.Nullable)

Example 25 with ReactiveAdapter

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

the class HandlerMethodArgumentResolverSupport method checkParamType.

/**
	 * Evaluate the {@code Predicate} on the the method parameter type or on
	 * the generic type within a reactive type wrapper.
	 */
protected boolean checkParamType(MethodParameter param, Predicate<Class<?>> predicate) {
    Class<?> type = param.getParameterType();
    ReactiveAdapter adapter = getAdapterRegistry().getAdapter(type);
    if (adapter != null) {
        assertHasValues(adapter, param);
        type = param.nested().getNestedParameterType();
    }
    return predicate.test(type);
}
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