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}