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}