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

org.springmodules.workflow.jbpm30.JbpmSessionFactoryUtils Maven / Gradle / Ivy

There is a newer version: 0.8a
Show newest version
/*
 * Copyright 2002-2005 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.springmodules.workflow.jbpm30;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.jbpm.db.JbpmSession;
import org.jbpm.db.JbpmSessionFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.orm.hibernate3.SessionFactoryUtils;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.Assert;

/**
 * Helper class featuring methods for jBPM Session handling, allowing for reuse of jBPM Session instances within transactions.
 * As jBPM 3.0.x actually stands on top of Hibernate, this class will delegate as much as possible work to Spring Hibernate SessionFactoryUtils.
 * 
 * @author Rob Harrop
 */
public abstract class JbpmSessionFactoryUtils {

	private static final Log logger = LogFactory.getLog(JbpmSessionFactoryUtils.class);

	/**
	 * Returns a jBPM session. It is aware of and will return the thread-bound session if one is found.
	 * 
	 * @param sessionFactory
	 * @return
	 */
	public static JbpmSession getSession(JbpmSessionFactory sessionFactory) {
		try {
			return doGetSession(sessionFactory, true);
		}
		catch (RuntimeException e) {
			throw new DataAccessResourceFailureException("Could not open jBPM Session", e);
		}
	}

	/**
	 * Returns a jBPM session. It is aware of and will return the thread-bound session if one is found.
	 * jBPM exceptions will not be translated.
	 * 
	 * @param sessionFactory
	 * @param allowCreate
	 * @return
	 */
	public static JbpmSession doGetSession(JbpmSessionFactory sessionFactory, boolean allowCreate) {
		Assert.notNull(sessionFactory, "No JbpmSessionFactory specified");

		JbpmSessionHolder jbpmSessionHolder = (JbpmSessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);

		if (jbpmSessionHolder != null && jbpmSessionHolder.getJbpmSession() != null) {
			return jbpmSessionHolder.getJbpmSession();
		}

		JbpmSession jbpmSession = sessionFactory.openJbpmSession();
		jbpmSessionHolder = new JbpmSessionHolder(jbpmSession);

		if (TransactionSynchronizationManager.isSynchronizationActive()) {
			TransactionSynchronizationManager.registerSynchronization(new SpringJbpmSessionSynchronization(
					jbpmSessionHolder, sessionFactory));
			TransactionSynchronizationManager.bindResource(sessionFactory, jbpmSessionHolder);
		}

		return jbpmSession;
	}

	/**
	 * Releases the jBPM session.
	 * 
	 * @param jbpmSession
	 * @param jbpmSessionFactory
	 */
	public static void releaseSession(JbpmSession jbpmSession, JbpmSessionFactory jbpmSessionFactory) {
		if (jbpmSession == null)
			return;

		if (!isTransactional(jbpmSession, jbpmSessionFactory)) {
			logger.debug("Closing jBPM session");
			jbpmSession.close();
		}

	}

	/**
	 * Return whether the given jBPM Session is transactional, that is,
	 * bound to the current thread by Spring's transaction facilities.
	 * 
	 * @param jbpmSession
	 * @param jbpmSessionFactory
	 * @return
	 */
	public static boolean isTransactional(JbpmSession jbpmSession, JbpmSessionFactory jbpmSessionFactory) {
		if (jbpmSessionFactory == null)
			return false;

		JbpmSessionHolder jbpmSessionHolder = (JbpmSessionHolder) TransactionSynchronizationManager.getResource(jbpmSessionFactory);
		return (jbpmSessionHolder != null && jbpmSessionHolder.getJbpmSession() == jbpmSession);
	}

	/**
	 * Converts Jbpm RuntimeExceptions into Spring specific ones (if possible).
	 * @param ex
	 * @return
	 */
	public static RuntimeException convertJbpmException(RuntimeException ex) {
		// try to decode and translate HibernateExceptions
		if (ex instanceof HibernateException) {
			return SessionFactoryUtils.convertHibernateAccessException((HibernateException) ex);
		}

		if (ex.getCause() instanceof HibernateException) {
			DataAccessException rootCause = SessionFactoryUtils.convertHibernateAccessException((HibernateException) ex.getCause());
			return new NestedDataAccessException(ex.getMessage(), rootCause);
		}

		// cannot convert the exception in any meaningful way
		return ex;
	}

	/**
	 * Callback for resource cleanup at the end of a transaction (e.g.
	 * when participating in a JtaTransactionManager transaction).
	 * 
	 * @see org.springframework.transaction.jta.JtaTransactionManager
	 */
	private static class SpringJbpmSessionSynchronization extends TransactionSynchronizationAdapter {

		private static final Log logger = LogFactory.getLog(SpringJbpmSessionSynchronization.class);
		
		private JbpmSessionHolder jbpmSessionHolder;
		private JbpmSessionFactory jbpmSessionFactory;

		public SpringJbpmSessionSynchronization(JbpmSessionHolder jbpmSessionHolder,
				JbpmSessionFactory jbpmSessionFactory) {
			this.jbpmSessionHolder = jbpmSessionHolder;
			this.jbpmSessionFactory = jbpmSessionFactory;
		}

		public void suspend() {
			if (logger.isDebugEnabled())
				logger.debug("suspend synchronization for jbpmSessionFactory " + System.identityHashCode(jbpmSessionFactory));
			TransactionSynchronizationManager.unbindResource(this.jbpmSessionFactory);
		}

		public void resume() {
			if (logger.isDebugEnabled())
				logger.debug("resume synchronization for jbpmSessionFactory " + System.identityHashCode(jbpmSessionFactory));
			TransactionSynchronizationManager.bindResource(jbpmSessionFactory, jbpmSessionHolder);
		}

		public void beforeCompletion() {
			if (logger.isDebugEnabled())
				logger.debug("beforeCompletion synchronization for jbpmSessionFactory " + System.identityHashCode(jbpmSessionFactory));

			TransactionSynchronizationManager.unbindResource(jbpmSessionFactory);
			releaseSession(this.jbpmSessionHolder.getJbpmSession(), this.jbpmSessionFactory);
			this.jbpmSessionHolder.clear();
			
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy