001/*
002 * Copyright 2002-2020 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.transaction.reactive;
018
019import reactor.core.publisher.Flux;
020import reactor.core.publisher.Mono;
021
022import org.springframework.transaction.ReactiveTransactionManager;
023import org.springframework.transaction.TransactionDefinition;
024import org.springframework.transaction.TransactionException;
025
026/**
027 * Operator class that simplifies programmatic transaction demarcation and
028 * transaction exception handling.
029 *
030 * <p>The central method is {@link #transactional}, supporting transactional wrapping
031 * of functional sequences code that. This operator handles the transaction lifecycle
032 * and possible exceptions such that neither the ReactiveTransactionCallback
033 * implementation nor the calling code needs to explicitly handle transactions.
034 *
035 * <p>Typical usage: Allows for writing low-level data access objects that use
036 * resources such as database connections but are not transaction-aware themselves.
037 * Instead, they can implicitly participate in transactions handled by higher-level
038 * application services utilizing this class, making calls to the low-level
039 * services via an inner-class callback object.
040 *
041 * <p><strong>Note:</strong> Transactional Publishers should avoid Subscription
042 * cancellation. See the
043 * <a href="https://docs.spring.io/spring/docs/current/spring-framework-reference/data-access.html#tx-prog-operator-cancel">Cancel Signals</a>
044 * section of the Spring Framework reference for more details.
045 *
046 * @author Mark Paluch
047 * @author Juergen Hoeller
048 * @since 5.2
049 * @see #execute
050 * @see ReactiveTransactionManager
051 */
052public interface TransactionalOperator {
053
054        /**
055         * Wrap the functional sequence specified by the given Flux within a transaction.
056         * @param flux the Flux that should be executed within the transaction
057         * @return a result publisher returned by the callback, or {@code null} if none
058         * @throws TransactionException in case of initialization, rollback, or system errors
059         * @throws RuntimeException if thrown by the TransactionCallback
060         */
061        default <T> Flux<T> transactional(Flux<T> flux) {
062                return execute(it -> flux);
063        }
064
065        /**
066         * Wrap the functional sequence specified by the given Mono within a transaction.
067         * @param mono the Mono that should be executed within the transaction
068         * @return a result publisher returned by the callback
069         * @throws TransactionException in case of initialization, rollback, or system errors
070         * @throws RuntimeException if thrown by the TransactionCallback
071         */
072        <T> Mono<T> transactional(Mono<T> mono);
073
074        /**
075         * Execute the action specified by the given callback object within a transaction.
076         * <p>Allows for returning a result object created within the transaction, that is,
077         * a domain object or a collection of domain objects. A RuntimeException thrown
078         * by the callback is treated as a fatal exception that enforces a rollback.
079         * Such an exception gets propagated to the caller of the template.
080         * @param action the callback object that specifies the transactional action
081         * @return a result object returned by the callback
082         * @throws TransactionException in case of initialization, rollback, or system errors
083         * @throws RuntimeException if thrown by the TransactionCallback
084         */
085        <T> Flux<T> execute(TransactionCallback<T> action) throws TransactionException;
086
087
088        // Static builder methods
089
090        /**
091         * Create a new {@link TransactionalOperator} using {@link ReactiveTransactionManager},
092         * using a default transaction.
093         * @param transactionManager the transaction management strategy to be used
094         * @return the transactional operator
095         */
096        static TransactionalOperator create(ReactiveTransactionManager transactionManager){
097                return create(transactionManager, TransactionDefinition.withDefaults());
098        }
099
100        /**
101         * Create a new {@link TransactionalOperator} using {@link ReactiveTransactionManager}
102         * and {@link TransactionDefinition}.
103         * @param transactionManager the transaction management strategy to be used
104         * @param transactionDefinition the transaction definition to apply
105         * @return the transactional operator
106         */
107        static TransactionalOperator create(
108                        ReactiveTransactionManager transactionManager, TransactionDefinition transactionDefinition){
109
110                return new TransactionalOperatorImpl(transactionManager, transactionDefinition);
111        }
112
113}