jtatransactionmanager.java

来自「spring framework 2.5.4源代码」· Java 代码 · 共 1,215 行 · 第 1/4 页

JAVA
1,215
字号
		try {
			if (logger.isDebugEnabled()) {
				logger.debug("Retrieving JTA TransactionSynchronizationRegistry from JNDI location [" + registryName + "]");
			}
			Class registryClass = ClassUtils.forName(TRANSACTION_SYNCHRONIZATION_REGISTRY_CLASS_NAME,
					JtaTransactionManager.class.getClassLoader());
			return getJndiTemplate().lookup(registryName, registryClass);
		}
		catch (ClassNotFoundException ex) {
			throw new TransactionSystemException(
					"JTA 1.1 [" + TRANSACTION_SYNCHRONIZATION_REGISTRY_CLASS_NAME + "] not available");
		}
		catch (NamingException ex) {
			throw new TransactionSystemException(
					"JTA TransactionSynchronizationRegistry is not available at JNDI location [" + registryName + "]", ex);
		}
	}

	/**
	 * Allows subclasses to retrieve the JTA UserTransaction in a vendor-specific manner.
	 * Only called if no "userTransaction" or "userTransactionName" specified.
	 * <p>The default implementation simply returns <code>null</code>.
	 * @return the JTA UserTransaction handle to use, or <code>null</code> if none found
	 * @throws TransactionSystemException in case of errors
	 * @see #setUserTransaction
	 * @see #setUserTransactionName
	 */
	protected UserTransaction retrieveUserTransaction() throws TransactionSystemException {
		return null;
	}

	/**
	 * Allows subclasses to retrieve the JTA TransactionManager in a vendor-specific manner.
	 * Only called if no "transactionManager" or "transactionManagerName" specified.
	 * <p>The default implementation simply returns <code>null</code>.
	 * @return the JTA TransactionManager handle to use, or <code>null</code> if none found
	 * @throws TransactionSystemException in case of errors
	 * @see #setTransactionManager
	 * @see #setTransactionManagerName
	 */
	protected TransactionManager retrieveTransactionManager() throws TransactionSystemException {
		return null;
	}

	/**
	 * Allows subclasses to retrieve the JTA 1.1 TransactionSynchronizationRegistry
	 * in a vendor-specific manner.
	 * <p>The default implementation simply returns <code>null</code>.
	 * @return the JTA TransactionSynchronizationRegistry handle to use,
	 * or <code>null</code> if none found
	 * @throws TransactionSystemException in case of errors
	 */
	protected Object retrieveTransactionSynchronizationRegistry() throws TransactionSystemException {
		return null;
	}

	/**
	 * Find the JTA UserTransaction through a default JNDI lookup:
	 * "java:comp/UserTransaction".
	 * @return the JTA UserTransaction reference, or <code>null</code> if not found
	 * @see #DEFAULT_USER_TRANSACTION_NAME
	 */
	protected UserTransaction findUserTransaction() {
		String jndiName = DEFAULT_USER_TRANSACTION_NAME;
		try {
			UserTransaction ut = (UserTransaction) getJndiTemplate().lookup(jndiName, UserTransaction.class);
			if (logger.isDebugEnabled()) {
				logger.debug("JTA UserTransaction found at default JNDI location [" + jndiName + "]");
			}
			this.userTransactionObtainedFromJndi = true;
			return ut;
		}
		catch (NamingException ex) {
			if (logger.isDebugEnabled()) {
				logger.debug("No JTA UserTransaction found at default JNDI location [" + jndiName + "]", ex);
			}
			return null;
		}
	}

	/**
	 * Find the JTA TransactionManager through autodetection: checking whether the
	 * UserTransaction object implements the TransactionManager, and checking the
	 * fallback JNDI locations.
	 * @param ut the JTA UserTransaction object
	 * @return the JTA TransactionManager reference, or <code>null</code> if not found
	 * @see #FALLBACK_TRANSACTION_MANAGER_NAMES
	 */
	protected TransactionManager findTransactionManager(UserTransaction ut) {
		if (ut instanceof TransactionManager) {
			if (logger.isDebugEnabled()) {
				logger.debug("JTA UserTransaction object [" + ut + "] implements TransactionManager");
			}
			return (TransactionManager) ut;
		}

		// Check fallback JNDI locations.
		for (int i = 0; i < FALLBACK_TRANSACTION_MANAGER_NAMES.length; i++) {
			String jndiName = FALLBACK_TRANSACTION_MANAGER_NAMES[i];
			try {
				TransactionManager tm = (TransactionManager) getJndiTemplate().lookup(jndiName, TransactionManager.class);
				if (logger.isDebugEnabled()) {
					logger.debug("JTA TransactionManager found at fallback JNDI location [" + jndiName + "]");
				}
				return tm;
			}
			catch (NamingException ex) {
				if (logger.isDebugEnabled()) {
					logger.debug("No JTA TransactionManager found at fallback JNDI location [" + jndiName + "]", ex);
				}
			}
		}

		// OK, so no JTA TransactionManager is available...
		return null;
	}

	/**
	 * 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</code>.
	 * @param ut the JTA UserTransaction object
	 * @param tm the JTA TransactionManager object
	 * @return the JTA TransactionSynchronizationRegistry handle to use,
	 * or <code>null</code> if none found
	 * @throws TransactionSystemException in case of errors
	 */
	protected Object findTransactionSynchronizationRegistry(UserTransaction ut, TransactionManager tm)
			throws TransactionSystemException {

		try {
			Class registryClass = ClassUtils.forName(TRANSACTION_SYNCHRONIZATION_REGISTRY_CLASS_NAME,
					JtaTransactionManager.class.getClassLoader());

			// If we came here, we might be on Java EE 5, since the JTA 1.1 API is present.
			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 {
					Object tsr = getJndiTemplate().lookup(jndiName, registryClass);
					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 (registryClass.isInstance(ut)) {
				return ut;
			}
			if (registryClass.isInstance(tm)) {
				return tm;
			}

			// OK, so no JTA 1.1 TransactionSynchronizationRegistry is available,
			// despite the API being present...
			return null;
		}
		catch (ClassNotFoundException ex) {
			logger.debug("JTA 1.1 [" + TRANSACTION_SYNCHRONIZATION_REGISTRY_CLASS_NAME + "] not available");
			return null;
		}
	}


	/**
	 * This implementation returns a JtaTransactionObject instance for the
	 * JTA UserTransaction.
	 * <p>The UserTransaction object will either be looked up freshly for the
	 * current transaction, or the cached one looked up at startup will be used.
	 * The latter is the default: Most application servers use a shared singleton
	 * UserTransaction that can be cached. Turn off the "cacheUserTransaction"
	 * flag to enforce a fresh lookup for every transaction.
	 * @see #setCacheUserTransaction
	 */
	protected Object doGetTransaction() {
		UserTransaction ut = getUserTransaction();
		if (ut == null) {
			throw new CannotCreateTransactionException("No JTA UserTransaction available - " +
					"programmatic PlatformTransactionManager.getTransaction usage not supported");
		}
		if (!this.cacheUserTransaction) {
			ut = lookupUserTransaction(
					this.userTransactionName != null ? this.userTransactionName : DEFAULT_USER_TRANSACTION_NAME);
		}
		return doGetJtaTransaction(ut);
	}

	/**
	 * Get a JTA transaction object for the given current UserTransaction.
	 * <p>Subclasses can override this to provide a JtaTransactionObject
	 * subclass, for example holding some additional JTA handle needed.
	 * @param ut the UserTransaction handle to use for the current transaction
	 * @return the JtaTransactionObject holding the UserTransaction
	 */
	protected JtaTransactionObject doGetJtaTransaction(UserTransaction ut) {
		return new JtaTransactionObject(ut);
	}

	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);
		}
	}

	/**
	 * This implementation returns false to cause a further invocation
	 * of doBegin despite an already existing transaction.
	 * <p>JTA implementations might support nested transactions via further
	 * <code>UserTransaction.begin()</code> invocations, but never support savepoints.
	 * @see #doBegin
	 * @see javax.transaction.UserTransaction#begin()
	 */
	protected boolean useSavepointForNestedTransaction() {
		return false;
	}


	protected void doBegin(Object transaction, TransactionDefinition definition) {
		JtaTransactionObject txObject = (JtaTransactionObject) transaction;
		try {
			doJtaBegin(txObject, definition);
		}
		catch (NotSupportedException ex) {
			// assume nested transaction not supported
			throw new NestedTransactionNotSupportedException(
			    "JTA implementation does not support nested transactions", ex);
		}
		catch (UnsupportedOperationException ex) {
			// assume nested transaction not supported
			throw new NestedTransactionNotSupportedException(
			    "JTA implementation does not support nested transactions", ex);
		}
		catch (SystemException ex) {
			throw new CannotCreateTransactionException("JTA failure on begin", ex);
		}
	}

	/**
	 * Perform a JTA begin on the JTA UserTransaction or TransactionManager.
	 * <p>This implementation only supports standard JTA functionality:
	 * that is, no per-transaction isolation levels and no transaction names.
	 * Can be overridden in subclasses, for specific JTA implementations.
	 * <p>Calls <code>applyIsolationLevel</code> and <code>applyTimeout</code>
	 * before invoking the UserTransaction's <code>begin</code> method.
	 * @param txObject the JtaTransactionObject containing the UserTransaction
	 * @param definition TransactionDefinition instance, describing propagation
	 * behavior, isolation level, read-only flag, timeout, and transaction name
	 * @throws NotSupportedException if thrown by JTA methods
	 * @throws SystemException if thrown by JTA methods
	 * @see #getUserTransaction
	 * @see #getTransactionManager
	 * @see #applyIsolationLevel
	 * @see #applyTimeout
	 * @see JtaTransactionObject#getUserTransaction()
	 * @see javax.transaction.UserTransaction#setTransactionTimeout
	 * @see javax.transaction.UserTransaction#begin
	 */
	protected void doJtaBegin(JtaTransactionObject txObject, TransactionDefinition definition)
			throws NotSupportedException, SystemException {

		applyIsolationLevel(txObject, definition.getIsolationLevel());
		int timeout = determineTimeout(definition);
		applyTimeout(txObject, timeout);
		txObject.getUserTransaction().begin();
	}

	/**
	 * Apply the given transaction isolation level. The default implementation
	 * will throw an exception for any level other than ISOLATION_DEFAULT.
	 * <p>To be overridden in subclasses for specific JTA implementations,
	 * as alternative to overriding the full {@link #doJtaBegin} method.
	 * @param txObject the JtaTransactionObject containing the UserTransaction
	 * @param isolationLevel isolation level taken from transaction definition
	 * @throws InvalidIsolationLevelException if the given isolation level
	 * cannot be applied
	 * @throws SystemException if thrown by the JTA implementation
	 * @see #doJtaBegin
	 * @see JtaTransactionObject#getUserTransaction()
	 * @see #getTransactionManager()
	 */
	protected void applyIsolationLevel(JtaTransactionObject txObject, int isolationLevel)
	    throws InvalidIsolationLevelException, SystemException {

		if (!this.allowCustomIsolationLevels && isolationLevel != TransactionDefinition.ISOLATION_DEFAULT) {
			throw new InvalidIsolationLevelException(
			    "JtaTransactionManager does not support custom isolation levels by default - " +
					"switch 'allowCustomIsolationLevels' to 'true'");
		}
	}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?