``

AppConfig is a configuration library which provides properties for applications deployed to different environments. For example, your local file storage is located at /home/joe/project1/files in a development environment (laptop), but in production it is located on the NFS: /opt/project1/files.

AppConfig makes it easy to configure multiple property files, one per environment and load just one depending what environment the application is running on.

As such, you may have a property file development.properties with content:

file_storage=/home/joe/project1/files

while the production.properties file will include:

file_storage=/opt/project1/files

Reading properties

First, import a static import AppConfig.p(...) method:

import static org.javalite.app_config.AppConfig.p;

then, simply call it as: p(..) in places where you need to inject a property:

String name = p("name");

Property substitution

AppConfig allows a property substitution to make it possible to refactor large property files by specifying a repeating value once.

If your property file has these properties:

first.name=John
phrase= And the name is ${first.name}

than this code will print And the name is John:

System.out.println(p("phrase"));

Note: The order of properties does not matter.

Setting up for multiple environments

AppConfig allows configuration of applications that is specific for different deployment environments. Applications have environment-specific files, whose names follow this pattern: environment.properties, where environment is a name of a deployment environment, such as development, staging, production, etc.

You can also provide a global file, properties from which will be loaded in all environments: global.properties.

In all cases the files need to be on the classpath under directory/package /app_config.

Environment-specific file will have an environment part of the file name match to an environment variable called ACTIVE_ENV. Such configuration is easy to achieve in Unix shell:

export ACTIVE_ENV=test

A typical file structure

/app_config
        |
        +--global.properties
        |
        +--development.properties
        |
        +--staging.properties
        |
        +--production.properties
        

If you are using Maven, then the location will be: src/main/resources/app_config.

Global property file will always be loaded, while others will be loaded depending on the value of `ACTIVE_ENV`` environment variable.

If environment variable ACTIVE_ENV is missing, AppConfig defaults to environment development.

System property override

You can also provide an environment as a system property app_config.properties.

Here is an example (add this to the startup script for your app):

-Dapp_config.properties=/opt/project1/production.properties

The app_config.properties system property points to a file specific to that computer (local box, server, etc.). Properties loaded from this file will override properties loaded from the classpath.

Environment Variables Override

Sometimes the DevOps will not allow production passwords and other sensitive data to be placed in the source code. If this is the case, any property can be overridden by a system environment variable. As long as that environment variable is named exactly the same as the property, its value will override the one from any other source (classpath files, external files, or custom providers).

Environment variables have the highest precedence and will override properties from all other configuration sources.

Watch out for log lines like: Duplicate property defined.. in case of a duplicate value override. It will tell you exactly where the new value is coming from and which property source is overridden with it.

Custom Configuration Provider

Note: This feature is available in version 3.4-SNAPSHOT and later in 3.4.

AppConfig supports a pluggable provider architecture that allows you to load properties from any custom source such as AWS Secrets Manager, Azure Key Vault, HashiCorp Vault, databases, or any other external configuration system.

Implementing a Provider

To create a custom provider, implement the AppConfigProvider interface:

package com.myapp.config;

import org.javalite.app_config.AppConfigProvider;
import java.util.HashMap;
import java.util.Map;

public class AwsSecretsProvider implements AppConfigProvider {
    @Override
    public Map<String, String> getProperties() {
        Map<String, String> properties = new HashMap<>();

        // Load properties from AWS Secrets Manager
        // ... your implementation here ...

        properties.put("database.password", "secret_from_aws");
        properties.put("api.key", "key_from_aws");

        return properties;
    }
}

Using a Provider

Specify your provider class using the app_config.provider system property when starting your application:

java -cp $CLASSPATH -Dapp_config.provider=com.myapp.config.AwsSecretsProvider com.myproject.Main

Provider Loading Priority

Properties are loaded in the following order (later sources override earlier ones):

  1. Classpath properties - global.properties and environment-specific files (lowest priority)
  2. External file - specified via -Dapp_config.properties system property
  3. Custom provider - specified via -Dapp_config.provider system property
  4. Environment variables - highest priority, overrides all other sources

This ensures that: - Provider properties can override file-based configuration - Environment variables still maintain the highest precedence for sensitive data - You can use providers for centralized configuration while allowing local overrides

Example Use Cases

AWS Secrets Manager Integration:

public class AwsSecretsProvider implements AppConfigProvider {
    public Map<String, String> getProperties() {
        // Use AWS SDK to fetch secrets
        return awsSecretsClient.getSecrets("my-app/config");
    }
}

Database Configuration:

public class DatabaseConfigProvider implements AppConfigProvider {
    public Map<String, String> getProperties() {
        // Load from a configuration database table
        return configRepository.getAllSettings();
    }
}

HashiCorp Vault:

public class VaultConfigProvider implements AppConfigProvider {
    public Map<String, String> getProperties() {
        // Fetch from Vault
        return vaultClient.read("secret/myapp").getData();
    }
}

Configuration Sources Summary

AppConfig supports multiple configuration sources that are loaded in a specific order. Later sources override earlier ones:

Priority Source How to Configure Use Case
1 (Lowest) Classpath Files /app_config/global.properties and /app_config/{env}.properties Default configuration committed to source control
2 External File -Dapp_config.properties=/path/to/file.properties Server-specific configuration, deployment overrides
3 Custom Provider -Dapp_config.provider=com.example.MyProvider Cloud secrets (AWS, Azure, Vault), centralized config
4 (Highest) Environment Variables Standard OS environment variables Sensitive data, container orchestration, CI/CD

Key Points

  • Properties from higher priority sources override those from lower priority sources
  • Environment variables can be accessed even if not defined in any property file
  • The ACTIVE_ENV environment variable (or active_env system property) determines which classpath file is loaded
  • All property values support ${placeholder} substitution regardless of source

How to comment

The comment section below is to discuss documentation on this page.

If you have an issue, or discover bug, please follow instructions on the Support page