diff --git a/config/alfresco/activiti-context.xml b/config/alfresco/activiti-context.xml
index 7e4f11fc7d..0cada51dd5 100644
--- a/config/alfresco/activiti-context.xml
+++ b/config/alfresco/activiti-context.xml
@@ -42,9 +42,11 @@
class="org.alfresco.repo.workflow.activiti.AlfrescoProcessEngineConfiguration">
-
+
-
+
+
+
@@ -185,5 +187,10 @@
factory-method="getManagementService" />
+
+
+
+
+
diff --git a/source/java/org/alfresco/repo/domain/schema/SchemaBootstrap.java b/source/java/org/alfresco/repo/domain/schema/SchemaBootstrap.java
index 6ebe88d582..52233a6eaf 100644
--- a/source/java/org/alfresco/repo/domain/schema/SchemaBootstrap.java
+++ b/source/java/org/alfresco/repo/domain/schema/SchemaBootstrap.java
@@ -26,12 +26,23 @@ import java.io.FileWriter;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Writer;
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.CallableStatement;
+import java.sql.Clob;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
+import java.sql.NClob;
+import java.sql.PreparedStatement;
import java.sql.ResultSet;
+import java.sql.SQLClientInfoException;
import java.sql.SQLException;
+import java.sql.SQLWarning;
+import java.sql.SQLXML;
+import java.sql.Savepoint;
import java.sql.Statement;
+import java.sql.Struct;
import java.sql.Types;
import java.util.ArrayList;
import java.util.HashMap;
@@ -791,8 +802,8 @@ public class SchemaBootstrap extends AbstractLifecycleBean
checkSchemaPatchScripts(cfg, connection, postUpdateScriptPatches, true);
}
- // initialise Activiti
-// initialiseActivitiDBSchema(connection);
+ // Initialise Activiti DB, using an unclosable connection
+ initialiseActivitiDBSchema(new UnclosableConnection(connection));
return create;
}
@@ -813,6 +824,8 @@ public class SchemaBootstrap extends AbstractLifecycleBean
// build the engine
engine = engineConfig.setDataSource(dataSource).
setDatabaseSchemaUpdate("none").
+ setProcessEngineName("activitiBootstrapEngine").
+ setHistory("full").
setJobExecutorActivate(false).
buildProcessEngine();
@@ -1677,4 +1690,323 @@ public class SchemaBootstrap extends AbstractLifecycleBean
return false;
}
}
+
+ /**
+ * A {@link Connection} wrapper that delegates all calls to the wrapped class
+ * except for the close methods, which are ignored.
+ *
+ * @author Frederik Heremans
+ */
+ public class UnclosableConnection implements Connection {
+
+ private Connection wrapped;
+
+ public UnclosableConnection(Connection wrappedConnection)
+ {
+ this.wrapped = wrappedConnection;
+ }
+ @Override
+ public boolean isWrapperFor(Class> iface) throws SQLException
+ {
+ return wrapped.isWrapperFor(iface);
+ }
+
+ @Override
+ public T unwrap(Class iface) throws SQLException
+ {
+ return wrapped.unwrap(iface);
+ }
+
+ @Override
+ public void clearWarnings() throws SQLException
+ {
+ wrapped.clearWarnings();
+ }
+
+ @Override
+ public void close() throws SQLException
+ {
+ // Ignore this call
+ }
+
+ @Override
+ public void commit() throws SQLException
+ {
+ wrapped.commit();
+ }
+
+ @Override
+ public Array createArrayOf(String typeName, Object[] elements) throws SQLException
+ {
+ return wrapped.createArrayOf(typeName, elements);
+ }
+
+ @Override
+ public Blob createBlob() throws SQLException
+ {
+ return wrapped.createBlob();
+ }
+
+ @Override
+ public Clob createClob() throws SQLException
+ {
+ return wrapped.createClob();
+ }
+
+ @Override
+ public NClob createNClob() throws SQLException
+ {
+ return wrapped.createNClob();
+ }
+
+ @Override
+ public SQLXML createSQLXML() throws SQLException
+ {
+ return wrapped.createSQLXML();
+ }
+
+ @Override
+ public Statement createStatement() throws SQLException
+ {
+ return wrapped.createStatement();
+ }
+
+ @Override
+ public Statement createStatement(int resultSetType, int resultSetConcurrency)
+ throws SQLException
+ {
+ return wrapped.createStatement(resultSetType, resultSetConcurrency);
+ }
+
+ @Override
+ public Statement createStatement(int resultSetType, int resultSetConcurrency,
+ int resultSetHoldability) throws SQLException
+ {
+ return wrapped.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);
+ }
+
+ @Override
+ public Struct createStruct(String typeName, Object[] attributes) throws SQLException
+ {
+ return wrapped.createStruct(typeName, attributes);
+ }
+
+ @Override
+ public boolean getAutoCommit() throws SQLException
+ {
+ return wrapped.getAutoCommit();
+ }
+
+ @Override
+ public String getCatalog() throws SQLException
+ {
+ return wrapped.getCatalog();
+ }
+
+ @Override
+ public Properties getClientInfo() throws SQLException
+ {
+ return wrapped.getClientInfo();
+ }
+
+ @Override
+ public String getClientInfo(String name) throws SQLException
+ {
+ return wrapped.getClientInfo(name);
+ }
+
+ @Override
+ public int getHoldability() throws SQLException
+ {
+ return wrapped.getHoldability();
+ }
+
+ @Override
+ public DatabaseMetaData getMetaData() throws SQLException
+ {
+ return wrapped.getMetaData();
+ }
+
+ @Override
+ public int getTransactionIsolation() throws SQLException
+ {
+ return wrapped.getTransactionIsolation();
+ }
+
+ @Override
+ public Map> getTypeMap() throws SQLException
+ {
+ return wrapped.getTypeMap();
+ }
+
+ @Override
+ public SQLWarning getWarnings() throws SQLException
+ {
+ return wrapped.getWarnings();
+ }
+
+ @Override
+ public boolean isClosed() throws SQLException
+ {
+ return wrapped.isClosed();
+ }
+
+ @Override
+ public boolean isReadOnly() throws SQLException
+ {
+ return wrapped.isReadOnly();
+ }
+
+ @Override
+ public boolean isValid(int timeout) throws SQLException
+ {
+ return wrapped.isValid(timeout);
+ }
+
+ @Override
+ public String nativeSQL(String sql) throws SQLException
+ {
+ return wrapped.nativeSQL(sql);
+ }
+
+ @Override
+ public CallableStatement prepareCall(String sql) throws SQLException
+ {
+ return wrapped.prepareCall(sql);
+ }
+
+ @Override
+ public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency)
+ throws SQLException
+ {
+ return wrapped.prepareCall(sql, resultSetType, resultSetConcurrency);
+ }
+
+ @Override
+ public CallableStatement prepareCall(String sql, int resultSetType,
+ int resultSetConcurrency, int resultSetHoldability) throws SQLException
+ {
+ return wrapped.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql) throws SQLException
+ {
+ return wrapped.prepareStatement(sql);
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
+ throws SQLException
+ {
+ return wrapped.prepareStatement(sql, autoGeneratedKeys);
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, int[] columnIndexes)
+ throws SQLException
+ {
+ return wrapped.prepareStatement(sql, columnIndexes);
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, String[] columnNames)
+ throws SQLException
+ {
+ return wrapped.prepareStatement(sql, columnNames);
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, int resultSetType,
+ int resultSetConcurrency) throws SQLException
+ {
+ return wrapped.prepareStatement(sql, resultSetType, resultSetConcurrency);
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, int resultSetType,
+ int resultSetConcurrency, int resultSetHoldability) throws SQLException
+ {
+ return wrapped.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
+ }
+
+ @Override
+ public void releaseSavepoint(Savepoint savepoint) throws SQLException
+ {
+ wrapped.releaseSavepoint(savepoint);
+ }
+
+ @Override
+ public void rollback() throws SQLException
+ {
+ wrapped.rollback();
+ }
+
+ @Override
+ public void rollback(Savepoint savepoint) throws SQLException
+ {
+ wrapped.rollback(savepoint);
+ }
+
+ @Override
+ public void setAutoCommit(boolean autoCommit) throws SQLException
+ {
+ wrapped.setAutoCommit(autoCommit);
+ }
+
+ @Override
+ public void setCatalog(String catalog) throws SQLException
+ {
+ wrapped.setCatalog(catalog);
+ }
+
+ @Override
+ public void setClientInfo(Properties properties) throws SQLClientInfoException
+ {
+ wrapped.setClientInfo(properties);
+ }
+
+ @Override
+ public void setClientInfo(String name, String value) throws SQLClientInfoException
+ {
+ wrapped.setClientInfo(name, value);
+ }
+
+ @Override
+ public void setHoldability(int holdability) throws SQLException
+ {
+ wrapped.setHoldability(holdability);
+ }
+
+ @Override
+ public void setReadOnly(boolean readOnly) throws SQLException
+ {
+ wrapped.setReadOnly(readOnly);
+ }
+
+ @Override
+ public Savepoint setSavepoint() throws SQLException
+ {
+ return wrapped.setSavepoint();
+ }
+
+ @Override
+ public Savepoint setSavepoint(String name) throws SQLException
+ {
+ return wrapped.setSavepoint(name);
+ }
+
+ @Override
+ public void setTransactionIsolation(int level) throws SQLException
+ {
+ wrapped.setTransactionIsolation(level);
+ }
+
+ @Override
+ public void setTypeMap(Map> map) throws SQLException
+ {
+ wrapped.setTypeMap(map);
+ }
+
+ }
}
diff --git a/source/java/org/alfresco/repo/workflow/activiti/ActivitiEngineInitializer.java b/source/java/org/alfresco/repo/workflow/activiti/ActivitiEngineInitializer.java
new file mode 100644
index 0000000000..a2fd8434d9
--- /dev/null
+++ b/source/java/org/alfresco/repo/workflow/activiti/ActivitiEngineInitializer.java
@@ -0,0 +1,51 @@
+/*
+ * 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 .
+ */
+package org.alfresco.repo.workflow.activiti;
+
+import org.activiti.engine.ProcessEngine;
+import org.activiti.engine.impl.ProcessEngineImpl;
+import org.alfresco.repo.domain.schema.SchemaAvailableEvent;
+import org.springframework.context.ApplicationEvent;
+import org.springframework.context.ApplicationListener;
+
+/**
+ * Class that waits for an {@link SchemaAvailableEvent} to start the activiti
+ * job executor.
+ *
+ * @author Frederik Heremans
+ */
+public class ActivitiEngineInitializer implements ApplicationListener
+{
+ private ProcessEngine processEngine;
+
+ @Override
+ public void onApplicationEvent(ApplicationEvent event)
+ {
+ if(event instanceof SchemaAvailableEvent && processEngine instanceof ProcessEngineImpl)
+ {
+ // Start the job-executor
+ ((ProcessEngineImpl)processEngine).getProcessEngineConfiguration().getJobExecutor().start();
+ }
+ }
+
+ public void setProcessEngine(ProcessEngine processEngine)
+ {
+ this.processEngine = processEngine;
+ }
+}