@Override protected void doRollback(DefaultTransactionStatus status) { JpaTransactionObject txObject = (JpaTransactionObject) status.getTransaction(); if (status.isDebug()) { logger.debug("Rolling back JPA transaction on EntityManager [" + txObject.getEntityManagerHolder().getEntityManager() + "]"); } try { EntityTransaction tx = txObject.getEntityManagerHolder().getEntityManager().getTransaction(); if (tx.isActive()) { tx.rollback(); } } catch (PersistenceException ex) { throw new TransactionSystemException("Could not roll back JPA transaction", ex); } finally { if (!txObject.isNewEntityManagerHolder()) { // Clear all pending inserts/updates/deletes in the EntityManager. // Necessary for pre-bound EntityManagers, to avoid inconsistent state. txObject.getEntityManagerHolder().getEntityManager().clear(); } } }
@Override protected void doRollback(DefaultTransactionStatus status) { JdoTransactionObject txObject = (JdoTransactionObject) status.getTransaction(); if (status.isDebug()) { logger.debug("Rolling back JDO transaction on PersistenceManager [" + txObject.getPersistenceManagerHolder().getPersistenceManager() + "]"); } try { Transaction tx = txObject.getPersistenceManagerHolder().getPersistenceManager().currentTransaction(); if (tx.isActive()) { tx.rollback(); } } catch (JDOException ex) { throw new TransactionSystemException("Could not roll back JDO transaction", ex); } }
@Test public void testTransactionWithExceptionOnCommit() throws Exception { willThrow(new SQLException("Cannot commit")).given(con).commit(); TransactionTemplate tt = new TransactionTemplate(tm); try { tt.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus status) { // something transactional } }); fail("Should have thrown TransactionSystemException"); } catch (TransactionSystemException ex) { // expected } assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); verify(con).close(); }
@Test public void testTransactionWithExceptionOnCommitAndRollbackOnCommitFailure() throws Exception { willThrow(new SQLException("Cannot commit")).given(con).commit(); tm.setRollbackOnCommitFailure(true); TransactionTemplate tt = new TransactionTemplate(tm); try { tt.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus status) { // something transactional } }); fail("Should have thrown TransactionSystemException"); } catch (TransactionSystemException ex) { // expected } assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); verify(con).rollback(); verify(con).close(); }
@Test public void testTransactionWithExceptionOnRollback() throws Exception { given(con.getAutoCommit()).willReturn(true); willThrow(new SQLException("Cannot rollback")).given(con).rollback(); TransactionTemplate tt = new TransactionTemplate(tm); try { tt.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException { status.setRollbackOnly(); } }); fail("Should have thrown TransactionSystemException"); } catch (TransactionSystemException ex) { // expected } assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); InOrder ordered = inOrder(con); ordered.verify(con).setAutoCommit(false); ordered.verify(con).rollback(); ordered.verify(con).setAutoCommit(true); verify(con).close(); }
@Override protected void doCommit(DefaultTransactionStatus status) { DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction(); Connection con = txObject.getConnectionHolder().getConnection(); if (status.isDebug()) { logger.debug("Committing JDBC transaction on Connection [" + con + "]"); } try { con.commit(); } catch (SQLException ex) { throw new TransactionSystemException("Could not commit JDBC transaction", ex); } /**modify by guosg 这里提交ldtm事务*/ SynchronizationManager.getCurrentUserTransation().commit(); }
@Override protected void doRollback(DefaultTransactionStatus status) { DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction(); Connection con = txObject.getConnectionHolder().getConnection(); if (status.isDebug()) { logger.debug("Rolling back JDBC transaction on Connection [" + con + "]"); } try { con.rollback(); } catch (SQLException ex) { throw new TransactionSystemException("Could not roll back JDBC transaction", ex); } /**modify by guosg 这里提交回滚事务*/ SynchronizationManager.getCurrentUserTransation().rollback(); }
/** * Look up the JTA 1.1 TransactionSynchronizationRegistry in JNDI via the configured name. * <p>Can be overridden in subclasses to provide a different TransactionManager object. * @param registryName the JNDI name of the * TransactionSynchronizationRegistry * @return the TransactionSynchronizationRegistry object * @throws TransactionSystemException if the JNDI lookup failed * @see #setJndiTemplate * @see #setTransactionSynchronizationRegistryName */ protected Object lookupTransactionSynchronizationRegistry(String registryName) throws TransactionSystemException { if (transactionSynchronizationRegistryClass == null) { throw new TransactionSystemException( "JTA 1.1 [" + TRANSACTION_SYNCHRONIZATION_REGISTRY_CLASS_NAME + "] API not available"); } try { if (logger.isDebugEnabled()) { logger.debug("Retrieving JTA TransactionSynchronizationRegistry from JNDI location [" + registryName + "]"); } return getJndiTemplate().lookup(registryName, transactionSynchronizationRegistryClass); } catch (NamingException ex) { throw new TransactionSystemException( "JTA TransactionSynchronizationRegistry is not available at JNDI location [" + registryName + "]", ex); } }
/** * Define how message exchanges are processed. * * @param exchange the InOut message exchange * @throws FcrepoOperationFailedException when the underlying HTTP request results in an error */ @Override public void process(final Exchange exchange) throws FcrepoOperationFailedException { if (exchange.isTransacted()) { transactionTemplate.execute(new TransactionCallbackWithoutResult() { protected void doInTransactionWithoutResult(final TransactionStatus status) { final DefaultTransactionStatus st = (DefaultTransactionStatus)status; final FcrepoTransactionObject tx = (FcrepoTransactionObject)st.getTransaction(); try { doRequest(exchange, tx.getSessionId()); } catch (FcrepoOperationFailedException ex) { throw new TransactionSystemException( "Error executing fcrepo request in transaction: ", ex); } } }); } else { doRequest(exchange, null); } }
@Override protected void doCommit(final DefaultTransactionStatus status) { final FcrepoTransactionObject tx = (FcrepoTransactionObject)status.getTransaction(); final InputStream is = null; final String contentType = null; try { getClient().post(URI.create(baseUrl + "/" + tx.getSessionId() + COMMIT)) .body(is, contentType).perform(); } catch (final FcrepoOperationFailedException ex) { LOGGER.debug("Transaction commit failed: ", ex); throw new TransactionSystemException("Could not commit fcrepo transaction"); } finally { tx.setSessionId(null); } }
@Override protected void doCommit(DefaultTransactionStatus status) { JcrTransactionObject txObject = (JcrTransactionObject) status .getTransaction(); if (status.isDebug()) { LOG.debug("Committing JCR transaction on session [" + txObject.getSessionHolder().getSession() + "]"); } try { txObject.getSessionHolder().getTransaction().commit(); } catch (Exception ex) { // assumably from commit call to the underlying JCR repository throw new TransactionSystemException( "Could not commit JCR transaction", ex); } }
@Override protected void doRollback(DefaultTransactionStatus status) { JcrTransactionObject txObject = (JcrTransactionObject) status .getTransaction(); if (status.isDebug()) { LOG.debug("Rolling back JCR transaction on session [" + txObject.getSessionHolder().getSession() + "]"); } try { txObject.getSessionHolder().getTransaction().rollback(); } catch (Exception ex) { throw new TransactionSystemException( "Could not roll back JCR transaction", ex); } finally { if (!txObject.isNewSessionHolder()) { // Clear all pending inserts/updates/deletes in the Session. // Necessary for pre-bound Sessions, to avoid inconsistent // state. try { txObject.getSessionHolder().getSession().refresh(false); } catch (RepositoryException e) { // we already throw an exception (hold back this one). } } } }
private void loadWebLogicTransactionClasses() throws TransactionSystemException { try { Class<?> userTransactionClass = getClass().getClassLoader().loadClass(USER_TRANSACTION_CLASS_NAME); this.weblogicUserTransactionAvailable = userTransactionClass.isInstance(getUserTransaction()); if (this.weblogicUserTransactionAvailable) { this.beginWithNameMethod = userTransactionClass.getMethod("begin", String.class); this.beginWithNameAndTimeoutMethod = userTransactionClass.getMethod("begin", String.class, int.class); logger.info("Support for WebLogic transaction names available"); } else { logger.info("Support for WebLogic transaction names not available"); } // Obtain WebLogic ClientTransactionManager interface. Class<?> transactionManagerClass = getClass().getClassLoader().loadClass(CLIENT_TRANSACTION_MANAGER_CLASS_NAME); logger.debug("WebLogic ClientTransactionManager found"); this.weblogicTransactionManagerAvailable = transactionManagerClass.isInstance(getTransactionManager()); if (this.weblogicTransactionManagerAvailable) { Class<?> transactionClass = getClass().getClassLoader().loadClass(TRANSACTION_CLASS_NAME); this.forceResumeMethod = transactionManagerClass.getMethod("forceResume", Transaction.class); this.setPropertyMethod = transactionClass.getMethod("setProperty", String.class, Serializable.class); logger.debug("Support for WebLogic forceResume available"); } else { logger.warn("Support for WebLogic forceResume not available"); } } catch (Exception ex) { throw new TransactionSystemException( "Could not initialize WebLogicJtaTransactionManager because WebLogic API classes are not available", ex); } }
/** * Initialize the UserTransaction as well as the TransactionManager handle. * @see #initUserTransactionAndTransactionManager() */ @Override public void afterPropertiesSet() throws TransactionSystemException { initUserTransactionAndTransactionManager(); checkUserTransactionAndTransactionManager(); initTransactionSynchronizationRegistry(); }
/** * Initialize the UserTransaction as well as the TransactionManager handle. * @throws TransactionSystemException if initialization failed */ protected void initUserTransactionAndTransactionManager() throws TransactionSystemException { if (this.userTransaction == null) { // Fetch JTA UserTransaction from JNDI, if necessary. if (StringUtils.hasLength(this.userTransactionName)) { this.userTransaction = lookupUserTransaction(this.userTransactionName); this.userTransactionObtainedFromJndi = true; } else { this.userTransaction = retrieveUserTransaction(); if (this.userTransaction == null && this.autodetectUserTransaction) { // Autodetect UserTransaction at its default JNDI location. this.userTransaction = findUserTransaction(); } } } if (this.transactionManager == null) { // Fetch JTA TransactionManager from JNDI, if necessary. if (StringUtils.hasLength(this.transactionManagerName)) { this.transactionManager = lookupTransactionManager(this.transactionManagerName); } else { this.transactionManager = retrieveTransactionManager(); if (this.transactionManager == null && this.autodetectTransactionManager) { // Autodetect UserTransaction object that implements TransactionManager, // and check fallback JNDI locations otherwise. this.transactionManager = findTransactionManager(this.userTransaction); } } } // If only JTA TransactionManager specified, create UserTransaction handle for it. if (this.userTransaction == null && this.transactionManager != null) { this.userTransaction = buildUserTransaction(this.transactionManager); } }
/** * Look up the JTA UserTransaction in JNDI via the configured name. * <p>Called by {@code afterPropertiesSet} if no direct UserTransaction reference was set. * Can be overridden in subclasses to provide a different UserTransaction object. * @param userTransactionName the JNDI name of the UserTransaction * @return the UserTransaction object * @throws TransactionSystemException if the JNDI lookup failed * @see #setJndiTemplate * @see #setUserTransactionName */ protected UserTransaction lookupUserTransaction(String userTransactionName) throws TransactionSystemException { try { if (logger.isDebugEnabled()) { logger.debug("Retrieving JTA UserTransaction from JNDI location [" + userTransactionName + "]"); } return getJndiTemplate().lookup(userTransactionName, UserTransaction.class); } catch (NamingException ex) { throw new TransactionSystemException( "JTA UserTransaction is not available at JNDI location [" + userTransactionName + "]", ex); } }
/** * Look up the JTA TransactionManager in JNDI via the configured name. * <p>Called by {@code afterPropertiesSet} if no direct TransactionManager reference was set. * Can be overridden in subclasses to provide a different TransactionManager object. * @param transactionManagerName the JNDI name of the TransactionManager * @return the UserTransaction object * @throws TransactionSystemException if the JNDI lookup failed * @see #setJndiTemplate * @see #setTransactionManagerName */ protected TransactionManager lookupTransactionManager(String transactionManagerName) throws TransactionSystemException { try { if (logger.isDebugEnabled()) { logger.debug("Retrieving JTA TransactionManager from JNDI location [" + transactionManagerName + "]"); } return getJndiTemplate().lookup(transactionManagerName, TransactionManager.class); } catch (NamingException ex) { throw new TransactionSystemException( "JTA TransactionManager is not available at JNDI location [" + transactionManagerName + "]", ex); } }
/** * Look up the JTA 1.1 TransactionSynchronizationRegistry in JNDI via the configured name. * <p>Can be overridden in subclasses to provide a different TransactionManager object. * @param registryName the JNDI name of the * TransactionSynchronizationRegistry * @return the TransactionSynchronizationRegistry object * @throws TransactionSystemException if the JNDI lookup failed * @see #setJndiTemplate * @see #setTransactionSynchronizationRegistryName */ protected TransactionSynchronizationRegistry lookupTransactionSynchronizationRegistry(String registryName) throws TransactionSystemException { try { if (logger.isDebugEnabled()) { logger.debug("Retrieving JTA TransactionSynchronizationRegistry from JNDI location [" + registryName + "]"); } return getJndiTemplate().lookup(registryName, TransactionSynchronizationRegistry.class); } catch (NamingException ex) { throw new TransactionSystemException( "JTA TransactionSynchronizationRegistry is not available at JNDI location [" + registryName + "]", ex); } }
/** * Find the JTA 1.1 TransactionSynchronizationRegistry through autodetection: * checking whether the UserTransaction object or TransactionManager object * implements it, and checking Java EE 5's standard JNDI location. * <p>The default implementation simply returns {@code null}. * @param ut the JTA UserTransaction object * @param tm the JTA TransactionManager object * @return the JTA TransactionSynchronizationRegistry handle to use, * or {@code null} if none found * @throws TransactionSystemException in case of errors */ protected TransactionSynchronizationRegistry findTransactionSynchronizationRegistry(UserTransaction ut, TransactionManager tm) throws TransactionSystemException { if (this.userTransactionObtainedFromJndi) { // UserTransaction has already been obtained from JNDI, so the // TransactionSynchronizationRegistry probably sits there as well. String jndiName = DEFAULT_TRANSACTION_SYNCHRONIZATION_REGISTRY_NAME; try { TransactionSynchronizationRegistry tsr = getJndiTemplate().lookup(jndiName, TransactionSynchronizationRegistry.class); if (logger.isDebugEnabled()) { logger.debug("JTA TransactionSynchronizationRegistry found at default JNDI location [" + jndiName + "]"); } return tsr; } catch (NamingException ex) { if (logger.isDebugEnabled()) { logger.debug( "No JTA TransactionSynchronizationRegistry found at default JNDI location [" + jndiName + "]", ex); } } } // Check whether the UserTransaction or TransactionManager implements it... if (ut instanceof TransactionSynchronizationRegistry) { return (TransactionSynchronizationRegistry) ut; } if (tm instanceof TransactionSynchronizationRegistry) { return (TransactionSynchronizationRegistry) tm; } // OK, so no JTA 1.1 TransactionSynchronizationRegistry is available... return null; }
@Override protected boolean isExistingTransaction(Object transaction) { JtaTransactionObject txObject = (JtaTransactionObject) transaction; try { return (txObject.getUserTransaction().getStatus() != Status.STATUS_NO_TRANSACTION); } catch (SystemException ex) { throw new TransactionSystemException("JTA failure on getStatus", ex); } }
@Override protected Object doSuspend(Object transaction) { JtaTransactionObject txObject = (JtaTransactionObject) transaction; try { return doJtaSuspend(txObject); } catch (SystemException ex) { throw new TransactionSystemException("JTA failure on suspend", ex); } }
/** * This implementation checks the UserTransaction's rollback-only flag. */ @Override public boolean isRollbackOnly() { if (this.userTransaction == null) { return false; } try { int jtaStatus = this.userTransaction.getStatus(); return (jtaStatus == Status.STATUS_MARKED_ROLLBACK || jtaStatus == Status.STATUS_ROLLEDBACK); } catch (SystemException ex) { throw new TransactionSystemException("JTA failure on getStatus", ex); } }
@Override public void afterPropertiesSet() throws TransactionSystemException { initUserTransactionAndTransactionManager(); // Fetch UOWManager handle from JNDI, if necessary. if (this.uowManager == null) { if (this.uowManagerName != null) { this.uowManager = lookupUowManager(this.uowManagerName); } else { this.uowManager = lookupDefaultUowManager(); } } }
/** * Look up the WebSphere UOWManager in JNDI via the configured name. * @param uowManagerName the JNDI name of the UOWManager * @return the UOWManager object * @throws TransactionSystemException if the JNDI lookup failed * @see #setJndiTemplate * @see #setUowManagerName */ protected UOWManager lookupUowManager(String uowManagerName) throws TransactionSystemException { try { if (logger.isDebugEnabled()) { logger.debug("Retrieving WebSphere UOWManager from JNDI location [" + uowManagerName + "]"); } return getJndiTemplate().lookup(uowManagerName, UOWManager.class); } catch (NamingException ex) { throw new TransactionSystemException( "WebSphere UOWManager is not available at JNDI location [" + uowManagerName + "]", ex); } }
/** * Obtain the WebSphere UOWManager from the default JNDI location * "java:comp/websphere/UOWManager". * @return the UOWManager object * @throws TransactionSystemException if the JNDI lookup failed * @see #setJndiTemplate */ protected UOWManager lookupDefaultUowManager() throws TransactionSystemException { try { logger.debug("Retrieving WebSphere UOWManager from default JNDI location [" + DEFAULT_UOW_MANAGER_NAME + "]"); return getJndiTemplate().lookup(DEFAULT_UOW_MANAGER_NAME, UOWManager.class); } catch (NamingException ex) { logger.debug("WebSphere UOWManager is not available at default JNDI location [" + DEFAULT_UOW_MANAGER_NAME + "] - falling back to UOWManagerFactory lookup"); return UOWManagerFactory.getUOWManager(); } }
@Override protected void doCommit(DefaultTransactionStatus status) { DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction(); Connection con = txObject.getConnectionHolder().getConnection(); if (status.isDebug()) { logger.debug("Committing JDBC transaction on Connection [" + con + "]"); } try { con.commit(); } catch (SQLException ex) { throw new TransactionSystemException("Could not commit JDBC transaction", ex); } }
@Override protected void doRollback(DefaultTransactionStatus status) { DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction(); Connection con = txObject.getConnectionHolder().getConnection(); if (status.isDebug()) { logger.debug("Rolling back JDBC transaction on Connection [" + con + "]"); } try { con.rollback(); } catch (SQLException ex) { throw new TransactionSystemException("Could not roll back JDBC transaction", ex); } }
/** * This implementation rolls back to the given JDBC 3.0 Savepoint. * @see java.sql.Connection#rollback(java.sql.Savepoint) */ @Override public void rollbackToSavepoint(Object savepoint) throws TransactionException { try { getConnectionHolderForSavepoint().getConnection().rollback((Savepoint) savepoint); } catch (Throwable ex) { throw new TransactionSystemException("Could not roll back to JDBC savepoint", ex); } }
/** * Register a transaction synchronization for closing the given LobCreator, * preferring Spring transaction synchronization and falling back to * plain JTA transaction synchronization. * @param lobCreator the LobCreator to close after transaction completion * @param jtaTransactionManager the JTA TransactionManager to fall back to * when no Spring transaction synchronization is active (may be {@code null}) * @throws IllegalStateException if there is neither active Spring transaction * synchronization nor active JTA transaction synchronization */ public static void registerTransactionSynchronization( LobCreator lobCreator, TransactionManager jtaTransactionManager) throws IllegalStateException { if (TransactionSynchronizationManager.isSynchronizationActive()) { logger.debug("Registering Spring transaction synchronization for LobCreator"); TransactionSynchronizationManager.registerSynchronization( new SpringLobCreatorSynchronization(lobCreator)); } else { if (jtaTransactionManager != null) { try { int jtaStatus = jtaTransactionManager.getStatus(); if (jtaStatus == Status.STATUS_ACTIVE || jtaStatus == Status.STATUS_MARKED_ROLLBACK) { logger.debug("Registering JTA transaction synchronization for LobCreator"); jtaTransactionManager.getTransaction().registerSynchronization( new JtaLobCreatorSynchronization(lobCreator)); return; } } catch (Throwable ex) { throw new TransactionSystemException( "Could not register synchronization with JTA TransactionManager", ex); } } throw new IllegalStateException("Active Spring transaction synchronization or active " + "JTA transaction with specified [javax.transaction.TransactionManager] required"); } }
@Override public Object createSavepoint() throws TransactionException { try { return transaction.getConnection().setSavepoint(); } catch (SQLException e) { throw new TransactionSystemException(e.getMessage(), e); } }
@Override public void rollbackToSavepoint(Object savepoint) throws TransactionException { try { transaction.getConnection().rollback((Savepoint) savepoint); } catch (SQLException e) { throw new TransactionSystemException(e.getMessage(), e); } }
@Override public void releaseSavepoint(Object savepoint) throws TransactionException { try { transaction.getConnection().releaseSavepoint((Savepoint) savepoint); } catch (SQLException e) { throw new TransactionSystemException(e.getMessage(), e); } }
@Override public Response toResponse(final TransactionSystemException ex) { if (ExceptionUtils.getRootCause(ex) instanceof ConstraintViolationException) { // Set the content type, and JSR-303 error into JSON format. return toResponse(Status.BAD_REQUEST, new ValidationJsonException((ConstraintViolationException) ExceptionUtils.getRootCause(ex))); } // Not yet managed exception log.error("Technical exception", ex); return toResponse(Status.INTERNAL_SERVER_ERROR, "technical", ex); }