No Configured Bean Provider Manager during bootstrap

Hey there, I’ve got:

  1. A custom IndexLayoutStrategy that I’ve defined. This is a bean in my application context. It uses another bean, which is autowired into it.
  2. A JpaProperties bean which includes all necessary HS setup, including pointing at my custom index layout strategy.

When I attempt to boot my test scenario, i get:

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in ca.uhn.fhir.jpa.config.TestR4ConfigWithElasticSearch: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: PU_TEST] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.search.util.common.SearchException: HSEARCH000520: Hibernate Search encountered failures during bootstrap. Failures:

    Hibernate ORM mapping: 
        type 'ca.test.tester.jpa.entity.MyEntity': 
            failures: 
              - Cannot invoke "ca.test.tester.jpa.api.config.MyAutowiredBean.someMethod()" because "this.MyAutowiredBean" is null

When I actually breakpoint through the ElasticsearchBackendFactory’s initialization, I see that the BeanResolver.beanManagerBeanProvider is set to NoConfiguredBeanProvider. This tells me that HS is simply creating a new instance of my class via public constructor, which explains why anything i had set to autowire is null. Below are the salient parts of the code. Any thoughts on what I’m missing here? Below is a sample @Configuration, if i run an empty test with this config, I get the above error:

@Configuration
public class DummyConfig {

	@Bean
	public MyAutowiredBean autowiredBean() {
		return new MyAutowiredBean();
	}

	@Bean
	public MyIndexLayoutStrategy indexLayoutStrategy() {
		return new MyIndexLayoutStrategy();
	}

	@Bean
	public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
		LocalContainerEntityManagerFactoryBean retVal = new HapiFhirLocalContainerEntityManagerFactoryBean();
		retVal.setJpaDialect(new HibernateJpaDialect());
		retVal.setPackagesToScan("ca.test.tester.jpa.model.entity", "ca.test.tester.jpa.entity");
		retVal.setPersistenceProvider(new HibernatePersistenceProvider());
		retVal.setPersistenceUnitName("PU_TEST");
		retVal.setDataSource(dataSource());
		retVal.setJpaProperties(jpaProperties());
		return retVal;
	}
	@Bean
	public DataSource dataSource() {
		BasicDataSource retVal = new BasicDataSource();
		retVal.setDriver(new org.h2.Driver());
		retVal.setUrl("jdbc:h2:mem:testdb_r4");
		retVal.setMaxWaitMillis(30000);
		retVal.setUsername("");
		retVal.setPassword("");
		retVal.setMaxTotal(5);
		DataSource dataSource = ProxyDataSourceBuilder
			.create(retVal)
			.build();

		return dataSource;
	}

	@Bean
	public Properties jpaProperties() {
		Properties extraProperties = new Properties();
		extraProperties.put("hibernate.format_sql", "false");
		extraProperties.put("hibernate.show_sql", "false");
		extraProperties.put("hibernate.hbm2ddl.auto", "update");
		extraProperties.put("hibernate.dialect", H2Dialect.class.getName());
		int httpPort = elasticContainer().getMappedPort(9200);
		String host = elasticContainer().getHost();
		extraProperties.put(BackendSettings.backendKey(BackendSettings.TYPE), "elasticsearch");
		extraProperties.put(BackendSettings.backendKey(ElasticsearchIndexSettings.ANALYSIS_CONFIGURER), HapiElasticsearchAnalysisConfigurer.class.getName());
		extraProperties.put(BackendSettings.backendKey(ElasticsearchBackendSettings.HOSTS), host + ":" + httpPort);
		extraProperties.put(BackendSettings.backendKey(ElasticsearchBackendSettings.PROTOCOL), "http");
		extraProperties.put(HibernateOrmMapperSettings.SCHEMA_MANAGEMENT_STRATEGY, SchemaManagementStrategyName.CREATE.externalRepresentation());
		extraProperties.put(BackendSettings.backendKey(ElasticsearchIndexSettings.SCHEMA_MANAGEMENT_MINIMAL_REQUIRED_STATUS_WAIT_TIMEOUT), Long.toString(10000));
		extraProperties.put(BackendSettings.backendKey(ElasticsearchIndexSettings.SCHEMA_MANAGEMENT_MINIMAL_REQUIRED_STATUS), IndexStatus.YELLOW.externalRepresentation());
		// Need the mapping to be dynamic because of terminology indexes.
		extraProperties.put(BackendSettings.backendKey(ElasticsearchIndexSettings.DYNAMIC_MAPPING), "true");
extraProperties.put(HibernateOrmMapperSettings.AUTOMATIC_INDEXING_SYNCHRONIZATION_STRATEGY, "read-sync");
extraProperties.put(BackendSettings.backendKey(ElasticsearchBackendSettings.LOG_JSON_PRETTY_PRINTING), Boolean.toString(true));
extraProperties.put(BackendSettings.backendKey(ElasticsearchBackendSettings.LAYOUT_STRATEGY), MyIndexLayoutStrategy.class.getName());
		return extraProperties;
	}

	@Bean
	public ElasticsearchContainer elasticContainer() {
		ElasticsearchContainer embeddedElasticSearch = TestElasticsearchContainerHelper.getEmbeddedElasticSearch();
		embeddedElasticSearch.start();
		return embeddedElasticSearch;
	}
}

My apologies for the verboseness, i"m just wondering why there is no bean provider during bootstrapping.

Hello,

One reason you’re getting this behavior could be because Hibernate ORM didn’t detect Spring.

I’m not very familiar with how Spring lets itself be known to Hibernate ORM, but I assume it’s possible that all your overriding of the creation of the EntityManagerFactory could have overridden a critical setting meant to pass the bean context to Hibernate ORM?

If you go through org.hibernate.resource.beans.spi.ManagedBeanRegistryInitiator#resolveBeanContainer in debug mode, explicitBeanContainer should be non-null. If it’s null, it means you did override some critical setting (probably by mistake) that usually gets set automatically by Spring.

Will check and report back. Cheers.

edit: Heh, yup, looks like it is null. Will try to go hunt it down

Based on some googling, I found this SO link which seems like a very likely candidate. Will investigate and report back for posterity

1 Like

So, if you are using even the very basic LocalContainerEntityManagerFactoryBean, you can fix this by manually setting the attribute by overriding getJpaPropertymap and adding: the jpaPropertyMap:

                        Properties props = super.getJpaProperties();
			props.put(AvailableSettings.BEAN_CONTAINER, new SpringBeanContainer(myConfigurableListableBeanFactory));

This has fixed my issue and HS bootstrapping can now find beans in context :tada:

1 Like