Package org.springmodules.workflow.jbpm30

Source Code of org.springmodules.workflow.jbpm30.JbpmSessionFactoryUtils$SpringJbpmSessionSynchronization

/*
* 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();
     
    }
  }
}
TOP

Related Classes of org.springmodules.workflow.jbpm30.JbpmSessionFactoryUtils$SpringJbpmSessionSynchronization

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.