Implementing feature toggles for a Spring Boot application - Part 1

In one of our recent projects at work, we implemented feature toggles for a Spring MVC / Angular JS code base and this series of blog posts discusses our motivations and requirements, the approach we took and what we learned from it.

Introduction

Feature Toggles are a mechanism to change the behavior of software without having to re-deploy code. Pete Hogdson has a comprehensive blog post explaining the complexities of feature toggles.

Requirements

Our application is a Spring Boot web application that gets deployed in a Tomcat instance. The application is deployed via Chef and chef sets up the appropriate configuration parameters for the application as Tomcat Environment entries. Since feature toggles are ultimately application parameters 1, we started by setting them as Tomcat environment variables. Having considered this, we identified the following requirements:

The ability to toggle dependency injection. For example, in some environments, we wanted to use Redis to store our sessions, while in some test environments, they were to be stored in memory.

The ability to expose the state of feature toggles to our front end so that Angular JS components can use the feature toggles.

Our initial approach

Toggling dependency injection.

We started by using configuration parameters with the feature prefix to toggle features. With this convention in place, we started using the @ConditionalOnProperty annotation in our configuration classes to toggle the beans that got wired up. For example, to toggle between Redis and in-memory store for sessions, we ended up with the following configuration:

Toggling individual controller methods

In order to prevent end points defined by controllers and controller methods that are toggled off from being accessed, we decided to configure a HandlerInterceptor2 to intercept requests to these end points.

This feature interceptor uses the FeatureToggle looks for the annotation, and the looks at a feature repository to see if the state of the feature flag is set to what the annotation expects and if it does not, returns a 404. The annotation has two attributes - isOn and feature.

The FeatureRepository has to look at all the properties that are available in the applications environment and filter out the ones that start with feature..

Collecting all the properties available in an environment is surprisingly complex, owing to the number of ways properties can be injected. Based on the approach discussed in that question, we can create a FeatureRepository as follows:

However, now we have two different mechanisms to toggle methods and controllers. It will be nice to consolidate them and doing so will allow us to use the same mechanism for toggling beans. This can be done by annotating FeatureToggle with the meta annotationConditional that looks up the state of feature toggles using the custom condition FeatureCondition. This will change FeatureToggle to: