hibernate/hibernate-orm · critical · ServiceException

Multiple BeanContainer service implementations found (set 'h

Error message

Multiple BeanContainer service implementations found (set 'hibernate.resource.beans.container' explicitly)

What it means

ManagedBeanRegistryInitiator discovers BeanContainer implementations through the Java ServiceLoader (META-INF/services/org.hibernate.resource.beans.spi.BeanContainer) and requires exactly one when 'hibernate.resource.beans.container' is unset. Finding more than one is ambiguous, so bootstrap fails with ServiceException('Multiple BeanContainer service implementations found (set hibernate.resource.beans.container explicitly)').

Source

Thrown at hibernate-core/src/main/java/org/hibernate/resource/beans/spi/ManagedBeanRegistryInitiator.java:69

		return new ManagedBeanRegistryImpl( resolveBeanContainer( configurationValues, serviceRegistry ) );
	}

	private BeanContainer resolveBeanContainer(Map<?,?> configurationValues, ServiceRegistry serviceRegistry) {
		// was a specific container explicitly specified?
		final Object explicitBeanContainer = configurationValues.get( BEAN_CONTAINER );
		return explicitBeanContainer == null
				? interpretImplicitBeanContainer( serviceRegistry )
				: interpretExplicitBeanContainer( explicitBeanContainer, serviceRegistry );
	}

	private static BeanContainer interpretImplicitBeanContainer(ServiceRegistry serviceRegistry) {
		final Collection<BeanContainer> beanContainers =
				serviceRegistry.requireService( ClassLoaderService.class )
						.loadJavaServices( BeanContainer.class );
		return switch ( beanContainers.size() ) {
			case 1 -> beanContainers.iterator().next();
			case 0 -> interpretImplicitCdiBeanContainer( serviceRegistry );
			default -> throw new ServiceException( "Multiple BeanContainer service implementations found"
													+ " (set '" + BEAN_CONTAINER + "' explicitly)" );
		};
	}

	// simplified CDI support
	private static BeanContainer interpretImplicitCdiBeanContainer(ServiceRegistry serviceRegistry) {
		final Object beanManager = getConfiguredBeanManager( serviceRegistry );
		final boolean isCdiAvailable = isCdiAvailable( serviceRegistry );
		if ( beanManager != null ) {
			if ( !isCdiAvailable ) {
				throw new ServiceException( "A bean manager was provided via '" + JAKARTA_CDI_BEAN_MANAGER
											+ "' but CDI is not available on the Hibernate class loader");
			}
			return CdiBeanContainerBuilder.fromBeanManagerReference( beanManager, serviceRegistry );
		}
		else {
			if ( isCdiAvailable ) {
				BEANS_MSG_LOGGER.noBeanManagerButCdiAvailable();

View on GitHub (pinned to fad1729dce)

Solutions

  1. Set the property explicitly to one implementation: props.put("hibernate.resource.beans.container", "org.hibernate.resource.beans.container.internal.CdiBeanContainerImpl").
  2. Find and exclude the duplicate integration dependency from the classpath (check the dependency tree).
  3. Inspect the merged META-INF/services/org.hibernate.resource.beans.spi.BeanContainer file in fat jars and keep a single line.
  4. Verify with ServiceLoader.load(BeanContainer.class) in a startup self-check that exactly one provider resolves.

Example fix

// before
// classpath contains both weld-hibernate-integration.jar and appserver-integration.jar,
// each registering META-INF/services/...BeanContainer -> ServiceException at boot

// after
Map<String, Object> props = new HashMap<>();
props.put("hibernate.resource.beans.container",
    "org.hibernate.resource.beans.container.internal.CdiBeanContainerImpl");
EntityManagerFactory emf = Persistence.createEntityManagerFactory("pu", props);
Defensive patterns

Strategy: validation

Validate before calling

// startup self-check: exactly one BeanContainer provider on the classpath
List<BeanContainer> providers = new ArrayList<>();
for (BeanContainer bc : ServiceLoader.load(BeanContainer.class, Thread.currentThread().getContextClassLoader())) {
    providers.add(bc);
}
if (providers.size() > 1) {
    props.put("hibernate.resource.beans.container", chosenProvider.getClass().getName());
}

Try / catch

try {
    emf = Persistence.createEntityManagerFactory("pu", props);
} catch (org.hibernate.service.spi.ServiceException e) {
    if (e.getMessage().contains("Multiple BeanContainer")) {
        // set hibernate.resource.beans.container explicitly or drop the duplicate integration jar
        throw new ConfigurationException(e.getMessage(), e);
    }
    throw e;
}

Prevention

When it happens

Trigger: The runtime classpath carries two or more BeanContainer service registrations: e.g. a Weld/Omnifaces-style CDI integration plus a platform-specific one (Quarkus, app server), or two copies of an integration jar.

Common situations: Fat/shaded jars that merge multiple META-INF/services files; mixing app-server integration fragments into a SE app; dependency upgrades pulling in an extra Hibernate-CDI integration transitively.

Related errors


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