Implementing feature toggles for a Spring Boot application - Part 2

Sun, Nov 27, 2016

In the second part of this series about implementing feature toggles for a Spring Boot application, we will look at exposing the features to the Angular front-end so that features can be toggled in UI components.

Toggling at the front end

We decided to use the angular-feature-flags library to toggle features at the front end because it provided us the three features that we were looking for:

  • The ability to load the state of feature flags from an HTTP end point instead of having to generate JS code through templates.
  • The ability to toggle entire html components through the feature-flag attribute directive.
  • The ability to expose these features to services and components to make if-else decisions through featureFlagsProvider.

Features end point

The library expects feature flags to be provided to featureFlagsProvider in the following format:

[
    { "key": "...", "active": "...", "name": "...", "description": "..." },
    ...
]

The FeatureController will use the FeatureRepository to expose this will look like this:

@RestController
@RequestMapping("/features")
public class FeatureController {
  @Autowired
  FeatureRepository featureRepository;

  @RequestMapping("")
  public List<Map> features() {
    return featureRepository.allFeatures()
        .entrySet()
        .stream()
        .map(entry -> new HashMap<String, Object>() {
          {
            put("key", entry.getKey());
            put("active", entry.getValue());
            put("name", entry.getKey());
            put("description", entry.getKey());
          }
        })
        .collect(Collectors.toList());
  }
}

We are using the double brace initialization technique to construct the map representing each feature. Initializing a map given a set of keys and values is still an exercise that requires a bunch of boiler plate code in Java. You can get around this by using the convenient ImmutableMap.of() provided by Google Collections.

It is also important to change our AppConfig to initialize the instance of Featurerepository as a bean.

@Configuration
public class AppConfig extends WebMvcConfigurerAdapter {
  @Autowired
  Environment env;

  // ...

  @Bean
  public FeatureRepository featureRepository() {
    return new FeatureRepository(env);
  }
}

With this configuration, we can get the feature state from the end point:

> curl -s "http://localhost:8080/features" | jq .
[
  {
    "name": "feature.foo",
    "active": false,
    "description": "feature.foo",
    "key": "feature.foo"
  },
  {
    "name": "feature.hello",
    "active": true,
    "description": "feature.hello",
    "key": "feature.hello"
  }
]

For our use case, we were comfortable re-using the feature key as the name and description of the feature. You may want to capture these meta data in your application configuration and expose this using Spring Boot’s ConfigurationProperties. You can find an example of how use structured configurations in my example project.

In the next part of this series, we will take a look at how to expose the feature information as an admin end point.