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; + } +}