A code example showing a simple way to feature flag in Java and Spring eliminating the code and checks when the flag is disabled.

Overview

There are many ways to do feature flags in Java and Spring and some excellent articles are listed at the bottom of this post.

However where possible this is my favourite technique because it eliminates the usual flag checking for each call.

Instead, the check is done once at start-up and the whole component is either enabled or disabled.

If the flag is disabled, then no further checks are done.

Getting The Code

The example is a simple rest controller that we turn off and on.

You can check out, build, test and run as below.

git clone https://github.com/johndobie-blog/feature-flag.git
mvn clean test spring-boot:run
http://localhost:8080/echo?message=test

Understanding The Example

We use a simple REST Controller that echoes any message that is passed.

EchoController.java
public class EchoController {

    public static final String ECHO_ENDPOINT = "/echo";

    @GetMapping(ECHO_ENDPOINT)
    public String echo(@RequestParam String message) {
        return message;
    }
}

Adding The Flag

We can add the flag echo.enabled as below.

@ConditionalOnProperty
(name = "echo.enabled",  havingingValue="true "matchIfMissing = false)

By default, if that flag is not set to true, the controller will not be enabled.
This is the safest way IMHO.

EchoController.java
@RestController
@ConditionalOnProperty(name = "echo.enabled", havingValue = "true", matchIfMissing = false)
public class EchoController {

    public static final String ECHO_ENDPOINT = "/echo";

    @GetMapping(ECHO_ENDPOINT)
    public String echo(@RequestParam String message) {
        return message;
    }
}

You can change to matchIfMissing to true.
Then the default behaviour will be to always enable the controller, unless the flag is specifically set to false.

Testing With The Flag On

First we can test that with the flag enabled, that the controller is loaded.
@TestPropertySource(properties = {“echo.enabled=true”})

EchoControllerEnabledMvcTest.java
@WebMvcTest(controllers = EchoController.class)
@TestPropertySource(properties = {"echo.enabled=true"})
public class EchoControllerEnabledMvcTest {

    private static final String MESSAGE = "Hello, World";

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void getShouldReturnMessage() throws Exception {
        this.mockMvc
                .perform(get(ECHO_ENDPOINT)
                        .param("message", MESSAGE))
                .andDo(print())
                .andExpect(status().isOk())
                .andExpect(content().string(containsString(MESSAGE)));
    }

}

We can see that the message is successfully echoed from the controller

Testing With The Flag Off

A similar test can be used to check we get an error when the flag is disabled.
@TestPropertySource(properties = {“echo.enabled=false”})

EchoController.java
@WebMvcTest(controllers = EchoController.class)
@TestPropertySource(properties = {"echo.enabled=false"})
public class EchoControllerDisabledMvcTest {

    private static final String MESSAGE = "Hello, World";

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void getShouldReturnError() throws Exception {
        this.mockMvc
                .perform(get(ECHO_ENDPOINT)
                        .param("message", MESSAGE))
                .andDo(print())
                .andExpect(status().is4xxClientError());
    }

}
ShellScript

In this case an error is returned because the controller does not exist.

Running The Application Standalone

When running the application the flag is set in properties as below.

application.properties
echo.enabled=true

You can then test as follows.

mvn spring-boot:run
feature flag enabled

Then disable the feature and start again
echo.enabled=false

feature flag disabled

Wrap up

This is a great way to implement feature flags that will only run at start-up.

This technique cannot be used in all circumstances, but is great for situations where you want to enable or disable whole components.

Further Info

Check out these resources for more detailed info on feature flags

https://martinfowler.com/articles/feature-toggles.html

https://www.baeldung.com/spring-feature-flags