Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
This article describes the Spring Cloud Azure App Configuration library. This library loads configurations and feature flags from the Azure App Configuration service. The library generates PropertySource abstractions to match the abstractions already generated by the Spring environment, such as environment variables, command-line configurations, local configuration files, and so on.
Spring is an open-source application framework developed by VMware that provides a simplified, modular approach for creating Java applications. Spring Cloud Azure is an open-source project that provides seamless Spring integration with Azure services.
Prerequisites
- An Azure subscription - create one for free.
- Java Development Kit (JDK) version 17 or higher.
- Apache Maven
- Azure CLI
Set up your App Configuration store
Use the following command to create your Azure App Configuration store:
az appconfig create \
--resource-group <your-resource-group> \
--name <name-of-your-new-store> \
--sku Standard
This command creates a new, empty configuration store. You can upload your configurations by using the following import command:
az appconfig kv import \
--name <name-of-your-new-store> \
--source file \
--path <location-of-your-properties-file> \
--format properties \
--prefix /application/
Confirm your configurations before loading them. You can upload YAML files by changing the format to YAML. The prefix field is important because it's the default prefix loaded by the client library.
Library usage
To use the feature in an application, build it as a Spring Boot application. The recommended dependency for servlet-based web applications is the Spring Boot starter com.azure.spring:spring-cloud-azure-starter-appconfiguration-config. This starter bundles spring-cloud-azure-appconfiguration-config-web and spring-cloud-azure-feature-management-web, which provide configuration loading, servlet-request-based refresh, support for Spring Boot Actuator refresh endpoints, and web feature management.
For applications without servlets, such as console applications, depend on com.azure.spring:spring-cloud-azure-appconfiguration-config directly instead of the starter. Use manual refresh to check for configuration changes.
The following example pom.xml file uses Azure App Configuration:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>{spring-boot-version}</version>
<relativePath />
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-dependencies</artifactId>
<version>7.4.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-starter-appconfiguration-config</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
The following example shows a basic Spring Boot application using App Configuration:
@SpringBootApplication
@RestController
public class Application {
@RequestMapping("/")
public String home() {
return "Hello World!";
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
For this example, the application.properties file contains the following line:
spring.config.import=azureAppConfiguration
spring.cloud.azure.appconfiguration.stores[0].endpoint=${CONFIG_STORE_ENDPOINT}
CONFIG_STORE_ENDPOINT is an environment variable with the endpoint URL to your Azure App Configuration Store.
Note
Microsoft recommends using the most secure authentication flow available. The authentication flow described in this procedure, such as for databases, caches, messaging, or AI services, requires a very high degree of trust in the application and carries risks not present in other flows. Use this flow only when more secure options, like managed identities for passwordless or keyless connections, are not viable. For local machine operations, prefer user identities for passwordless or keyless connections.
By default, if you don't set any configurations, the configurations starting with /application/ load with a default label of (No Label) unless you set a Spring Profile, in which case the default label is your Spring Profile.
A property source named /application/https://<name-of-your-store>.azconfig.io/ is created containing the properties of that store. The label used in the request is appended to the end of the name. If you don't set a label, the character \0 is present as an empty space.
Loading configuration
The library supports loading one or multiple App Configuration stores. If a key is duplicated across multiple stores, the last one wins.
spring.cloud.azure.appconfiguration.stores[0].endpoint=[first-store-endpoint]
spring.cloud.azure.appconfiguration.stores[1].endpoint=[second-store-endpoint]
In this example, if both stores have the same configuration key, the configuration in the second store has the highest priority.
Note
You can use Azure App Configuration settings like any other Spring Configuration. For more information, see Core Features in the Spring Boot documentation or Quickstart: Create a Java Spring app with Azure App Configuration.
Startup timeout
The spring.cloud.azure.appconfiguration.startup-timeout property controls how long the library retries loading configuration during application startup when transient failures occur. The default is 100s. You can set a duration from 30 through 600 seconds, inclusive. For example, the following configuration sets the timeout to 120 seconds:
spring.cloud.azure.appconfiguration.startup-timeout=120s
Selecting configurations
The library loads configurations by using their key and label, or snapshot. When you don't use a method of selection, the library loads all keys with the prefix /application/ and the label \0, which appears as (No Label) in the Azure portal.
The default key filter is /application/*. The default label filter is \0, which appears as (No Label) in the Azure portal. If you set a Spring profile and don't provide a label, the default label is your Spring Profile, which is ${spring.profiles.active}.
You can also load configurations from a specific snapshot by using the snapshot-name property. For more information, see Snapshots.
You can select configurations by using key and label filters or a snapshot name in separate selectors:
spring.cloud.azure.appconfiguration.stores[0].selects[0].key-filter=[my-key]
spring.cloud.azure.appconfiguration.stores[0].selects[0].label-filter=[my-label]
spring.cloud.azure.appconfiguration.stores[0].selects[1].snapshot-name=[snapshot-name]
Note
You can't combine snapshot selection with key, label, or tag filters in the same selector. When you use snapshot selection, all keys in the snapshot are loaded.
The key-filter property supports the following filters:
| Key filter | Effect |
|---|---|
* |
Matches any key. |
abc |
Matches a key named abc. |
abc* |
Matches key names that start with abc. |
abc,xyz |
Matches key names abc or xyz. Limited to five comma-separated values. |
The label-filter property supports the following filters:
| Label | Description |
|---|---|
* |
Matches any label, including \0. |
\0 |
Matches null labels, which appear as (No Label) in the Azure portal. |
1.0.0 |
Matches label 1.0.0 exactly. |
1.0.* |
Matches labels that start with 1.0.*. |
,1.0.0 |
Matches labels null and 1.0.0. Limited to five comma-separated values. |
If you're using YAML with label filters, and you want to load configurations with no label and more configurations with other labels, you need to include an empty ,. For example, ,dev matches \0 and dev. In this case, surround the label filter with single quotes. This value enables you to load configuration with no label first, followed by configurations with specific labels, in the same filter:
spring:
cloud:
azure:
appconfiguration:
stores:
- selects:
- label-filter: ',1.0.0'
Note
You can't combine * with , in filters. In that case, you need to use an additional select value.
When you use * in the label filter, and multiple configurations with the same key are loaded, they're loaded in alphabetical order, and the label last in alphabetical order is used.
Tag filters
Use tags-filter to load only settings with specific tags. Each entry has the format tagName=tagValue. When you specify multiple entries, a setting must match all of them (AND logic). Tag filters further restrict the settings selected by the key and label filters.
The following example loads settings with both the environment=production and team=payments tags:
spring.cloud.azure.appconfiguration.stores[0].selects[0].tags-filter[0]=environment=production
spring.cloud.azure.appconfiguration.stores[0].selects[0].tags-filter[1]=team=payments
You can also configure tag filters separately for feature flags.
Snapshots
A snapshot is an immutable view of configuration at a given point in time. The snapshot must have the composition type Key. To use different configuration values, create another snapshot and update snapshot-name to load it.
You can load multiple snapshots or combine snapshots with key, label, and tag filters in separate selectors. Selectors are applied in order. If duplicate keys are loaded, the last selector has the highest priority.
The following example loads a snapshot first, then loads settings with the production label. Settings from the second selector override matching keys from the snapshot:
spring.cloud.azure.appconfiguration.stores[0].selects[0].snapshot-name=[snapshot-name]
spring.cloud.azure.appconfiguration.stores[0].selects[1].key-filter=/application/
spring.cloud.azure.appconfiguration.stores[0].selects[1].label-filter=production
spring.cloud.azure.appconfiguration.stores[0].trim-key-prefix[0]=/application/
Snapshot loading doesn't automatically trim a key prefix. If snapshot keys use a prefix such as /application/, set trim-key-prefix explicitly so that /application/config.message is available as config.message. This setting applies to all selected keys in the store and overrides automatic trimming based on the key filter. For more information, see Trimming keys.
Because snapshots are immutable, you don't need to enable monitoring when loading only snapshots. If you also select settings outside snapshots, you can enable monitoring to refresh those settings.
Note
Feature flags included in a snapshot are loaded even when feature-flags.enabled is false. If you enable feature-flag loading, flags loaded through the feature-flag selectors take priority over flags loaded from snapshots.
Spring profiles
By default, the library sets spring.profiles.active as the default label-filter for all selected configurations. You can override this functionality by using label-filter. Use Spring Profiles in the label-filter by using ${spring.profiles.active}, as shown in the following example:
spring.cloud.azure.appconfiguration.stores[0].selects[0].label-filter=,${spring.profiles.active}
spring.cloud.azure.appconfiguration.stores[0].selects[1].label-filter=${spring.profiles.active}_local
In the first label-filter, the library first loads all configurations with the \0 label, followed by all configurations that match the Spring Profiles. Spring Profiles have priority over the \0 configurations because they're at the end.
In the second label-filter, the string _local is appended to the end of the Spring Profiles, though only to the last Spring Profile if there's more than one.
Disabled stores
Use the configuration spring.cloud.azure.appconfiguration.enabled to disable loading for all configuration stores. Use the configuration spring.cloud.azure.appconfiguration.stores[0].enabled to disable an individual store.
If you disable a store, you must still load another store, or the App Configuration import must be optional. To let the application start when no stores are loaded, use optional:azureAppConfiguration:
spring.config.import=optional:azureAppConfiguration
spring.cloud.azure.appconfiguration.stores[0].enabled=false
Note
If you use health metrics, you still see your stores listed, but with the value NOT LOADED. When you check loaded property sources, you still see them listed, but they contain no values. This behavior is due to the spring.config.import property being set. If you don't set azureAppConfiguration for spring.config.import, no values are shown.
Authentication
The library supports all forms of identity supported by the Azure Identity Library. You can authenticate through configuration for connection strings and managed identity.
Note
Microsoft recommends using the most secure authentication flow available. The authentication flow described in this procedure, such as for databases, caches, messaging, or AI services, requires a very high degree of trust in the application and carries risks not present in other flows. Use this flow only when more secure options, like managed identities for passwordless or keyless connections, are not viable. For local machine operations, prefer user identities for passwordless or keyless connections.
Connection string (not recommended)
Authentication through connection string is the simplest form to set up, though it isn't recommended. You can access a store's connection strings by using the following command:
az appconfig credential list --name <name-of-your-store>
You can then set the spring.cloud.azure.appconfiguration.stores[0].connection-string property to the connection string. When using this approach, set the connection string in the local configuration file to a placeholder value that maps to an environment variable. This approach helps you avoid adding the connection string to source control.
Spring Cloud Azure configuration
Use Spring Cloud Azure configuration to configure the library. Use the following properties to configure the library:
spring.cloud.azure.appconfiguration.stores[0].endpoint= <URI-of-your-configuration-store>
When you set only the endpoint, the client library uses the DefaultAzureCredential to authenticate.
You need to assign the identity used to read configurations. Create this assignment by using the following command:
az role assignment create \
--role "App Configuration Data Reader" \
--assignee <your-client-ID> \
--scope /subscriptions/<your-subscription>/resourceGroups/<your-stores-resource-group>/providers/Microsoft.AppConfiguration/configurationStores/<name-of-your-configuration-store>
Note
Define only one authentication method per endpoint: connection string, user assigned identity, or token credential. If you need to mix and match, use ConfigurationClientCustomizer to modify the ConfigurationClientBuilder to use different methods.
Note
Microsoft recommends using the most secure authentication flow available. The authentication flow described in this procedure, such as for databases, caches, messaging, or AI services, requires a very high degree of trust in the application and carries risks not present in other flows. Use this flow only when more secure options, like managed identities for passwordless or keyless connections, are not viable. For local machine operations, prefer user identities for passwordless or keyless connections.
Managed identity
To use managed identity, enable a system-assigned or user-assigned managed identity on the Azure resource that hosts your application. Assign that identity the App Configuration Data Reader role on your store, as described in the previous section.
Configure the store endpoint and enable managed identity authentication:
spring.cloud.azure.appconfiguration.stores[0].endpoint=${CONFIG_STORE_ENDPOINT}
spring.cloud.azure.appconfiguration.credential.managed-identity-enabled=true
For a user-assigned managed identity, also set its client ID:
spring.cloud.azure.appconfiguration.credential.client-id=[your-managed-identity-client-id]
These credential properties apply specifically to App Configuration. To share the managed identity configuration across Azure services, use spring.cloud.azure.credential.managed-identity-enabled and spring.cloud.azure.credential.client-id instead.
Geo-replication
The library supports the geo-replication feature of Azure App Configuration. This feature enables you to replicate your data to other locations. This feature is useful for high availability and disaster recovery.
Each replica you create has a dedicated endpoint. If your application resides in multiple geolocations, you can update each deployment of your application in a location to connect to the replica closer to that location, which helps minimize the network latency between your application and App Configuration. Because each replica has its separate request quota, this setup also helps the scalability of your application while it grows to a multi-region distributed service.
By default, the library automatically discovers replicas that exist for a configuration store. You don't need to configure multiple endpoints to enable replica discovery. When a request is made to the provided store and fails, the library automatically retries the request against the available replicas.
The failover might occur if the library observes any of the following conditions:
- Receives responses with service unavailable status code (HTTP 500 or above) from an endpoint.
- Experiences network connectivity issues.
- Requests are throttled (HTTP status code 429).
After the provided store comes back online, the library automatically retries the request against the provided store.
If you want to control the failover behavior, you can manually provide a list of replica endpoints or connection strings in priority order, from most preferred to least preferred.
spring.cloud.azure.appconfiguration.stores[0].endpoints[0]=[your primary store endpoint]
spring.cloud.azure.appconfiguration.stores[0].endpoints[1]=[your replica store endpoint]
or
spring.cloud.azure.appconfiguration.stores[0].connection-strings[0]=[your primary store connection string]
spring.cloud.azure.appconfiguration.stores[0].connection-strings[1]=[your replica store connection string]
If replica discovery is enabled and all provided replica endpoints fail, the library attempts to connect to automatically discovered replicas of the primary store.
You can disable automatic replica discovery with the setting spring.cloud.azure.appconfiguration.stores[0].replica-discovery-enabled=false. This setting doesn't disable geo-replication in Azure App Configuration or failover between explicitly configured replica endpoints.
Load balancing
By default, spring.cloud.azure.appconfiguration.stores[0].load-balancing-enabled is false, and the library prefers the highest-priority reachable endpoint. To distribute requests across the configured endpoints instead, enable load balancing:
spring.cloud.azure.appconfiguration.stores[0].load-balancing-enabled=true
Load balancing controls how requests are distributed. Replica discovery controls whether the library automatically finds replica endpoints. Enabling or disabling either setting doesn't change geo-replication in the Azure App Configuration service.
Creating a configuration store with geo-replication
To create a replica of your configuration store, use the Azure CLI or the Azure portal. The following example uses the Azure CLI to create a replica in the East US 2 region:
az appconfig replica create --location --name --store-name [--resource-group]
Key values
Azure App Configuration supports multiple types of key values, some of which have special features built into them. Azure App Configuration has built-in support for the JSON content type, Spring placeholders, and Key Vault references.
Trimming keys
By default when loading keys from Azure App Configuration, the library trims the prefix defined by spring.cloud.azure.appconfiguration.stores[0].selects[0].key-filter from the key. For example, if you have a key named /application/config.message and a key filter of /application/*, the library trims the prefix /application/ and loads the key as config.message. This trimming makes it easier to reference keys in your code.
Override this behavior by setting spring.cloud.azure.appconfiguration.stores[0].trim-key-prefix[0] to a different value. Setting this property to an empty string disables the trimming behavior, and the key is loaded with its full name.
Placeholders
The library supports configurations with ${}-style environment placeholders. When referencing an Azure App Configuration key with a placeholder, remove prefixes from the reference. For example, /application/config.message is referenced as ${config.message}.
Note
The prefix being removed matches the value spring.cloud.azure.appconfiguration.stores[0].selects[0].key-filter. Change the prefix being trimmed by setting a value for spring.cloud.azure.appconfiguration.stores[0].trim-key-prefix[0].
JSON
You can create JSON key-values in App Configuration. When you load key-values from Azure App Configuration, the configuration provider automatically converts configuration settings to complex objects inside a @ConfigurationProperties. For example, consider the JSON key /application/config.colors with the following value:
{
"key": "font",
"label": null,
"value": "{\r\n\t\"size\": 12,\r\n\t\"color\": \"red\"\r\n}",
"content_type": "application/json"
}
This JSON content results in the key-value being loaded as { size: 12, color: "red" }.
@ConfigurationProperties(prefix = "config")
public class MyConfigurations {
private Font font;
}
Note
Starting with version 6.0.0 of spring-cloud-azure-appconfiguration-config, the configuration provider supports comments, as defined in (JSONC), in key-values with an application/json content type.
Key Vault references
Azure App Configuration and its libraries support referencing secrets stored in Key Vault. In App Configuration, you can create keys with values that map to secrets stored in a Key Vault. Secrets remain secure in Key Vault, but you can access them in the same way as any other configuration when loading the app.
Your application uses the client provider to retrieve Key Vault references, just as it does for any other keys stored in App Configuration. Because the client recognizes the keys as Key Vault references, they have a unique content-type, and the client connects to Key Vault to retrieve their values for you.
Note
Key Vault only allows for secrets to be retrieved one at a time, so each Key Vault reference stored in App Configuration results in a pull against Key Vault.
Creating Key Vault references
You can create a Key Vault reference in the Azure portal by going to Configuration explorer > Create > Key Vault reference. You can then select a secret to reference from any of the Key Vaults you have access to. You can also create arbitrary Key Vault references from the Input tab. In the Azure portal, enter a valid URI.
You can also create a Key Vault reference through the Azure CLI by using the following command:
az appconfig kv set-keyvault \
--name <name-of-your-store> \
--key <key-name> \
--secret-identifier <URI-to-your-secret>
You can create any secret-identifier through the Azure CLI. Secret identifiers just require the format {vault}/{collection}/{name}/{version?} where the version section is optional.
Using Key Vault references
You can use Spring Cloud Azure configuration to configure the library. You can use the same credential used to connect to App Configuration to connect to Azure Key Vault.
You can also create a SecretClientCustomizer the same way as you would create a ConfigurationClientCustomizer to provide your own authentication method.
Resolve non-Key Vault secrets
The App Configuration library provides a method to override the resolution of key vault references. For example, you can use it to locally resolve secrets in a dev environment. This resolution is done through the KeyVaultSecretProvider. The KeyVaultSecretProvider, if provided, is called on every key vault reference. If getSecret returns a non-null value, it's used as the secret value. Otherwise, the Key Vault Reference is resolved normally.
public class MySecretProvider implements KeyVaultSecretProvider {
@Override
public String getSecret(String uri) {
...
}
}
Feature management
Feature management provides a way for Spring Boot applications to dynamically access content. Feature management has various functions such as the following ones:
- Feature flags that can enable or disable content
- Feature filters for targeting when content is shown
- Customized feature filters
- Feature gates for dynamically enabling endpoints
You can enable feature flags through the following configuration:
spring.cloud.azure.appconfiguration.stores[0].feature-flags.enabled= true
Enabled feature flags are loaded into the Spring configuration system with the prefix feature-management. You can also register feature flags in the local configuration file. For more information, see the Feature flag declaration section.
The easiest way to use feature management is by using the spring-cloud-azure-feature-management and spring-cloud-azure-feature-management-web libraries. The difference between the two libraries is that spring-cloud-azure-feature-management-web takes a dependency on the spring-web and spring-webmvc libraries to add more features, such as feature gates.
By default, active Spring profiles are used as the label filters for feature flags. If no Spring profiles are active, all feature flags with a \0 label, seen as (No Label), are loaded. You can override this behavior by setting a label filter, as shown in the following example:
spring.cloud.azure.appconfiguration.stores[0].feature-flags.selects[0].key-filter=A*
spring.cloud.azure.appconfiguration.stores[0].feature-flags.selects[0].label-filter= dev
You can also filter feature flags by tags. Set tags-filter on a feature-flag selector independently of the tag filters for configuration settings. Each entry has the format tagName=tagValue, and a flag must match all entries:
spring.cloud.azure.appconfiguration.stores[0].feature-flags.selects[0].tags-filter[0]=environment=production
spring.cloud.azure.appconfiguration.stores[0].feature-flags.selects[0].tags-filter[1]=team=payments
Feature flag telemetry
When feature flag telemetry is enabled, the Azure App Configuration provider injects additional properties to feature flag telemetry data. These properties provide more context about the feature flag and its evaluation:
- AllocationID: A unique identifier representing the state of the feature flag's allocation.
- ETag: The current ETag for the feature flag.
- FeatureFlagReference: A reference to the feature flag in the format of
<your_store_endpoint>kv/<feature_flag_key>. When a label is present, the reference includes it as a query parameter:<your_store_endpoint>kv/<feature_flag_key>?label=<feature_flag_label>.
Feature management basics
Feature flags
Feature flags include a name and a list of feature filters that turn on the feature. Feature flags can either have a boolean state of on or off, or they can have a list of feature filters. Feature flags evaluate feature filters until one returns true. If no feature filter returns true, the feature flag returns false.
Feature filters
Feature filters define a scenario for when a feature should be enabled. Feature filters are evaluated synchronously.
The feature management library includes four predefined filters: AlwaysOnFilter, PercentageFilter, TimeWindowFilter, and TargetingFilter.
You can create custom feature filters. For example, you can use a feature filter to provide a custom experience for customers who use the Microsoft Edge browser. You can customize the features in this feature filter, for example, to show a specific header for the Microsoft Edge browser audience.
Feature flag declaration
The feature management library supports Azure App Configuration along with application.yml or application.properties as sources for feature flags. Here's an example of the format used to set up feature flags in an application.yml file:
feature-management:
feature_flags:
- id: feature-t
enabled: false
- id: feature-u
conditions:
client_filters:
- name: Random
- id: feature-v
conditions:
client_filters:
- name: TimeWindowFilter
parameters:
Start: "Wed, 01 May 2019 13:59:59 GMT"
End: "Mon, 01 July 2019 00:00:00 GMT"
- id: feature-w
evaluate: false
conditions:
client_filters:
- name: AlwaysOnFilter
This example has the following feature flags:
feature-tis set tofalse. This setting always returns the feature flag's value.feature-uis used with feature filters. Define these filters under theenabled-forproperty. In this case,feature-uhas one feature filter calledRandom, which doesn't require any configuration, so only the name property is required.feature-vspecifies a feature filter namedTimeWindowFilter. You can pass parameters to this feature filter for use as configuration. In this example, aTimeWindowFilterpasses in the start and end times during which the feature is active.feature-wis used for theAlwaysOnFilter, which always evaluates totrue. Theevaluatefield stops the evaluation of the feature filters and results in the feature filter always returningfalse.
Evaluating feature flags
The spring-cloud-azure-feature-management library provides FeatureManager to determine whether a feature flag is enabled. FeatureManager provides an asynchronous way to check the state of the flag.
spring-cloud-azure-feature-management-web, along with providing FeatureManager, contains FeatureManagerSnapshot, which caches the state of previously evaluated feature flags in the @RequestScope to guarantee that all requests return the same value. In addition, the web library provides @FeatureGate, which can either block or redirect web requests to different endpoints.
Feature flag check
FeatureManager is a @Bean that can be @Autowired or injected into @Component type objects. FeatureManager has a method isEnabled that, when passed the name of a feature flag, returns its state.
@Autowired
FeatureManager featureManager;
...
if (featureManager.isEnabled("feature-t")) {
// Do Something
}
Note
FeatureManager also has an asynchronous version of isEnabled called isEnabledAsync.
Without feature management configuration or when the feature flag doesn't exist, isEnabled always returns false. If an existing feature flag is configured with an unknown feature filter, then a FilterNotFoundException is thrown. You can change this behavior to return false by configuring fail-fast to false. The following table describes fail-fast:
| Name | Description | Required | Default |
|---|---|---|---|
spring.cloud.azure.feature.management.fail-fast |
If an exception occurs, a RuntimeException is thrown. If this property is set to false, then isEnabled returns false instead. |
No | true |
The only difference between FeatureManagerSnapshot and FeatureManager is the caching of results in the @RequestScope.
Feature gate
With the feature management web library, you can require that a given feature is enabled in order to execute an endpoint. You can set up this requirement by using the @FeatureGate annotation, as shown in the following example:
@GetMapping("/featureT")
@FeatureGate(feature = "feature-t")
@ResponseBody
public String featureT() {
...
}
You can only access the featureT endpoint if "feature-t" is enabled.
Disabled action handling
When an endpoint is blocked because the feature it specifies is disabled, DisabledFeaturesHandler is invoked. By default, an HTTP 404 is returned. You can override this behavior by implementing DisabledFeaturesHandler, as shown in the following example:
@Component
public class MyDisabledFeaturesHandler implements DisabledFeaturesHandler {
@Override
public HttpServletResponse handleDisabledFeatures(HttpServletRequest request, HttpServletResponse response) {
...
return response;
}
}
Routing
Features might gate certain routes that expose application capabilities. If a feature is disabled, you can redirect these routes to another endpoint, as shown in the following example:
@GetMapping("/featureT")
@FeatureGate(feature = "feature-t", fallback = "/oldEndpoint")
@ResponseBody
public String featureT() {
...
}
@GetMapping("/oldEndpoint")
@ResponseBody
public String oldEndpoint() {
...
}
Built-in feature filters
The spring-cloud-azure-feature-management package includes several built-in feature filters. The system adds these feature filters automatically.
AlwaysOnFilter
This filter always returns true. For a usage example, see the feature flag declaration section.
PercentageFilter
PercentageFilter can return a different result on each check. You can circumvent this inconsistency by using FeatureManagementSnapshot, which caches the result of the feature flag per request.
feature-management:
feature_flags:
- name: feature-v
conditions:
client_filters:
- name: PercentageFilter
parameters:
Value: 50
TimeWindowFilter
This filter enables a feature based on a time window. If you specify only End, the feature is on until that time. If you specify only Start, the feature is on at all points after that time. If you specify both, the feature is valid between the two times.
feature-management:
feature_flags:
- name: feature-v
conditions:
client_filters:
- name: TimeWindowFilter
parameters:
Start: "Wed, 01 May 2019 13:59:59 GMT"
End: "Mon, 01 July 2019 00:00:00 GMT"
This filter also supports recurring time window filters. It supports both daily and weekly recurrences, along with an expiration time.
feature-management:
feature_flags:
- name: feature-v
conditions:
client_filters:
- name: TimeWindowFilter
parameters:
Start: "Mon, 01 July 2019 00:00:00 GMT"
End: "Mon, 01 July 2019 12:00:00 GMT"
Recurrence:
Pattern:
Type: Weekly
Interval: 1
FirstDayOfWeek: Sunday
DaysOfWeek:
- Monday
- Wednesday
This recurrence pattern happens every week on Monday and Wednesday from 00:00:00 GMT to 12:00:00 GMT and doesn't expire.
feature-management:
feature_flags:
- name: feature-v
conditions:
client_filters:
- name: TimeWindowFilter
parameters:
Start: "Mon, 01 July 2019 00:00:00 GMT"
End: "Mon, 01 July 2019 12:00:00 GMT"
Recurrence:
Pattern:
Type: Daily
Interval: 2
Range:
Type: EndDate
EndDate: "Fri, 15 Aug 2025 07:00:00 GMT"
This recurrence pattern happens every other day from 00:00:00 GMT to 12:00:00 GMT until the end date.
TargetingFilter
This filter enables a feature for a target audience. For an in-depth explanation of targeting, see the targeting section. The filter parameters include an audience object that describes users, groups, and a default percentage of the user base that should have access to the feature. For each group object that you list in the target audience, you must include a percentage that defines the percentage of that group's members that have access to the feature. A user has the feature enabled in the following cases:
- The user is specified in the users section directly.
- The user is in the included percentage of any of the group rollouts.
- The user falls into the default rollout percentage.
feature-management:
feature_flags:
- name: target
conditions:
client_filters:
- name: targetingFilter
parameters:
users:
- Jeff
- Alicia
groups:
- name: Ring0
rollout-percentage: 100
- name: Ring1
rolloutPercentage: 100
default-rollout-percentage: 50
Custom feature filters
Creating a custom feature filter provides a way to enable features based on criteria that you define. To create a custom feature filter, you must implement the FeatureFilter interface. FeatureFilter has a single method evaluate. When a feature specifies that it can be enabled with a feature filter, the evaluate method is called. If evaluate returns true, it means that the feature should be enabled. If it returns false, it continues evaluating feature filters until one returns true. If all filters return false, then the feature is off.
Define feature filters as Spring Beans, so define them as @Component or define them in a @Configuration.
@Component("Random")
public class Random implements FeatureFilter {
@Override
public boolean evaluate(FeatureFilterEvaluationContext context) {
double chance = Double.valueOf((String) context.getParameters().get("chance"));
return Math.random() > chance / 100;
}
}
Parameterized feature filters
Some feature filters require parameters to determine whether a feature should be turned on. For example, a browser feature filter might turn on a feature for a certain set of browsers. You might want a feature enabled for Microsoft Edge and Chrome browsers, but not Firefox. To set up this situation, you can design a feature filter to expect parameters. Specify these parameters in the feature configuration and in code. Access these parameters through the FeatureFilterEvaluationContext parameter of evaluate. FeatureFilterEvaluationContext has a property parameters, which is a Map<String, Object>.
Targeting
Targeting is a feature management strategy that enables developers to progressively roll out new features to their user base. The strategy is built on the concept of targeting a set of users known as the target audience. An audience is made up of specific users, groups, and a designated percentage of the entire user base. The groups that are included in the audience can be broken down further into percentages of their total members.
The following steps demonstrate an example of a progressive rollout for a new 'Beta' feature:
- Individual users Jeff and Alicia are granted access to the Beta.
- Another user, Mark, asks to opt in and is included.
- Twenty percent of a group known as "Ring1" users are included in the Beta.
- The number of "Ring1" users included in the beta is bumped up to 100 percent.
- Five percent of the user base is included in the beta.
- The rollout percentage is bumped up to 100 percent and the feature is completely rolled out.
This strategy for rolling out a feature is built into the library through the included TargetingFilter feature filter.
Targeting in an application
An example web application that uses the targeting feature filter is available in the example project.
To begin using the TargetingFilter in an application, you must add it as a @Bean like any other feature filter. TargetingFilter relies on another @Bean to be added to the application TargetingContextAccessor. The TargetingContextAccessor allows for defining the current TargetingContext to be used for defining the current user ID and groups, as shown in the following example:
public class MyTargetingContextAccessor implements TargetingContextAccessor {
@Override
public void configureTargetingContext(TargetingContext context) {
context.setUserId("Jeff");
ArrayList<String> groups = new ArrayList<String>();
groups.add("Ring0");
context.setGroups(groups);
}
}
Targeting evaluation options
Options are available to customize how targeting evaluation is performed across a given TargetingFilter. You can set an optional parameter, TargetingEvaluationOptions, during the TargetingFilter creation.
@Bean
public TargetingFilter targetingFilter(MyTargetingContextAccessor contextAccessor) {
return new TargetingFilter(contextAccessor, new TargetingEvaluationOptions().setIgnoreCase(true));
}
Configuration refresh
When you enable configuration refresh, your application can pull the latest values for your configurations from your App Configuration store or stores without restarting.
To enable refresh, enable monitoring. If you don't configure monitoring triggers, the library uses collection-level monitoring to check the settings that match your configured selectors for changes.
spring.cloud.azure.appconfiguration.stores[0].monitoring.enabled=true
Alternatively, you can configure monitoring triggers to watch specific sentinel keys. A monitoring trigger is a key with an optional label that the system monitors for changes to trigger updates. The value of the monitoring trigger can be any value, as long as it changes when a refresh is needed.
Note
Any operation that changes the ETag of a monitoring trigger causes a refresh, such as a content-type change.
spring:
cloud:
azure:
appconfiguration:
stores:
- monitoring:
enabled: true
triggers:
- key: [my-watched-key]
label: [my-watched-label]
With collection-level monitoring, change a setting that matches your selectors. If you configure monitoring triggers, change your settings first, then update one of the watched keys. The next refresh attempt after the refresh interval passes detects the change and refreshes the configuration. For example, changing the value of /application/config.message produces the following log message when the configuration is refreshed:
INFO 17496 --- [TaskScheduler-1] o.s.c.e.event.RefreshEventListener : Refresh keys changed: [config.message]
After the application generates the log, it refreshes all @Beans in the refresh scope.
Note
By default, @ConfigurationProperties annotated beans are included in this scope.
Pull-based refresh
The App Configuration Spring libraries use a refresh interval to limit how often they check for changes. By default, the refresh interval is set to 30 seconds. After the refresh interval passes, the next refresh attempt checks the selected settings or, if configured, the monitoring triggers in the given store for changes. A detected change triggers a refresh. Because the libraries integrate with the Spring refresh system, any refresh reloads all configurations from all stores. You can set the refresh interval to any interval of at least 1 second. The supported units for the refresh interval are s, m, h, and d for seconds, minutes, hours, and days respectively. The following example sets the refresh interval to 5 minutes:
spring.cloud.azure.appconfiguration.stores[0].monitoring.refresh-interval= 5m
Automated
When you use the spring-cloud-azure-appconfiguration-config-web library, the application automatically checks for a refresh whenever a servlet request occurs, specifically ServletRequestHandledEvent. The most common way this event is sent is by requests to endpoints in a @RestController.
Manual
In applications that use only spring-cloud-azure-appconfiguration-config, such as console applications, you can manually attempt a refresh by calling the refreshConfigurations() method on the AppConfigurationRefresh bean. This method returns a Mono<Boolean> that indicates whether a refresh event was published. The refresh interval still applies. AppConfigurationRefresh is a @Bean that you can inject into any @Component.
Also, because the library uses Spring's configuration system, triggering a refresh causes a refresh of all of your configurations, not just a reload of the ones from your Azure App Configuration store.
Push-based refresh (not recommended)
Note
This method is no longer recommended, but is currently still supported.
You can set up the spring-cloud-azure-appconfiguration-config-web library to receive push notifications from your Azure App Configuration store to refresh your configuration values. You can set up this configuration through an Azure Event Grid Web Hook, which you can configure to send notifications of changes to specified keys. By adding the Spring Actuator library as a dependency, you can expose App Configuration's refresh endpoints. There are two different endpoints: appconfiguration-refresh and appconfiguration-refresh-bus. These endpoints work similarly to their counterparts refresh and refresh-bus, where the app configuration endpoints expire the refresh interval instead of forcing a refresh upon receiving. You can still use the refresh and refresh-bus, but you can't connect them directly to Azure Event Grid with a Web Hook because they require a response in setup.
The appconfiguration-refresh property expires the refresh interval, so the remaining refresh interval isn't waited on before the next refresh check. The appconfiguration-refresh-bus property sends a notification to a connected messaging service, such as Azure Service Bus, to notify all instances of an application to refresh. In both cases, it doesn't completely expire at the refresh interval, but is off by a small jitter amount. This jitter ensures that every instance of your application doesn't try to refresh at the same time.
management.endpoints.web.exposure.include= appconfiguration-refresh, appconfiguration-refresh-bus
In addition to exposing the refresh endpoints, the library requires a query parameter for security. No token name or value exists by default, but you must set one to use the endpoints, as shown in the following example:
spring.cloud.azure.appconfiguration.stores[0].monitoring.push-notification.primary-token.name=[primary-token-name]
spring.cloud.azure.appconfiguration.stores[0].monitoring.push-notification.primary-token.secret=[primary-token-secret]
spring.cloud.azure.appconfiguration.stores[0].monitoring.push-notification.secondary-token.name=[secondary-token-name]
spring.cloud.azure.appconfiguration.stores[0].monitoring.push-notification.secondary-token.secret=[secondary-token-secret]
Setting up web hooks
To set up a web hook, open your Azure App Configuration store and open Events from the navigation menu. Then, select Event Subscription. Set the name of your event and select the endpoint type to be Web Hook. Selecting Web Hook causes an Endpoint option to appear. Select Select an endpoint. Your endpoint should look like the following example: https://www.myaplication.com/actuator/appconfiguration-refresh?myTokenName=mySecret.
Confirm Selection sends a setup notification to the given URI and it expects a response. If no response is returned, the setup fails. The azure-spring-cloud-appconfiguration-web library setup for endpoints returns the correct response if the Azure App Configuration store is configured for the application. This confirmation can be sent in other ways. For more information about web hook delivery, see Webhook event delivery.
Note
This validation happens only upon the creation or modification of the endpoint.
Set up filters because otherwise, a refresh is triggered after every key creation and modification.
Forced client refresh
You can configure the library to force a refresh of all configurations at a refresh interval. The following table describes the refresh-interval property:
| Name | Description | Required | Default |
|---|---|---|---|
spring.cloud.azure.appconfiguration.refresh-interval |
The standard amount of time between refreshes. Is a Duration. |
No | null |
Refreshing by using spring.cloud.azure.appconfiguration.refresh-interval doesn't check any configured watch keys. Use this property to ensure Key Vault secrets stay up to date because Azure App Configuration can't tell when they're updated.
Because Azure Key Vault stores the public and private key pair of a certificate as a secret, your application can retrieve any certificate as a Key Vault reference in App Configuration. Because certificates need to be rotated periodically, client applications need to update just as frequently. Use the client refresh interval to set this frequency.
Feature flag refresh
If you enable both feature flags and monitoring, the refresh interval for feature flags is 30 seconds by default. After the refresh interval passes, the next refresh attempt checks all selected feature flags in the given store for changes. A detected change triggers a refresh. Because the libraries integrate with the Spring refresh system, any refresh reloads all configurations from all stores. You can set the refresh interval to any interval of at least one second. The supported units for the refresh interval are s, m, h, and d for seconds, minutes, hours, and days respectively. The following example sets the refresh interval to five minutes:
spring.cloud.azure.appconfiguration.stores[0].monitoring.feature-flag-refresh-interval= 5m
Health indicator
The client library includes a health indicator that checks whether the connection to the Azure App Configuration store or stores is healthy. If you enable it for each store, it gives one of the following status values:
- UP - The last connection was successful.
- DOWN - The last connection resulted in a non-200 error code. This status could be due to issues ranging from credentials expiring to a service issue. The client library automatically retries to connect to the store at the next refresh interval.
- NOT LOADED - The config store is listed in the local configuration file, but the config store wasn't loaded from the file at startup. The config store is disabled in the configuration file or the configuration failed to load at startup while the
fail-fastconfiguration for the store was set tofalse.
Set management.health.azure-app-configuration.enabled=true to enable the health indicator.
Client customization
The App Configuration library uses the Azure SDK for Java to connect to Azure App Configuration and Azure Key Vault. To modify the clients, use the two interfaces ConfigurationClientCustomizer and SecretClientCustomizer. Each interface includes a customize method that takes its respective builder and the String value of the URI for the client configuration, as shown in the following interface definitions:
public interface ConfigurationClientCustomizer {
public void customize(ConfigurationClientBuilder builder, String endpoint);
}
public interface SecretClientCustomizer {
public void customize(SecretClientBuilder builder, String endpoint);
}
By using these interfaces, you can customize the HTTP client and its configurations. The following example replaces the default HttpClient with another one that uses a proxy for all traffic directed to App Configuration and Key Vault.
Note
The ConfigurationClientBuilder and SecretClientBuilder are already set up for use when passed into customize. Any changes to the clients, including the credentials and retry policy, override the defaults.
You can also configure these settings by using Spring Cloud Azure configuration.
public class CustomClient implements ConfigurationClientCustomizer, SecretClientCustomizer {
@Override
public void customize(ConfigurationClientBuilder builder, String endpoint) {
builder.httpClient(buildHttpClient());
}
@Override
public void customize(SecretClientBuilder builder, String endpoint) {
builder.httpClient(buildHttpClient());
}
private HttpClient buildHttpClient() {
String hostname = System.getProperty("https.proxyHosts");
String portString = System.getProperty("https.proxyPort");
int port = Integer.valueOf(portString);
ProxyOptions proxyOptions = new ProxyOptions(ProxyOptions.Type.HTTP,
new InetSocketAddress(hostname, port));
return new NettyAsyncHttpClientBuilder()
.proxy(proxyOptions)
.build();
}
}