{"record":{"id":"c2a183e454787e0e","repo":"hibernate/hibernate-orm","slug":"a-bean-manager-was-provided-via-jakarta-persisten","errorCode":null,"errorMessage":"A bean manager was provided via 'jakarta.persistence.bean.manager' but CDI is not available on the Hibernate class loader","messagePattern":"A bean manager was provided via 'jakarta\\.persistence\\.bean\\.manager' but CDI is not available on the Hibernate class loader","errorType":"exception","errorClass":"ServiceException","httpStatus":null,"severity":"critical","filePath":"hibernate-core/src/main/java/org/hibernate/resource/beans/spi/ManagedBeanRegistryInitiator.java","lineNumber":80,"sourceCode":"\tprivate static BeanContainer interpretImplicitBeanContainer(ServiceRegistry serviceRegistry) {\n\t\tfinal Collection<BeanContainer> beanContainers =\n\t\t\t\tserviceRegistry.requireService( ClassLoaderService.class )\n\t\t\t\t\t\t.loadJavaServices( BeanContainer.class );\n\t\treturn switch ( beanContainers.size() ) {\n\t\t\tcase 1 -> beanContainers.iterator().next();\n\t\t\tcase 0 -> interpretImplicitCdiBeanContainer( serviceRegistry );\n\t\t\tdefault -> throw new ServiceException( \"Multiple BeanContainer service implementations found\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t+ \" (set '\" + BEAN_CONTAINER + \"' explicitly)\" );\n\t\t};\n\t}\n\n\t// simplified CDI support\n\tprivate static BeanContainer interpretImplicitCdiBeanContainer(ServiceRegistry serviceRegistry) {\n\t\tfinal Object beanManager = getConfiguredBeanManager( serviceRegistry );\n\t\tfinal boolean isCdiAvailable = isCdiAvailable( serviceRegistry );\n\t\tif ( beanManager != null ) {\n\t\t\tif ( !isCdiAvailable ) {\n\t\t\t\tthrow new ServiceException( \"A bean manager was provided via '\" + JAKARTA_CDI_BEAN_MANAGER\n\t\t\t\t\t\t\t\t\t\t\t+ \"' but CDI is not available on the Hibernate class loader\");\n\t\t\t}\n\t\t\treturn CdiBeanContainerBuilder.fromBeanManagerReference( beanManager, serviceRegistry );\n\t\t}\n\t\telse {\n\t\t\tif ( isCdiAvailable ) {\n\t\t\t\tBEANS_MSG_LOGGER.noBeanManagerButCdiAvailable();\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tprivate static Object getConfiguredBeanManager(ServiceRegistry serviceRegistry) {\n\t\tfinal Map<String, Object> settings = serviceRegistry.requireService( ConfigurationService.class ).getSettings();\n\t\tfinal Object beanManager = settings.get( JAKARTA_CDI_BEAN_MANAGER );\n\t\treturn beanManager != null ? beanManager : settings.get( CDI_BEAN_MANAGER );\n\t}\n","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/resource/beans/spi/ManagedBeanRegistryInitiator.java#L62-L98","documentation":"When a BeanManager reference is supplied via 'jakarta.persistence.bean.manager', Hibernate first verifies that the CDI API itself is loadable through its own ClassLoaderService (isCdiAvailable). If jakarta.enterprise.inject.spi.BeanManager cannot be loaded from Hibernate's class loader, it refuses to use the reference and throws ServiceException at bootstrap.","triggerScenarios":"Passing a BeanManager while hibernate-core cannot see the CDI API: cdi-api missing from the application classpath, a module-path/layered classloading setup where Hibernate's class loader does not read the CDI module, or the bean manager object coming from a different classloader than Hibernate.","commonSituations":"Shaded/modular applications that omit jakarta.enterprise.cdi-api; app-server deployments with visibility restrictions on Hibernate's class loader; SE apps where the property is set globally but CDI is not actually used.","solutions":["Add jakarta.enterprise:jakarta.enterprise.cdi-api (and an implementation if beans are used) to the same classpath/classloader as hibernate-core.","In modular setups, ensure Hibernate's module reads the CDI API module (requires static jakarta.enterprise.cdi).","Remove the 'jakarta.persistence.bean.manager' property when CDI is not actually in use.","Verify with Class.forName(\"jakarta.enterprise.inject.spi.BeanManager\") on Hibernate's classloader during a startup check."],"exampleFix":"// before\nMap<String, Object> props = Map.of(\"jakarta.persistence.bean.manager\", weldBeanManager);\n// hibernate-core cannot load jakarta.enterprise.inject.spi.BeanManager -> ServiceException\n\n// after - put the CDI API next to hibernate-core (Maven)\n<dependency>\n  <groupId>jakarta.enterprise</groupId>\n  <artifactId>jakarta.enterprise.cdi-api</artifactId>\n</dependency>\n// or drop the property entirely when CDI is not used","handlingStrategy":"validation","validationCode":"// only pass a bean manager if Hibernate can see the CDI API on its classloader\ntry {\n    Class.forName(\"jakarta.enterprise.inject.spi.BeanManager\", false,\n        org.hibernate.Internal.class.getClassLoader());\n} catch (ClassNotFoundException e) {\n    props.remove(\"jakarta.persistence.bean.manager\"); // or fix the classpath first\n}","typeGuard":null,"tryCatchPattern":"try {\n    emf = Persistence.createEntityManagerFactory(\"pu\", props);\n} catch (org.hibernate.service.spi.ServiceException e) {\n    if (e.getMessage().contains(\"CDI is not available\")) {\n        // add cdi-api next to hibernate-core, or remove the bean.manager property\n        throw new ConfigurationException(e.getMessage(), e);\n    }\n    throw e;\n}","preventionTips":["Ship jakarta.enterprise.cdi-api on the same classloader as hibernate-core.","In JPMS deployments, make Hibernate's module read the CDI module.","Do not set jakarta.persistence.bean.manager unless CDI is really in use."],"tags":["hibernate","cdi","classpath","module-system","bootstrap"],"backgroundTag":"classloader-visibility","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}