flowable/flowable-engine · error · ActivitiIllegalArgumentException

EntityManagerFactory must implement 'jakarta.persistence.Ent

Error message

EntityManagerFactory must implement 'jakarta.persistence.EntityManagerFactory'

What it means

EntityManagerSessionFactory's constructor type-checks the entityManagerFactory argument against jakarta.persistence.EntityManagerFactory and throws ActivitiIllegalArgumentException if it is any other type. This catches callers passing a wrong-typed object (e.g. a Hibernate SessionFactory or a javax version of EntityManagerFactory after a namespace migration).

Source

Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/variable/EntityManagerSessionFactory.java:37

import org.activiti.engine.impl.interceptor.Session;
import org.activiti.engine.impl.interceptor.SessionFactory;
import org.flowable.variable.service.impl.types.EntityManagerSession;

/**
 * @author Frederik Heremans
 */
public class EntityManagerSessionFactory implements SessionFactory {

    protected EntityManagerFactory entityManagerFactory;
    protected boolean handleTransactions;
    protected boolean closeEntityManager;

    public EntityManagerSessionFactory(Object entityManagerFactory, boolean handleTransactions, boolean closeEntityManager) {
        if (entityManagerFactory == null) {
            throw new ActivitiIllegalArgumentException("entityManagerFactory is null");
        }
        if (!(entityManagerFactory instanceof EntityManagerFactory)) {
            throw new ActivitiIllegalArgumentException("EntityManagerFactory must implement 'jakarta.persistence.EntityManagerFactory'");
        }

        this.entityManagerFactory = (EntityManagerFactory) entityManagerFactory;
        this.handleTransactions = handleTransactions;
        this.closeEntityManager = closeEntityManager;
    }

    @Override
    public Class<?> getSessionType() {
        return EntityManagerSession.class;
    }

    @Override
    public Session openSession() {
        return new EntityManagerSessionImpl(entityManagerFactory, handleTransactions, closeEntityManager);
    }

    public EntityManagerFactory getEntityManagerFactory() {

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Pass a jakarta.persistence.EntityManagerFactory instance (e.g. Spring's LocalContainerEntityManagerFactoryBean's getObject())
  2. Upgrade/downgrade dependencies so all JPA classes come from the jakarta.persistence namespace, not javax.persistence
  3. Replace direct Hibernate SessionFactory usage with the JPA EntityManagerFactory facade
  4. Check import statements: jakarta.persistence.EntityManagerFactory, not javax.persistence

Example fix

// before
import javax.persistence.EntityManagerFactory; // wrong namespace
processEngineConfiguration.setJpaEntityManagerFactory(javaxEmf);
// after
import jakarta.persistence.EntityManagerFactory;
processEngineConfiguration.setJpaEntityManagerFactory(jakartaEmf);
Defensive patterns

Strategy: type-guard

Validate before calling

// check the exact type before constructing
if (!(obj instanceof jakarta.persistence.EntityManagerFactory)) {
  throw new IllegalStateException("expected jakarta.persistence.EntityManagerFactory, got " + obj.getClass().getName());
}

Type guard

boolean isJakartaEmf(Object o) {
  return o instanceof jakarta.persistence.EntityManagerFactory;
}

Try / catch

try {
  processEngineConfiguration.setJpaEntityManagerFactory(emf);
} catch (ActivitiIllegalArgumentException e) {
  logger.error("wrong EntityManagerFactory type: " + emf.getClass().getName(), e);
  throw e;
}

Prevention

When it happens

Trigger: new EntityManagerSessionFactory(someObject, ...) where someObject is non-null but not an instance of jakarta.persistence.EntityManagerFactory — e.g. javax.persistence.EntityManagerFactory from a pre-Jakarta JPA provider, or a raw Hibernate SessionFactory.

Common situations: Migrating from Java EE javax.* to Jakarta EE 9+ namespaces with mixed dependency versions; passing a Hibernate ORM SessionFactory instead of a JPA EntityManagerFactory; wrong bean injected by type confusion.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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