Some of these patterns I learned while developing the Drug Database and API for Telus Health. However, the major portion of these patterns I picked up while developing with ProntoForms Inc.
Requirements
R1) Environment variance: Some of the configuration will vary depending on whether we are in a production, staging, qa or dev deployment.
R2) Developer and Task specific: We will allow for developer and task discriminators to further specialize and override properties
R3) Plural properties: We need the ability to specify arbitrary sets or lists of property values - via XML or YAML
Implementation
Normally I would put the ecosystem, discriminator and developer variables in the @Value annotation to do some runtime dynamic substitution. However, this would target only a specific node in the properties tree. What we need is a layered resolution of properties where we override any properties previously loaded with those deeper in the tree. We accomplish this by loading the properties in sequence.
<context:property-placeholder
location="file:///${os.environment.configuration.dir}//${os.environment.ecosystem}/biometric.properties"
order="1" ignore-unresolvable="true" ignore-resource-not-found="true"/>
<context:property-placeholder
location="file:///${os.environment.configuration.dir}//${os.environment.ecosystem}/${os.environment.discriminator:}/biometric.properties"
order="2" ignore-unresolvable="true" ignore-resource-not-found="true"/>
<context:property-placeholder
location="file:///${os.environment.configuration.dir}//${os.environment.ecosystem}/${os.environment.developer.username:}/biometric.properties"
order="3" ignore-unresolvable="true" ignore-resource-not-found="true"/>
<context:property-placeholder
location="file:///${os.environment.configuration.dir}//${os.environment.ecosystem}/${os.environment.discriminator:}/${os.environment.developer.username:}/biometric.properties"
order="4" ignore-unresolvable="true" ignore-resource-not-found="true"/>
System environment variables
Tomcat container - Launch Configuration | Environmentos.environment.ecosystem=dev
os.environment.developer=obrien
os.environment.discriminator=<empty>
os.environment.configuration.dir=/wsc/os/config
File System property files
/wsc/os/config/biometric.propertiesos.environment.persistencecontext.applicationservice.name=from
Note: for external resources you also need the following for missing directories
ignore-resource-not-found="true"
Spring context xml
<context:property-placeholder
location="file:///${os.environment.configuration.dir}/biometric.properties" />
<util:list id="locationsList">
<value>${os.environment.configuration.dir:classpath:}/${os.environment.ecosystem}}</value>
<value>${os.environment.configuration.dir:classpath:}/${os.environment.ecosystem}/${os.environment.discriminator:}}</value>
<value>${os.environment.configuration.dir:classpath:}/${os.environment.ecosystem}/${os.environment.developer.username:}}</value>
<value>${os.environment.configuration.dir:classpath:}/${os.environment.ecosystem}/${os.environment.discriminator:}/${os.environment.developer.username:}}</value>
</util:list>
Spring Bean
private @Value("${server}") String server;
@PersistenceContext(name="${os.environment.persistencecontext.applicationservice.name}")
private EntityManager entityManager;
References
https://jira.spring.io/browse/SPR-5719
https://jira.spring.io/browse/SPR-6428
References
https://jira.spring.io/browse/SPR-5719
https://jira.spring.io/browse/SPR-6428