Hi all,
I am having a problem with eager bean creation. Lets assume we have the following @Configuration class:
Testing this with the following throws an error - everything works fine when not using @PropertySource for DataSource properties and env.getProperty():Code:@Configuration @Profile("development") @PropertySource("classpath:dev.properties") public class DevelopmentRepositoryConfig { @Autowired @Qualifier("wurthshopDataSource") private DataSource shopDataSource; //more datasources - not needed for demonstration @Autowired Environment env; @Bean(autowire = Autowire.BY_NAME) public ComboPooledDataSource shopDataSource() throws PropertyVetoException { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setUser(env.getProperty("db.user")); dataSource.setPassword(env.getProperty("db.password")); dataSource.setJdbcUrl(env.getProperty("db.url")); dataSource.setDriverClass(env.getProperty("db.driverClass.mysql")); dataSource.setIdleConnectionTestPeriod(600); dataSource.setPreferredTestQuery("SELECT 1;"); dataSource.setMinPoolSize(5); dataSource.setMaxPoolSize(10); dataSource.setMaxIdleTime(60); return dataSource; } @Bean(autowire = Autowire.BY_NAME) public SessionFactory wurthshopSessionFactory(){ Properties props = new Properties(); props.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQLDialect"); props.setProperty("hibernate.current_session_context_class", "org.springframework.orm.hibernate4.SpringSessionContext"); props.setProperty("hibernate.connection.driver_class", env.getProperty("db.driverClass.mysql")); props.setProperty("hibernate.connection.url", env.getProperty("db.url")); props.setProperty("hibernate.connection.username", env.getProperty("db.user")); props.setProperty("hibernate.connection.password", env.getProperty("db.password")); props.setProperty("hibernate.c3p0.min_size", "10"); props.setProperty("hibernate.c3p0.max_size", "50"); //props.setProperty("hibernate.c3p0.timeout", "1800"); props.setProperty("hibernate.c3p0.max_statements", "50"); props.setProperty("hibernate.c3p0.preferredTestQuery", "SELECT 1;"); props.setProperty("hibernate.c3p0.idle_test_period", "600"); props.setProperty("hibernate.c3p0.validate", "true"); props.setProperty("hibernate.c3p0.timeout", "300"); return new LocalSessionFactoryBuilder(shopDataSource) .scanPackages("com.shop.domain") .setProperties(props) .buildSessionFactory(); } //more datasources and sessionFactories - not needed for demonstration }
I will end up with java.lang.IllegalStateException: Failed to load ApplicationContext and the following log:Code:@ContextConfiguration(classes= {PropertiesConfig.class, DevelopmentRepositoryConfig.class}, loader = AnnotationConfigContextLoader.class) @ActiveProfiles("development") public class HibernateConfigurationTest extends AbstractJUnit4SpringContextTests { @Autowired @Qualifier("shopSessionFactory") private SessionFactory sessionFactory; @Autowired Environment env; @Test public void testEnvironment() { assertTrue("environment is dev", "development".equals(env.getActiveProfiles()[0])); assertTrue("shop user is root", "root".equals(env.getProperty("db.user"))); assertTrue("shop password is root", "root".equals(env.getProperty("db.password"))); assertTrue("shop url is", "jdbc:mysql://localhost/shop".equals(env.getProperty("db.url"))); assertTrue("shop driver is", "com.mysql.jdbc.Driver".equals(env.getProperty("db.driverClass.mysql"))); } @Test public void testHibernateConfiguration() { // Spring IOC container instantiated and prepared sessionFactory assertNotNull(sessionFactory); } }
Could it be that @PropertySource is initialized too late to actually be used within the DevelopmentRepositoryConfig? Both tests will fail when using @PropertySource properties in DataSource/SessionFactory bean but pass when db.user etc. are set directly - meaning Environment itself seems to be fine.Code:14:09:10,119 DEBUG DefaultListableBeanFactory:217 - Creating shared instance of singleton bean 'developmentRepositoryConfig' 14:09:10,120 DEBUG DefaultListableBeanFactory:430 - Creating instance of bean 'developmentRepositoryConfig' 14:09:10,122 DEBUG InjectionMetadata:60 - Found injected element on class [com.wurthusa.intranet.config.DevelopmentRepositoryConfig$$EnhancerByCGLIB$$6a31034a]: AutowiredFieldElement for private javax.sql.DataSource com.shop.config.DevelopmentRepositoryConfig.shopDataSource 14:09:10,123 DEBUG InjectionMetadata:60 - Found injected element on class [com.shop.config.DevelopmentRepositoryConfig$$EnhancerByCGLIB$$6a31034a]: AutowiredFieldElement for private javax.sql.DataSource com.shop.config.DevelopmentRepositoryConfig.specialOrdersDataSource 14:09:10,123 DEBUG InjectionMetadata:60 - Found injected element on class [com.shop.config.DevelopmentRepositoryConfig$$EnhancerByCGLIB$$6a31034a]: AutowiredFieldElement for private javax.sql.DataSource com.shop.config.DevelopmentRepositoryConfig.vacationDataSource 14:09:10,123 DEBUG InjectionMetadata:60 - Found injected element on class [com.shop.config.DevelopmentRepositoryConfig$$EnhancerByCGLIB$$6a31034a]: AutowiredFieldElement for org.springframework.core.env.Environment com.shop.config.DevelopmentRepositoryConfig.env 14:09:10,123 DEBUG DefaultListableBeanFactory:504 - Eagerly caching bean 'developmentRepositoryConfig' to allow for resolving potential circular references 14:09:10,126 DEBUG InjectionMetadata:85 - Processing injected method of bean 'developmentRepositoryConfig': AutowiredFieldElement for private javax.sql.DataSource com.shop.config.DevelopmentRepositoryConfig.shopDataSource 14:09:10,127 DEBUG DefaultListableBeanFactory:217 - Creating shared instance of singleton bean 'shopDataSource' 14:09:10,127 DEBUG DefaultListableBeanFactory:430 - Creating instance of bean 'shopDataSource' 14:09:10,127 DEBUG DefaultListableBeanFactory:241 - Returning eagerly cached instance of singleton bean 'developmentRepositoryConfig' that is not fully initialized yet - a consequence of a circular reference
Any input is appreciated,
Michael
dev.properties:
Code:db.driverClass.mysql=com.mysql.jdbc.Driver db.user.shop=root db.password.shop=root db.url.shop=jdbc\:mysql\://localhost/shop


Reply With Quote