Configuration Providers
The configuration system uses property sources (also called providers) to supply configuration values. Multiple providers can be active simultaneously, with values resolved by priority order.
Available Providers
| Provider | Module | Priority | Description |
|---|---|---|---|
| Environment Variables | IDK Core | Highest | System environment variables |
| System Properties | IDK Core | High | JVM -D properties |
| Azure App Configuration | EDK | High | Cloud-based configuration from Azure |
| REST Config Client | EDK | High | Configuration from a REST API server |
| Database (PostgreSQL) | VDX | Medium | Persisted settings in PostgreSQL |
| Database (MySQL) | VDX | Medium | Persisted settings in MySQL |
| Database (SQLite) | VDX | Medium | Persisted settings in SQLite |
| Properties Files | IDK Core | Low | application-{profile}.properties |
| Programmatic Maps | IDK Core | Lowest | Code-defined configuration |
Auto-Registration
Providers are automatically registered when their module is on the classpath. You don't need to write any code to enable them - just add the dependency and configure connection details.
dependencies {
// Adding this dependency automatically enables Azure App Configuration
implementation("com.sphereon.edk:lib-conf-azure-app-config:$version")
// Adding this enables REST-based configuration
implementation("com.sphereon.edk:lib-conf-config-rest-client:$version")
}
When the application starts, the PropertySourceBootstrap service:
- Discovers all available providers via dependency injection
- Checks if each provider is enabled (via configuration)
- Registers enabled providers with the appropriate
ConfigService - Initializes providers that need async setup (like cloud providers)
Enabling and Disabling Providers
Each provider has a unique ID used to control whether it's enabled:
| Provider | Provider ID | Enable/Disable Key |
|---|---|---|
| Azure App Config | azure-app-config | config.providers.azure-app-config.enabled |
| REST Config Client | rest-config | config.providers.rest-config.enabled |
| PostgreSQL Database | postgresql-db | config.providers.postgresql-db.enabled |
| MySQL Database | mysql-db | config.providers.mysql-db.enabled |
| SQLite Database | sqlite-db | config.providers.sqlite-db.enabled |
Disabling a Provider
Providers are enabled by default when their module is on the classpath. To disable a provider:
- Environment Variable
- Properties File
# Disable Azure App Configuration
export CONFIG_PROVIDERS_AZURE_APP_CONFIG_ENABLED=false
# Disable database provider
export CONFIG_PROVIDERS_POSTGRESQL_DB_ENABLED=false
# Disable Azure App Configuration
config.providers.azure-app-config.enabled=false
# Disable database provider
config.providers.postgresql-db.enabled=false
Conditional Enablement
Some providers only enable themselves when properly configured. For example, Azure App Configuration only registers if connection details are provided:
# Azure provider enables itself when these are set
export AZURE_APPCONFIG_CONNECTION_STRING=Endpoint=https://myconfig.azconfig.io;...
# Or using endpoint + managed identity
export AZURE_APPCONFIG_ENDPOINT=https://myconfig.azconfig.io
Built-in Providers (IDK Core)
These providers are always available in IDK applications.
Environment Variables
Automatically reads all system environment variables. Keys are converted:
API_BASE_URL→api.base.url- Uppercase with underscores → lowercase with dots
Priority: Highest (always wins)
System Properties
Reads JVM system properties set via -D flags:
java -Dapi.base.url=https://api.example.com -jar myapp.jar
Priority: High
Properties Files
Reads application-{profile}.properties from the classpath:
api.base.url=https://api.production.example.com
http.timeout.ms=30000
The profile is set during app initialization via profile parameter.
Priority: Low
Programmatic Maps
Add configuration programmatically using MapPropertySource:
val defaults = MapPropertySource(
name = "app-defaults",
source = mapOf(
"http.timeout.ms" to 30000,
"retry.max.attempts" to 3
)
)
configService.addPropertySource(defaults)
Priority: Lowest
Cloud Providers (EDK)
Cloud providers fetch configuration from external services and provide:
- Centralized configuration management
- Dynamic configuration updates
- Offline caching for resilience
See Cloud Providers for detailed configuration.
Azure App Configuration
Fetches configuration from Azure App Configuration service.
Module: lib-conf-azure-app-config
Configuration:
azure.appconfig.connection-string=Endpoint=https://myconfig.azconfig.io;Id=...;Secret=...
# Or use endpoint with managed identity
azure.appconfig.endpoint=https://myconfig.azconfig.io
# Optional settings
azure.appconfig.key-filter=myapp/*
azure.appconfig.label-filter=production
azure.appconfig.key-prefix=myapp/
azure.appconfig.trim-key-prefix=true
REST Configuration Client
Fetches configuration from a VDX or compatible REST API server.
Module: lib-conf-config-rest-client
Configuration:
rest.config.base-url=https://config.example.com
rest.config.tenant-id=my-tenant
rest.config.profile=production
# Authentication
rest.config.auth.method=API_KEY
rest.config.auth.api-key=my-api-key
rest.config.auth.api-key-header=X-API-Key
Database Providers (VDX)
Database providers store and retrieve configuration from SQL databases, supporting:
- Persistent configuration storage
- Multi-tenant isolation
- Profile-aware settings
- In-memory caching for performance
See Settings Persistence for detailed configuration.
PostgreSQL
Module: vdx-conf-settings-persistence-postgresql
Stores settings in a PostgreSQL database with caching.
MySQL
Module: vdx-conf-settings-persistence-mysql
Stores settings in a MySQL database with caching.
SQLite
Module: vdx-conf-settings-persistence-sqlite
Stores settings in a SQLite database. Ideal for embedded or single-server deployments.
Provider Priority
When the same key exists in multiple providers, the highest-priority provider wins:
Environment Variable: api.url=https://env.example.com ← WINS
Azure App Config: api.url=https://azure.example.com
Database: api.url=https://db.example.com
Properties File: api.url=https://file.example.com
This allows you to:
- Define defaults in property files
- Override with cloud configuration
- Override everything with environment variables in production
Creating Custom Providers
To create a custom configuration provider:
- Implement
PropertySource:
class MyCustomPropertySource(
private val dataSource: MyDataSource
) : AbstractPropertySource<MyDataSource>(
name = "my-custom-source",
source = dataSource,
order = Order.MEDIUM.orderValue
) {
override fun <T : Any> getProperty(name: String, targetType: KClass<T>): T? {
val value = dataSource.getValue(name) ?: return null
// Convert and return value
return convertValue(value, targetType)
}
override fun getAllPropertyNames(): Set<String> {
return dataSource.getAllKeys()
}
override val isPlatformSupported: Boolean = true
}
- Create a contribution for auto-registration (optional):
@Inject
@SingleIn(AppScope::class)
@ContributesBinding(AppScope::class, boundType = PropertySourceContribution::class, multibinding = true)
class MyCustomProviderContribution(
private val dataSource: MyDataSource
) : PropertySourceContribution {
override val configLevel = ConfigLevel.APP
override val providerId = "my-custom-provider"
override fun isEnabled(resolver: PropertyResolver): Boolean {
val disabled = resolver.getProperty(
"config.providers.my-custom-provider.enabled",
Boolean::class
)
return disabled != false && dataSource.isConfigured
}
override fun getPropertySource(): PropertySource<*> {
return MyCustomPropertySource(dataSource)
}
override fun getOrder(): Int = Order.MEDIUM.orderValue
}
- Register manually (if not using auto-registration):
val mySource = MyCustomPropertySource(dataSource)
configService.addPropertySource(mySource)
Caching
Providers use caching to improve performance:
| Provider Type | Cache Type | Purpose |
|---|---|---|
| Cloud Providers | OfflineConfigCache | Persists config to disk for network failure resilience |
| Database Providers | SettingsCache | In-memory cache to reduce database queries |
Offline Cache
Cloud providers (Azure, REST) can persist configuration locally. When the cloud service is unavailable, the cached configuration is used:
# Enable offline caching (enabled by default when available)
azure.appconfig.offline-cache.enabled=true
Database Cache
Database providers cache query results in memory with TTL-based expiration:
- Cache hit: Returns immediately from memory
- Cache miss: Queries database, caches result
- Write/Delete: Invalidates relevant cache entries
Troubleshooting
Provider Not Registering
- Check module is on classpath: Verify the dependency is in your build file
- Check enable flag: Ensure
config.providers.{id}.enabledisn't set tofalse - Check required config: Some providers need connection details to enable
Wrong Value Being Used
- Check provider priority: Higher priority sources override lower ones
- Check key normalization:
api.baseUrlandapi.base.urlresolve to the same key - Enable debug logging: Set
logging.level.config=DEBUGto see resolution details
Cloud Provider Failing
- Check credentials: Verify connection strings, API keys, or managed identity setup
- Check network: Ensure firewall allows connections to cloud service
- Check offline cache: If available, cached values may be returned during outages