Fixed ALF-9515: Activiti can no longer be disabled

Both Activiti and JBPM can now be "disabled" using the properties "system.workflow.engine.activiti.enabled" and "system.workflow.engine.jbpm.enabled", respectively. However, disabling JBPM is NOT recommended as several parts of the system are reliant on it. Furthermore, "disabled" just means the process definitions are not deployed and the engine is not registered with the WorkflowService, all DB tables etc. are still present. This means the engines can be disabled and re-enabled at will.

Also added back-end support for ALF-9392: More workflow metrics are required on the Workflow Console Admin Tool. An MBean is now available in Enterprise mode that provides the number of tasks, workflow definitions deployed and workflow instances in the system.

Added ENGINE_ID constant to JBPMEngine and globally replaced use of "jbpm" hard coded string.

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@29326 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Gavin Cornwell
2011-07-25 21:42:37 +00:00
parent a7b885a1c6
commit b3ce73691e
11 changed files with 274 additions and 89 deletions

View File

@@ -42,6 +42,15 @@ system.workflow.deployservlet.enabled=false
# Sets the location for the JBPM Configuration File
system.workflow.jbpm.config.location=classpath:org/alfresco/repo/workflow/jbpm/jbpm.cfg.xml
# Determines if the JBPM engine is enabled
# NOTE: The JBPM engine is used by several parts of the system so it's recommended that
# it remains enabled. Only change this setting if you have alternative solutions
# for the affected areas i.e. site invitations, publishing and WCM
system.workflow.engine.jbpm.enabled=true
# Determines if the Activiti engine is enabled
system.workflow.engine.activiti.enabled=true
index.subsystem.name=lucene
# ######################################### #

View File

@@ -11,6 +11,7 @@
<property name="transactionService" ref="transactionService"/>
<property name="authenticationContext" ref="authenticationContext" />
<property name="workflowService" ref="WorkflowService" />
<property name="workflowAdminService" ref="workflowAdminService" />
<property name="dictionaryDAO" ref="dictionaryDAO"/>
<property name="nodeService" ref="NodeService"/>
<property name="searchService" ref="SearchService"/>
@@ -61,6 +62,19 @@
</property>
</bean>
<!-- -->
<!-- Workflow Admin Service Implementation -->
<!-- -->
<bean id="workflowAdminService" class="org.alfresco.repo.workflow.WorkflowAdminServiceImpl">
<property name="jbpmEngineEnabled">
<value>${system.workflow.engine.jbpm.enabled}</value>
</property>
<property name="activitiEngineEnabled">
<value>${system.workflow.engine.activiti.enabled}</value>
</property>
</bean>
<!-- -->
<!-- Workflow Action -->
<!-- -->
@@ -77,6 +91,7 @@
<!-- -->
<bean id="bpm_engineRegistry" class="org.alfresco.repo.workflow.BPMEngineRegistry">
<property name="workflowAdminService" ref="workflowAdminService" />
</bean>
<bean id="bpm_engine" class="org.alfresco.repo.workflow.AlfrescoBpmEngine" abstract="true">

View File

@@ -21,6 +21,7 @@ package org.alfresco.repo.workflow;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.service.cmr.workflow.WorkflowAdminService;
import org.alfresco.service.cmr.workflow.WorkflowException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -46,6 +47,8 @@ public class BPMEngineRegistry
/** Logging support */
private static Log logger = LogFactory.getLog("org.alfresco.repo.workflow");
private WorkflowAdminService workflowAdminService;
private Map<String, WorkflowComponent> workflowComponents;
private Map<String, TaskComponent> taskComponents;
@@ -58,6 +61,16 @@ public class BPMEngineRegistry
taskComponents = new HashMap<String, TaskComponent>();
}
/**
* Sets the workflow admin service
*
* @param workflowAdminService the workflow admin service
*/
public void setWorkflowAdminService(WorkflowAdminService workflowAdminService)
{
this.workflowAdminService = workflowAdminService;
}
/**
* Register a BPM Engine Workflow Component
*
@@ -70,10 +83,19 @@ public class BPMEngineRegistry
{
throw new WorkflowException("Workflow Component already registered for engine id '" + engineId + "'");
}
if (workflowAdminService.isEngineEnabled(engineId))
{
workflowComponents.put(engineId, engine);
if (logger.isInfoEnabled())
logger.info("Registered Workflow Component '" + engineId + "' (" + engine.getClass() + ")");
if (logger.isDebugEnabled())
logger.debug("Registered Workflow Component '" + engineId + "' (" + engine.getClass() + ")");
}
else
{
if (logger.isWarnEnabled())
logger.warn("Ignoring Workflow Component '" + engineId + "' (" + engine.getClass() + ") as the engine is disabled");
}
}
/**
@@ -109,10 +131,19 @@ public class BPMEngineRegistry
{
throw new WorkflowException("Task Component already registered for engine id '" + engineId + "'");
}
if (workflowAdminService.isEngineEnabled(engineId))
{
taskComponents.put(engineId, engine);
if (logger.isInfoEnabled())
logger.info("Registered Task Component '" + engineId + "' (" + engine.getClass() + ")");
if (logger.isDebugEnabled())
logger.debug("Registered Task Component '" + engineId + "' (" + engine.getClass() + ")");
}
else
{
if (logger.isWarnEnabled())
logger.warn("Ignoring Task Component '" + engineId + "' (" + engine.getClass() + ") as the engine is disabled");
}
}
/**

View File

@@ -0,0 +1,63 @@
/*
* Copyright (C) 2005-2011 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco 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 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.workflow;
import org.alfresco.repo.workflow.activiti.ActivitiConstants;
import org.alfresco.repo.workflow.jbpm.JBPMEngine;
import org.alfresco.service.cmr.workflow.WorkflowAdminService;
/**
* Default implementation of the workflow admin service.
*
* @author Gavin Cornwell
* @since 4.0
*/
public class WorkflowAdminServiceImpl implements WorkflowAdminService
{
private boolean jbpmEngineEnabled = true;
private boolean activitiEngineEnabled = true;
public void setJbpmEngineEnabled(boolean jbpmEngineEnabled)
{
this.jbpmEngineEnabled = jbpmEngineEnabled;
}
public void setActivitiEngineEnabled(boolean activitiEngineEnabled)
{
this.activitiEngineEnabled = activitiEngineEnabled;
}
@Override
public boolean isEngineEnabled(String engineId)
{
if (JBPMEngine.ENGINE_ID.equals(engineId))
{
return jbpmEngineEnabled;
}
else if (ActivitiConstants.ENGINE_ID.equals(engineId))
{
return activitiEngineEnabled;
}
else
{
// if the engine id is not recognised it can't be enabled!
return false;
}
}
}

View File

@@ -40,6 +40,7 @@ import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.workflow.WorkflowAdminService;
import org.alfresco.service.cmr.workflow.WorkflowDefinition;
import org.alfresco.service.cmr.workflow.WorkflowDeployment;
import org.alfresco.service.cmr.workflow.WorkflowException;
@@ -73,6 +74,7 @@ public class WorkflowDeployer extends AbstractLifecycleBean
// Dependencies
private TransactionService transactionService;
private WorkflowService workflowService;
private WorkflowAdminService workflowAdminService;
private AuthenticationContext authenticationContext;
private DictionaryDAO dictionaryDAO;
private List<Properties> workflowDefinitions;
@@ -100,15 +102,25 @@ public class WorkflowDeployer extends AbstractLifecycleBean
}
/**
* Sets the namespace service
* Sets the workflow service
*
* @param namespaceService the namespace service
* @param workflowService the workflow service
*/
public void setWorkflowService(WorkflowService workflowService)
{
this.workflowService = workflowService;
}
/**
* Sets the workflow admin service
*
* @param workflowAdminService the workflow admin service
*/
public void setWorkflowAdminService(WorkflowAdminService workflowAdminService)
{
this.workflowAdminService = workflowAdminService;
}
/**
* Set the authentication component
*
@@ -223,7 +235,9 @@ public class WorkflowDeployer extends AbstractLifecycleBean
}
if (!transactionService.getAllowWrite())
{
if (logger.isWarnEnabled())
logger.warn("Repository is in read-only mode; not deploying workflows.");
return;
}
@@ -254,11 +268,15 @@ public class WorkflowDeployer extends AbstractLifecycleBean
{
throw new WorkflowException("Workflow Engine Id must be provided");
}
String location = workflowDefinition.getProperty(LOCATION);
if (location == null || location.length() == 0)
{
throw new WorkflowException("Workflow definition location must be provided");
}
if (workflowAdminService.isEngineEnabled(engineId))
{
Boolean redeploy = Boolean.valueOf(workflowDefinition.getProperty(REDEPLOY));
String mimetype = workflowDefinition.getProperty(MIMETYPE);
@@ -286,6 +304,12 @@ public class WorkflowDeployer extends AbstractLifecycleBean
}
}
}
else
{
if (logger.isDebugEnabled())
logger.debug("Workflow deployer: Definition '" + location + "' not deployed as the '" + engineId + "' engine is disabled");
}
}
}
// deploy workflow definitions from repository (if any)
@@ -328,14 +352,16 @@ public class WorkflowDeployer extends AbstractLifecycleBean
{
Boolean value = (Boolean)nodeService.getProperty(nodeRef, WorkflowModel.PROP_WORKFLOW_DEF_DEPLOYED);
if ((value != null) && (value.booleanValue() == true))
{
String engineId = (String) nodeService.getProperty(nodeRef, WorkflowModel.PROP_WORKFLOW_DEF_ENGINE_ID);
if (workflowAdminService.isEngineEnabled(engineId))
{
if (!redeploy && workflowService.isDefinitionDeployed(nodeRef))
{
if (logger.isDebugEnabled())
{
logger.debug("Workflow deployer: Definition '" + nodeRef + "' already deployed");
}
}
else
{
// deploy / re-deploy
@@ -355,6 +381,7 @@ public class WorkflowDeployer extends AbstractLifecycleBean
{
for (String problem : deployment.getProblems())
{
if (logger.isWarnEnabled())
logger.warn(problem);
}
}
@@ -363,24 +390,28 @@ public class WorkflowDeployer extends AbstractLifecycleBean
}
}
}
else
{
if (logger.isDebugEnabled())
logger.debug("Workflow deployer: Definition '" + nodeRef + "' not deployed as the '" + engineId + "' engine is disabled");
}
}
}
else
{
if (logger.isDebugEnabled())
{
logger.debug("Workflow deployer: Definition '" + nodeRef + "' not deployed since it is a working copy");
}
}
}
private void logDeployment(Object location, WorkflowDeployment deployment)
{
if (logger.isInfoEnabled())
if (logger.isDebugEnabled())
{
String title = deployment.getDefinition().getTitle();
String version = deployment.getDefinition().getVersion();
int problemLength = deployment.getProblems().length;
logger.info("Workflow deployer: Deployed process definition '" + title + "' (version " + version + ") from '" + location + "' with " + problemLength + " problems");
logger.debug("Workflow deployer: Deployed process definition '" + title + "' (version " + version + ") from '" + location + "' with " + problemLength + " problems");
}
}
@@ -396,26 +427,22 @@ public class WorkflowDeployer extends AbstractLifecycleBean
List<WorkflowDefinition> defs = workflowService.getAllDefinitionsByName(defName);
for (WorkflowDefinition def: defs)
{
if (logger.isInfoEnabled())
{
logger.info("Undeploying workflow '" + defName + "' ...");
}
if (logger.isDebugEnabled())
logger.debug("Undeploying workflow '" + defName + "' ...");
workflowService.undeployDefinition(def.getId());
if (logger.isInfoEnabled())
{
logger.info("... undeployed '" + def.getId() + "' v" + def.getVersion());
}
if (logger.isDebugEnabled())
logger.debug("... undeployed '" + def.getId() + "' v" + def.getVersion());
}
}
}
else
{
if (logger.isDebugEnabled())
{
logger.debug("Workflow deployer: Definition '" + nodeRef + "' not undeployed since it is a working copy");
}
}
}
@Override
protected void onBootstrap(ApplicationEvent event)

View File

@@ -195,6 +195,9 @@ public class JBPMEngine extends AlfrescoBpmEngine implements WorkflowEngine
private static final String ERR_GET_COMPANY_HOME_INVALID = "jbpm.engine.get.company.home.invalid";
private static final String ERR_GET_COMPANY_HOME_MULTIPLE = "jbpm.engine.get.company.home.multiple";
// engine ID
public static final String ENGINE_ID = "jbpm";
/**
* Sets the JBPM Template used for accessing JBoss JBPM in the correct
* context

View File

@@ -84,8 +84,8 @@ public class JBPMEngineTest extends BaseAlfrescoSpringTest
person3 = createPerson(USER3);
BPMEngineRegistry registry = (BPMEngineRegistry)applicationContext.getBean("bpm_engineRegistry");
workflowComponent = registry.getWorkflowComponent("jbpm");
taskComponent = registry.getTaskComponent("jbpm");
workflowComponent = registry.getWorkflowComponent(JBPMEngine.ENGINE_ID);
taskComponent = registry.getTaskComponent(JBPMEngine.ENGINE_ID);
packageComponent = (WorkflowPackageComponent)applicationContext.getBean("workflowPackageImpl");
// deploy test process messages

View File

@@ -65,7 +65,7 @@ public abstract class JBPMSpringActionHandler implements ActionHandler
protected String getWorkflowInstanceId(ExecutionContext context)
{
String id = new Long(context.getProcessInstance().getId()).toString();
return BPMEngineRegistry.createGlobalId("jbpm", id);
return BPMEngineRegistry.createGlobalId(JBPMEngine.ENGINE_ID, id);
}
}

View File

@@ -112,7 +112,7 @@ public class JbpmWorkflowServiceIntegrationTest extends AbstractWorkflowServiceI
@Override
protected String getEngine()
{
return "jbpm";
return JBPMEngine.ENGINE_ID;
}
@Override

View File

@@ -67,8 +67,8 @@ public class ReviewAndApproveTest extends BaseSpringTest
{
personService = (PersonService)applicationContext.getBean("personService");
BPMEngineRegistry registry = (BPMEngineRegistry)applicationContext.getBean("bpm_engineRegistry");
workflowComponent = registry.getWorkflowComponent("jbpm");
taskComponent = registry.getTaskComponent("jbpm");
workflowComponent = registry.getWorkflowComponent(JBPMEngine.ENGINE_ID);
taskComponent = registry.getTaskComponent(JBPMEngine.ENGINE_ID);
// deploy latest review and approve process definition
ClassPathResource processDef = new ClassPathResource("alfresco/workflow/review_processdefinition.xml");

View File

@@ -0,0 +1,37 @@
/*
* Copyright (C) 2005-2011 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco 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 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.service.cmr.workflow;
/**
* Client facing API for providing administration information about the
* {@link WorkflowService}.
*
* @author Gavin Cornwell
* @since 4.0
*/
public interface WorkflowAdminService
{
/**
* Determines whether the engine with the given id is enabled.
*
* @param engineId The id of a workflow engine
* @return true if the engine id is valid and is enabled
*/
public boolean isEngineEnabled(String engineId);
}