Type Safe Feature Toggles Using Properties in Spring Boot

Sujit Kamthe
Oct 3, 2020 · 3 min read

What are feature toggles?

Feature Toggles (often also referred to as Feature Flags) are a powerful technique, allowing teams to modify system behavior without changing code.

- Martin Fowler

Feature toggles is a mechanism by which one can modify the system behavior by enabling or disabling the feature toggles as required. It’s also a great way to keep certain features enabled in certain environment and keep them disabled in other environments to minimize any impact on the system failures.

It helps release half baked functionality in to the production without worrying about it’s impact on the system, it also helps hide functionality until it’s ready.

There are different types of feature toggles which have different use cases. Read more: https://martinfowler.com/articles/feature-toggles.html

Do you need a feature toggle tool/library?

Honestly, it depends on your use case. If you want features like

  • Support for multiple source like property files, database, files etc.

then you can go for a dedicated tool/lib like togglz (https://www.togglz.org/)

But otherwise if your use case is very simple, you probably don’t even need a third part tool or lib. You can implement your own feature toggle framework which works with property files in relatively very short time.

Implementation

TLDR

We would be using spring features like @ConfigurationProperties, @ConfigurationPropertiesBinding, @EnableConfigurationProperties

Toggle Properties

If specified using a common readable prefix, all the feature toggles can be represented using a Java POJO.

feature.toggles.showFormatted = false
feature.toggles.debug = true

The feature toggle class

This class represents a single toggle, and has methods isEnabled and isDisabled which can be used to check if toggle is enabled or disabled. Another convention which can be used for these methods is isActive and isInactive. The choice of these methods also depends on what convention is followed for properties in application.properties.

e.g. if the toggle property name is debug then both isEnabled or isActive are relevant. But if the toggle property name is enableDebug, then isActive reads better than isEnabled.

FeatureToggle.java

package beingprofessional.featuretogglesdemo.featuretoggles;

public class FeatureToggle {

private final boolean value;

public FeatureToggle(boolean value) {
this.value = value;
}

public boolean isEnabled() {
return value;
}

public boolean isDisabled() {
return !value;
}
}

FeatureToggleConverter

Then we introduce a converter which converts boolean feature toggle properties from the property file into the FeatureToggle class we created above

package beingprofessional.featuretogglesdemo.featuretoggles;

import org.springframework.boot.context.properties.ConfigurationPropertiesBinding;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;

@ConfigurationPropertiesBinding
@Component
public class FeatureToggleConverter implements Converter<String, FeatureToggle> {

@Override
public FeatureToggle convert(String isEnabled) {
return new FeatureToggle(Boolean.parseBoolean(isEnabled));
}
}

Make sure to mark the class with @Component

FeatureToggles

This class holds reads all the toggle properties under a common prefix into a class.

For this we make use of @ConfigurationProperties Refer: https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config-typesafe-configuration-properties

Also notice that we have made the FeatureToggles class as an immutable class, so that the toggle values are not modified accidentally. For this we have made use of @ Refer: https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config-constructor-binding

package beingprofessional.featuretogglesdemo.featuretoggles;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.ConstructorBinding;

@ConfigurationProperties(prefix = "feature.toggles")
@ConstructorBinding
public class FeatureToggles {
private final FeatureToggle showFormatted;
private final FeatureToggle debug;

public FeatureToggles(FeatureToggle showFormatted, FeatureToggle debug) {
this.showFormatted = showFormatted;
this.debug = debug;
}

public FeatureToggle showFormatted() {
return showFormatted;
}

public FeatureToggle debug() {
return debug;
}
}

Enable the FeatureToggles configuration properties

Note: When using @ConstructorBinding, We need to explicitly register the FeatureToggles class with the spring context using @EnableConfigurationProperties

package beingprofessional.featuretogglesdemo;

import beingprofessional.featuretogglesdemo.featuretoggles.FeatureToggles;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;

@SpringBootApplication
@EnableConfigurationProperties(FeatureToggles.class)
public class FeaturetogglesdemoApplication {

public static void main(String[] args) {
SpringApplication.run(FeaturetogglesdemoApplication.class, args);
}

}

Usage

The feature toggles framework is now ready and can be used in the code. Example usage.

package beingprofessional.featuretogglesdemo.controllers;

import beingprofessional.featuretogglesdemo.featuretoggles.FeatureToggles;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {
private final FeatureToggles featureToggles;

@Autowired
public HelloController(FeatureToggles featureToggles) {
this.featureToggles = featureToggles;
}

@GetMapping("/hello")
public String hello(@RequestParam String name) {
if (featureToggles.showFormatted().isEnabled()) {
return String.format("<h1>Hello, %s</h1>", name);
} else {
return String.format("Hello, %s", name);
}
}
}

Refer Code: https://github.com/sujeet100/featuretogglesdemo

Being Professional

Learning to become a professional one step at a time