001/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- 002 * 003 * Copyright © 2019 microBean. 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 014 * implied. See the License for the specific language governing 015 * permissions and limitations under the License. 016 */ 017package org.microbean.narayana.jta.cdi; 018 019import java.util.Objects; 020 021import javax.transaction.HeuristicMixedException; 022import javax.transaction.HeuristicRollbackException; 023import javax.transaction.InvalidTransactionException; 024import javax.transaction.NotSupportedException; 025import javax.transaction.RollbackException; 026import javax.transaction.Status; // for javadoc only 027import javax.transaction.SystemException; 028import javax.transaction.Transaction; 029import javax.transaction.TransactionManager; 030 031/** 032 * An {@code abstract} {@link TransactionManager} implementation that 033 * delegates all method invocations to another {@link 034 * TransactionManager}. 035 * 036 * @author <a href="https://about.me/lairdnelson" target="_parent">Laird Nelson</a> 037 * 038 * @see TransactionManager 039 */ 040public abstract class DelegatingTransactionManager implements TransactionManager { 041 042 private final TransactionManager delegate; 043 044 /** 045 * Creates a new, <strong>nonfunctional</strong> {@link 046 * DelegatingTransactionManager}. 047 * 048 * <p>This constructor exists only to conform with section 3.11 of 049 * the CDI specification.</p> 050 * 051 * @deprecated This constructor exists only to conform with section 052 * 3.11 of the CDI specification; please use the {@link 053 * #DelegatingTransactionManager(TransactionManager)} constructor 054 * instead. 055 */ 056 @Deprecated 057 protected DelegatingTransactionManager() { 058 super(); 059 this.delegate = null; 060 } 061 062 /** 063 * Creates a new {@link DelegatingTransactionManager}. 064 * 065 * @param delegate the {@link TransactionManager} to which all 066 * method invocations will be delegated; must not be {@code null} 067 * 068 * @exception NullPointerException if {@code delegate} is {@code null} 069 */ 070 protected DelegatingTransactionManager(final TransactionManager delegate) { 071 super(); 072 this.delegate = Objects.requireNonNull(delegate); 073 } 074 075 /** 076 * Creates a new transaction and associates it with the current thread. 077 * 078 * @exception NotSupportedException if the thread is already 079 * associated with a transaction and this {@link TransactionManager} 080 * implementation does not support nested transactions 081 * 082 * @exception SystemException if this {@link TransactionManager} 083 * encounters an unexpected error condition 084 */ 085 @Override 086 public void begin() throws NotSupportedException, SystemException { 087 if (this.delegate == null) { 088 throw new SystemException("delegate == null"); 089 } 090 this.delegate.begin(); 091 } 092 093 /** 094 * Completes the transaction associated with the current thread. 095 * 096 * <p>When this method completes, the thread is no longer associated 097 * with a transaction.</p> 098 * 099 * @exception RollbackException if the transaction has been rolled 100 * back rather than committed 101 * 102 * @exception HeuristicMixedException if a heuristic decision was 103 * made and that some relevant updates have been committed while 104 * others have been rolled back 105 * 106 * @exception HeuristicRollbackException if a heuristic decision was 107 * made and all relevant updates have been rolled back 108 * 109 * @exception SecurityException if the thread is not allowed to 110 * commit the transaction 111 * 112 * @exception IllegalStateException if the current thread is not 113 * associated with a transaction 114 * 115 * @exception SystemException if this {@link TransactionManager} 116 * encounters an unexpected error condition 117 */ 118 @Override 119 public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException, SystemException { 120 if (this.delegate == null) { 121 throw new SystemException("delegate == null"); 122 } 123 this.delegate.commit(); 124 } 125 126 /** 127 * Returns the status of the transaction associated with the current 128 * thread. 129 * 130 * @return the transaction status expressed as the value of one of 131 * the {@code int} constants in the {@link Status} class; if no 132 * transaction is associated with the current thread, this method 133 * returns {@link Status#STATUS_NO_TRANSACTION} 134 * 135 * @exception SystemException if this {@link TransactionManager} 136 * encounters an unexpected error condition 137 * 138 * @see Status 139 */ 140 @Override 141 public int getStatus() throws SystemException { 142 if (this.delegate == null) { 143 throw new SystemException("delegate == null"); 144 } 145 return this.delegate.getStatus(); 146 } 147 148 /** 149 * Returns the {@link Transaction} object that represents the 150 * transaction context of the calling thread. 151 * 152 * <p>This method never returns {@code null}.</p> 153 * 154 * @return the {@link Transaction} object representing the 155 * transaction associated with the calling thread; never {@code 156 * null} 157 * 158 * @exception SystemException if this {@link TransactionManager} 159 * encounters an unexpected error condition 160 */ 161 @Override 162 public Transaction getTransaction() throws SystemException { 163 if (this.delegate == null) { 164 throw new SystemException("delegate == null"); 165 } 166 return this.delegate.getTransaction(); 167 } 168 169 /** 170 * Resumes the transaction context association of the calling thread 171 * with the transaction represented by the supplied {@link 172 * Transaction} object. 173 * 174 * <p>When this method returns, the calling thread is associated 175 * with the transaction context specified.</p> 176 * 177 * @param transaction the {@link Transaction} representing the 178 * transaction to be resumed; must not be {@code null} 179 * 180 * @exception InvalidTransactionException if {@code transaction} is 181 * invalid 182 * 183 * @exception IllegalStateException if the thread is already 184 * associated with another transaction 185 * 186 * @exception SystemException if this {@link TransactionManager} 187 * encounters an unexpected error condition 188 */ 189 @Override 190 public void resume(final Transaction transaction) throws InvalidTransactionException, SystemException { 191 if (this.delegate == null) { 192 throw new SystemException("delegate == null"); 193 } 194 this.delegate.resume(transaction); 195 } 196 197 /** 198 * Rolls back the transaction associated with the current thread. 199 * 200 * <p>When this method completes, the thread is no longer associated 201 * with a transaction.</p> 202 * 203 * @exception SecurityException if the thread is not allowed to roll 204 * back the transaction 205 * 206 * @exception IllegalStateException if the current thread is not 207 * associated with a transaction 208 * 209 * @exception SystemException if this {@link TransactionManager} 210 * encounters an unexpected error condition 211 */ 212 @Override 213 public void rollback() throws SystemException { 214 if (this.delegate == null) { 215 throw new SystemException("delegate == null"); 216 } 217 this.delegate.rollback(); 218 } 219 220 /** 221 * Irrevocably modifies the transaction associated with the current 222 * thread such that the only possible outcome is for it to 223 * {@linkplain #rollback() roll back}. 224 * 225 * @exception IllegalStateException if the current thread is not 226 * associated with a transaction 227 * 228 * @exception SystemException if this {@link TransactionManager} 229 * encounters an unexpected error condition 230 */ 231 @Override 232 public void setRollbackOnly() throws SystemException { 233 if (this.delegate == null) { 234 throw new SystemException("delegate == null"); 235 } 236 this.delegate.setRollbackOnly(); 237 } 238 239 /** 240 * Sets the timeout value that is associated with transactions 241 * started by the current thread with the {@link #begin()} method. 242 * 243 * <p>If an application has not called this method, the transaction 244 * service uses some default value for the transaction timeout.</p> 245 * 246 * @param seconds the timeout in seconds; if the value is zero, the 247 * transaction service restores the default value; if the value is 248 * negative a {@link SystemException} is thrown 249 * 250 * @exception SystemException if this {@link TransactionManager} 251 * encounters an unexpected error condition or if {@code seconds} is 252 * less than zero 253 */ 254 @Override 255 public void setTransactionTimeout(final int seconds) throws SystemException { 256 if (this.delegate == null) { 257 throw new SystemException("delegate == null"); 258 } 259 this.delegate.setTransactionTimeout(seconds); 260 } 261 262 /** 263 * Suspends the transaction currently associated with the calling 264 * thread and returns a {@link Transaction} that represents the 265 * transaction context being suspended, or {@code null} if the 266 * calling thread is not associated with a transaction. 267 * 268 * <p>This method may return {@code null}.</p> 269 * 270 * <p>When this method returns, the calling thread is no longer 271 * associated with a transaction.</p> 272 * 273 * @return a {@link Transaction} representing the suspended 274 * transaction, or {@code null} 275 * 276 * @exception SystemException if this {@link TransactionManager} 277 * encounters an unexpected error condition 278 */ 279 @Override 280 public Transaction suspend() throws SystemException { 281 if (this.delegate == null) { 282 throw new SystemException("delegate == null"); 283 } 284 return this.delegate.suspend(); 285 } 286 287}