All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springframework.transaction.jta.OC4JJtaTransactionManager Maven / Gradle / Ivy

There is a newer version: 5.3.39
Show newest version
/*
 * Copyright 2002-2007 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.transaction.jta;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import javax.transaction.NotSupportedException;
import javax.transaction.SystemException;
import javax.transaction.Transaction;
import javax.transaction.UserTransaction;

import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionSystemException;
import org.springframework.util.ClassUtils;

/**
 * Special {@link JtaTransactionManager} variant for Oracle OC4J (10.1.3 and higher).
 * Supports the full power of Spring's transaction definitions on OC4J's
 * transaction coordinator, beyond standard JTA: transaction names
 * and per-transaction isolation levels.
 *
 * 

Uses OC4J's special begin(name) method to start a JTA transaction, * in orderto make Spring-driven transactions visible in OC4J's transaction * monitor. In case of Spring's declarative transactions, the exposed name will * (by default) be the fully-qualified class name + "." + method name. * *

Supports a per-transaction isolation level through OC4J's corresponding * OC4JTransaction.setTransactionIsolation(int) method. This will * apply the specified isolation level (e.g. ISOLATION_SERIALIZABLE) to all * JDBC Connections that participate in the given transaction. * *

Automatically detects the available OC4J server version and adapts accordingly. * Supports the "com.evermind.server" package in OC4J 10.1.3.2 as well as the * "oracle.j2ee.transaction" package in later OC4J versions. * *

By default, the JTA UserTransaction and TransactionManager handles are * fetched directly from OC4J's TransactionUtility in 10.1.3.2+. * This can be overridden by specifying "userTransaction"/"userTransactionName" * and "transactionManager"/"transactionManagerName", passing in existing handles * or specifying corresponding JNDI locations to look up. * *

Thanks to Oracle for donating the original version of this extended OC4J * integration code to the Spring project! * * @author Paul Parkinson * @author Juergen Hoeller * @since 2.0.3 * @see org.springframework.transaction.TransactionDefinition#getName * @see org.springframework.transaction.TransactionDefinition#getIsolationLevel * @see oracle.j2ee.transaction.OC4JTransactionManager#begin(String) * @see oracle.j2ee.transaction.OC4JTransaction#setTransactionIsolation * @see oracle.j2ee.transaction.TransactionUtility */ public class OC4JJtaTransactionManager extends JtaTransactionManager { private static final String TRANSACTION_UTILITY_CLASS_NAME = "oracle.j2ee.transaction.TransactionUtility"; private static final String TRANSACTION_MANAGER_CLASS_NAME = "oracle.j2ee.transaction.OC4JTransactionManager"; private static final String TRANSACTION_CLASS_NAME = "oracle.j2ee.transaction.OC4JTransaction"; private static final String FALLBACK_TRANSACTION_MANAGER_CLASS_NAME = "com.evermind.server.ApplicationServerTransactionManager"; private static final String FALLBACK_TRANSACTION_CLASS_NAME = "com.evermind.server.ApplicationServerTransaction"; private Method beginWithNameMethod; private Method setTransactionIsolationMethod; public void afterPropertiesSet() throws TransactionSystemException { super.afterPropertiesSet(); loadOC4JTransactionClasses(); } protected UserTransaction retrieveUserTransaction() throws TransactionSystemException { try { Class transactionUtilityClass = getClass().getClassLoader().loadClass(TRANSACTION_UTILITY_CLASS_NAME); Method getInstanceMethod = transactionUtilityClass.getMethod("getInstance", new Class[0]); Object transactionUtility = getInstanceMethod.invoke(null, new Object[0]); logger.debug("Retrieving JTA UserTransaction from OC4J TransactionUtility"); Method getUserTransactionMethod = transactionUtility.getClass().getMethod("getOC4JUserTransaction", new Class[0]); return (UserTransaction) getUserTransactionMethod.invoke(transactionUtility, new Object[0]); } catch (ClassNotFoundException ex) { logger.debug("Could not find OC4J 10.1.3.2 TransactionUtility: " + ex); // Return null to make the superclass perform its standard J2EE lookup, // which will work on earlier OC4J versions. return null; } catch (InvocationTargetException ex) { throw new TransactionSystemException( "OC4J's TransactionUtility.getOC4JUserTransaction() method failed", ex.getTargetException()); } catch (Exception ex) { throw new TransactionSystemException( "Could not invoke OC4J's TransactionUtility.getOC4JUserTransaction() method", ex); } } private void loadOC4JTransactionClasses() throws TransactionSystemException { // Find available OC4J API (in "oracle.j2ee.transaction" or "com.evermind.server") Class transactionManagerClass = null; Class transactionClass = null; try { transactionManagerClass = getClass().getClassLoader().loadClass(TRANSACTION_MANAGER_CLASS_NAME); transactionClass = getClass().getClassLoader().loadClass(TRANSACTION_CLASS_NAME); } catch (ClassNotFoundException ex) { try { transactionManagerClass = getClass().getClassLoader().loadClass(FALLBACK_TRANSACTION_MANAGER_CLASS_NAME); transactionClass = getClass().getClassLoader().loadClass(FALLBACK_TRANSACTION_CLASS_NAME); } catch (ClassNotFoundException ex2) { throw new TransactionSystemException( "Could not initialize OC4JJtaTransactionManager because OC4J API classes are not available", ex); } } // Cache reflective Method references for later use. if (transactionManagerClass.isInstance(getUserTransaction())) { this.beginWithNameMethod = ClassUtils.getMethodIfAvailable( transactionManagerClass, "begin", new Class[] {String.class}); this.setTransactionIsolationMethod = ClassUtils.getMethodIfAvailable( transactionClass, "setTransactionIsolation", new Class[] {int.class}); logger.info("Support for OC4J transaction names and isolation levels available"); } else { logger.info("Support for OC4J transaction names and isolation levels not available"); } } protected void doJtaBegin(JtaTransactionObject txObject, TransactionDefinition definition) throws NotSupportedException, SystemException { int timeout = determineTimeout(definition); applyTimeout(txObject, timeout); // Apply transaction name, if any, through the extended OC4J transaction begin method. if (this.beginWithNameMethod != null && definition.getName() != null) { /* oracle.j2ee.transaction.OC4JTransactionManager otm = (oracle.j2ee.transaction.OC4JTransactionManager) ut; otm.begin(definition.getName()); */ try { this.beginWithNameMethod.invoke(txObject.getUserTransaction(), new Object[] {definition.getName()}); } catch (InvocationTargetException ex) { throw new TransactionSystemException( "OC4J's UserTransaction.begin(String) method failed", ex.getTargetException()); } catch (Exception ex) { throw new TransactionSystemException( "Could not invoke OC4J's UserTransaction.begin(String) method", ex); } } else { // No OC4J UserTransaction available or no transaction name specified // -> standard JTA begin call. txObject.getUserTransaction().begin(); } // Specify isolation level, if any, through the corresponding OC4J transaction method. if (this.setTransactionIsolationMethod != null) { if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) { try { Transaction tx = getTransactionManager().getTransaction(); /* oracle.j2ee.transaction.OC4JTransaction otx = (oracle.j2ee.transaction.OC4JTransaction) tx; otx.setTransactionIsolation(definition.getIsolationLevel()); */ Integer isolationLevel = new Integer(definition.getIsolationLevel()); this.setTransactionIsolationMethod.invoke(tx, new Object[] {isolationLevel}); } catch (InvocationTargetException ex) { throw new TransactionSystemException( "OC4J's Transaction.setTransactionIsolation(int) method failed", ex.getTargetException()); } catch (Exception ex) { throw new TransactionSystemException( "Could not invoke OC4J's Transaction.setTransactionIsolation(int) method", ex); } } } else { applyIsolationLevel(txObject, definition.getIsolationLevel()); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy