Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.arjuna.ats.jta.cdi.NarayanaTransactionManager Maven / Gradle / Ivy
/*
Copyright The Narayana Authors
SPDX short identifier: Apache-2.0
*/
package com.arjuna.ats.jta.cdi;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.util.function.Supplier;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.context.BeforeDestroyed;
import jakarta.enterprise.context.Destroyed;
import jakarta.enterprise.context.Initialized;
import jakarta.enterprise.event.Event;
import jakarta.enterprise.inject.CreationException;
import jakarta.enterprise.inject.Instance;
import jakarta.enterprise.inject.spi.CDI;
import jakarta.inject.Inject;
import javax.naming.NamingException;
import jakarta.transaction.HeuristicMixedException;
import jakarta.transaction.HeuristicRollbackException;
import jakarta.transaction.NotSupportedException;
import jakarta.transaction.RollbackException;
import jakarta.transaction.SystemException;
import jakarta.transaction.Transaction;
import jakarta.transaction.TransactionManager;
import jakarta.transaction.TransactionScoped;
import com.arjuna.ats.jta.common.JTAEnvironmentBean;
import com.arjuna.common.internal.util.propertyservice.BeanPopulator;
/**
* A {@link DelegatingTransactionManager} in {@linkplain ApplicationScoped application scope}
* that uses the return value that results from invoking the
* {@link com.arjuna.ats.jta.TransactionManager#transactionManager()} method
* as its backing implementation.
*
* @author Laird Nelson
*
* @see com.arjuna.ats.jta.TransactionManager#transactionManager()
*/
@ApplicationScoped
class NarayanaTransactionManager extends DelegatingTransactionManager {
/**
* The version of this class for {@linkplain Serializable serialization} purposes.
*/
private static final long serialVersionUID = 596L; // 596 ~= 5.9.9.Final-SNAPSHOT
/**
* An {@link Event} that can {@linkplain Event#fire(Object) fire}
* {@link Transaction}s when the {@linkplain TransactionScoped transaction scope} is initialized.
*
* @see #NarayanaTransactionManager(Instance, Event, Event, Event)
*/
private final Event transactionScopeInitializedBroadcaster;
/**
* An {@link Event} that can {@linkplain Event#fire(Object) fire}
* {@link Object}s when the {@linkplain TransactionScoped transaction scope} is destroyed.
*
* @see #NarayanaTransactionManager(Instance, Event, Event, Event)
*/
private final Event transactionScopeDestroyedBroadcaster;
/**
* An {@link Event} that can {@linkplain Event#fire(Object) fire}
* {@link Object}s when the {@linkplain TransactionScoped transaction scope} is before to be destroyed.
*
* @see #NarayanaTransactionManager(Instance, Event, Event, Event)
*/
private final Event transactionScopeBeforeDestroyedBroadcaster;
/**
* Creates a new, possibly non-functional {@link
* NarayanaTransactionManager}.
*
* This constructor exists only to conform with section
* 3.15 of the CDI specification .
*
* @deprecated This constructor exists only to conform with section
* 3.15 of the CDI specification . Please use the {@link
* #NarayanaTransactionManager(Instance, Event, Event, Event)} constructor
* instead.
*
* @see #NarayanaTransactionManager(Instance, Event, Event, Event)
*/
@Deprecated
NarayanaTransactionManager() {
this((Supplier)null, null, null, null);
}
/**
* Creates a new {@link NarayanaTransactionManager}.
*
* @param jtaEnvironmentBeanInstance an {@link Instance} providing
* access to a {@link JTAEnvironmentBean} used to help with delegate
* computation; may be {@code null} in which case all method
* invocations will throw {@link IllegalStateException}s
*
* @param transactionScopeInitializedBroadcaster an {@link Event}
* for broadcasting the {@linkplain Initialized initialization} of
* the {@linkplain TransactionScoped transaction scope}; may be {@code null}
*
* @param transactionScopeDestroyedBroadcaster an {@link Event} for
* broadcasting the {@linkplain Destroyed destruction} of the
* {@link TransactionScoped transaction scope}; may be {@code null}
*
* @param transactionScopeBeforeDestroyedBroadcaster an {@link Event} for
* broadcasting the {@linkplain BeforeDestroyed before destruction} of the
* {@link TransactionScoped transaction scope}; may be {@code null}
*
* @see JTAEnvironmentBean#getTransactionManager()
*
* @see #begin()
*
* @see #commit()
*
* @see #rollback()
*
* @see TransactionScoped
*/
@Inject
NarayanaTransactionManager(final Instance jtaEnvironmentBeanInstance,
@Initialized(TransactionScoped.class)
final Event transactionScopeInitializedBroadcaster,
@Destroyed(TransactionScoped.class)
final Event transactionScopeDestroyedBroadcaster,
@BeforeDestroyed(TransactionScoped.class)
final Event transactionScopeBeforeDestroyedBroadcaster) {
this(jtaEnvironmentBeanInstance == null ? (Supplier extends JTAEnvironmentBean>)null : jtaEnvironmentBeanInstance.isUnsatisfied() ? () -> BeanPopulator.getDefaultInstance(JTAEnvironmentBean.class) : jtaEnvironmentBeanInstance::get,
transactionScopeInitializedBroadcaster,
transactionScopeDestroyedBroadcaster,
transactionScopeBeforeDestroyedBroadcaster);
}
/**
* Creates a new {@link NarayanaTransactionManager}.
*
* @param jtaEnvironmentBeanSupplier a {@link Supplier} providing
* access to a {@link JTAEnvironmentBean} used to help with delegate
* computation; may be {@code null} in which case all method
* invocations will throw {@link IllegalStateException}s; may be
* {@linkplain Instance#isUnsatisfied() unsatisfied} in which case
* the return value of an invocation of {@link
* BeanPopulator#getDefaultInstance(Class)} will be supplied instead
*
* @param transactionScopeInitializedBroadcaster an {@link Event}
* for broadcasting the {@linkplain Initialized initialization} of
* the {@linkplain TransactionScoped transaction scope}; may be
* {@code null}
*
* @param transactionScopeDestroyedBroadcaster an {@link Event} for
* broadcasting the {@linkplain Destroyed destruction} of the {@link
* TransactionScoped transaction scope}; may be {@code null}
*/
private NarayanaTransactionManager(final Supplier extends JTAEnvironmentBean> jtaEnvironmentBeanSupplier,
final Event transactionScopeInitializedBroadcaster,
final Event transactionScopeDestroyedBroadcaster,
final Event transactionScopeBeforeDestroyedBroadcaster) {
super(getDelegate(jtaEnvironmentBeanSupplier));
this.transactionScopeInitializedBroadcaster = transactionScopeInitializedBroadcaster;
this.transactionScopeDestroyedBroadcaster = transactionScopeDestroyedBroadcaster;
this.transactionScopeBeforeDestroyedBroadcaster = transactionScopeBeforeDestroyedBroadcaster;
}
/**
* Returns an appropriately initialized {@link
* NarayanaTransactionManager} when invoked as part of the Java
* serialization mechanism.
*
* @return a non-{@code null} {@link NarayanaTransactionManager}
*
* @exception ObjectStreamException if a serialization error occurs
*
* @see #NarayanaTransactionManager(Instance, Event, Event, Event)
*
* @see Section
* 3.7 of the Java Serialization Specification
*/
private Object readResolve() throws ObjectStreamException {
// Note that this readResolve() method must NOT be declared final,
// though normally this would be permitted, or certain
// interceptor-based tests fail in Wildfly.
Supplier extends JTAEnvironmentBean> supplier = null;
try {
final Instance instance = CDI.current().select(JTAEnvironmentBean.class);
if (instance != null && !instance.isUnsatisfied()) {
supplier = instance::get;
}
} catch (final IllegalStateException cdiCurrentFailed) {
}
if (supplier == null) {
supplier = () -> BeanPopulator.getDefaultInstance(JTAEnvironmentBean.class);
}
return new NarayanaTransactionManager(supplier,
this.transactionScopeInitializedBroadcaster,
this.transactionScopeDestroyedBroadcaster,
this.transactionScopeBeforeDestroyedBroadcaster);
}
/**
* Returns a {@link TransactionManager} to use as a delegate {@link TransactionManager}
* for a {@link NarayanaTransactionManager} instance.
*
* This method may return {@code null}.
*
* @param jtaEnvironmentBeanSupplier a {@link Supplier} capable of
* supplying a {@link JTAEnvironmentBean}; may be {@code null}
*
* @return a {@link TransactionManager}, or {@code null}
*
* @exception CreationException if an error occurs
*
* @see JTASupplier#get(String, Supplier)
*/
private static TransactionManager getDelegate(final Supplier extends JTAEnvironmentBean> jtaEnvironmentBeanSupplier) {
final TransactionManager returnValue;
if (jtaEnvironmentBeanSupplier == null) {
returnValue = null;
} else {
final JTAEnvironmentBean jtaEnvironmentBean = jtaEnvironmentBeanSupplier.get();
if (jtaEnvironmentBean == null) {
returnValue = null;
} else {
TransactionManager temp = null;
try {
temp = JTASupplier.get(jtaEnvironmentBean.getTransactionManagerJNDIContext(),
jtaEnvironmentBean::getTransactionManager);
} catch (final NamingException namingException) {
throw new CreationException(namingException.getMessage(), namingException);
} finally {
returnValue = temp;
}
}
}
return returnValue;
}
/**
* Overrides {@link DelegatingTransactionManager#begin()} to
* additionally {@linkplain Event#fire(Object) fire} an {@link Object} representing
* the {@linkplain Initialized initialization} of the {@linkplain TransactionScoped transaction scope}.
*
* @exception NotSupportedException if the thread is already
* associated with a transaction and this {@link TransactionManager}
* implementation does not support nested transactions
*
* @exception SystemException if this {@link TransactionManager}
* encounters an unexpected error condition
*
* @see DelegatingTransactionManager#begin()
*
* @see Event#fire(Object)
*
* @see Initialized
*
* @see TransactionScoped
*/
@Override
public void begin() throws NotSupportedException, SystemException {
super.begin();
if (this.transactionScopeInitializedBroadcaster != null) {
this.transactionScopeInitializedBroadcaster.fire(this.getTransaction());
}
}
/**
* Overrides {@link DelegatingTransactionManager#commit()} to
* additionally {@linkplain Event#fire(Object) fire} an {@link Object} representing
* the {@linkplain Destroyed destruction} of the {@linkplain TransactionScoped transaction scope}.
*
* @exception RollbackException if the transaction has been rolled
* back rather than committed
*
* @exception HeuristicMixedException if a heuristic decision was
* made and that some relevant updates have been committed while
* others have been rolled back
*
* @exception HeuristicRollbackException if a heuristic decision was
* made and all relevant updates have been rolled back
*
* @exception SecurityException if the thread is not allowed to
* commit the transaction
*
* @exception IllegalStateException if the current thread is not
* associated with a transaction
*
* @exception SystemException if this {@link TransactionManager}
* encounters an unexpected error condition
*
* @see DelegatingTransactionManager#commit()
*
* @see Event#fire(Object)
*
* @see Destroyed
*
* @see TransactionScoped
*/
@Override
public void commit() throws HeuristicMixedException, HeuristicRollbackException, RollbackException, SystemException {
if (this.transactionScopeBeforeDestroyedBroadcaster != null) {
this.transactionScopeBeforeDestroyedBroadcaster.fire(this.getTransaction());
}
try {
super.commit();
} finally {
if (this.transactionScopeDestroyedBroadcaster != null) {
this.transactionScopeDestroyedBroadcaster.fire(this.toString());
}
}
}
/**
* Overrides {@link DelegatingTransactionManager#rollback()} to
* additionally {@linkplain Event#fire(Object) fire} an {@link Object} representing
* the {@linkplain Destroyed destruction} of the {@linkplain TransactionScoped transaction scope}.
*
* @exception SecurityException if the thread is not allowed to roll
* back the transaction
*
* @exception IllegalStateException if the current thread is not
* associated with a transaction
*
* @exception SystemException if this {@link TransactionManager}
* encounters an unexpected error condition
*
* @see DelegatingTransactionManager#rollback()
*
* @see Event#fire(Object)
*
* @see Destroyed
*
* @see TransactionScoped
*/
@Override
public void rollback() throws SystemException {
if (this.transactionScopeBeforeDestroyedBroadcaster != null) {
this.transactionScopeBeforeDestroyedBroadcaster.fire(this.getTransaction());
}
try {
super.rollback();
} finally {
if (this.transactionScopeDestroyedBroadcaster != null) {
this.transactionScopeDestroyedBroadcaster.fire(this.toString());
}
}
}
}