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
- Set the property explicitly to one implementation: props.put("hibernate.resource.beans.container", "org.hibernate.resource.beans.container.internal.CdiBeanContainerImpl").
- Find and exclude the duplicate integration dependency from the classpath (check the dependency tree).
- Inspect the merged META-INF/services/org.hibernate.resource.beans.spi.BeanContainer file in fat jars and keep a single line.
- 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
- Audit META-INF/services/org.hibernate.resource.beans.spi.BeanContainer after shading or merging jars.
- Keep a single CDI integration dependency on the classpath.
- Set 'hibernate.resource.beans.container' explicitly in managed environments.
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
- A bean manager was provided via 'jakarta.persistence.bean.ma
- Unable to locate schema [{}] via classpath
- Multiple MutationExecutorService service registrations found
- Custom event-type already registered:
- ExtendedBeanManager.LifecycleListener callback not yet calle
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/1524f8083b472cbb.
Report an issue: GitHub.