use of org.datanucleus.transaction.NucleusTransactionException in project datanucleus-core by datanucleus.
the class TransactionImpl method commit.
/**
* Method to commit the transaction.
*/
public void commit() {
if (!isActive()) {
throw new TransactionNotActiveException();
}
// the exception and call rollback themselves. i.e we don't need to close the DB connection or set "active" to false.
if (rollbackOnly) {
// Throw an exception since can only exit via rollback
if (NucleusLogger.TRANSACTION.isDebugEnabled()) {
NucleusLogger.TRANSACTION.debug(Localiser.msg("015020"));
}
throw new NucleusDataStoreException(Localiser.msg("015020")).setFatal();
}
long startTime = System.currentTimeMillis();
boolean success = false;
// whether the transaction can be completed
boolean canComplete = true;
List<Throwable> errors = new ArrayList();
try {
// TODO Is this needed? om.preCommit will handle flush calls
flush();
internalPreCommit();
internalCommit();
success = true;
} catch (RollbackException e) {
// in Transaction.Synchronization and they should cascade up to user code
if (NucleusLogger.TRANSACTION.isDebugEnabled()) {
NucleusLogger.TRANSACTION.debug(StringUtils.getStringFromStackTrace(e));
}
errors.add(e);
} catch (HeuristicRollbackException e) {
// in Transaction.Synchronization and they should cascade up to user code
if (NucleusLogger.TRANSACTION.isDebugEnabled()) {
NucleusLogger.TRANSACTION.debug(StringUtils.getStringFromStackTrace(e));
}
errors.add(e);
} catch (HeuristicMixedException e) {
// in Transaction.Synchronization and they should cascade up to user code
if (NucleusLogger.TRANSACTION.isDebugEnabled()) {
NucleusLogger.TRANSACTION.debug(StringUtils.getStringFromStackTrace(e));
}
errors.add(e);
} catch (NucleusUserException e) {
// they must be cascade up to user code and transaction is still alive
if (NucleusLogger.TRANSACTION.isDebugEnabled()) {
NucleusLogger.TRANSACTION.debug(StringUtils.getStringFromStackTrace(e));
}
canComplete = false;
throw e;
} catch (NucleusException e) {
// in Transaction.Synchronization and they should cascade up to user code
if (NucleusLogger.TRANSACTION.isDebugEnabled()) {
NucleusLogger.TRANSACTION.debug(StringUtils.getStringFromStackTrace(e));
}
errors.add(e);
} finally {
if (canComplete) {
try {
if (!success) {
rollback();
} else {
internalPostCommit();
}
} catch (Throwable e) {
errors.add(e);
}
}
}
if (!errors.isEmpty()) {
throw new NucleusTransactionException(Localiser.msg("015007"), errors.toArray(new Throwable[errors.size()]));
}
if (NucleusLogger.TRANSACTION.isDebugEnabled()) {
NucleusLogger.TRANSACTION.debug(Localiser.msg("015022", System.currentTimeMillis() - startTime));
}
}
use of org.datanucleus.transaction.NucleusTransactionException in project datanucleus-core by datanucleus.
the class JTAJCATransactionImpl method joinTransaction.
// ------------------- Methods to get the JTA transaction for synchronising --------------------------
/**
* Synchronise our active state with that of the JTA transaction, if it exists.
* Look for an active JTA transaction. if there is one, begin() ourselves
* and register synchronisation. We must poll because there is no
* way of getting notified of a newly begun transaction.<p>
*/
private synchronized void joinTransaction() {
if (active) {
return;
}
// try to registerSynchronization()
try {
if (jtaTM == null) {
// Retrieve the JTA TransactionManager. Unfortunately, before JavaEE 5 there is no specified way to do it,
// only app-server-specific ways. In JavaEE 5, we can use TransactionSynchronizationRegistry
jtaTM = ec.getNucleusContext().getJtaTransactionManager();
if (jtaTM == null) {
throw new NucleusTransactionException(Localiser.msg("015030"));
}
}
jtaTx = jtaTM.getTransaction();
if (jtaTx != null && jtaTx.getStatus() == Status.STATUS_ACTIVE) {
if (// TODO Aren't we always in JCA mode with this class?
!ec.getNucleusContext().isJcaMode()) {
// in JCA mode, we do not register Synchronization TODO Use JtaSyncRegistry if available?
jtaTx.registerSynchronization(this);
}
// the transaction is active here
begin();
} else {
// If a transaction was marked for rollback before we could register synchronisation, we won't be called back when it is rolled back
if (markedForRollback) {
// as jtaTx is null there is no active transaction, meaning that the jtaTx was actually rolled back after it had been marked for rollback: catch up
rollback();
markedForRollback = false;
}
}
} catch (SystemException se) {
throw new NucleusTransactionException(Localiser.msg("015026"), se);
} catch (RollbackException e) {
NucleusLogger.TRANSACTION.error("Exception while joining transaction: " + StringUtils.getStringFromStackTrace(e));
// tx is marked for rollback: leave registeredSynchronizationOnJtaTx==false so that we try to register again next time we're called
}
}
use of org.datanucleus.transaction.NucleusTransactionException in project datanucleus-core by datanucleus.
the class JTATransactionImpl method joinTransaction.
/**
* Method to call if you want to join to the underlying UserTransaction.
* Will be called by isActive() and constructor if "autoJoin" is set, otherwise has to be called by user code.
*/
public void joinTransaction() {
if (joinStatus != JoinStatus.JOINED) {
try {
javax.transaction.Transaction txn = jtaTM.getTransaction();
if (jtaTx != null && !jtaTx.equals(txn)) {
// it should happen only if joinStatus == JOIN_STATUS_IMPOSSIBLE
if (!(joinStatus == JoinStatus.IMPOSSIBLE)) {
throw new InternalError("JTA Transaction changed without being notified");
}
jtaTx = null;
joinStatus = JoinStatus.NO_TXN;
joinTransaction();
} else {
if (jtaTx == null) {
jtaTx = txn;
boolean allow_join = (jtaTM.getStatus() == Status.STATUS_ACTIVE);
if (allow_join) {
joinStatus = JoinStatus.IMPOSSIBLE;
try {
if (jtaSyncRegistry != null) {
// Register via TransactionSynchronizationRegistry
jtaSyncRegistry.register(this);
} else {
// Register via Transaction
if (jtaTx != null) {
jtaTx.registerSynchronization(this);
}
}
if (!super.isActive()) {
// the transaction is active here
internalBegin();
}
} catch (Exception e) {
throw new NucleusTransactionException("Cannot register Synchronization to a valid JTA Transaction", e);
}
NucleusLogger.TRANSACTION.debug("JTA transaction for ExecutionContext=" + ec + " has JOINED to its UserTransaction");
joinStatus = JoinStatus.JOINED;
} else {
if (jtaTx != null) {
joinStatus = JoinStatus.IMPOSSIBLE;
}
}
}
}
} catch (SystemException e) {
throw new NucleusTransactionException(Localiser.msg("015026"), e);
}
}
}
use of org.datanucleus.transaction.NucleusTransactionException in project datanucleus-core by datanucleus.
the class JTATransactionImpl method begin.
/**
* JDO spec "16.1.3 Stateless Session Bean with Bean Managed Transactions": "acquiring a PM without beginning a UserTransaction results
* in the PM being able to manage transaction boundaries via begin, commit, and rollback methods on JDO Transaction.
* The PM will automatically begin the User-Transaction during Transaction.begin and automatically commit the UserTransaction during Transaction.commit"
*/
public void begin() {
joinTransaction();
if (joinStatus != JoinStatus.NO_TXN) {
throw new NucleusTransactionException("JTA Transaction is already active");
}
UserTransaction utx;
try {
Context ctx = new InitialContext();
if (// TODO If JBoss starts using the JavaEE standard location, we need to remove this alternative location
JBOSS_SERVER) {
// JBoss unfortunately doesn't always provide UserTransaction at the JavaEE standard location, see e.g. http://docs.jboss.org/admin-devel/Chap4.html
try {
utx = (UserTransaction) ctx.lookup("UserTransaction");
} catch (NamingException e) {
// Fallback to standard location
utx = (UserTransaction) ctx.lookup("java:comp/UserTransaction");
}
} else {
utx = (UserTransaction) ctx.lookup("java:comp/UserTransaction");
}
} catch (NamingException e) {
throw ec.getApiAdapter().getUserExceptionForException("Failed to obtain JTA UserTransaction", e);
}
try {
utx.begin();
} catch (NotSupportedException | SystemException e) {
throw ec.getApiAdapter().getUserExceptionForException("Failed to begin JTA UserTransaction", e);
}
joinTransaction();
if (joinStatus != JoinStatus.JOINED) {
throw new NucleusTransactionException("Cannot join an auto started JTA UserTransaction");
}
userTransaction = utx;
}
Aggregations