There can be only one properties file
Two good things happened this week:
-
Eclipse did not crash.
-
I discovered a new command to add to my Linux text manipulation arsenal.
I’m sure I don’t need to explain any further about my first point above. We’ve all experienced it. I think I must just have been lucky this week.
But I’m not here to write about IDEs.
This week I made a nice new automation recipe, which is going in my cookbook.
And it’s down to a use case I saw this week, which is the use of multiple Java properties files to specify an application’s config.
For example, we might see a properties loader defined somewhere, which loads, in the following order:
my-application-core.properties
my-environment.properties
my-special-overrides.properties
.
The idea here is that properties defined in my-environment
should override those in my-application-core
. And the ones in my-special-overrides
, well as they’re super-special, they should override everything.
In the world of Spring Boot, we could do this using spring.config.location
property. Spring will use this property as a list of locations to search for application.properties
files. It will load the ones it finds, in turn.
But I’m not a fan of this, because it’s not easy to see your application’s config at a glance (unless you left Spring Boot’s env endpoint enabled, which probably isn’t a good idea).
In Kubernetes we have the ConfigMap object. Wouldn’t it be nice if we could specify just one ConfigMap for a Spring Boot application – e.g. using the Spring Cloud Kubernetes bridge – and then have all of our properties set in there?
What I want to do is merge the three .properties
files together, removing duplicate keys and ignoring earlier entries.
We can use Linux text manipulation commands to get us there, specifically tac
and awk
.
tac
will print a file backwards (it’scat
backwards, geddit?)awk
will do almost anything with text
The following will merge 2 properties files together, using awk
as a text processor. awk
processes the files as tabular-like, and, using the =
sign as a column separator, takes the first occurrence of a key=
as its accepted value. The special operator seen
removes a line if this specific key=
has been seen before:
cat props1.properties props2.properties | awk -F'=' '!seen[$1]++'
BUT, if we want to take the final occurrence of a key=
as its accepted value (i.e. overriding an earlier property definition with a later one), then we can just use tac
to flip the list, de-duplicate, and then tac
to flip it again:
cat props1.properties props2.properties |
tac |
awk -F'=' '!seen[$1]++' |
tac
Example
Take the file dogs.properties
:
legs=4
colour=black
Take the file cats.properties
:
pet=cat
food=whiskas
colour=ginger
When running the command above, we get this merged properties file, where colour=ginger
overrides colour=black
:
legs=4
pet=cat
food=whiskas
colour=ginger