001/*
002 * Copyright 2002-2019 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 org.springframework.lang.Nullable;
020import org.springframework.transaction.ReactiveTransaction;
021import org.springframework.util.Assert;
022
023/**
024 * Default implementation of the {@link ReactiveTransaction} interface,
025 * used by {@link AbstractReactiveTransactionManager}. Based on the concept
026 * of an underlying "transaction object".
027 *
028 * <p>Holds all status information that {@link AbstractReactiveTransactionManager}
029 * needs internally, including a generic transaction object determined by the
030 * concrete transaction manager implementation.
031 *
032 * <p><b>NOTE:</b> This is <i>not</i> intended for use with other ReactiveTransactionManager
033 * implementations, in particular not for mock transaction managers in testing environments.
034 *
035 * @author Mark Paluch
036 * @author Juergen Hoeller
037 * @since 5.2
038 * @see AbstractReactiveTransactionManager
039 * @see #getTransaction
040 */
041public class GenericReactiveTransaction implements ReactiveTransaction {
042
043        @Nullable
044        private final Object transaction;
045
046        private final boolean newTransaction;
047
048        private final boolean newSynchronization;
049
050        private final boolean readOnly;
051
052        private final boolean debug;
053
054        @Nullable
055        private final Object suspendedResources;
056
057        private boolean rollbackOnly = false;
058
059        private boolean completed = false;
060
061
062        /**
063         * Create a new {@code DefaultReactiveTransactionStatus} instance.
064         * @param transaction underlying transaction object that can hold state
065         * for the internal transaction implementation
066         * @param newTransaction if the transaction is new, otherwise participating
067         * in an existing transaction
068         * @param newSynchronization if a new transaction synchronization has been
069         * opened for the given transaction
070         * @param readOnly whether the transaction is marked as read-only
071         * @param debug should debug logging be enabled for the handling of this transaction?
072         * Caching it in here can prevent repeated calls to ask the logging system whether
073         * debug logging should be enabled.
074         * @param suspendedResources a holder for resources that have been suspended
075         * for this transaction, if any
076         */
077        public GenericReactiveTransaction(
078                        @Nullable Object transaction, boolean newTransaction, boolean newSynchronization,
079                        boolean readOnly, boolean debug, @Nullable Object suspendedResources) {
080
081                this.transaction = transaction;
082                this.newTransaction = newTransaction;
083                this.newSynchronization = newSynchronization;
084                this.readOnly = readOnly;
085                this.debug = debug;
086                this.suspendedResources = suspendedResources;
087        }
088
089
090        /**
091         * Return the underlying transaction object.
092         * @throws IllegalStateException if no transaction is active
093         */
094        public Object getTransaction() {
095                Assert.state(this.transaction != null, "No transaction active");
096                return this.transaction;
097        }
098
099        /**
100         * Return whether there is an actual transaction active.
101         */
102        public boolean hasTransaction() {
103                return (this.transaction != null);
104        }
105
106        @Override
107        public boolean isNewTransaction() {
108                return (hasTransaction() && this.newTransaction);
109        }
110
111        /**
112         * Return if a new transaction synchronization has been opened
113         * for this transaction.
114         */
115        public boolean isNewSynchronization() {
116                return this.newSynchronization;
117        }
118
119        /**
120         * Return if this transaction is defined as read-only transaction.
121         */
122        public boolean isReadOnly() {
123                return this.readOnly;
124        }
125
126        /**
127         * Return whether the progress of this transaction is debugged. This is used by
128         * {@link AbstractReactiveTransactionManager} as an optimization, to prevent repeated
129         * calls to {@code logger.isDebugEnabled()}. Not really intended for client code.
130         */
131        public boolean isDebug() {
132                return this.debug;
133        }
134
135        /**
136         * Return the holder for resources that have been suspended for this transaction,
137         * if any.
138         */
139        @Nullable
140        public Object getSuspendedResources() {
141                return this.suspendedResources;
142        }
143
144        @Override
145        public void setRollbackOnly() {
146                this.rollbackOnly = true;
147        }
148
149        /**
150         * Determine the rollback-only flag via checking this ReactiveTransactionStatus.
151         * <p>Will only return "true" if the application called {@code setRollbackOnly}
152         * on this TransactionStatus object.
153         */
154        @Override
155        public boolean isRollbackOnly() {
156                return this.rollbackOnly;
157        }
158
159        /**
160         * Mark this transaction as completed, that is, committed or rolled back.
161         */
162        public void setCompleted() {
163                this.completed = true;
164        }
165
166        @Override
167        public boolean isCompleted() {
168                return this.completed;
169        }
170
171}