Open/Closed principle on the example of Togglz Java library + Spring Boot

1. Introduction. Push your commits directly to prod? Why not, Togllz for the rescue!

I started using a java library called Togglz last year and so far happy with what it offers. It’s a relatively simple java library, which implements various ways of toggling features in your code. I found the library easy to integrate into a Spring-managed project. Besides, Togglz comes with an extension, ready-to-use web GUI. But what I value in this library more than everything it offers is its openness for customization. A developer using Togglz can tune its functionality using instruments shipped together with the framework or bringing in their own self-written pieces of code. For example Feature toggles’ states (on/off) can be loaded from Spring property files, JDBC data source, DynamoDB table, etc. I am leaving “etc.” here as the implementations of Togglz’ StateRepository interface that I’ve touched and found useful for my projects are the previously mentioned ones. However, the library offers a variety of its own implementations for StateRepository, an interface that you can implement yourself if you wish and as you wish. The same applies to other interfaces of Togglz: you can substitute default functionalities of the library with your own without much hustle. I believe this came true because object oriented design rules lying behind the famous acronym SOLID was well followed:

  • Single-responsibility. Interfaces inside of Togglz mechanism are assumed to trigger simple tasks.
  • Open/Closed principle. The core functionality of the library doesn’t need to be changed in order for it to be customized. We will stop on this one in particular.
  • Liskov substitution principle. Classes ensuring the whole feature toggling business can be easily substituted with their subtypes.
  • Interface segregation. Many simple task performing small interfaces are provided to collectively maintain the whole feature toggling business.
  • Dependency inversion. The core functionality of the library does not depend on the specifics of interface implementations meaning various implementations can be injected into the framework.

2. Building a simple spring boot application.

A rest controller that calls a HelloService:

My friendly controller

And the service, which is quite basic, simple enough, just returns its hello:

A really basic service

After an ordinary spring boot deployment our application starts handling HTTP requests:

One simple curl

As part of our next task let’s imagine we want to make the HelloService to speak some other language, for example, Kazakh (“Hello world” in Kazakh would be “Sálem Álem”). Additionally, the task has a requirement saying that the application maintenance team wants to be able to switch the language at their will without needing to redeploy the application. It sounds like a good reason to try out Togglz library.

3. Integrating Togglz library into the application. Basic app feature.

First things first. The maven dependencies to bring Togglz and the Togglz UI into our project:

Togglz maven dependencies in pom.xml

Next we want to setup a property-file sourced by spring. The following lines are there to enable the Togglz console. Its GUI console has its own security mechanisms, which I ignored for this post’s scope. Besides the Togglz security, it’s also possible to use spring security module to configure access to the Togglz web console.

Togglz’ properties

A Spring Java configuration defining beans needed for the library to function. The most important bean here is featureManager of type org.togglz.core.manager.FeatureManager, which is dependent on other two beans.

A spring config class defining featureManager bean

The org.togglz.core.spi.FeatureProvider instance is initialized as org.togglz.core.manager.EnumBasedFeatureProvider and uses the following enum as representations of feature names:

A lonely enum value representing a single togglz feature

So far we have only one lonely feature to toggle on and off. Note that the enum has to extends org.togglz.core.Feature class.

To store states of feature toggles I chose org.togglz.core.repository.jdbc.JDBCStateRepository implementation coming from Togglz package, which is expecting and depending on javax.sql.DataSource configured for an underlying SQL database. Besides, many different implementation classes of org.togglz.core.repository.StateRepository interface are shipped in the jars we’ve already imported to the project:

StateRepository implementations

I’ve used extensions of the library that make it possible for Togglz to store the feature states in NoSQL databases as well (e.g. AWS DynamoDB). However, this time we use a relational database as an example.
Querying the data from the DB:

A simple SQL query to see what’s in the automatically created table

I place the feature toggle in the service class. Note, as usage of the featureManager becomes part of the application’s functionality, it’s important to test both states of the feature: when it’s toggled on and off.

Our basic service is getting bit more complicated

Let’s see how the toggle can be turned on. It’s done pretty easily actually. One mouse click sends an HTTP request, which is automatically handled and persisted by Togglz.

It’s red

…aaand it’s on.

Green

DB’s state should change as well as the color of the button on UI. Since the data is saved in the database application restarts will not make it forget that feature is enabled.

The changes can be noticed in the app’s behavior:

curl is giving another result as the feature is on

4. Feature activation strategies. Time based toggling.

Built-in activation strategies on Togglz web GUI

I chose the ‘Release date’ activation strategy and entered the release date I wanted in the text-boxes appeared below:

Activation strategy parameters shown on Toggz web GUI

The params are reflected in the feature state repository. You could notice the columns called “strategy_id” and “strategy_params”.

Application strategy parameters stored in a relational DB

What I appreciated about the activation strategy mechanisms in Togglz is the fact that the params for different strategies have a generic form of storage. How is it even useful for a developer? For answering this question let’s imagine another situation. Time passes and now our lovely maintenance team wants the feature to be enabled automatically every day, but only during certain day hours. And again, it’s expected to be possible to change the activation time without needing to redeploy the server or touch the codebase. We’re lucky that we already have Togglz in place. Thanks to the unified format of inputting parameters in the UI, and the generic way of how they’re stored in StateRepository, and the way they’re handled by the framework, developers can use this entire mechanism for building their own custom activation strategies. So let’s experience some openness for extension principle, which means extending the library’s features without even touching its source code.

5. Extending the library. Building a custom feature activation strategy.

Custom ActivationStrategy java class

Note that we’re obliged to implement methods of the ActivationStrategy parent class. Those methods are needed by the framework to display strategy’s parameters on the GUI, and . Obviously, we also are expected to handle these parameters in isActive() function, which is declared as a method returning a boolean value. Some parameter validation is recommended in the method, but I don’t want to over-complicate the example code.

Activation strategies are wired into an activationStrategyProvider bean, which is itself a dependency of the featureManager bean:

Slightly modified DefaultActivationStrategyProvider being injected into the FeatureManager bean

The results of this exercise can be immediately seen on the web GUI. We set the parameters to the desired values so that app can practice speaking Kazakh 2 minutes a day from 19:25 to 19:27 Zulu time:

Custom activation strategy on web GUI

And consequentially the parameters are reflected on the underlying database’s state:

Results:

Few more curls. Feature activation strategy works as desired

6. Conclusion

Best regards,

Saga

7. Useful links

Welcome!

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store