task: better document property mapping (#40873)

* task: better document property mapping

closes: #40872

Signed-off-by: Steve Hawkins <shawkins@redhat.com>

* Update quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/PropertyMapper.java

Co-authored-by: Martin Bartoš <mabartos@redhat.com>
Signed-off-by: Steven Hawkins <shawkins@redhat.com>

* further refinements to the property mapping docs

Signed-off-by: Steve Hawkins <shawkins@redhat.com>

* Apply suggestions from code review

Co-authored-by: Martin Bartoš <mabartos@redhat.com>
Signed-off-by: Steven Hawkins <shawkins@redhat.com>

---------

Signed-off-by: Steve Hawkins <shawkins@redhat.com>
Signed-off-by: Steven Hawkins <shawkins@redhat.com>
Co-authored-by: Martin Bartoš <mabartos@redhat.com>
This commit is contained in:
Steven Hawkins 2025-07-30 11:36:45 -04:00 committed by GitHub
parent c9943af4f3
commit e4882f88ef
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 33 additions and 3 deletions

View File

@ -48,6 +48,9 @@ import jakarta.annotation.Priority;
*
* <p>This interceptor must execute after the {@link io.smallrye.config.ExpressionConfigSourceInterceptor} so that expressions
* are properly resolved before executing this interceptor.
*
* <p>The {@link NestedPropertyMappingInterceptor} catches property mappings that need to be performed within expressions.
*
* <p>
* The reason for the used priority is to always execute the interceptor before default Application Config Source interceptors
*/

View File

@ -100,6 +100,28 @@ public class PropertyMapper<T> {
this.namedProperty = namedProperty;
}
/**
* This is the heart of the property mapping logic. In the first step, we need to find the value of the property and then transform it into a form of our needs.
* <p>
*
* <b>1. Find value</b>
* <p>
* In preference order we are looking for:
* <pre>
* [ {@link #from} ] ---> [ {@link #mapFrom} ] ---> [ {@link #getDefaultValue()} ] ---> [ {@link #to} ]
* (explicit) (derived) (fallback) (fallback)
* </pre>
* <p>
*
* <b>2. Transform found value</b>
* <p>
* If we found a value for the attribute name, it needs to be transformed via {@link #transformValue} method. How to transform it?
* <ul>
* <li>If the name matches {@link #from} or we using the {@link #mapFrom} value, then apply the {@link PropertyMapper.Builder#transformer} or the {@link PropertyMapper.Builder#mapFrom(Option, ValueMapper)}
* <li>If the value contains an expression, expand it using SmallRye logic
* <li>Finally the returned {@link ConfigValue} is made to match what was requested - with the name, value, rawValue, and ordinal set appropriately.
* </ul>
*/
ConfigValue getConfigValue(String name, ConfigSourceInterceptorContext context) {
String from = getFrom();
@ -126,7 +148,7 @@ public class PropertyMapper<T> {
context, false);
}
if (config != null) {
if (config != null || name.equals(from)) {
return config;
}
@ -359,8 +381,7 @@ public class PropertyMapper<T> {
}
/**
* NOTE: This transformer will not apply to the mapFrom value. When using
* {@link #mapFrom} you generally need a transformer specifically for the parent
* When using {@link #mapFrom} you generally need a transformer specifically for the parent
* value, see {@link #mapFrom(Option, BiFunction)}
* <p>
* The value passed into the transformer may be null if the property has no value set, and no default
@ -369,6 +390,12 @@ public class PropertyMapper<T> {
return transformer((name, value, context) -> mapper.apply(value, context));
}
/**
* When using {@link #mapFrom} you generally need a transformer specifically for the parent
* value, see {@link #mapFrom(Option, BiFunction)}
* <p>
* The value passed into the transformer may be null if the property has no value set, and no default
*/
public Builder<T> transformer(ValueMapper mapper) {
this.mapper = mapper;
return this;