Class LiveConfiguration
java.lang.Object
org.j7m.middleware.application.components.LiveConfiguration
- All Implemented Interfaces:
AutoCloseable
Host-owned, versioned configuration with atomically validated typed bindings.
Each accepted update validates every refreshing binding before publication. Failed conversion or
validation preserves the previous version. Values and exception details are never echoed in
diagnostics. Validators and record constructors are trusted, side-effect-free application code;
they may run more than once after concurrent registration/update. They run outside the owner
monitor and must not mutate this owner reentrantly. Scalar values and public records of supported
scalar components are supported, without private reflection or JPMS opens. Instances are
thread-safe; external configuration sources feed complete snapshots through update(long, Map).
Source reconnect must preserve a monotonically increasing version namespace.
-
Constructor Summary
ConstructorsConstructorDescriptionLiveConfiguration(long initialVersion, Map<String, String> initial) Creates an owner with no registrations. -
Method Summary
Modifier and TypeMethodDescriptionattach(org.j7m.middleware.application.api.ConfigurationSource source) Attaches one trusted source, including initial snapshot and tail delivery.intReturns the number of active binding registrations.<T> org.j7m.middleware.application.api.ConfigBinding<T> bindProperties(Class<T> type, Consumer<? super T> validator) Registers a public record annotated with ConfigProperties as an immutable whole-value binding.<T> org.j7m.middleware.application.api.ConfigBinding<T> bindValue(Class<T> type, String key, boolean required, String defaultValue, boolean refresh, Consumer<? super T> validator) Registers a typed scalar binding, validated against the current complete snapshot.voidclose()Closes all registrations idempotently and discards owned raw values.longReturns rejected source deliveries without exposing their contents.booleanPublishes a newer full source snapshot after validating all registered refresh bindings.longversion()Returns the accepted complete source version, without any configuration values.
-
Constructor Details
-
LiveConfiguration
Creates an owner with no registrations.- Parameters:
initialVersion- nonnegative initial source versioninitial- complete initial string snapshot, at most 1024 entries- Throws:
IllegalArgumentException- if bounds or the version are invalid
-
-
Method Details
-
bindValue
public <T> org.j7m.middleware.application.api.ConfigBinding<T> bindValue(Class<T> type, String key, boolean required, String defaultValue, boolean refresh, Consumer<? super T> validator) Registers a typed scalar binding, validated against the current complete snapshot. Supported types are String, primitive wrappers, Duration and enums; primitive Class tokens are normalized to their wrappers. A required missing value is rejected even with a default. An optional missing scalar uses a nonempty default, empty String, or null for other types.- Type Parameters:
T- scalar value type- Parameters:
type- supported scalar typekey- exact configuration keyrequired- whether absence is invaliddefaultValue- optional textual default, never included in diagnosticsrefresh- whether later accepted versions replace this binding's initial valuevalidator- side-effect-free validation, never null; exceptions reject safely- Returns:
- closeable stable typed provider
- Throws:
IllegalArgumentException- if conversion, validation or metadata is invalidIllegalStateException- if closed, called reentrantly or registration capacity is exhausted
-
bindProperties
public <T> org.j7m.middleware.application.api.ConfigBinding<T> bindProperties(Class<T> type, Consumer<? super T> validator) Registers a public record annotated with ConfigProperties as an immutable whole-value binding. Components use prefix plus their name; ConfigValue can override the relative name, required flag and default. A component without ConfigValue is required. Component-level refresh is rejected: refresh is selected for the whole properties record. The public canonical constructor must be accessible through normal JPMS exports, without setAccessible.- Type Parameters:
T- immutable record type- Parameters:
type- public annotated record type with at most 128 supported scalar componentsvalidator- side-effect-free whole-record validation- Returns:
- closeable whole-record provider
- Throws:
IllegalArgumentException- if the record, conversion or validation is invalidIllegalStateException- if closed, reentrant or capacity is exhausted
-
update
Publishes a newer full source snapshot after validating all registered refresh bindings. Conversions occur outside the owner monitor; concurrent structural changes cause at most eight retries. A source may replay snapshots after reconnect: stale versions return false.- Parameters:
version- positive or zero monotonically increasing source versionvalues- complete replacement snapshot, not a patch- Returns:
- true if published, false if no newer than the current version
- Throws:
IllegalArgumentException- if input or any binding validation failsIllegalStateException- if closed, reentrant or repeatedly changed concurrently
-
version
public long version()Returns the accepted complete source version, without any configuration values.- Returns:
- nonnegative accepted version
- Throws:
IllegalStateException- if closed
-
bindingCount
public int bindingCount()Returns the number of active binding registrations.- Returns:
- bounded active count, zero after close
-
attach
Attaches one trusted source, including initial snapshot and tail delivery. A second active source is rejected; detach before reconnecting a replacement source. Late detached-source events cannot publish. Invalid live updates are rejected and counted without terminating the subscription, so a later valid snapshot can recover. The owner closes this subscription.- Parameters:
source- trusted host-selected configuration provider- Returns:
- idempotent detach handle; source close failures have redacted errors
- Throws:
IllegalArgumentException- if subscribing fails or the source returns no handleIllegalStateException- if closed, reentrant or another source is attachedNullPointerException- if source is null
-
rejectedSourceUpdates
public long rejectedSourceUpdates()Returns rejected source deliveries without exposing their contents.- Returns:
- rejection count; stale or detached-source events are ignored, not counted
-
close
public void close()Closes all registrations idempotently and discards owned raw values.- Specified by:
closein interfaceAutoCloseable- Throws:
IllegalStateException- if called reentrantly by a validator
-