flowable/flowable-engine · error · FlowableException

transactionManager is required property for…

Error message

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

What it means

JtaProcessEngineConfiguration requires a JTA TransactionManager; its createTransactionInterceptor override throws this FlowableException at engine bootstrap when transactionManager was never set. The message points you to StandaloneProcessEngineConfiguration as the alternative if you do not run inside a JTA environment. The failure happens while building the command-interceptor chain, i.e. before the process engine becomes usable.

Solutions

  1. Set the JTA transactionManager before buildProcessEngine(), e.g. configuration.setTransactionManager((TransactionManager) new InitialContext().lookup("java:/TransactionManager")) for JNDI-provided JTA
  2. If you do not need JTA, switch to org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration so transaction handling matches your environment
  3. In Spring setups, use SpringProcessEngineConfiguration with the Spring PlatformTransactionManager instead of manual JTA wiring

Example fix

// before
ProcessEngineConfiguration cfg = new JtaProcessEngineConfiguration()
    .setDataSource(dataSource);
ProcessEngine engine = cfg.buildProcessEngine(); // throws

// after
TransactionManager tm = (TransactionManager) new InitialContext().lookup("java:/TransactionManager");
JtaProcessEngineConfiguration cfg = new JtaProcessEngineConfiguration();
cfg.setDataSource(dataSource);
cfg.setTransactionManager(tm);
ProcessEngine engine = cfg.buildProcessEngine();
Defensive patterns

Strategy: validation

Validate before calling

// before buildProcessEngine()
if (cfg instanceof JtaProcessEngineConfiguration
    && ((JtaProcessEngineConfiguration) cfg).getTransactionManager() == null) {
  throw new IllegalStateException(
    "JtaProcessEngineConfiguration requires a transactionManager; "
    + "or use StandaloneProcessEngineConfiguration");
}

Type guard

boolean isJtaConfigReady(ProcessEngineConfiguration cfg) {
  return !(cfg instanceof JtaProcessEngineConfiguration)
      || ((JtaProcessEngineConfiguration) cfg).getTransactionManager() != null;
}

Try / catch

try {
  return processEngineConfiguration.buildProcessEngine();
} catch (FlowableException e) {
  if (e.getMessage() != null && e.getMessage().startsWith("transactionManager is required")) {
    throw new IllegalStateException(
      "Wire a JTA TransactionManager into the configuration, or switch to "
      + "StandaloneProcessEngineConfiguration", e);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling buildProcessEngine() on a JtaProcessEngineConfiguration without calling setTransactionManager(...); creating the config from a flowable.cfg.xml / properties file where the transactionManager property is missing; bootstrapping in a non-JTA environment with the wrong configuration class.

Common situations: Migrating from StandaloneProcessEngineConfiguration to JtaProcessEngineConfiguration (e.g. deploying inside WildFly/WebSphere/WebLogic) and forgetting to wire the app server's JTA TransactionManager; misconfigured Java EE datasource setup; copying a standalone flowable.cfg.xml into a JTA environment.

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/e9f062fa58e5e682. Report an issue: GitHub.

Appendix: source

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

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

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

    protected TransactionManager transactionManager;

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

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

        return new JtaTransactionInterceptor(transactionManager);
    }

    @Override
    public 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)