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

org.jbpm.db.AbstractDbTestCase Maven / Gradle / Ivy

/*
 * JBoss, Home of Professional Open Source
 * Copyright 2005, JBoss Inc., and individual contributors as indicated
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.jbpm.db;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.hibernate.Session;
import org.hibernate.cfg.Environment;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.jbpm.AbstractJbpmTestCase;
import org.jbpm.JbpmConfiguration;
import org.jbpm.JbpmContext;
import org.jbpm.db.hibernate.JbpmHibernateConfiguration;
import org.jbpm.graph.def.ProcessDefinition;
import org.jbpm.graph.exe.ProcessInstance;
import org.jbpm.job.Job;
import org.jbpm.job.Timer;
import org.jbpm.job.executor.JobExecutor;
import org.jbpm.logging.log.ProcessLog;
import org.jbpm.persistence.db.DbPersistenceServiceFactory;
import org.jbpm.svc.Services;
import org.jbpm.taskmgmt.exe.TaskInstance;

public abstract class AbstractDbTestCase extends AbstractJbpmTestCase {

  protected JbpmConfiguration jbpmConfiguration;
  protected JbpmContext jbpmContext;

  protected Session session;
  protected GraphSession graphSession;
  protected TaskMgmtSession taskMgmtSession;
  protected ContextSession contextSession;
  protected JobSession jobSession;
  protected LoggingSession loggingSession;

  protected JobExecutor jobExecutor;

  private List processDefinitionIds;

  private static final long JOB_TIMEOUT = 90 * 1000;

  protected void setUp() throws Exception {
    super.setUp();
    createJbpmContext();
  }

  protected void runTest() throws Throwable {
    try {
      super.runTest();
    }
    catch (Exception e) {
      // prevent unsafe use of the session after an exception occurs
      if (!jbpmContext.isClosed()) jbpmContext.setRollbackOnly();
      throw e;
    }
  }

  protected void tearDown() throws Exception {
    if (processDefinitionIds != null) deleteProcessDefinitions();
    closeJbpmContext();
    ensureCleanDatabase();

    super.tearDown();
  }

  private void deleteProcessDefinitions() {
    for (Iterator i = processDefinitionIds.iterator(); i.hasNext();) {
      newTransaction();
      try {
        Long processDefinitionId = (Long) i.next();
        graphSession.deleteProcessDefinition(processDefinitionId.longValue());
      }
      catch (RuntimeException e) {
        jbpmContext.setRollbackOnly();
      }
    }
  }

  private void ensureCleanDatabase() {
    DbPersistenceServiceFactory persistenceServiceFactory =
      (DbPersistenceServiceFactory) getJbpmConfiguration().getServiceFactory("persistence");
    if (persistenceServiceFactory == null) return;

    boolean hasLeftOvers = false;
    JbpmHibernateConfiguration jbpmHibernateConfiguration = persistenceServiceFactory.getJbpmHibernateConfiguration();
    JbpmSchema jbpmSchema = new JbpmSchema(jbpmHibernateConfiguration);

    for (Iterator i = jbpmSchema.getRowsPerTable().entrySet().iterator(); i.hasNext();) {
      Map.Entry entry = (Map.Entry) i.next();
      Long count = (Long) entry.getValue();
      if (count.intValue() != 0) {
        hasLeftOvers = true;
        log.error(getName() + " left " + count + " records in " + entry.getKey());
      }
    }

    if (hasLeftOvers) {
      jbpmSchema.cleanSchema();
    }
  }

  protected String getHibernateDialect() {
    DbPersistenceServiceFactory persistenceServiceFactory = (DbPersistenceServiceFactory) jbpmContext.getServiceFactory(Services.SERVICENAME_PERSISTENCE);
    return persistenceServiceFactory.getJbpmHibernateConfiguration().getConfigurationProxy().getProperty(Environment.DIALECT);
  }

  protected void newTransaction() {
    closeJbpmContext();
    createJbpmContext();
  }

  protected ProcessInstance saveAndReload(ProcessInstance pi) {
    jbpmContext.save(pi);
    newTransaction();
    return graphSession.loadProcessInstance(pi.getId());
  }

  protected TaskInstance saveAndReload(TaskInstance taskInstance) {
    jbpmContext.save(taskInstance);
    newTransaction();
    return (TaskInstance) session.load(TaskInstance.class, new Long(taskInstance.getId()));
  }

  protected ProcessDefinition saveAndReload(ProcessDefinition pd) {
    graphSession.saveProcessDefinition(pd);
    registerForDeletion(pd);
    return graphSession.loadProcessDefinition(pd.getId());
  }

  protected ProcessLog saveAndReload(ProcessLog processLog) {
    loggingSession.saveProcessLog(processLog);
    newTransaction();
    return loggingSession.loadProcessLog(processLog.getId());
  }

  protected void createSchema() {
    getJbpmConfiguration().createSchema();
  }

  protected void cleanSchema() {
    getJbpmConfiguration().cleanSchema();
  }

  protected void dropSchema() {
    getJbpmConfiguration().dropSchema();
  }

  protected String getJbpmTestConfig() {
    return null;
  }

  protected JbpmConfiguration getJbpmConfiguration() {
    if (jbpmConfiguration == null) {
      String configurationResource = getJbpmTestConfig();
      jbpmConfiguration = JbpmConfiguration.getInstance(configurationResource);
    }
    return jbpmConfiguration;
  }

  protected void createJbpmContext() {
    jbpmContext = getJbpmConfiguration().createJbpmContext();
    initializeMembers();
  }

  protected void closeJbpmContext() {
    if (jbpmContext != null) {
      resetMembers();

      jbpmContext.close();
      jbpmContext = null;
    }
  }

  protected void startJobExecutor() {
    jobExecutor = getJbpmConfiguration().getJobExecutor();
    jobExecutor.start();
  }

  /**
   * Waits until all jobs are processed or a specified amount of time has elapsed. Unlike
   * {@link #processJobs(long)}, this method is not concerned about the job executor or
   * the jBPM context.
   */
  protected void waitForJobs(final long timeout) {
    final long startTime = System.currentTimeMillis();
    long previousTime = 0;
    long waitPeriod = 500;

    for (int currentCount, previousCount = 0; (currentCount = getNbrOfJobsAvailable()) > 0;) {
      long currentTime = System.currentTimeMillis();

      long elapsedTime = currentTime - startTime;
      if (elapsedTime > timeout) {
        fail("test execution exceeded threshold of " + timeout + " ms");
      }

      if (currentCount < previousCount) {
        waitPeriod = currentCount * (currentTime - previousTime)
          / (previousCount - currentCount);
        if (waitPeriod < 500) waitPeriod = 500;
      }
      else {
        waitPeriod <<= 1;
      }

      if (waitPeriod > 5000) {
        waitPeriod = 5000;
      }
      else {
        long remainingTime = timeout - elapsedTime;
        if (waitPeriod > remainingTime) waitPeriod = remainingTime;
      }

      if (log.isDebugEnabled()) {
        log.debug("waiting " + waitPeriod + " ms for " + currentCount + " jobs");
      }
      try {
        Thread.sleep(waitPeriod);
      }
      catch (InterruptedException e) {
        fail("wait for jobs got interrupted");
      }

      previousCount = currentCount;
      previousTime = currentTime;
    }
  }

  protected int getNbrOfJobsAvailable() {
    if (session != null) {
      return getJobCount(session);
    }
    else {
      createJbpmContext();
      try {
        return getJobCount(session);
      }
      finally {
        closeJbpmContext();
      }
    }
  }

  private int getJobCount(Session session) {
    Number jobCount = (Number) session.createCriteria(Job.class)
      .add(Restrictions.gt("retries", new Integer(0)))
      .setProjection(Projections.rowCount())
      .uniqueResult();
    return jobCount.intValue();
  }

  protected int getTimerCount() {
    Number timerCount = (Number) session.createCriteria(Timer.class)
      .add(Restrictions.gt("retries", new Integer(0)))
      .setProjection(Projections.rowCount())
      .uniqueResult();
    return timerCount.intValue();
  }

  /**
   * Starts the job executor and waits until all jobs are processed or a predefined amount of
   * time has elapsed. The current jBPM context is closed before waiting and a new one is opened
   * after processing the jobs.
   */
  protected void processJobs() {
    processJobs(JOB_TIMEOUT);
  }

  /**
   * Starts the job executor and waits until all jobs are processed or a specified amount of
   * time has elapsed. The current jBPM context is closed before waiting and a new one is opened
   * after processing the jobs.
   */
  protected void processJobs(long timeout) {
    closeJbpmContext();
    try {
      startJobExecutor();
      waitForJobs(timeout);
    }
    finally {
      stopJobExecutor();
      createJbpmContext();
    }
  }

  protected void stopJobExecutor() {
    if (jobExecutor != null) {
      try {
        jobExecutor.stopAndJoin();
      }
      catch (InterruptedException e) {
        fail("wait for job executor to stop got interrupted");
      }
      finally {
        jobExecutor = null;
      }
    }
  }

  protected void deployProcessDefinition(ProcessDefinition processDefinition) {
    jbpmContext.deployProcessDefinition(processDefinition);
    registerForDeletion(processDefinition);
  }

  private void registerForDeletion(ProcessDefinition processDefinition) {
    // start new transaction to avoid registering an uncommitted process definition
    newTransaction();
    if (processDefinitionIds == null) processDefinitionIds = new ArrayList();
    processDefinitionIds.add(new Long(processDefinition.getId()));
  }

  protected void initializeMembers() {
    session = jbpmContext.getSession();
    graphSession = jbpmContext.getGraphSession();
    taskMgmtSession = jbpmContext.getTaskMgmtSession();
    loggingSession = jbpmContext.getLoggingSession();
    jobSession = jbpmContext.getJobSession();
    contextSession = jbpmContext.getContextSession();
  }

  protected void resetMembers() {
    session = null;
    graphSession = null;
    taskMgmtSession = null;
    loggingSession = null;
    jobSession = null;
    contextSession = null;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy