How to Use the @Key Annotation to Map Method Names to Custom Property Keys in Owner
The @Key annotation lets you explicitly bind interface methods to custom property keys, overriding Owner's default behavior of converting camelCase method names to dot-separated keys.
Owner is a Java library that implements interface-based configuration management. When your property files use keys that differ from your Java method names, the @Key annotation provides the exact mapping needed to bridge the two.
Understanding the @Key Annotation Definition
The @Key annotation is declared inside org.aeonbits.owner.Config as a runtime-visible method-target annotation. In owner/src/main/java/org/aeonbits/owner/Config.java, the annotation is defined as:
@Retention(RUNTIME)
@Target(METHOD)
@Documented
@interface Key {
String value(); // the exact property key to look up
}
This definition ensures that the annotation is retained at runtime and can only be applied to interface methods. The value() field accepts the exact string Owner uses to look up the property from loaded sources.
How Owner Resolves Property Keys
When Owner generates a runtime implementation of your configuration interface—via owner/src/main/java/org/aeonbits/owner/Factory.java—it follows a deterministic lookup algorithm to resolve values:
- Load sources according to
@Sourcesor the default search order (files, classpath resources, system properties, etc.). - Inspect each method in the interface:
- If
@Keyis present, use the supplied string as the lookup key. - Else, derive the key from the method name (converting camelCase to dot-separated format).
- If
- Retrieve the value from the merged properties map.
- Convert the raw
Stringto the method's declared return type (int, boolean, enum, etc.). - Apply additional annotations (
@DefaultValue,@ConverterClass,@EncryptedValue) if present.
The annotation value is used verbatim for the lookup, though it can contain variable placeholders (${…}) that are resolved before the key is used (introduced in Owner 1.0.6).
Practical @Key Annotation Examples
Basic Property Key Mapping
When your properties file uses verbose or namespaced keys, map them directly to concise method names. Consider a ServerConfig.properties file:
server.http.port=80
server.host.name=foobar.com
server.max.threads=100
Define the mapping in your interface:
public interface ServerConfig extends Config {
@Key("server.http.port")
int port();
@Key("server.host.name")
String hostname();
@Key("server.max.threads")
@DefaultValue("42")
int maxThreads();
}
As shown in owner-site/site/docs/usage.md, the @Key annotation tells Owner to read exactly the keys specified, regardless of the method names.
Dynamic Keys with Variable Expansion
You can inject variables into the @Key value to select different properties based on runtime context. This requires Owner 1.0.6 or later.
Given this properties file:
servers.dev.port=6000
servers.uat.port=60020
servers.prod.port=600
Use variable expansion to select the environment dynamically:
@Sources("classpath:org/aeonbits/owner/variableexpansion/KeyExpansionExample.properties")
public interface EnvConfig extends Config {
@DefaultValue("dev")
String env(); // can be overridden via system/property
@Key("servers.${env}.port")
int port(); // resolves to servers.dev.port, etc.
}
The ${env} placeholder is replaced with the value returned by the env() method (or its default) before the property lookup occurs, as documented in owner-site/site/docs/variables-expansion.md.
Validating @Key Mappings in Unit Tests
The test suite validates that @Key correctly reads custom keys from various sources including XML. In owner/src/test/java/org/aeonbits/owner/xml/XmlSourceTest.java, the mapping is verified:
public interface ServerConfig extends Config, Accessible {
@Key("server.http.port")
int httpPort();
@Key("server.http.hostname")
String httpHostname();
}
@Test
public void testXmlReading() {
ServerConfig cfg = factory.create(ServerConfig.class);
assertEquals(80, cfg.httpPort());
assertEquals("localhost", cfg.httpHostname());
}
This demonstrates that Owner correctly associates the annotated keys with the underlying XML structure, proving the abstraction works across different configuration formats.
Summary
- The
@Keyannotation is defined inorg.aeonbits.owner.Configand targets methods exclusively. - It overrides the default key derivation logic, allowing any string to serve as the property lookup key.
- Variable placeholders like
${variable}inside@Keyvalues are resolved at runtime before lookup (Owner 1.0.6+). - The annotation works uniformly across all property sources, including
.properties, XML, and system properties. - Owner's
Factoryclass processes these annotations when generating the dynamic proxy implementation.
Frequently Asked Questions
What happens if I don't use @Key on a method?
Owner converts the method name from camelCase to a dot-separated property key automatically. For example, a method named serverPort() becomes the lookup key server.port.
Can I use variables inside the @Key annotation value?
Yes. Since Owner 1.0.6, you can include placeholders like ${env} inside the @Key string. Owner resolves these variables using values from the same configuration interface or system properties before performing the property lookup.
Does @Key work with all property sources?
Yes. The @Key annotation is source-agnostic. Whether your configuration comes from properties files, XML documents, JSON, or system environment variables, Owner uses the annotated key to retrieve the value from the merged configuration map.
Where is the @Key annotation processed in the Owner source code?
The annotation is defined in owner/src/main/java/org/aeonbits/owner/Config.java. The runtime processing logic that reads @Key values and performs the property lookup resides in owner/src/main/java/org/aeonbits/owner/Factory.java, which generates the dynamic proxy implementation of your configuration interface.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →