Tom Donohue Tom Donohue

There can be only one properties file

Two good things happened this week:

  1. Eclipse did not crash.

  2. 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’s cat 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

Comments

What do you think? You can use Markdown in your comment.

To write code, indent each line with 4 spaces. Or, to paste a lot of code, you can put it in pastebin.com and share the link in your comment.