1. Welcome to ConfNG
ConfNG is a configuration management library designed specifically for Java applications with first-class TestNG integration. It provides a flexible, type-safe way to manage configuration across multiple sources with automatic precedence handling.
Key features include:
- Zero-configuration TestNG integration - TestNG parameters automatically injected via service loader
- Type-safe configuration - Enum-based keys with compile-time checking
- Multiple configuration sources - Environment variables, system properties, files (Properties, JSON, YAML, TOML), secret managers, and custom sources
- Smart precedence - Configurable source priority with sensible defaults
- Extensible architecture - Easy to add custom configuration sources
- Secret management - Built-in support for AWS, Azure, and HashiCorp Vault
- Thread-safe - Safe for concurrent access
- Lightweight - Minimal dependencies
Here is a very simple example:
package com.example;
import org.confng.ConfNG;
import org.confng.ConfNGKey;
import org.testng.annotations.*;
public enum AppConfig implements ConfNGKey {
BASE_URL("base.url", "http://localhost:8080"),
TIMEOUT("timeout", "30"),
BROWSER("browser", "chrome");
private final String key;
private final String defaultValue;
AppConfig(String key, String defaultValue) {
this.key = key;
this.defaultValue = defaultValue;
}
@Override
public String getKey() { return key; }
@Override
public String getDefaultValue() { return defaultValue; }
}
public class SimpleTest {
@BeforeClass
public void setUp() {
// TestNG parameters automatically available!
// No configuration needed
}
@Test
public void testApplication() {
String url = ConfNG.get(AppConfig.BASE_URL);
Integer timeout = ConfNG.getInt(AppConfig.TIMEOUT);
String browser = ConfNG.get(AppConfig.BROWSER);
System.out.println("Testing " + url + " with " + browser);
}
}
The enum AppConfig defines your configuration keys with default values. TestNG parameters are automatically injected when tests run - no setup required!
1.1. Requirements
ConfNG requires Java 11 or higher.
1.2. Mailing-lists
For questions, support, or discussions, please contact us at team@confng.org.
1.3. Locations of the projects
- Main Repository: https://github.com/confng/confng
- Playground Examples: https://github.com/confng/confng-playground
- Documentation: https://confng.github.io
1.4. Bug reports
Bug reports and feature requests can be submitted on the GitHub Issues page.
1.5. License
ConfNG is released under the Apache License 2.0.
2. Download
ConfNG is available through Maven Central. Add it to your project using Maven or Gradle:
2.1. Maven
<dependency>
<groupId>org.confng</groupId>
<artifactId>confng</artifactId>
<version>1.1.0</version>
</dependency>
2.2. Gradle
dependencies {
implementation 'org.confng:confng:1.1.0'
}
2.3. Gradle Plugin (Recommended)
For seamless system property forwarding, add the ConfNG Gradle plugin:
plugins {
id 'org.confng' version '1.1.0'
}
This automatically forwards all -D flags to the test JVM:
./gradlew test -Dbrowser=firefox -Ddatabase.url=jdbc:mysql://localhost/test
No additional configuration needed - properties are automatically available via ConfNG.get().
Plugin Configuration (Optional)
confng {
// Disable automatic forwarding (default: true)
forwardSystemProperties = false
// Only forward properties matching these patterns
includePatterns = ['app.', 'database.', 'browser']
// Exclude properties matching these patterns
excludePatterns = ['secret.', 'password']
}
2.4. Build from source
To build ConfNG from source:
git clone https://github.com/confng/confng.git
cd confng
./gradlew build
2.6. What's New in 1.1.0
Version 1.1.0 introduces the ConfNG Gradle Plugin and powerful features for configuration management:
🔌 Gradle Plugin
New org.confng Gradle plugin automatically forwards system properties to test JVM. No more manual systemProperty configuration needed!
📊 Typed Configuration Getters
New getLong(), getDouble(), getList(), and getDuration() methods for type-safe configuration access with human-readable duration parsing.
✅ Optional/Required Values
New getOptional(), getRequired(), and getOrDefault() methods for explicit null handling and fail-fast configuration.
🔍 Validation Framework
Annotation-based validation with @Required, @NotEmpty, @Pattern, and @Range for configuration integrity checks.
🔬 Source Diagnostics
New getSourceInfo() method to see exactly where each configuration value comes from for easier debugging.
🏷️ Prefix-based Retrieval
New getByPrefix() and getKeysWithPrefix() methods for retrieving grouped configuration values.
3. ConfNG Documentation
3.1. Introduction
ConfNG simplifies configuration management in Java applications, especially for TestNG-based test automation. It eliminates boilerplate code and provides a unified API for accessing configuration from multiple sources.
3.2. Quick Start
Getting started with ConfNG is simple:
- Add the dependency to your project
- Create an enum implementing
ConfNGKey - Use
ConfNG.get()to access configuration values - Run your tests - TestNG parameters are automatically available!
3.3. Configuration Keys
Configuration keys in ConfNG are defined using enums that implement the ConfNGKey interface. This provides type-safety and compile-time checking.
public enum MyConfig implements ConfNGKey {
API_URL("api.url", "https://api.example.com"),
TIMEOUT("timeout", "30"),
RETRY_COUNT("retry.count", "3");
private final String key;
private final String defaultValue;
MyConfig(String key, String defaultValue) {
this.key = key;
this.defaultValue = defaultValue;
}
@Override
public String getKey() { return key; }
@Override
public String getDefaultValue() { return defaultValue; }
}
Access configuration values using the ConfNG class:
// Get as String
String url = ConfNG.get(MyConfig.API_URL);
// Get as Integer
Integer timeout = ConfNG.getInt(MyConfig.TIMEOUT);
// Get as Boolean
Boolean enabled = ConfNG.getBoolean(MyConfig.FEATURE_ENABLED);
// Get as Long
Long count = ConfNG.getLong(MyConfig.MAX_RECORDS);
3.4. Configuration Sources
ConfNG supports multiple configuration sources with automatic precedence handling. Sources are checked in the following order (highest to lowest priority):
- Environment Variables - System environment variables
- System Properties - Java system properties (-D flags)
- TestNG Parameters - Parameters from TestNG XML (Method > Test > Suite levels)
- Properties Files - .properties files
- JSON Files - .json configuration files
- YAML Files - .yaml/.yml files (requires custom source)
- TOML Files - .toml files (requires custom source)
- Secret Managers - AWS Secrets Manager, Azure Key Vault, HashiCorp Vault
- Custom Sources - Implement your own configuration source
- Default Values - Values defined in the enum
Example of loading from a properties file:
# config.properties
api.url=https://production.example.com
timeout=60
retry.count=5
Example of loading from a JSON file:
{
"api": {
"url": "https://production.example.com",
"timeout": 60
},
"retry": {
"count": 5
}
}
3.5. TestNG Integration
ConfNG provides zero-configuration TestNG integration through a service-loaded listener. TestNG parameters are automatically captured and made available through the ConfNG API.
Example TestNG XML:
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="Test Suite" verbose="1">
<parameter name="base.url" value="https://test.example.com"/>
<parameter name="browser" value="firefox"/>
<test name="Smoke Tests">
<parameter name="timeout" value="45"/>
<classes>
<class name="com.example.SmokeTest"/>
</classes>
</test>
</suite>
Access these parameters in your test:
public class SmokeTest {
@Test
public void testApplication() {
// No @Parameters annotation needed!
String url = ConfNG.get(AppConfig.BASE_URL);
String browser = ConfNG.get(AppConfig.BROWSER);
Integer timeout = ConfNG.getInt(AppConfig.TIMEOUT);
// Use the configuration...
}
}
The TestNG listener is automatically registered via Java's ServiceLoader mechanism. No manual configuration is required!
3.6. Gradle Plugin
The ConfNG Gradle Plugin (org.confng) automatically forwards system properties from the Gradle command line to the test JVM. This eliminates the need for manual systemProperty configuration in your build files.
Installation
plugins {
id 'java'
id 'org.confng' version '1.1.0'
}
Usage
Once applied, any -D flags passed to Gradle are automatically available in your tests:
# Run tests with custom configuration
./gradlew test -Dbrowser=firefox -Dbase.url=https://staging.example.com
# All properties are available via ConfNG.get()
String browser = ConfNG.get(AppConfig.BROWSER); // "firefox"
String url = ConfNG.get(AppConfig.BASE_URL); // "https://staging.example.com"
Configuration Options
The plugin provides a confng extension for customization:
confng {
// Enable/disable automatic property forwarding (default: true)
forwardSystemProperties = true
// Only forward properties matching these prefixes
includePatterns = ['app.', 'database.', 'browser', 'env']
// Exclude properties matching these patterns (takes precedence over includes)
excludePatterns = ['secret.', 'password', 'credential']
}
Pattern Matching
The plugin uses prefix matching for filtering:
- Include patterns: If specified, only properties starting with these prefixes are forwarded
- Exclude patterns: Properties starting with these prefixes are never forwarded
- Precedence: Exclude patterns take precedence over include patterns
confng {
// Forward only app.* and db.* properties, but never secrets
includePatterns = ['app.', 'db.']
excludePatterns = ['app.secret.', 'db.password']
}
// With this config:
// -Dapp.name=MyApp → forwarded
// -Dapp.secret.key=xxx → NOT forwarded (excluded)
// -Ddb.host=localhost → forwarded
// -Ddb.password=secret → NOT forwarded (excluded)
// -Dother.prop=value → NOT forwarded (not in includes)
Why Use the Plugin?
Without the plugin, you need to manually forward each property:
// Without plugin - manual and error-prone
test {
systemProperty 'browser', System.getProperty('browser')
systemProperty 'base.url', System.getProperty('base.url')
systemProperty 'timeout', System.getProperty('timeout')
// ... repeat for every property
}
With the plugin, all properties are forwarded automatically:
// With plugin - zero configuration needed!
plugins {
id 'org.confng' version '1.1.0'
}
// That's it! All -D properties are automatically available in tests
3.7. Typed Configuration Getters
ConfNG 1.1.0 introduces additional typed getter methods for common data types:
// Long values
Long maxFileSize = ConfNG.getLong(AppConfig.MAX_FILE_SIZE);
// Double values
Double taxRate = ConfNG.getDouble(AppConfig.TAX_RATE);
// List values (comma-separated)
List<String> allowedOrigins = ConfNG.getList(AppConfig.ALLOWED_ORIGINS);
// Config: "http://localhost,http://example.com" -> ["http://localhost", "http://example.com"]
// List with custom delimiter
List<String> features = ConfNG.getList(AppConfig.FEATURES, ";");
// Duration values (human-readable formats)
Duration timeout = ConfNG.getDuration(AppConfig.SESSION_TIMEOUT);
// Supports: "30s", "5m", "2h", "1d", "500ms", "PT30S" (ISO-8601)
3.8. Optional/Required Configuration
Explicit methods for handling optional and required configuration values:
// Optional - returns Optional<String>, never null
Optional<String> apiKey = ConfNG.getOptional(AppConfig.API_KEY);
apiKey.ifPresent(key -> client.setApiKey(key));
// Required - throws ConfigurationException if missing
String databaseUrl = ConfNG.getRequired(DatabaseConfig.URL);
// With explicit fallback default
String browser = ConfNG.getOrDefault(AppConfig.BROWSER, "firefox");
Integer timeout = ConfNG.getOrDefault(AppConfig.TIMEOUT, 60);
3.9. Configuration Validation Framework
Annotation-based validation for configuration values:
public enum AppConfig implements ConfNGKey {
@Required
DATABASE_URL("database.url"),
@NotEmpty
API_KEY("api.key", "default-key"),
@Range(min = 1, max = 65535)
SERVER_PORT("server.port", "8080"),
@Pattern(regex = "^(debug|info|warn|error)$")
LOG_LEVEL("log.level", "info");
// ... implementation
}
// Validate configuration
ValidationResult result = ConfNG.validate(AppConfig.values());
if (!result.isValid()) {
for (ValidationError error : result.getErrors()) {
System.err.println(error.getKey() + ": " + error.getMessage());
}
}
3.10. Configuration Source Diagnostics
See exactly where each configuration value comes from:
// Get source info for a single key
ConfigSourceInfo info = ConfNG.getSourceInfo(AppConfig.DATABASE_URL);
System.out.println("Key: " + info.getKey()); // "database.url"
System.out.println("Value: " + info.getValue()); // "jdbc:mysql://..." (masked if sensitive)
System.out.println("Source: " + info.getSourceName()); // "Environment", "SystemProperties", etc.
System.out.println("Found: " + info.isFound()); // true/false
System.out.println("Default: " + info.isFromDefault()); // true if using default value
// Get source info for multiple keys
Map<String, ConfigSourceInfo> infos = ConfNG.getAllSourceInfo(AppConfig.values());
3.11. Prefix-based Configuration Retrieval
Retrieve all configuration values with a common prefix:
// Get all values with prefix
Map<String, String> dbConfig = ConfNG.getByPrefix("db.");
// Returns: {"db.host": "localhost", "db.port": "5432", "db.name": "mydb"}
// Get just the key names
Set<String> apiKeys = ConfNG.getKeysWithPrefix("api.");
// Returns: {"api.url", "api.key", "api.version"}
// Use cases: feature flags, tenant config, environment overrides
Map<String, String> features = ConfNG.getByPrefix("feature.");
for (Map.Entry<String, String> entry : features.entrySet()) {
String featureName = entry.getKey().substring("feature.".length());
boolean enabled = Boolean.parseBoolean(entry.getValue());
featureManager.setEnabled(featureName, enabled);
}
4. Examples
The ConfNG Playground repository contains comprehensive examples demonstrating various features and use cases:
Basic Examples
- Environment Auto-Loading - Automatic environment detection and configuration loading
- Properties Configuration - Using .properties files for configuration
- JSON Configuration - Using JSON files for configuration
Advanced Examples
- Multi-Source Configuration - Combining multiple configuration sources with precedence
- YAML Configuration - Custom YAML source implementation
- Secret Managers - Integration with AWS, Azure, and HashiCorp Vault
- Database Configuration - Using a database as a configuration source
TestNG Integration Examples
- TestNG Integration - Comprehensive TestNG patterns and best practices
- Environment Variables - Using environment variables in tests
- System Properties - Using Java system properties
5. API Documentation
For detailed API documentation and additional resources:
- JavaDoc: Complete API reference and documentation at docs.confng.org
- Source Code: Browse the complete source code and JavaDoc comments in the GitHub repository
- README: View the comprehensive README documentation on GitHub
- Issues & Support: Report bugs or request features on GitHub Issues
6. GitHub Repository
ConfNG is open source and hosted on GitHub:
- Main Repository: https://github.com/confng/confng
- Playground Examples: https://github.com/confng/confng-playground
Contributions, bug reports, and feature requests are welcome!