Posts Tagged ‘setRollbackOnly

23
Jan
09

WebSphere UOW TransactionManagerLookup for Hibernate

For those interested in experimenting the latest Transaction Management API from WebSphere (available on newer 6.0 and 6.1 versions), I’ll place the code here of a draft implementation I made (partly based on original WebSphereExtendedTransactionLookup, WebSphere documentations [1][2][3][4] and Spring’s Transaction Manager for WAS).
I hope someday it gets integrated into Hibernate mainstream code but while it isn’t I’ll place here so more people may test it and improve it (reducing the burden over Hibernate team).

package org.hibernate.transaction;

import java.lang.reflect.Method;
import java.util.Properties;

import javax.naming.NamingException;
import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
import javax.transaction.InvalidTransactionException;
import javax.transaction.NotSupportedException;
import javax.transaction.RollbackException;
import javax.transaction.Status;
import javax.transaction.Synchronization;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import javax.transaction.xa.XAResource;

import org.hibernate.HibernateException;
import org.hibernate.util.NamingHelper;
import org.omg.CORBA.SystemException;

/**
 * @author rafaelri
 * Support for proprietary interfaces for registering synchronizations in WebSphere 6.1+
 */
public class WebSphereUOWTransactionLookup implements TransactionManagerLookup {

	private static final String UOW_MANAGER_JNDI = "java:comp/websphere/UOWManager";
	private static final String UOW_SYNCHRONIZATION_MANAGER_JNDI = "java:comp/websphere/UOWSynchronizationRegistry";
	public TransactionManager getTransactionManager(Properties props)
	throws HibernateException {
		return new TransactionManagerAdapter(props);
	}

	public String getUserTransactionName() {
		return "java:comp/UserTransaction";
	}

	public static class TransactionManagerAdapter implements TransactionManager {

		private final Object uowManager;
		private final Class uowManagerClass;
		private final Object uowSynchronizationRegistry;
		private final Class uowSynchronizationRegistryClass;
		private final Method registerSynchronizationMethod;
		private final Method setRollbackOnlyMethod;

		private final Properties properties;
		private final Method getLocalIdMethod;

		private TransactionManagerAdapter(Properties props) {
			this.properties = props;
			try {
				uowManager = NamingHelper.getInitialContext(props).lookup( UOW_MANAGER_JNDI );
				uowManagerClass = Class.forName("com.ibm.wsspi.uow.UOWManager");
				setRollbackOnlyMethod = uowManagerClass.getMethod(
						"setRollbackOnly",
						new Class[] {}
					);

				uowSynchronizationRegistry = NamingHelper.getInitialContext(props).lookup( UOW_SYNCHRONIZATION_MANAGER_JNDI );
				uowSynchronizationRegistryClass = Class.forName("com.ibm.websphere.uow.UOWSynchronizationRegistry");

				registerSynchronizationMethod = uowSynchronizationRegistryClass.getMethod(
						"registerInterposedSynchronization",
						new Class[] { Synchronization.class }
					);
				Class extendedJTATransactionClass = Class.forName("com.ibm.websphere.jtaextensions.ExtendedJTATransaction");
				getLocalIdMethod = extendedJTATransactionClass.getMethod( "getLocalId", null );

			}
			catch (ClassNotFoundException cnfe) {
				throw new HibernateException(cnfe);
			}
			catch (NoSuchMethodException nsme) {
				throw new HibernateException(nsme);
			} catch (NamingException ne) {
				throw new HibernateException(ne);
			}
		}

		public void begin() throws NotSupportedException, SystemException {
			throw new UnsupportedOperationException();
		}

		public void commit() throws RollbackException, HeuristicMixedException,
				HeuristicRollbackException, SecurityException,
				IllegalStateException, SystemException {
			throw new UnsupportedOperationException();
		}

		public int getStatus() throws SystemException {
			throw new UnsupportedOperationException();
		}

		public Transaction getTransaction() throws SystemException {
			return new TransactionAdapter(properties);
		}

		public void resume(Transaction txn) throws  InvalidTransactionException,
				IllegalStateException, SystemException {
			throw new UnsupportedOperationException();
		}

		public void rollback() throws IllegalStateException, SecurityException,
				SystemException {
			throw new UnsupportedOperationException();
		}

		public void setRollbackOnly() throws IllegalStateException,
				SystemException {
			try {
				setRollbackOnlyMethod.invoke(
					uowManager,
					new Object[] { }
				);
			}
			catch (Exception e) {
				throw new HibernateException(e);
			}
		}

		public void setTransactionTimeout(int i) throws SystemException {
			throw new UnsupportedOperationException();
		}

		public Transaction suspend() throws SystemException {
			throw new UnsupportedOperationException();
		}

		public class TransactionAdapter implements Transaction {

			private final Object extendedJTATransaction;

			private TransactionAdapter(Properties props) {
				try {
					extendedJTATransaction = NamingHelper.getInitialContext(props)
						.lookup("java:comp/websphere/ExtendedJTATransaction");

				}
				catch (NamingException ne) {
					throw new HibernateException(ne);
				}
			}

			public void registerSynchronization(final Synchronization synchronization)
					throws RollbackException, IllegalStateException,
					SystemException {

				try {
					registerSynchronizationMethod.invoke(
							uowSynchronizationRegistry,
							new Object[] { synchronization }
						);
				}
				catch (Exception e) {
					throw new HibernateException(e);
				}

			}

			public int hashCode() {
				return getLocalId().hashCode();
			}

			public boolean equals(Object other) {
				if ( !(other instanceof TransactionAdapter) ) return false;
				TransactionAdapter that = (TransactionAdapter) other;
				return getLocalId().equals( that.getLocalId() );
			}

			private Object getLocalId() {
				try {
					return getLocalIdMethod.invoke(extendedJTATransaction, null);
				}
				catch (Exception e) {
					throw new HibernateException(e);
				}
			}

			public void commit() throws RollbackException, HeuristicMixedException,
					HeuristicRollbackException, SecurityException,
					IllegalStateException, SystemException {
				throw new UnsupportedOperationException();
			}

			public boolean delistResource(XAResource resource, int i)
					throws IllegalStateException, SystemException {
				throw new UnsupportedOperationException();
			}

			public boolean enlistResource(XAResource resource)
					throws RollbackException, IllegalStateException,
					SystemException {
				throw new UnsupportedOperationException();
			}

			public int getStatus() throws SystemException {
				return new Integer(0).equals( getLocalId() ) ?
						Status.STATUS_NO_TRANSACTION : Status.STATUS_ACTIVE;
			}

			public void rollback() throws IllegalStateException, SystemException {
				throw new UnsupportedOperationException();
			}

			public void setRollbackOnly() throws IllegalStateException,
					SystemException {
				try {
					setRollbackOnlyMethod.invoke(
						uowManager,
						new Object[] { }
					);
				}
				catch (Exception e) {
					throw new HibernateException(e);
				}
			}
		}

	}

}

Please, if you use it and find any bugs, comments or suggestions, leave a comment on this post.

Update:

I’ve recently improved this implementation to support the Isolater.Delegate interface on WebSphere anyone interested please take a look at this post.

Advertisements



ClustrMaps

Blog Stats

  • 359,408 hits since aug'08

%d bloggers like this: