title: Spring : Loading multiple property files using a java configuration style
body: <p><strong>Given</strong> the following simple spring boot example application:</p>
  
  <pre><code>@SpringBootApplication
  public class Application {
  
      public static void main(String[] args) throws Exception {
          SpringApplication.run(Application.class, args);
      }   
  }
  </code></pre>
  
  <p>and</p>
  
  <pre><code>@PropertySource(value="classpath:properties/tables/adres.properties")
  @PropertySource(value="classpath:properties/tables/person.properties")
  @Component
  public class Sample {
  
      @Value("${table.name}")
      private String tableName;
  
      @Value("${table.columns}")
      private String[] columns;
  
      @Value("${table.data.types}")
      private String[] dataTypes;
  
      @PostConstruct
      public void init() {
          // do something with values from properties...
          for (String column : columns) {
              System.out.println(column);
          }
      }
  }
  </code></pre>
  
  <p>and the following example properties:<br>
  adres.properties:</p>
  
  <pre><code>table.name=adres
  table.columns=personId,streetName,cityName
  table.data.types=integer,string,string
  </code></pre>
  
  <p>person.properties:</p>
  
  <pre><code>table.name=person
  table.columns=personId,firstName,lastName
  table.data.types=integer,string,string
  </code></pre>
  
  <p><strong>I want to</strong></p>
  
  <ol>
  <li>add all the properties files from a directory using one import instead of having to add each individual property as a <code>@PropertySource</code></li>
  <li>retreive the values for each individual property file and do something with them</li>
  </ol>
  
  <p><strong>I have tried the following:</strong></p>
  
  <p>1.</p>
  
  <p>Using the wildcard <code>*</code> to get all properties from a directory ( <a href="http://docs.spring.io/spring/docs/current/spring-framework-reference/html/resources.html#resources-classpath-wildcards" rel="nofollow noreferrer">http://docs.spring.io/spring/docs/current/spring-framework-reference/html/resources.html#resources-classpath-wildcards</a> ) as follows: </p>
  
  <pre><code>@PropertySource(value="classpath*:properties/tables/*.properties")
  </code></pre>
  
  <p>throws <code>java.io.FileNotFoundException: class path resource [properties/tables/*.properties] cannot be opened because it does not exist</code>, so it looks like it is parsing the <code>*</code> as a literal value instead of a wildcard.</p>
  
  <p>Adding a <code>PropertySourcesPlaceholderConfigurer</code> to the Application class as suggested in <a href="https://stackoverflow.com/questions/10433186/how-to-read-multiple-properties-having-the-same-keys-in-spring?rq=1">How to read multiple properties having the same keys in Spring?</a>: </p>
  
  <pre><code>@Bean
  public static PropertySourcesPlaceholderConfigurer properties() {
      PropertySourcesPlaceholderConfigurer config = new PropertySourcesPlaceholderConfigurer();
      config.setIgnoreUnresolvablePlaceholders(true);
      return config;
  }
  </code></pre>
  
  <p>Doesn't seem to work either because the <code>java.io.FileNotFoundException</code> gets thrown before the <code>PropertySourcesPlaceholderConfigurer</code> is loaded.</p>
  
  <p>2.</p>
  
  <p>Retreiving the values also prove difficult because each individual property uses the same keys. This is done for consistency and maintability of the property files. I have tried solving this by using some more placeholders:</p>
  
  <pre><code>table.name=person
  {table.name}.columns=personId,firstName,lastName
  {table.name}.data.types=integer,string,string
  </code></pre>
  
  <p>and in the Sample.class</p>
  
  <pre><code>@Value("${table.name}")
  private String tableName;
  
  @Value("${{table.name}.columns}")
  private String[] columns;
  
  @Value("${{table.name}.data.types}")
  private String[] dataTypes;
  </code></pre>
  
  <p>The placeholders work, but I still have to manually add all the <code>@PropertySource</code> and can only get the <code>@Value</code> from the <code>@PropertySource</code> that was loaded last.</p>
  
  <p><strong>EDIT:</strong> the placeholders actually dont work. When using the the following syntax:
  <code>${table.name}.columns=personId,firstName,lastName</code> and <code>@Value("${${table.name}.columns}")</code> the  following exception occurs:</p>
  
  <pre><code>Could not resolve placeholder 'person.columns' in string value "${${table.name}.columns}" 
  </code></pre>
  
  <p><strong>Question</strong></p>
  
  <p>How do I solve my problem with regard to loading multiple property files and then retrieving the values from each individual property file in a java configuration style manner (<em>but still using the same key names</em>) ?   </p>
  
  <p><strong>EDIT 2: Partial solution / Workaround</strong></p>
  
  <p>Managed to create a workaround solution with regard to the value clashing:</p>
  
  <pre><code>@PropertySource(value="classpath:properties/tables/tables.properties")
  @PropertySource(value="classpath:properties/tables/person.properties")
  @PropertySource(value="classpath:properties/tables/address.properties")
  @Component
  public class Sample {
  
      private static final String COLUMNS = ".columns";
      private static final String DATA_TYPES = ".data.types";
  
      @Autowired
      private Environment env;
  
      @Value("${table.names}")
      private String[] tableNames;    
  
      @PostConstruct
      public void init() {
          for (String tableName : tableNames) {
              getTableValues(tableName);
          }       
      }
  
      private void getTableValues(String tableName) {
          String col = env.getProperty(tableName + COLUMNS);
          List&lt;String&gt; columns = Arrays.asList(col.split("\\s*,\\s*"));
          for (String column : columns) {
              System.out.println(String.format("The table %s contains the column %s", tableName, column));
          }
          String types = env.getProperty(tableName + DATA_TYPES);
          List&lt;String&gt; dataTypes = Arrays.asList(types.split("\\s*,\\s*"));
          // do more stuff
      }
  }
  </code></pre>