Announcement Announcement Module
Collapse
No announcement yet.
@PropertySource with AbstractJUnit4SpringContextTests and @ContextConfiguration Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • @PropertySource with AbstractJUnit4SpringContextTests and @ContextConfiguration

    Hi all,

    I am having a problem with eager bean creation. Lets assume we have the following @Configuration class:

    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
    
    }
    Testing this with the following throws an error - everything works fine when not using @PropertySource for DataSource properties and env.getProperty():

    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);
    	}
    
    }
    I will end up with java.lang.IllegalStateException: Failed to load ApplicationContext and the following log:

    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
    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.

    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
Working...
X