How to Set Default Values with @DefaultValue When Properties Are Missing in Owner
Use the @DefaultValue annotation on interface methods in Owner to specify fallback strings that are automatically converted to the method's return type when a property key is absent from all configuration sources.
The Owner library (matteobaccan/owner) provides a type-safe configuration mapping framework for Java. When you need to set default values with @DefaultValue when properties are missing, you annotate methods in your Config interface with literal fallback strings that Owner converts and returns when no matching key exists in property files, environment variables, or system properties.
Understanding the @DefaultValue Annotation
The @DefaultValue annotation is defined directly in the Config interface at owner/src/main/java/org/aeonbits/owner/Config.java (lines 79-81). It is a method-level annotation that accepts a single string element:
@Retention(RUNTIME)
@Target(METHOD)
public @interface DefaultValue {
String value();
}
When you declare a method in your configuration interface, placing @DefaultValue("your-fallback") above it instructs Owner to use "your-fallback" as the raw input string whenever the property key cannot be resolved.
How Default Value Resolution Works
Owner applies a specific resolution hierarchy when you invoke a method on a configuration proxy created via ConfigFactory.create():
- Key Lookup – Owner first attempts to locate the property key, either derived from the method name or overridden via the
@Keyannotation. - Source Scanning – It scans all configured sources (files, URLs, classpath resources, environment variables, system properties).
- Default Fallback – If the key is absent, Owner retrieves the string from
@DefaultValueand processes it through the same type conversion pipeline used for real property values.
Type Conversion and Variable Expansion
The default string undergoes automatic conversion to the method's declared return type using Owner's internal Converters utility. This supports primitives, wrappers, enums, collections, and custom types via registered Converter instances.
Additionally, the default value can contain ${...} placeholders. These are expanded against the same configuration instance after the default is selected, allowing dynamic defaults like ${user.home}/logs.
Practical Implementation Examples
Basic Primitive Defaults
Define fallback values for primitive types and booleans when properties are missing:
public interface ServerConfig extends Config {
@DefaultValue("8080")
int port();
@DefaultValue("false")
boolean debugMode();
@DefaultValue("localhost")
String host();
}
Collection and Complex Defaults
Owner automatically tokenizes comma-separated strings into List implementations:
public interface AppConfig extends Config {
@DefaultValue("US,CA,MX")
List<String> supportedRegions();
@DefaultValue("read,write,admin")
Set<String> defaultPermissions();
}
Placeholder Expansion in Defaults
Reference other configuration values or system properties within your defaults:
public interface PathConfig extends Config {
@DefaultValue("${user.home}/app/logs")
String logDirectory();
@DefaultValue("${java.io.tmpdir}/cache")
File tempCachePath();
}
Handling Invalid Default Values
If the string provided to @DefaultValue cannot be converted to the target type, Owner throws an UnsupportedOperationException. This behavior is verified in owner/src/test/java/org/aeonbits/owner/typeconversion/PrimitiveTypesTest.java:
public interface InvalidConfig extends Config {
@DefaultValue("not-a-number")
int malformedPort(); // Throws UnsupportedOperationException on access
}
Always ensure that default literals match the expected format for complex types, especially when using custom Converter classes or Tokenizer annotations.
Summary
- Annotation Location:
@DefaultValueis defined inConfig.java(lines 79-81) and applied to interface methods. - Fallback Mechanism: When a property key is missing from all sources, Owner uses the annotated string as the raw value.
- Automatic Conversion: Default strings are converted to the method's return type using the same pipeline as regular properties, supporting primitives, collections, and custom objects.
- Placeholder Support: Default values can reference variables like
${user.home}which are resolved after selection. - Error Handling: Malformed defaults that fail type conversion trigger
UnsupportedOperationException.
Frequently Asked Questions
What happens if I don't use @DefaultValue and the property is missing?
If no @DefaultValue is specified and the property cannot be found in any configured source, Owner returns null for object return types or throws a NullPointerException for primitive return types when attempting to unbox the null value.
Can I use @DefaultValue with @Key annotations?
Yes. When you use @Key("custom.property.name") to override the default key derivation, @DefaultValue still functions as the fallback if custom.property.name is absent from the configuration sources. The annotation order does not matter.
Does @DefaultValue support multi-line strings or complex JSON defaults?
The @DefaultValue annotation accepts any single string literal. For multi-line values, you can use \n escape sequences or include literal newlines within the string (Java 15+ text blocks work in source). For complex structures like JSON, store the JSON as a single string default and use a custom Converter to parse it into your target object type.
How do I debug which default value is being applied?
Owner does not provide a specific debug mode for default value selection. However, you can verify behavior by ensuring the property is absent from all sources (files, environment variables, system properties) and asserting the returned value matches your @DefaultValue annotation. For programmatic verification, inspect the generated proxy or use unit tests as demonstrated in PrimitiveTypesTest.java.
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 →