title: How do I configure Spring to partially and optionally override properties?
body: <p>I would like to have a properties setup which can, on certain environments, override specific properties. For example, our default JDBC properties for dev are: </p>
  
  <ul>
  <li>db.driverClassName=com.mysql.jdbc.Driver</li>
  <li>db.url=jdbc:mysql://localhost:3306/ourdb</li>
  <li>db.username=root</li>
  <li>db.password=</li>
  </ul>
  
  <p>The problem is that some of our devs would like to have a different username/password on the db, or possibly even a non locally hosted db. The same is true for our rabbitMQ configuration, which currently uses a similar localhost, guest/guest setup. Being able to override the properties of certain elements of this configuration on a per-developer basis would allow us to move much of the infrastructure/installation requirements for building the software off the local machine and onto dedicated servers.</p>
  
  <p>I have set-up a simple project to wrap my head around the configuration required to achieve what I want, and this is my first foray into the world of spring property configuration, since up till now, property loading and management is done with some custom code. Here is my setup:</p>
  
  <pre><code>class Main_PropertyTest {
      public static void main(String[] args) {
          String environment = System.getenv("APPLICATION_ENVIRONMENT"); // Environment, for example: "dev"
          String subEnvironment = System.getenv("APPLICATION_SUB_ENVIRONMENT"); // Developer name, for example: "joe.bloggs"
          System.setProperty("spring.profiles.active", environment);
          System.setProperty("spring.profiles.sub", subEnvironment);
  
          try(AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(PropertyTestConfiguration.class)) {
              Main_PropertyTest main = context.getBean(Main_PropertyTest.class);
              main.printProperty();
          }
      }
  
      private final String property;
  
      public Main_PropertyTest(String property) {
          this.property = property;
      }
  
      public void printProperty() {
          System.out.println("And the property is: '" + property + "'.");
      }
  }
  </code></pre>
  
  <p>And my configuration:</p>
  
  <pre><code>@Configuration
  public class PropertyTestConfiguration {
      @Bean
      public static PropertySourcesPlaceholderConfigurer primaryPlaceholderConfigurer() {
          PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
          propertySourcesPlaceholderConfigurer.setLocation(new ClassPathResource(System.getProperty("spring.profiles.active") + ".main.properties"));
          return propertySourcesPlaceholderConfigurer;
      }
  
      @Bean
      public static PropertySourcesPlaceholderConfigurer secondaryPlaceholderConfigurer() {
          PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
          propertySourcesPlaceholderConfigurer.setLocation(new ClassPathResource(System.getProperty("spring.profiles.sub") + ".main.properties"));
          propertySourcesPlaceholderConfigurer.setIgnoreResourceNotFound(true);
          propertySourcesPlaceholderConfigurer.setIgnoreResourceNotFound(true);
          propertySourcesPlaceholderConfigurer.setOrder(-1);
          return propertySourcesPlaceholderConfigurer;
      }
  
      @Bean
      public Main_PropertyTest main_PropertyTest(@Value("${main.property}") String property) {
          Main_PropertyTest main_PropertyTest = new Main_PropertyTest(property);
          return main_PropertyTest;
      }
  }
  </code></pre>
  
  <p>And for completeness, my dev.main.properties and test.main.properties:</p>
  
  <pre><code>main.property=dev
  
  main.property=test
  </code></pre>
  
  <p>The main problem is that I get an illegal argument exception. As far as I can tell, what I have written should be the javaconfig equivalent of this method: <a href="http://taidevcouk.wordpress.com/2013/07/04/overriding-a-packaged-spring-application-properties-file-via-an-external-file/" rel="nofollow">http://taidevcouk.wordpress.com/2013/07/04/overriding-a-packaged-spring-application-properties-file-via-an-external-file/</a>
  Unfortunately I get the following error:  java.lang.IllegalArgumentException: Could not resolve placeholder 'main.property' in string value "${main.property}". Note that I also need to take care of the case where there is no sub-environment, and this is the case I have started with (although I get the same error even if both files exist). If I remove the bean which sets up the second propertysourcesplaceholderconfigurer, then it all works fine (by which I mean dev.main.properties is loaded and "And the property is: 'dev'." is printed out).</p>
  
  <p>A secondary problem is that the code doesn't look great, and each layer of the system will need two PSPC's set-up so that they can access these properties. Furthermore, it requires a lot of manual calls to System.getProperty(), since I couldn't pass ${spring.profiles.active} to PSPC.setLocation();</p>
  
  <p><b>Note:</b> I have tried @PropertySources({primaryproperties, secondaryProperties}), but this fails because secondaryProperties does not exist. I have also tried @Autowired Environment environment; and getting the properties from that, but the secondary PSPC causes the environment to not be autowired...</p>
  
  <p>So following this lengthy explanation, my questions are: </p>
  
  <ul>
  <li>Is this the right way of solving this problem?</li>
  <li>If so, what is wrong with my configuration?</li>
  <li>How can I simplify the configuration (if at all)?</li>
  <li>Is there an alternative mechanism available which would solve my problem?</li>
  </ul>
  
  <p>Thank you for your time! :)</p>