All Downloads are FREE. Search and download functionalities are using the official Maven repository.

se.config.mutability-support.adoc Maven / Gradle / Ivy

There is a newer version: 4.2.0
Show newest version
///////////////////////////////////////////////////////////////////////////////

    Copyright (c) 2018, 2024 Oracle and/or its affiliates.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.

///////////////////////////////////////////////////////////////////////////////

= Mutability Support
:description: Helidon mutability support
:keywords: helidon, config
:feature-name: Config
:rootdir: {docdir}/../..

include::{rootdir}/includes/se.adoc[]

== Contents

- <>
- <>
- <>
- <>

== Overview
An in-memory config tree, once loaded, is immutable, even though the data in the underlying
config sources _can_ change over time. The config system internally
records which config sources it used to load each config tree and some metadata
about the configuration. Your application can be aware of updates to the underlying
config sources by:

1. using the metadata the config system maintains,
2. responding to change when the config sources are updated, or
3. using ``Supplier``s of particular config values to obtain the always-current
value for a key.

== Using Config Metadata
=== Loading Time
The config system records when it loads each configuration into memory.
Your application can retrieve it by invoking the link:{config-javadoc-base-url}/io/helidon/config/Config.html#timestamp--[timestamp method] on any config node:

[source,java]
----
include::{sourcedir}/se/config/MutabilitySupportSnippets.java[tag=snippet_1, indent=0]
----

=== Config Context
The config system maintains a link:{config-javadoc-base-url}/io/helidon/config/Config.Context.html[`Config.Context`]
for each `Config` node. Your application can retrieve the context by invoking the `Config.context()`
method and then use it for these operations:

.Uses of `Config.Context`
|===
|Method |Usage

|`Instant timestamp()` |Returns the load time of the last loaded configuration
that used the context.
|`Config last()` |Returns the most recently loaded configuration that used the context.
|`Config reload()` |Reloads the
entire config tree from the current contents of the same config sources used to
load the tree in which the current node resides.
|===

Note that the config context describes or replaces a currently-loaded config tree.
It by itself does not help your application decide _when_ reloading the config might be
useful.

== Responding to Changes in Config Sources [[polling]]

Although in-memory config trees do not change once loaded, applications can respond to change
in the underlying config sources by:

1. setting up change detection for the config sources used to build a configuration, and
2. registering a response to be run when a source changes.

Your code's response can react to the changes in whatever way makes sense
for your application.

The following sections describe these steps in detail.

=== Setting up Config Source Change Detection
When the application creates a config source, it can set up change detection for
that source. This is called _polling_ in the Helidon API but specific change detection
algorithms might not use actual polling. You choose a specific
link:{config-javadoc-base-url}/io/helidon/config/spi/PollingStrategy.html[`PollingStrategy`] for each
config source you want to monitor. See the section on
xref:extensions.adoc#Config-SPI-PollingStrategy[polling strategies] in the
config extensions doc page for more information.

The config system provides some built-in polling strategies, exposed as these methods
on the link:{config-javadoc-base-url}/io/helidon/config/PollingStrategies.html[`PollingStrategies`] class:

- `regular(Duration interval)` - a general-purpose scheduled polling strategy with a specified,
 constant polling interval.
- `watch(Path watchedPath)` - a filesystem-specific strategy to watch
 specified path. You can use this strategy with the `file`
built-in config sources.
- `nop()` - a no-op strategy

This example builds a `Config` object from three sources, each set up with a
different polling strategy:

[source,java]
.Build a `Config` with a different `PollingStrategy` for each config source
----
include::{sourcedir}/se/config/MutabilitySupportSnippets.java[tag=snippet_2, indent=0]
----
<1> Optional `file` source `conf/dev.properties` will be checked for changes every
 `2` seconds.
<2> Optional `file` source `conf/config.properties` will be watched by the Java
 `WatchService` for changes on filesystem.
<3> The `file` resource `my.properties` will not be checked for
 changes.
`PollingStrategies.nop()` polling strategy is default.

The polling strategies internally inform the config system when they
detect changes in the monitored config sources (except that the `nop` strategy does
nothing).

=== Registering a Config Change Response
To know when config sources have changed, your application must register its interest
on the `Config` node of interest. The config system will then notify
your application of any change within the subtree rooted at that node.
In particular, if you register on the root node,
then the config system notifies your code of changes anywhere in the config tree.

==== Registering Actions

You register a function that runs when a change occurs by using the
link:{config-javadoc-base-url}/io/helidon/config/Config.html#onChange(java.util.function.Consumer)[`Config.onChange()`]
method on the node of interest.

[source,java]
.Subscribe on `greeting` property changes via `onChange` method
----
include::{sourcedir}/se/config/MutabilitySupportSnippets.java[tag=snippet_3, indent=0]
----
<1> Navigate to the `Config` node on which you want to register.
<2> Invoke the `onChange` method, passing a consumer (`Consumer`).
The config system invokes that consumer each time the subtree rooted at the
`greeting` node changes. The `changedNode` is a new instance of `Config`
representing the updated subtree rooted at `greeting`.

== Accessing Always-current Values
Some applications do not need to respond to change as they happen. Instead, it's
sufficient that they simply have access to the current value for a particular
key in the configuration.

Each `asXXX` method on the `Config` class has a companion `asXXXSupplier` method.
These supplier methods return `Supplier`, and when your application invokes
the supplier's `get` method the config system returns the _then-current value_
as stored in the config source.

[source,java]
.Access `greeting` property as `Supplier`
----
include::{sourcedir}/se/config/MutabilitySupportSnippets.java[tag=snippet_4, indent=0]
----
<1> Navigate to the `Config` node for which you want access to the always-current
value.
<2> Retrieve and store the returned supplier for later use.
<3> Invoke the supplier's `get()` method to retrieve the current value of the node.

[IMPORTANT]
=========
Supplier support requires that you create the `Config` object from config sources that
have proper polling strategies set up. The supplier returns refreshed values only
after changes have been detected by the polling strategy.
=========




© 2015 - 2025 Weber Informatics LLC | Privacy Policy