Question

Okay, I know this question has been asked several times over and I've tried every solution from their suggested answers but have yet to find one that works so I'm hoping someone on here can point me in the right direction.

I am trying to use Spring 4 with a Java-centric configuration but am having issues loading properties from a properties file. My latest approach is following almost verbatim Spring's documentation here but even that isn't working.

Here is my properties-config.xml file (located within a /config directory on my classpath):

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:context="http://www.springframework.org/schema/context"
   xsi:schemaLocation="
   http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
   http://www.springframework.org/schema/context
   http://www.springframework.org/schema/context/spring-context-4.0.xsd">

   <context:property-placeholder location="classpath:db.properties"/>

</beans>

Here is my web app initializer class (a snippet, anyways):

public class TestWebAppInitializer implements WebApplicationInitializer
{
   @Override
   public void onStartup(ServletContext container)
   {
      // Instantiate a new web application context
      AnnotationConfigWebApplicationContext appContext = 
            new AnnotationConfigWebApplicationContext();

      // Load the configurations
      appContext.scan("com.acme.config");
      appContext.refresh();

      // Add the dispatcher servlet
      ServletRegistration.Dynamic dispatcher =
            container.addServlet("dispatcher", new DispatcherServlet(appContext));
      dispatcher.setLoadOnStartup(1);

      // Add the various listeners
      container.addListener(new ContextLoaderListener(appContext));
      container.addListener(new RequestContextListener());
   }
}

And then finally a small sample configuration class which utilizes the properties file:

package com.acme.config;

@Configuration
@ImportResource("classpath:config/properties-config.xml")
public class HibernateConfiguration
{
   @Value("${jdbc.url}")
   private String jdbcUrl;

   @Value("${jdbc.username}")
   private String jdbcUsername;

   @Value("${jdbc.password")
   private String jdbcPassword;

   @Bean(name = "dataSource")
   public ComboPooledDataSource getDataSource() throws PropertyVetoException
   {
      // Define a variable to hold the result
      ComboPooledDataSource ds = new ComboPooledDataSource();

      System.out.println("URL: " + jdbcUrl);
      System.out.println("Username: " + jdbcUsername);
      System.out.println("Password: " + jdbcPassword);

      // Set the properties for the data source
      ds.setJdbcUrl(jdbcUrl);
      ds.setUser(jdbcUsername);
      ds.setPassword(jdbcPassword);

      // Return the result
      return ds;
   }
}

And last but not least, the properties file:

jdbc.url=jdbc:hsqldb:hsql://localhost/test
jdbc.username=myusername
jdbc.password=mypassword

The System.out.println statements all return "null" for each of the values which prevents my data source from getting setup.

Can someone please tell me what I am doing wrong? Thanks!

Was it helpful?

Solution 2

I finally found the issue. Actually, there were two. First, the order of the Bean definitions appeared to have mattered. Once I reordered them into a more appropriate order (ie, beanA is created first, beanB references beanA, beanC references beanA and beanB) it seemed to make a difference.

The main issue, however, was that there was a Bean definition for a PersistenceAnnotationBeanPostProcessor within the HibernateConfiguration class. This definition is why the Environment variable was null and no properties were being resolved.

Thanks to @Artem Bilan for all the help!

OTHER TIPS

The real issue here that annotation configuration is loaded before any imported XML and you really have to move the property-placeholder configuration to the @Configuration:

@Configuration    
@PropertySource("classpath:db.properties")
public class HibernateConfiguration {

    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }
}

Pay attention, please, for the propertySourcesPlaceholderConfigurer bean definition. Without it you can get access to you properties from file only using autowired Environment.

From here that property-placeholder configuration will be available for imported xml too.

For more info see PropertySource JavaDocs

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top