Search in sources :

Example 6 with ReactiveAdapter

use of cn.taketoday.core.ReactiveAdapter in project today-infrastructure by TAKETODAY.

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) {
        ReactiveTransactionSupport txSupport = this.transactionSupportCache.computeIfAbsent(method, key -> {
            Class<?> reactiveType = 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);
        });
        return txSupport.invokeWithinTransaction(method, targetClass, invocation, txAttr, (ReactiveTransactionManager) tm);
    }
    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);
        }
        commitTransactionAfterReturning(txInfo);
        return retVal;
    } else {
        Object result;
        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 {
                    return invocation.proceedWithInvocation();
                } 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) {
                log.error("Application exception overridden by commit exception", throwableHolder.throwable);
                ex2.initApplicationException(throwableHolder.throwable);
            }
            throw ex2;
        } catch (Throwable ex2) {
            if (throwableHolder.throwable != null) {
                log.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 : StringUtils(cn.taketoday.util.StringUtils) Assert(cn.taketoday.lang.Assert) CallbackPreferringPlatformTransactionManager(cn.taketoday.transaction.support.CallbackPreferringPlatformTransactionManager) NoTransactionException(cn.taketoday.transaction.NoTransactionException) TransactionManager(cn.taketoday.transaction.TransactionManager) ClassUtils(cn.taketoday.util.ClassUtils) TransactionStatus(cn.taketoday.transaction.TransactionStatus) TransactionContextManager(cn.taketoday.transaction.reactive.TransactionContextManager) ConcurrentMap(java.util.concurrent.ConcurrentMap) Method(java.lang.reflect.Method) ReactiveTransaction(cn.taketoday.transaction.ReactiveTransaction) Properties(java.util.Properties) BeanFactoryAware(cn.taketoday.beans.factory.BeanFactoryAware) NamedThreadLocal(cn.taketoday.core.NamedThreadLocal) ConcurrentReferenceHashMap(cn.taketoday.util.ConcurrentReferenceHashMap) ReactiveAdapterRegistry(cn.taketoday.core.ReactiveAdapterRegistry) ReactiveTransactionManager(cn.taketoday.transaction.ReactiveTransactionManager) BeanFactory(cn.taketoday.beans.factory.BeanFactory) Mono(reactor.core.publisher.Mono) PlatformTransactionManager(cn.taketoday.transaction.PlatformTransactionManager) LoggerFactory(cn.taketoday.logging.LoggerFactory) Flux(reactor.core.publisher.Flux) BeanFactoryAnnotationUtils(cn.taketoday.beans.factory.annotation.BeanFactoryAnnotationUtils) ReactiveAdapter(cn.taketoday.core.ReactiveAdapter) Nullable(cn.taketoday.lang.Nullable) TransactionSystemException(cn.taketoday.transaction.TransactionSystemException) Logger(cn.taketoday.logging.Logger) InitializingBean(cn.taketoday.beans.factory.InitializingBean) TransactionSystemException(cn.taketoday.transaction.TransactionSystemException) CallbackPreferringPlatformTransactionManager(cn.taketoday.transaction.support.CallbackPreferringPlatformTransactionManager) PlatformTransactionManager(cn.taketoday.transaction.PlatformTransactionManager) CallbackPreferringPlatformTransactionManager(cn.taketoday.transaction.support.CallbackPreferringPlatformTransactionManager) CallbackPreferringPlatformTransactionManager(cn.taketoday.transaction.support.CallbackPreferringPlatformTransactionManager) TransactionManager(cn.taketoday.transaction.TransactionManager) ReactiveTransactionManager(cn.taketoday.transaction.ReactiveTransactionManager) PlatformTransactionManager(cn.taketoday.transaction.PlatformTransactionManager) ReactiveTransactionManager(cn.taketoday.transaction.ReactiveTransactionManager) ReactiveAdapter(cn.taketoday.core.ReactiveAdapter) Nullable(cn.taketoday.lang.Nullable)

Example 7 with ReactiveAdapter

use of cn.taketoday.core.ReactiveAdapter in project today-infrastructure by TAKETODAY.

the class BodyInserters method writeWithMessageWriters.

private static <M extends ReactiveHttpOutputMessage> Mono<Void> writeWithMessageWriters(M outputMessage, BodyInserter.Context context, Object body, ResolvableType bodyType, @Nullable ReactiveAdapter adapter) {
    Publisher<?> publisher;
    if (body instanceof Publisher) {
        publisher = (Publisher<?>) body;
    } else if (adapter != null) {
        publisher = adapter.toPublisher(body);
    } else {
        publisher = Mono.just(body);
    }
    MediaType mediaType = outputMessage.getHeaders().getContentType();
    return context.messageWriters().stream().filter(messageWriter -> messageWriter.canWrite(bodyType, mediaType)).findFirst().map(BodyInserters::cast).map(writer -> write(publisher, bodyType, mediaType, outputMessage, context, writer)).orElseGet(() -> Mono.error(unsupportedError(bodyType, context, mediaType)));
}
Also used : LinkedMultiValueMap(cn.taketoday.core.LinkedMultiValueMap) Assert(cn.taketoday.lang.Assert) WebClient(cn.taketoday.web.reactive.function.client.WebClient) ServerSentEvent(cn.taketoday.http.codec.ServerSentEvent) Publisher(org.reactivestreams.Publisher) ReactiveAdapterRegistry(cn.taketoday.core.ReactiveAdapterRegistry) ResolvableType(cn.taketoday.core.ResolvableType) Resource(cn.taketoday.core.io.Resource) MultipartBodyBuilder(cn.taketoday.http.client.MultipartBodyBuilder) HttpMessageWriter(cn.taketoday.http.codec.HttpMessageWriter) ServerHttpResponse(cn.taketoday.http.server.reactive.ServerHttpResponse) Mono(reactor.core.publisher.Mono) Collectors(java.util.stream.Collectors) List(java.util.List) ReactiveAdapter(cn.taketoday.core.ReactiveAdapter) ReactiveHttpOutputMessage(cn.taketoday.http.ReactiveHttpOutputMessage) Nullable(cn.taketoday.lang.Nullable) DataBuffer(cn.taketoday.core.io.buffer.DataBuffer) MultiValueMap(cn.taketoday.core.MultiValueMap) HttpEntity(cn.taketoday.http.HttpEntity) TypeReference(cn.taketoday.core.TypeReference) MediaType(cn.taketoday.http.MediaType) ClientHttpRequest(cn.taketoday.http.client.reactive.ClientHttpRequest) MediaType(cn.taketoday.http.MediaType) Publisher(org.reactivestreams.Publisher)

Example 8 with ReactiveAdapter

use of cn.taketoday.core.ReactiveAdapter in project today-infrastructure by TAKETODAY.

the class BodyInserters method fromProducer.

/**
 * Inserter to write the given producer of value(s) which must be a {@link Publisher}
 * or another producer adaptable to a {@code Publisher} via
 * {@link ReactiveAdapterRegistry}.
 * <p>Alternatively, consider using the {@code body} shortcuts on
 * {@link WebClient WebClient} and
 * {@link cn.taketoday.web.reactive.function.server.ServerResponse ServerResponse}.
 *
 * @param <T> the type of the body
 * @param producer the source of body value(s).
 * @param elementTypeRef the type of values to be produced
 * @return the inserter to write a producer
 * @since 4.0
 */
public static <T> BodyInserter<T, ReactiveHttpOutputMessage> fromProducer(T producer, TypeReference<?> elementTypeRef) {
    Assert.notNull(producer, "'producer' must not be null");
    Assert.notNull(elementTypeRef, "'elementTypeRef' must not be null");
    ReactiveAdapter adapter = ReactiveAdapterRegistry.getSharedInstance().getAdapter(producer.getClass());
    Assert.notNull(adapter, "'producer' type is unknown to ReactiveAdapterRegistry");
    return (message, context) -> writeWithMessageWriters(message, context, producer, ResolvableType.fromType(elementTypeRef), adapter);
}
Also used : LinkedMultiValueMap(cn.taketoday.core.LinkedMultiValueMap) Assert(cn.taketoday.lang.Assert) WebClient(cn.taketoday.web.reactive.function.client.WebClient) ServerSentEvent(cn.taketoday.http.codec.ServerSentEvent) Publisher(org.reactivestreams.Publisher) ReactiveAdapterRegistry(cn.taketoday.core.ReactiveAdapterRegistry) ResolvableType(cn.taketoday.core.ResolvableType) Resource(cn.taketoday.core.io.Resource) MultipartBodyBuilder(cn.taketoday.http.client.MultipartBodyBuilder) HttpMessageWriter(cn.taketoday.http.codec.HttpMessageWriter) ServerHttpResponse(cn.taketoday.http.server.reactive.ServerHttpResponse) Mono(reactor.core.publisher.Mono) Collectors(java.util.stream.Collectors) List(java.util.List) ReactiveAdapter(cn.taketoday.core.ReactiveAdapter) ReactiveHttpOutputMessage(cn.taketoday.http.ReactiveHttpOutputMessage) Nullable(cn.taketoday.lang.Nullable) DataBuffer(cn.taketoday.core.io.buffer.DataBuffer) MultiValueMap(cn.taketoday.core.MultiValueMap) HttpEntity(cn.taketoday.http.HttpEntity) TypeReference(cn.taketoday.core.TypeReference) MediaType(cn.taketoday.http.MediaType) ClientHttpRequest(cn.taketoday.http.client.reactive.ClientHttpRequest) ReactiveAdapter(cn.taketoday.core.ReactiveAdapter)

Aggregations

ReactiveAdapter (cn.taketoday.core.ReactiveAdapter)8 ReactiveAdapterRegistry (cn.taketoday.core.ReactiveAdapterRegistry)8 Assert (cn.taketoday.lang.Assert)8 Nullable (cn.taketoday.lang.Nullable)8 Mono (reactor.core.publisher.Mono)8 LinkedMultiValueMap (cn.taketoday.core.LinkedMultiValueMap)6 MultiValueMap (cn.taketoday.core.MultiValueMap)6 ResolvableType (cn.taketoday.core.ResolvableType)6 TypeReference (cn.taketoday.core.TypeReference)6 Resource (cn.taketoday.core.io.Resource)6 DataBuffer (cn.taketoday.core.io.buffer.DataBuffer)6 HttpEntity (cn.taketoday.http.HttpEntity)6 MediaType (cn.taketoday.http.MediaType)6 ReactiveHttpOutputMessage (cn.taketoday.http.ReactiveHttpOutputMessage)6 MultipartBodyBuilder (cn.taketoday.http.client.MultipartBodyBuilder)6 ClientHttpRequest (cn.taketoday.http.client.reactive.ClientHttpRequest)6 HttpMessageWriter (cn.taketoday.http.codec.HttpMessageWriter)6 ServerSentEvent (cn.taketoday.http.codec.ServerSentEvent)6 ServerHttpResponse (cn.taketoday.http.server.reactive.ServerHttpResponse)6 WebClient (cn.taketoday.web.reactive.function.client.WebClient)6