Set it up
In Java, we often have framework support for importing settings from the file system of our application. If we’re lucky, and we often are, these settings can be customised and overridden by system properties or environment variables.
However, there are a couple of situations where this doesn’t quite apply:
- Very lightweight applications that use no frameworks
- Loading custom settings based on business logic
Though we can shoe-horn heavier frameworks like Spring into the first, or try to force Spring to process properties for us, often we need a lighter solution.
Lightweight Config
I recently wrote and released Lightweight Config, an open source package to solve this with either .yaml
or .properties
files.
I’ve demonstrated its use in AWS Lambdas in an article on Baeldung.com.
I thought it might be nice to cover a different use case in this article, notably how it might be used to load settings up in a test.
At The Max
I wrote Lightweight Config from the ground up, but I’ve used its predecessors extensively. Originally, it was a test-helper library. Then I created one for loading settings for lambdas.
At full strength, you’d define a .yml
file:
1 2 3 4 5 6 7 | hardCoded: true interpolated: ${SOME_ENV_VAR:- default } partialInterpolation: Welcome to ${APP_NAME} database: url: ${DB_URL} username: ${DB_USER} password: ${DB_PASSWORD} |
Then a POJO to load the file into:
1 2 3 4 5 6 7 8 | public class Settings { private boolean hardCoded; private String interpolated; private String partialInterpolation; private DatabaseSettings database; // getters and setters } |
Then it’s a one liner to load from the yaml into the Settings
object – Settings settings = ConfigLoader.loadYmlConfigFromResource("settings.yaml", Settings.class)
There are also some hooks that can be applied to plug in custom tags if necessary.
Reading Per Environment Properties
Let’s flip to an example where we just want some Java .properties
loaded into Properties
. One might argue that the POJO approach gives us a better API, but let’s say we’re using something that’s already bound to Properties
, such as an email client, or DB connection pool.
Here’s a snippet of some settings that relate to dev:
1 2 3 | workers=12 sourceEmail= test @mytest.com pdfFolder= /home/test/pdf |
Let’s call this file profiles/dev.properties
.
Now let’s create a parent file with all the global settings in:
1 2 3 4 5 6 | #import profiles/${ENV_NAME}.properties threadPoolSize=24 versionNumber=${BUILD_VERSION:-Unknown} adminUser=admin adminPassword=${ADMIN_PASSWORD} |
Let’s call this file app.properties
and put it in the same directory as contains the profiles
directory mentioned above.
Now we can load both the above files into a Properties
object by:
1 2 | Path appPropertiesPath = PROPERTIES_DIR.resolve( "app.properties" ); Properties properties = ConfigLoader.loadProperties(appPropertiesPath); |
What happens in this case is that the various placeholders are filled in from environment variables (or system properties if you prefer). Included in this is the #import
statement, which not only describes how a child file is imported, but allows placeholder interpolation into the path of that file.
So, by setting a different ENV_NAME
environment variable, the same loading code could import a different set of per-environment properties into the whole Properties
object being loaded.
It’s a simple syntax/approach that’s flexible enough to use for a variety of things.
I hope it’s useful.
Published on Java Code Geeks with permission by Ashley Frieze, partner at our JCG program. See the original article here: Set it up Opinions expressed by Java Code Geeks contributors are their own. |