The Spring Feature Toggle: Your Guide to Getting Started Quickly

This is a post I wrote for Rollout, a tech company that has a system for managing feature toggles in enterprise applications. The original post is here.

When it comes to agile development and “moving fast and breaking stuff,” many people think of REST APIs. Decomposing services into manageable building blocks with clearly defined interfaces is a good step in designing any large system. Even if one doesn’t necessarily wish to be “agile,” REST microservices are an effective design pattern.

But wouldn’t it be nice to separate “move fast and break stuff” into two parts and throw the second one away?

Feature toggles (also known as feature flags) can help with that. They provide us with a way to add new behavior to an application and then enable or disable the new behavior without deploying a different version. Toggles give us immediate advantages when implementing a REST microservice. We can toggle new behavior for a subset of users or only enable it after deploying a new client application.

So we add a feature toggle to our configuration file or the command line, default it to “off,” and wait until later to flip it, right?

Does that describe a complete solution? Not really. Updating a configuration file isn’t always more straightforward than deploying a new release and adding a boolean flag for each new feature seems like a bit of a hack.

There is a better way. There’s feature flag management. Instead of using conditionals that will inevitably turn into technical debt, you can include these toggles as part of a strategy for improving your code and your ability to support it.

Let’s explore feature toggles in a REST service written with Spring Boot. We’ll start with a simple flag and build it into a fully managed feature flag with Rollout’s secure feature management system.

This tutorial assumes familiarity with basic Spring concepts and the ability to set up a development environment. While we will look at several Spring components, we’ll leave whether you run your application from Gradle, Maven, and IDE, etc. up to you.

The source code for the completed project is available here.

A Basic Feature Toggle

Let’s start with a straightforward Boot application.

We have an interface that supplies a greeting.

And a handler class that implements it.

We’ll create a controller with a single request mapping.

Finally, there is the main class to run the service.

We can use Curl to test this service, but any test client will do.

Above, we see our response with the standard HTTP headers.

A Spring Feature Toggle

So let’s imagine we want to replace this greeting with a different one depending on the season.

Spring already has tools for solving this problem. After all, dependency injection and programmatic configuration are two of the main reasons Spring has gained a lot of traction in the Java development community.

First, we’ll add a property to our configuration. We’ll use application.properties for the sake of simplicity and add a new parameter to the file.

Next, we create a new implementation of our GreetingHandler.

Then we’ll modify our controller to accept a handler via dependency injection.

Lastly, we add configuration code to the main class.

If holidaySeason is true, Spring overrides the primary bean, StandardGreetingHandler, with HolidayGreetingHandler.

If we run this version with the current configuration, everything looks the same.

But when we set feature.toggle.holidaySeason=true and restart the application, we see the new greeting.

We’ve added our first feature flag. The value of feature.toggle.holidaySeason controls our application’s behavior. We can load the desired controller by modifying application configuration without deploying new code.

Managing Spring Feature Toggles Centrally

Spring Properties are, at best, a limited version of feature flag management. They require modifying and distributing configuration files to toggle features. Many organizations manage their configurations like software with version control, packaging, and testing. Changing configuration requires a release cycle and it should.

Let’s look at a better way to manage feature toggles.

Getting Started With Rollout

First, you’ll need to create a free Rollout account here.

Once that’s done, sign in to your Rollout account and create a new application.

Create New App dialog on Rollout.io
Be sure to select Java and Java Server, as shown above.

Next, you’ll see instructions for adding Rollout to your application. Use the dropdowns to select Java and Java Server to see instructions like these:

Rollout Feature Toggle Installation Instructions

Your application will be assigned a unique initialization key.

Add the Rollout library to your dependencies. At the time of this writing, the current version of the rox-java-server library is 2.0.3. Here are my Gradle build dependencies for both Spring Boot and Rollout:

Initialize the API

Now we need to add the call to Rox.setup() to initialize the SDK with the application key. This requires some additional thought in a Spring application, though.

Rollout’s API is asynchronous. It uses okHttp to make REST requests for application information, including the feature toggles that we’ll add later. If we attempt to access our feature toggles before initialization has been completed, we may get an incorrect value. We need to make sure that Rollout is completely initialized and our feature toggles have been updated before Spring uses them to decide how to set up our application.

A Spring Feature Toggle Class

Let’s create a new component and use it to initialize Rollout. It will have code to wait until the Rollout initialization is complete before the application finishes loading.

Then we’ll continue to set the class up for managing flags.

This class adds two bits of functionality to our application.

Rox.setup() accepts an optional RoxOptions class. We built one that installs Rollout API’s ConfigurationFetchedHandler callback, which is called after Rollout’s configuration is retrieved.

The callback sets a CountDownLatch after the Rollout is fully initialized. We also wrapped the call to initializeRox() in a static AtomicBoolean in case the condition is instantiated in more than one place.

Second, we’re implementing the getMatchOutcome() method in SpringBootCondition. We’ve hard-coded it to return false for now. This SpringBootCondition class will be loaded when it is referenced in a @Conditional annotation. This class isn’t complete yet, but it’s good enough for this first step. We’ll point our application at it so Spring loads it and initializes the API.

Our previous revision uses the @ConditionalOnProperty to read Spring properties to decide which handler to load. We need to change to an annotation that can look at code instead of configuration. @Conditional does this. A new instance of RolloutCondition is created for each annotation that refers to it, which is why we set up the AtomicBoolean to ensure that initialization is only done once.

Selecting a Spring Controller From a Feature Toggle

Replace the @ConditionalOnProperty annotation on getGreetingHandler() and move the @Primary bean annotation to this method.

On getStandardGreetingHandler(), replace @ConditionalOnProperty with @ConditionalOnMissingbean. If the HolidayGreetingHandler is not created, we’ll fall through to the standard implementation.

Back on the Rollout website, click Next for the prompt to build and run your application.

Build and Run Dialog to initialize Spring Feature Toggle

Build and run it, and after a few moments you’ll see this message:
Feature Toggle Application Initialized for Spring Feature Toggle

Implementing a Managed Spring Feature Toggle

With the return value of getMatchOutcome() set to false, we see the standard greeting when we run our app. Now, let’s turn that return value into a managed feature flag.

If we look at our Rollout dashboard and check flags, we see this:
Create Spring Feature Toggle image

There are no flags and there is no way to create one. That’s because we create them from our application, not from the dashboard.

In Java, managed flags are RoxFlags. These flags are members of a RoxContainer, which is registered with the Rollout API.

Let’s make a few changes to RolloutCondition.

First, add a variable declaration toward the top and an implements qualification to the class definition.

Next, add a call to Rox.register() to iniitalizeRox():

Finally, change matchOutcome() to use the feature toggle.

RoxContainer is an interface with no methods. By having RolloutCondition implement it, we can pass it to Rox.register() inside initializeRox(). The call to register() accepts a String that acts as a namespace. We used Flags.

Then we added a single RoxFlag member named holidaySeason. Managed flags must be public so Rollout can see them.

Last, we modified getMatchOutcome() to return the result of holidaySeason.isEnabled(), which is a boolean value.

Run the application again and then look for your feature toggle in the Rollout dashboard.

Spring Feature Toggle Dashboard on Rollout.io

Flags.holidaySeason is there!

We’re ready to start using our flag from the management console.

Managing a Feature Flag

We manage flags by adding them to experiments. An experiment is a scheme for controlling flags (and other variables) in production.

Click on Production in the left-hand side menu and then click Experiments. This will bring up a screen with a Create Experiment button. Click that and then fill out the new experiment window appropriately.

New Experiment Dialog on Rollout.io
Select Set Audience.

Experiment Dashboard

And we see a console for setting flags to true, false, or split.

If we run our tests now, we see that holidaySeason is false.

Let’s change it to true and restart the service.

When we run our tests again, the results are different!

We can change the behavior of our application without touching code or configuration files.

Before we wrap up, let’s take a look at the experiment on the console again. Flip the flag from true to split.

Split Settings for a Feature Toggle

We don’t just have the ability to change the application behavior from the console; we can also experiment (hence the name) with how often the application loads the different greeting handler.

This is the power of feature flags.

Conclusion

This guide demonstrates how to get started with Rollout in a Java project. Rollout’s documentation has details on how you can do a great deal more with flags, experiments, and groupings.

You now have an understanding of feature flag management and how it can improve your Java code.  You’ve seen how it can help you manage projects and eliminate unnecessary deployments. Get to it!

Leave a Reply

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: