4.5 AI Guidance (Notes for Code-Generating Tools)
We just know people will use code generators. So it's probably for the best to give the AI some hints.
This document summarizes mConfig behaviours that code generators often miss. The goal is to prevent boilerplate, duplicate logic, or incorrect assumptions.
Logging and runtime debug control
- Runtime logging overrides are provided by
mConfigSourceEnvVarand are only enabled ifALLOW_MCONFIG_RUNTIME_SETTINGSis set totrue. - Environment variables start with
MCONFIG_RUNTIME_: MCONFIG_RUNTIME_DEBUG_LEVEL= off|0, error|1, warn|2, info|3, debug|4, trace|5MCONFIG_RUNTIME_DEBUG_OUTPUT= "stderr", "stdout", "quiet", orfile:<path>(appended if present, created if missing)MCONFIG_RUNTIME_DEBUG_OUTPUTis handled internally byInternalLogger. You do not need to implement a custom logger for this.
Related docs: - mConfigSourceEnvVar README - logging
Console logging for dev/tests
ConsoleLogginginmConfigCoremain jar (service"console").- Production logging should use
mConfigLoggingSlf4jor the defaultNullLogging. - Enable with
ConfigFeature.LOGGING_TO_USE_IN_CONFIGLIB = "console".
Related docs: - logging
Defaults belong in resources, not in code
mConfigSourceJARautomatically loads defaults from resources located at.config/<company>/<app>/<config>.<ext>.- For a standard Maven layout, the default location is:
src/main/resources/.config/<company>/<app>/<config>.properties- Schemes (typed defaults and validation) live next to the config file:
src/main/resources/.config/<company>/<app>/<config>.scheme.json- Avoid manual loading of
Propertiesdefaults. mConfig already layers JAR defaults with filesystem, environment, and other sources. - Avoid null checks. mConfig has ConfigFeature flags to control behaviour, whether to throw an exception or return a default value. Prefer setting defaults as described above.
Related docs: - simple configuration loading - 3.8 code improvements - regular use
Fallbacks and conversion are built in
- Fallback across scopes is a first-class feature:
FALLBACKS_ACROSS_SCOPEScontrols reads (default: true)WRITE_FALLBACK_ACROSS_SCOPEScontrols writes (default: false)- Typed getters (
getInteger,getBoolean, etc.) perform conversion for you. Do not parse values manually. - To return scheme defaults on missing entries, use:
EXCEPTION_ON_MISSING_ENTRY=falseDEFAULT_ON_MISSING_ENTRY=true
Related docs: - 2.5 config features - design consolidated - 3.8 code improvements
converters and mappers
- ConfigMapper is provided to map from and to POJOs.
- ConfigUtil.fromProperties(...) is a bridge to convert legacy
Properties. - ConfigUtil.withOverrides(...) is a bridge to merge custom maps.
- ConfigUtil.remapped(...) is a bridge to prefix sub-configs.
- See examples/configuration_views.md for more.
Overrides: use scopes, not ad-hoc logic
- For in-process overrides, prefer
ConfigScope.RUNTIMEviaput(...). It is the highest regular scope and overrides everything exceptPOLICY. - For environment/session overrides, use
ConfigScope.SESSION(env vars and CLI). Avoid custom precedence logic.
Related docs: - regular use - 2.1 how it works
Test Mode is a first-class feature
- Enable with
ConfigFactoryBuilder.setTestMode(true)or viaMCONFIG_RUNTIME_TEST_MODE=truewhenALLOW_MCONFIG_RUNTIME_SETTINGSis on. - Test Mode bypasses OS paths and prefers test resources such as
src/test/resources/.config/<company>/<app>/andsrc/test/resources/config/{SCOPE}. - Test Mode can be locked down globally with
ConfigFactoryBuilder.forbidTestMode().
Related docs: - test mode - testing configuration
Prefer mConfigUtil adapters for legacy interop
ConfigUtil.withOverrides(...): immutable overlay; prefer over custom map merges.ConfigUtil.remapped(...): prefix remapping for sub-config views.ConfigUtil.fromProperties(...): bridge legacyPropertieswithout re-parsing.
Related docs:
- configuration views
- mConfigUtil/src/main/java/org/metabit/platform/support/config/util/ConfigUtil.java