flowable/flowable-engine · critical · ActivitiException

transactionManager is required property for…

Error message

transactionManager is required property for JtaProcessEngineConfiguration, use org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration otherwise

What it means

JtaProcessEngineConfiguration requires a JTA transactionManager to build its transaction interceptor. If createTransactionInterceptor runs with transactionManager still null, the engine throws this ActivitiException because JTA-managed transactions are impossible without one. The message points to StandaloneProcessEngineConfiguration as the alternative for non-JTA setups.

Solutions

  1. Set the JTA transaction manager: configuration.setTransactionManager(transactionManager) before buildProcessEngine()
  2. If not running in a JTA environment, switch to StandaloneProcessEngineConfiguration (or StandaloneInMemProcessEngineConfiguration for tests)
  3. In Spring, ensure the JtaTransactionManager bean is injected into the configuration factory bean

Example fix

// before
JtaProcessEngineConfiguration cfg = new JtaProcessEngineConfiguration();
cfg.buildProcessEngine(); // throws
// after
JtaProcessEngineConfiguration cfg = new JtaProcessEngineConfiguration();
cfg.setTransactionManager(jtaTransactionManager);
cfg.buildProcessEngine();
Defensive patterns

Strategy: validation

Validate before calling

if (cfg instanceof JtaProcessEngineConfiguration
    && ((JtaProcessEngineConfiguration) cfg).getTransactionManager() == null) {
  throw new IllegalStateException("JtaProcessEngineConfiguration requires setTransactionManager()");
}

Try / catch

try {
  processEngine = cfg.buildProcessEngine();
} catch (ActivitiException e) {
  if (e.getMessage().contains("transactionManager is required")) {
    throw new ConfigurationException("Provide a JTA TransactionManager or use StandaloneProcessEngineConfiguration", e);
  } else throw e;
}

Prevention

When it happens

Trigger: Building a process engine from a JtaProcessEngineConfiguration (or its Spring/CDI subclasses) without calling setTransactionManager before processEngine build; createTransactionInterceptor is invoked during engine initialization.

Common situations: Migrating a standalone Activiti config to JTA in an app server and forgetting the JTA TransactionManager bean; using JtaProcessEngineConfiguration outside a container that provides javax.transaction.TransactionManager; Spring wiring where the transactionManager bean isn't injected.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/d46bd32283f538c3. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/cfg/JtaProcessEngineConfiguration.java:36

import org.activiti.engine.impl.cfg.jta.JtaTransactionContextFactory;
import org.activiti.engine.impl.interceptor.CommandInterceptor;
import org.activiti.engine.impl.interceptor.JtaTransactionInterceptor;

/**
 * @author Tom Baeyens
 */
public class JtaProcessEngineConfiguration extends ProcessEngineConfigurationImpl {

    protected TransactionManager transactionManager;

    public JtaProcessEngineConfiguration() {
        this.transactionsExternallyManaged = true;
    }

    @Override
    protected CommandInterceptor createTransactionInterceptor() {
        if (transactionManager == null) {
            throw new ActivitiException("transactionManager is required property for JtaProcessEngineConfiguration, use " + StandaloneProcessEngineConfiguration.class.getName() + " otherwise");
        }

        return new JtaTransactionInterceptor(transactionManager);
    }

    @Override
    protected void initTransactionContextFactory() {
        if (transactionContextFactory == null) {
            transactionContextFactory = new JtaTransactionContextFactory(transactionManager);
        }
    }

    public TransactionManager getTransactionManager() {
        return transactionManager;
    }

    public void setTransactionManager(TransactionManager transactionManager) {
        this.transactionManager = transactionManager;

View on GitHub (pinned to d6d39ce1c6)