# INI files for easy multi-environment config in Java

Almost all applications need to run in multiple environments.  If nothing else, they are tested on a developer’s workstation before deployment to a production box.  There can be QA and UAT environments in between, and there might even be more than one production target.  At runtime, applications usually need environment-specific info such as which database to use, credentials, etc.

Large-scale apps normally manage this with a dependency-injection framework like Spring.  The typical “cloud” host approach is to use environment variables.  Both of these can be used in combination.  However, what about small, simple apps?  Scenarios where you don’t want to add tens of megs of unnecessary frameworks, yet there is more information than you care to sick in environment variables?

One approach is to use traditional properties files, parsed and loaded by the java.util.Properties class.  You would maintain a separate properties file for each target environment, and rely on your build system to bundle the correct version with each distribution.

For an even easier approach, take a minute and go search the hard drive of a Windows box for files having the “*.ini” extension.

These INI files have long been forgotten, as Windows configuration moved into the registry almost twenty years ago.  However, they were once the standard means for managing DOS and Windows config.  Some of them are still there today, such as this C:\WINDOWS\SYSTEM.INI:

; for 16-bit app support
[386Enh]
woafont=dosapp.fon
EGA80WOA.FON=EGA80WOA.FON
EGA40WOA.FON=EGA40WOA.FON
CGA80WOA.FON=CGA80WOA.FON
CGA40WOA.FON=CGA40WOA.FON

[drivers]
wave=mmdrv.dll
timer=timer.drv

[mci]


This looks like standard java.util.Properties file, with information stored in “name”=”value” pairs.  However, notice the bracketed lines splitting the properties into groups.  These groups are called “sections”, or sometimes “stanzas”, and are a really useful means for logically separating config values.

Imagine using the sections to configure a database connection and web service endpoint for multiple environments:

[dev]
JDBC_URL = jdbc:h2:mem:mem_test;MODE=Oracle

SERVICE_ENDPOINT = http://localhost:8080/Central/api/AppService

[qa]
JDBC_URL = jdbc:oracle:thin:@qa-oracle:1521:qa

SERVICE_ENDPOINT = http://qa-services/Central/api/AppService

[prod]
JDBC_URL = jdbc:oracle:thin:@prod-oracle:1521:prod

SERVICE_ENDPOINT = http://prod-services/Central/api/AppService


(Perhaps you would use an environment variable for the database password, rather than sticking it in a plaintext file, but you see the basic idea.)

All database and web service information is in one centralized place, and it’s easy to see and manage differences between environments.  The dev environment uses an in-memory H2 database for testing, and runs the web service on localhost.  The qa and prod environments use Oracle, and the web services they use are on dedicated machines.

To easily use this information in Java (or Scala, Groovy, etc), you can use the open-source [ini4j] library.  [ini4j] is tiny, and has no additional dependencies.  You can download it directly from SourceForge, or from Maven Central as a dependency in your Maven project’s POM:

...
<dependency>
<groupId>org.ini4j</groupId>
<artifactId>ini4j</artifactId>
<version>0.5.2</version>
</dependency>
...

The [ini4j] website has very good documentation and tutorials, but using the library in your applications is really as simple as knowing two classes:

...
Ini ini = new Ini();
...