Given the following simple spring boot example application:
@SpringBootApplication
public class Application {
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
and
@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);
}
}
}
and the following example properties:
adres.properties:
table.name=adres
table.columns=personId,streetName,cityName
table.data.types=integer,string,string
person.properties:
table.name=person
table.columns=personId,firstName,lastName
table.data.types=integer,string,string
I want to
- add all the properties files from a directory using one import instead of having to add each individual property as a
@PropertySource
- retreive the values for each individual property file and do something with them
I have tried the following:
1.
Using the wildcard *
to get all properties from a directory ( http://docs.spring.io/spring/docs/current/spring-framework-reference/html/resources.html#resources-classpath-wildcards ) as follows:
@PropertySource(value="classpath*:properties/tables/*.properties")
throws java.io.FileNotFoundException: class path resource [properties/tables/*.properties] cannot be opened because it does not exist
, so it looks like it is parsing the *
as a literal value instead of a wildcard.
Adding a PropertySourcesPlaceholderConfigurer
to the Application class as suggested in How to read multiple properties having the same keys in Spring?:
@Bean
public static PropertySourcesPlaceholderConfigurer properties() {
PropertySourcesPlaceholderConfigurer config = new PropertySourcesPlaceholderConfigurer();
config.setIgnoreUnresolvablePlaceholders(true);
return config;
}
Doesn't seem to work either because the java.io.FileNotFoundException
gets thrown before the PropertySourcesPlaceholderConfigurer
is loaded.
2.
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:
table.name=person
{table.name}.columns=personId,firstName,lastName
{table.name}.data.types=integer,string,string
and in the Sample.class
@Value("${table.name}")
private String tableName;
@Value("${{table.name}.columns}")
private String[] columns;
@Value("${{table.name}.data.types}")
private String[] dataTypes;
The placeholders work, but I still have to manually add all the @PropertySource
and can only get the @Value
from the @PropertySource
that was loaded last.
EDIT: the placeholders actually dont work. When using the the following syntax:
${table.name}.columns=personId,firstName,lastName
and @Value("${${table.name}.columns}")
the following exception occurs:
Could not resolve placeholder 'person.columns' in string value "${${table.name}.columns}"
Question
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 (but still using the same key names) ?
EDIT 2: Partial solution / Workaround
Managed to create a workaround solution with regard to the value clashing:
@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<String> 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<String> dataTypes = Arrays.asList(types.split("\\s*,\\s*"));
// do more stuff
}
}