CDI Extensions

SmallRye Config provides a set of additional extensions to enhance MicroProfile Config and CDI integration.

Config Source Injection

The Config Source Injection extension allows you to use CDI injection to inject a ConfigSource by name in your CDI aware beans, or by looking it up programatically in the CDI BeanManager.

Usage

To use the Config Source Injection, add the following to your Maven pom.xml:

<dependency>
    <groupId>io.smallrye.config</groupId>
    <artifactId>smallrye-config-source-injection</artifactId>
    <version>2.4.0</version>
</dependency>

Injecting Sources

You can inject a ConfigSource by referencing it by name:

@Inject
@Name("MemoryConfigSource")
private ConfigSource memoryConfigSource;

@Inject
@Name("SysPropConfigSource")
private ConfigSource systemPropertiesConfigSource;

You can also get a Map of all config sources. The map key holds the ConfigSource name and the map value the ConfigSource:

@Inject
@ConfigSourceMap
private Map<String,ConfigSource> configSourceMap;

Config Events

The Config Events extension allows you to fire change events on Config Sources.

Usage

To use the Config Events, add the following to your Maven pom.xml:

<dependency>
    <groupId>io.smallrye.config</groupId>
    <artifactId>smallrye-config-events</artifactId>
    <version>2.4.0</version>
</dependency>

Events

The CDI Event is a ChangeEvent and contains the following fields:

  • String key

  • Optional<String> oldValue

  • String newValue

  • Type type

  • String fromSource

The ChangeEvent can be of any of the following types:

  • NEW - When you create a new key and value (i.e. the key does not exist anywhere in any config source)

  • UPDATE - When you update a value of an existing key (i.e. the key and value exist somewhere in a config source)

  • REMOVE - When you remove the value from the source (and that changed the overall config)

Observing Events

You can listen to all or some of these events, filtering by type and/or key and/or source, example:

// Getting all config event
public void all(@Observes ChangeEvent changeEvent){
    log.log(Level.SEVERE, "ALL: Received a config change event: {0}", changeEvent);
}

// Get only new values
public void newValue(@Observes @TypeFilter(Type.NEW) ChangeEvent changeEvent){
    log.log(Level.SEVERE, "NEW: Received a config change event: {0}", changeEvent);
}

// Get only override values
public void overrideValue(@Observes @TypeFilter(Type.UPDATE) ChangeEvent changeEvent){
    log.log(Level.SEVERE, "UPDATE: Received a config change event: {0}", changeEvent);
}

// Get only revert values
public void revertValue(@Observes @TypeFilter(Type.REMOVE) ChangeEvent changeEvent){
    log.log(Level.SEVERE, "REMOVE: Received a config change event: {0}", changeEvent);
}

// Getting all config event when key is some.key
public void allForKey(@Observes @KeyFilter("some.key") ChangeEvent changeEvent){
    log.log(Level.SEVERE, "ALL for key [some.key]: Received a config change event: {0}", changeEvent);
}

// Getting all config event when key is some.key for new events
public void newForKey(@Observes @TypeFilter(Type.NEW) @KeyFilter("some.key") ChangeEvent changeEvent){
    log.log(Level.SEVERE, "NEW for key [some.key]: Received a config change event: {0}", changeEvent);
}

// Getting all config event when key is some.key for override events
public void overrideForKey(@Observes @TypeFilter(Type.UPDATE) @KeyFilter("some.key") ChangeEvent changeEvent){
    log.log(Level.SEVERE, "UPDATE for key [some.key]: Received a config change event: {0}", changeEvent);
}

// Getting all config event when key is some.key for revert events
public void revertForKey(@Observes @TypeFilter(Type.REMOVE) @KeyFilter("some.key") ChangeEvent changeEvent){
    log.log(Level.SEVERE, "REMOVE for key [some.key]: Received a config change event: {0}", changeEvent);
}

// Getting all config events for a certain source
public void allForSource(@Observes @SourceFilter("MemoryConfigSource") ChangeEvent changeEvent){
    log.log(Level.SEVERE, "ALL for source [MemoryConfigSource]: Received a config change event: {0}", changeEvent);
}

// Getting all config events for a certain source
public void allForSourceAndKey(@Observes @SourceFilter("MemoryConfigSource") @KeyFilter("some.key")  ChangeEvent changeEvent){
    log.log(Level.SEVERE, "ALL for source [MemoryConfigSource] and for key [some.key]: Received a config change event: {0}", changeEvent);
}

// Getting all config events for a certain source
public void overrideForSourceAndKey(@Observes @TypeFilter(Type.UPDATE) @SourceFilter("MemoryConfigSource") @KeyFilter("some.key")  ChangeEvent changeEvent){
    log.log(Level.SEVERE, "UPDATE for source [MemoryConfigSource] and for key [some.key]: Received a config change event: {0}", changeEvent);
}

Note: You can filter by including the @TypeFilter and/or the @KeyFilter and/or the @SourceFilter.

Pattern matching on field.

You might want to listen for fields that match a certain regex.

Example, listen to all keys that starts with some.:

@RegexFilter("^some\\..+")
public void allForPatternMatchOnKey(@Observes ChangeEvent changeEvent){
    log.log(Level.SEVERE, "Pattern match on key: Received a config change event: {0}", changeEvent);
}

By default, it will match on key, however you also listen on another field, for example, listen to all oldValue that starts with some.:

@RegexFilter(onField = Field.oldValue, value = "^some\\..+")
public void allForPatternMatchOnOldValue(@Observes ChangeEvent changeEvent){
    log.log(Level.SEVERE, "Pattern match on old value: Received a config change event: {0}", changeEvent);
}

You can Match on the following fields of the ChangeEvent object:

  • key

  • oldValue

  • newValue

  • fromSource

Implementing Events in a ConfigSource

The ChangeEventNotifier allows you to detect changes and fire the appropriate events.

To use it in your own source:

  • Get a snapshot of the properties before the change.

  • Get a snapshot of the properties after the change.

  • Call detectChangesAndFire method:

Example:

Map<String,String> before = new HashMap<>(configSource.getProperties());
memoryConfigSource.getProperties().remove(key);
Map<String,String> after = new HashMap<>(configSource.getProperties());
ChangeEventNotifier.getInstance().detectChangesAndFire(before, after,configSource.getName());

or if you know the change and do not need detection:

configSource.getProperties().remove(key);
ChangeEventNotifier.getInstance().fire(new ChangeEvent(Type.REMOVE,key,getOptionalOldValue(oldValue),null,configSource.getName()));