# How to Handle Parameter Formatting with Placeholders in Owner Configuration

> Learn how to handle parameter formatting in Owner configuration using String.format with percent-style placeholders for dynamic values. Get clear syntax examples.

- Repository: [Matteo Baccan/owner](https://github.com/matteobaccan/owner)
- Tags: how-to-guide
- Published: 2026-03-07

---

**Owner automatically injects method arguments into configuration values using Java's standard `String.format` with percent-style placeholders (`%s`, `%d`), not the indexed `{0}`, `{1}` syntax found in other frameworks.**

Owner (matteobaccan/owner) is a lightweight Java library that maps property files to type-safe interfaces. When handling parameter formatting with placeholders in values, Owner delegates to `java.util.Formatter`, allowing dynamic substitution of method arguments into configuration strings at runtime.

## How Owner Implements Parameter Formatting

Owner detects non-null argument lists on configuration interface methods and automatically applies `String.format` to the backing property value.

### The %s Placeholder Syntax vs {0} Indexes

Unlike MessageFormat-style libraries that use `{0}` and `{1}` indexed placeholders, Owner follows the `java.util.Formatter` convention. In [`owner/src/main/java/org/aeonbits/owner/PropertiesInvocationHandler.java`](https://github.com/matteobaccan/owner/blob/main/owner/src/main/java/org/aeonbits/owner/PropertiesInvocationHandler.java), the `format(Method, String, Object...)` method checks for arguments and invokes `String.format(format, args)`.

The placeholders use standard Java conversion specifiers:

- **%s** for strings
- **%d** for integers
- **%f** for floating-point numbers

### Automatic Formatting Trigger

When a method declaration includes parameters and the property value contains format specifiers, Owner substitutes arguments automatically. This occurs in `PropertiesInvocationHandler.format()`, which evaluates whether the **PARAMETER_FORMATTING** feature is enabled before processing.

## Disabling Automatic Formatting

Sometimes configuration values contain literal percent signs or you need raw values without interpolation. Owner provides the `@DisableFeature` annotation defined in [`owner/src/main/java/org/aeonbits/owner/Config.java`](https://github.com/matteobaccan/owner/blob/main/owner/src/main/java/org/aeonbits/owner/Config.java).

### Method-Level Control

Apply `@DisableFeature(PARAMETER_FORMATTING)` to individual methods to return raw property values unchanged:

```java
public interface RawConfig extends Config {
    @DisableFeature(PARAMETER_FORMATTING)
    @DefaultValue("Hello %s, welcome on ${planet}!")
    String rawHello(String name);
}

```

When `rawHello("Luigi")` executes, it returns `"Hello %s, welcome on ${planet}!"` without attempting to format the `%s` placeholder.

### Interface-Level Configuration

To disable formatting for all methods in an interface, annotate the interface itself:

```java
@DisableFeature(PARAMETER_FORMATTING)
public interface AllRawConfig extends Config {
    @DefaultValue("Path=%s")
    String path(String dummy);
}

```

All methods inherit the disabled state, returning literal strings like `Path=%s` regardless of arguments passed.

## Escaping Literal Percent Characters

When formatting remains enabled but values contain literal percent signs, use the standard Java escape sequence `%%`. This inserts a single `%` character without triggering format conversion.

```java
public interface PercentConfig extends Config {
    @DefaultValue("Discount is 20%% for %s")
    String discount(String product);
}

```

Calling `discount("books")` produces: `Discount is 20% for books`.

## Code Examples

### Basic Parameter Substitution

```java
public interface GreetingConfig extends Config {
    @DefaultValue("Hello %s, welcome on %s!")
    String hello(String name, String planet);
}

GreetingConfig cfg = ConfigFactory.create(GreetingConfig.class);
System.out.println(cfg.hello("Luigi", "Earth"));
// Output: Hello Luigi, welcome on Earth!

```

Owner passes the method arguments to `String.format("Hello %s, welcome on %s!", "Luigi", "Earth")` automatically.

### Disabling Formatting for Passwords or URLs

```java
public interface DatabaseConfig extends Config {
    @DisableFeature(PARAMETER_FORMATTING)
    @DefaultValue("jdbc:mysql://localhost?password=%s123")
    String connectionString(String ignored);
}

```

The `%s123` sequence remains unchanged in the output, preventing accidental format errors when passwords contain special characters.

### Interface-Wide Raw Values

```java
@DisableFeature(PARAMETER_FORMATTING)
public interface TemplateConfig extends Config {
    @DefaultValue("Progress: 50%% complete")
    String status();
}

```

Every method returns values literally, treating `%%` as two separate percent characters rather than an escaped sequence.

## Summary

- Owner uses **percent-style placeholders** (`%s`, `%d`) via `String.format`, not `{0}` or `{1}` indexed syntax.
- The **PARAMETER_FORMATTING** feature is enabled by default and implemented in [`PropertiesInvocationHandler.java`](https://github.com/matteobaccan/owner/blob/main/PropertiesInvocationHandler.java).
- Use **`@DisableFeature(PARAMETER_FORMATTING)`** to return raw configuration values without interpolation.
- Escape literal percent signs with **`%%`** when formatting is enabled.
- The `DisableableFeature` enum and `@DisableFeature` annotation are defined in [`Config.java`](https://github.com/matteobaccan/owner/blob/main/Config.java).

## Frequently Asked Questions

### Does Owner support MessageFormat-style {0} and {1} placeholders?

No. Owner exclusively uses `java.util.Formatter` syntax with percent-style conversion specifiers like `%s` and `%d`. The `{0}` and `{1}` syntax used by `java.text.MessageFormat` is not recognized by Owner's `PropertiesInvocationHandler.format()` method. You must convert existing `{0}` patterns to `%s` format strings.

### How do I prevent Owner from interpreting % characters as format specifiers?

Annotate the method or interface with `@DisableFeature(PARAMETER_FORMATTING)` as defined in [`owner/src/main/java/org/aeonbits/owner/Config.java`](https://github.com/matteobaccan/owner/blob/main/owner/src/main/java/org/aeonbits/owner/Config.java). This bypasses the automatic `String.format` call in [`PropertiesInvocationHandler.java`](https://github.com/matteobaccan/owner/blob/main/PropertiesInvocationHandler.java), returning the raw property value including literal `%` characters.

### Can I mix formatted and non-formatted methods in the same interface?

Yes. The `@DisableFeature` annotation works at the method level, allowing fine-grained control. Methods without the annotation process `%` placeholders normally, while annotated methods return raw values. This is demonstrated in [`owner/src/test/java/org/aeonbits/owner/DisableFeatureTest.java`](https://github.com/matteobaccan/owner/blob/main/owner/src/test/java/org/aeonbits/owner/DisableFeatureTest.java).

### What happens if I pass more arguments than format specifiers?

Owner delegates to Java's `String.format`, which throws `java.util.MissingFormatArgumentException` if there are more arguments than format specifiers in the string. Ensure your property values contain the correct number of `%` placeholders matching the method parameter count.