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:

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:

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:

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:

#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:

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.

3 comments

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s