hibernate/hibernate-orm · error · IllegalStateException

EntityManagerFactory is closed

Error message

EntityManagerFactory is closed

What it means

Most SessionFactory/EntityManagerFactory accessors (getProperties(), metamodel access, createEntityManager()) start with validateNotClosed(), which throws IllegalStateException once the factory's status is CLOSED. Hibernate intentionally fails fast instead of serving stale data from a shut-down factory. The factory is a heavyweight object whose services are released by close().

Source

Thrown at hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java:780

	public StatelessSession openStatelessSession(@Nonnull Connection connection) {
		return withStatelessOptions().connection( connection ).openStatelessSession();
	}

	@Override
	public void addObserver(@Nonnull SessionFactoryObserver observer) {
		observerChain.addObserver( observer );
	}

	@Override
	@Nonnull
	public Map<String, Object> getProperties() {
		validateNotClosed();
		return settings;
	}

	protected void validateNotClosed() {
		if ( status == Status.CLOSED ) {
			throw new IllegalStateException( "EntityManagerFactory is closed" );
		}
	}

	@Override
	public String getUuid() {
		return uuid;
	}

	@Override
	public String getName() {
		return name;
	}

	@Override
	public String getJndiName() {
		return jndiName;
	}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Guard every access with if (emf != null && emf.isOpen()) before using the factory
  2. Fix the lifecycle ordering: close the EMF last, after all components that use it (check @PreDestroy / shutdown-hook order, Spring dependsOn)
  3. Cache any settings you need after close (e.g. copy getProperties() into your own map during startup) instead of reading them later
  4. In tests, use a shared EMF per suite or recreate it in @BeforeAll/@AfterAll so no test touches a closed factory

Example fix

// before
public Map<String, Object> config() {
    return emf.getProperties(); // throws if container already closed the EMF
}

// after
public Map<String, Object> config() {
    if (emf == null || !emf.isOpen()) {
        throw new IllegalStateException("application context already shut down");
    }
    return emf.getProperties();
}
Defensive patterns

Strategy: validation

Validate before calling

public Map<String, Object> safeProperties(EntityManagerFactory emf) {
    if (!emf.isOpen()) {
        throw new IllegalStateException("EntityManagerFactory is closed; cannot read properties");
    }
    return emf.getProperties();
}

Try / catch

try {
    return emf.getProperties();
} catch (IllegalStateException e) {
    // factory closed — fall back to a snapshot captured at startup
    return startupPropertySnapshot;
}

Prevention

When it happens

Trigger: Calling emf.getProperties(), emf.createEntityManager(), or any other guarded method after emf.close() (or Spring container shutdown closing the shared EMF). Typical in @PreDestroy ordering bugs, static EMF holders, or code that caches the EMF across application restarts in the same JVM.

Common situations: Spring Boot devtools restart or context refresh closing the EMF while a background thread still uses it; shutdown hooks that close the factory before other hooks read settings; test classes sharing a container-managed EMF that was closed by a previous test suite; fat-client apps that rebuild the factory but keep old references.

Related errors


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/d186f6c2a8bdfb64. Report an issue: GitHub.