# How to Implement the Reloadable Interface for Manual Property Reload in Owner

> Implement the Reloadable interface in OWNER for manual property reloads. Extend Reloadable with Config and call reload() to refresh properties at runtime without app restarts.

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

---

**Extend `Reloadable` alongside `Config` and call `reload()` on your configuration instance to refresh properties at runtime without restarting your application.**

The Owner library provides type-safe access to Java properties through dynamic proxies. When you need to pick up external configuration changes on demand, you must implement the Reloadable interface for manual property reload capabilities. This approach complements automatic hot-reload features by giving you explicit control over exactly when configuration refreshes occur.

## Understanding the Reloadable Interface

The **`Reloadable`** interface in `org.aeonbits.owner` extends `Config` and declares three methods that Owner implements dynamically at runtime. When you invoke `ConfigFactory.create()`, the framework generates a proxy that handles these methods—you provide no method bodies.

The interface defines these operations:

- `void reload()` – Re-executes the loading pipeline to refresh cached property values.
- `void addReloadListener(ReloadListener listener)` – Registers a callback invoked after each reload.
- `void removeReloadListener(ReloadListener listener)` – Unregisters a previously added listener.

According to the source code in [[`Reloadable.java`](https://github.com/matteobaccan/owner/blob/main/Reloadable.java)](https://github.com/matteobaccan/owner/blob/master/owner/src/main/java/org/aeonbits/owner/Reloadable.java), these methods enable programmatic control over configuration refresh cycles while maintaining type safety.

## Step-by-Step Implementation

Follow these steps to implement the Reloadable interface for manual property reload:

1. **Define your interface** by extending both `Config` and `Reloadable`.
2. **Annotate with sources** using `@Sources` to specify property file locations.
3. **Create the proxy** via `ConfigFactory.create(MyConfig.class)`.
4. **Trigger reloads** by calling `cfg.reload()` when external changes occur.
5. **Manage observers** by registering `ReloadListener` instances to react to refresh events.

## Code Examples

### Basic Reloadable Configuration

Define an interface that extends `Reloadable` and map your properties:

```java
import org.aeonbits.owner.Config;
import org.aeonbits.owner.Config.Sources;
import org.aeonbits.owner.Reloadable;

@Sources("file:./my.properties")
public interface MyConfig extends Config, Reloadable {
    int timeout();
    String endpoint();
}

```

Use the configuration and trigger manual reloads at runtime:

```java
import org.aeonbits.owner.ConfigFactory;

public class ConfigDemo {
    public static void main(String[] args) {
        MyConfig cfg = ConfigFactory.create(MyConfig.class);
        System.out.println("Initial timeout: " + cfg.timeout());

        // External process modifies ./my.properties...
        
        cfg.reload();  // Manual reload
        System.out.println("After reload: " + cfg.timeout());
    }
}

```

This pattern mirrors the implementation verified in [[`ReloadTest.java`](https://github.com/matteobaccan/owner/blob/main/ReloadTest.java)](https://github.com/matteobaccan/owner/blob/master/owner/src/test/java/org/aeonbits/owner/reload/ReloadTest.java#L63-L66).

### Reloading with Mutable Properties

When importing properties programmatically, `reload()` refreshes from the current state of the `Properties` object:

```java
Properties overrides = new Properties();
overrides.setProperty("timeout", "30");

MyConfig cfg = ConfigFactory.create(MyConfig.class, overrides);
System.out.println(cfg.timeout());  // Output: 30

overrides.setProperty("timeout", "45");
cfg.reload();  // Forces re-read of imports
System.out.println(cfg.timeout());  // Output: 45

```

This technique is demonstrated in [`ReloadTest.testReloadWithImportedProperties`](https://github.com/matteobaccan/owner/blob/master/owner/src/test/java/org/aeonbits/owner/reload/ReloadTest.java#L88-L99).

### Observing Reload Events

Register listeners to execute logic when configurations refresh:

```java
import org.aeonbits.owner.event.ReloadListener;
import org.aeonbits.owner.event.ReloadEvent;

ReloadListener logger = event -> System.out.println(
    "Reload performed on " + event.getSource());

MyConfig cfg = ConfigFactory.create(MyConfig.class);
cfg.addReloadListener(logger);

cfg.reload();  // Listener invoked
cfg.removeReloadListener(logger);
cfg.reload();  // Listener not invoked

```

The `ReloadEvent` object provides access to the source configuration instance via `getSource()`. This behavior is verified in [[`ReloadTest.java`](https://github.com/matteobaccan/owner/blob/main/ReloadTest.java)](https://github.com/matteobaccan/owner/blob/master/owner/src/test/java/org/aeonbits/owner/reload/ReloadTest.java#L8-L26).

### Combining with Automatic Hot-Reload

Combine `Reloadable` with the `@HotReload` annotation for hybrid refresh strategies:

```java
import org.aeonbits.owner.Config.HotReload;

@Sources("file:./dynamic.properties")
@HotReload(2)  // Check every 2 seconds
public interface LiveConfig extends Config, Reloadable {
    String value();
}

```

When using `@HotReload`, Owner automatically invokes `reload()` on the schedule you specify. You can still call `reload()` manually for immediate updates. This interaction is documented in [[`reload.md`](https://github.com/matteobaccan/owner/blob/main/reload.md)](https://github.com/matteobaccan/owner/blob/master/owner-site/site/docs/reload.md#L18-L30).

## Internal Architecture of Manual Reload

When you invoke `reload()`, Owner delegates to **`HotReloadLogic`**, the same component used by the automatic hot-reload feature. The process follows this sequence:

1. **Pipeline Re-execution**: Owner re-runs the loading logic, including source resolution, variable expansion, and type conversion.
2. **Cache Update**: The dynamic proxy updates its internal `Properties` snapshot with new values.
3. **Listener Notification**: For each registered `ReloadListener`, Owner fires a `ReloadEvent` containing the configuration source.

This architecture ensures that manual reloads behave identically to automatic ones, maintaining consistency across the configuration lifecycle.

## Summary

- Extend **`Reloadable`** alongside `Config` to enable manual reload capabilities in your configuration interfaces.
- Call **`reload()`** to refresh properties on-demand without recreating the configuration instance.
- Use **`addReloadListener()`** and **`removeReloadListener()`** to observe reload events and trigger side effects.
- The implementation is generated at runtime by **`ConfigFactory.create()`**; you define only the interface structure.
- Manual reload shares the same **`HotReloadLogic`** path as automatic reloading, ensuring consistent behavior.

## Frequently Asked Questions

### Do I need to implement the methods in the Reloadable interface?

No. The Owner framework generates the implementation dynamically when you call `ConfigFactory.create()`. The proxy handles `reload()`, `addReloadListener()`, and `removeReloadListener()` internally using the loading pipeline defined by your `@Sources` annotations.

### Can I use Reloadable with immutable Properties objects?

Yes, but you will only see value changes if the underlying source data changes. If you pass a `Properties` object to `ConfigFactory.create()`, calling `reload()` re-reads from that same object. For immutable sources like classpath files, ensure the file content changes on disk before invoking `reload()`.

### How do I unregister a ReloadListener?

Call `removeReloadListener(ReloadListener listener)` on your configuration instance, passing the same listener object you previously registered via `addReloadListener()`. This is useful for preventing memory leaks when configuration objects have long lifecycles but listeners become obsolete.

### What is the difference between @HotReload and manual reload?

The `@HotReload` annotation schedules automatic `reload()` calls at a fixed interval, while manual reload requires explicit invocation of the method. You can use both simultaneously: automatic reload handles periodic updates, while manual reload provides immediate consistency when you know external changes have occurred.