Spring Boot Toggle Feature using Togglz

  • Feature toggle is a design pattern used to hide, enable or disable a feature during runtime.
  • For example, during the deployment, a developer can disable the feature in the code which is released to production and enable it later in the next iterations when its 100% ready or enable the feature for testing to limited set of users , profiles or certain geographic location.
  • It gives the power to reduce risk, iterate quicker, and gain more control and allows you to decouple feature rollout from code deployment.
  • This separation allows you unprecedented control on who sees what and when, independent of release.
  • Feature flagging is a core component of continuous delivery that empowers software organizations to release quickly and reliably.
  • While there are many ways to achieve this but in this blog we will see how this can be done in Spring Boot microservice using Togglz library
  • The Togglz library provides an implementation of the Feature Toggles design pattern.
  • To demonstrate this feature we will build the following use case
    • Expose a Product API , which will return product information
    • When the festive period is on , then enable the feature to show discounted price
    • Add the code for new product but enable it only when its ready
  • To use Togglz library include the following dependency in pom.xml file
<dependency>
<groupId>org.togglz</groupId>
<artifactId>togglz-spring-boot-starter</artifactId>
<version>${togglz.version}</version>
</dependency>
  • Togglz library also comes with a user interface and to enable it , add the below dependency
<dependency>
<groupId>org.togglz</groupId>
<artifactId>togglz-console</artifactId>
<version>${togglz.version}</version>
</dependency>
  • The main interaction with the Togglz library is done using the FeatureManager class, which is injectable and configured automatically.
public enum ProductFeatureFlag implements Feature {

    @EnabledByDefault
    @Label("Additional information about a book")
    ADDITIONAL_INFORMATION,

    @Label("Price during festive period")
    FESTIVE_DISCOUNT,
}
  • The other way to define the feature toggle is defining it in the application.properties file and accessing with new NamedFeature(“NAME”)
togglz.features.NEW_PRODUCT.enabled=true
togglz.feature-enums=com.raj.nola.togglz.config.ProductFeatureFlag
  • When ADDITIONAL_INFORMATION flag is active then we need to show additional info and when FESTIVE DISCOUNT is active then the discounted price should be shown
@GetMapping
@RequestMapping("/product")
public ResponseEntity<JsonNode> getProduct() {

ObjectNode product = objectMapper.createObjectNode();
product.put("productID", "NB101");
product.put("productName", "NoteBook");
product.put("price", 5.00);
product.put("description", "Good Note Book");
product.put("availabileFrom", "30-Jan-2020");

if (featureManager.isActive(ProductFeatureFlag.ADDITIONAL_INFORMATION)) {
product.put("additionalInfo", "8\" x 10-1/2\", college-ruled notebooks fit more writing per page than wide-ruled sheets; each notebook provides 70 double-sided sheets with red margin lines");
}

if (featureManager.isActive(ProductFeatureFlag.FESTIVE_DISCOUNT)) {
product.put("price", 4.00);
}
return ResponseEntity.ok(product);
}

When NEW_PRODUCT flag is active then the new endpoint should be shown, this is configured using application.properties

togglz.features.NEW_PRODUCT.enabled
@GetMapping
@RequestMapping("/productV2")
public ResponseEntity<JsonNode> getBookWishlist() {

if (featureManager.isActive(new NamedFeature("NEW_PRODUCT"))) {

ObjectNode product = objectMapper.createObjectNode();
product.put("productID", "NB102");
product.put("productName", "B5 Spiral Notebook Lined");
product.put("price", 10.00);
product.put("description", "Spiral Ruled Journal");
product.put("availabileFrom", "1-Feb-2020");
product.put("additionalInfo", "B5 Size: 26cm x 18cm / 10.3\" x 7.2\", 70 sheets (140 pages) per notebook");

return ResponseEntity.ok(product);
}
  • So what we have is a Product API , with additional information feature ON by default.
  • Price for Festive discount disabled and controlled by Feature Flag
  • A New V2 API of Product controlled by Feature Flag but disabled
  • Togglz library also comes with a web UI and its configured to run on the same part in which service is running . This is defined in application.properties
togglz.console.enabled=true
togglz.console.path=/togglz-console
togglz.console.secured=false
togglz.console.use-management-port=false
  • API by default will return following output
  • If you turn on festive discount feature and hit the API , you will notice the new price is shown now.
  • As the NEW Product API is not enabled, when you hit the API you will not get any response.
  • Once the flag is turned on , and then if you hit the endpoint again. It will return a response.
  • If you click on Actions for the feature, it will help you set an Activation strategy for the API like enabled it on a certain date or only for a certain user
  • Using the default configuration, Togglz manages the state of a feature toggle with an in-memory based solution.
  • There are out-of-the-box integrations for feature state management with a JDBC data source and MongoDB for maintaining the state.

Thanks and share your comments / feedback

2 thoughts on “Spring Boot Toggle Feature using Togglz

  1. Great write up Rajesh!

    Togglz looks like a nifty tool. But by itself, it will not prevent ‘if/then/else’ to pop a bit here and there in the code.
    I would not be too worry about it since togglz would scoop all the occurrence of that type of logic.

    I had decent success using in controller only, and finding OK places in the UI ( like the UI-component for the page level )

    But I think it’s still some type of technical debt.

    Martin Fowler wrote has a great in-dept example of bringing that to the next level with an extra serving of patterns ( Of course… the guy sells pattern! what do you expect :p )

    I actually never implemented something as he describes, but Ihis example makes senses, basically the point of code that needs to do “IF FeatureA THEN” is reworked with a Strategy-like pattern, so all the conditional logic is one place rather than scattered in the rest of the code.

    From personal experience, it becomes important when you have 10-ish feature, and that they start to influence each other. If the logic starts to be “on/off except if that other thing is also off”… it’s when it needs to be abstracted away somewhere else.

    Liked by 1 person

  2. Great write up Rajesh!

    Togglz looks like a nifty tool. But by itself, it will not prevent ‘if/then/else’ to pop a bit here and there in the code.
    I would not be too worry about it since togglz would scoop all the occurrence of that type of logic.

    I had decent success using in controller only, and finding OK places in the UI ( like the UI-component for the page level )

    But I think it’s still some type of technical debt.

    Martin Fowler wrote has a great in-dept example of bringing that to the next level with an extra serving of patterns ( Of course… the guy sells pattern! what do you expect :p )

    I actually never implemented something as he describes, but Ihis example makes senses, basically the point of code that needs to do “IF FeatureA THEN” is reworked with a Strategy-like pattern, so all the conditional logic is one place rather than scattered in the rest of the code.

    From personal experience, it becomes important when you have 10-ish feature, and that they start to influence each other. If the logic starts to be “on/off except if that other thing is also off”… it’s when it needs to be abstracted away somewhere else.

    Liked by 1 person

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s