BLOG
13 August 2020

Java Feature Togglers: How to Be Prepared for the Unpreparable?

tech

Releasing new feature is often a stressful event. That’s also the case within the entire software development process.

It requires the attention of developers, DevOps or customer support, with possible release errors leading to temporary application failures. The Feature Toggler mechanism was invented to minimize the probability of application instability during the release process.

Feature Toggler is a mechanism that helps you with managing your functionalities by enabling and disabling them in real-time. With that functionality, you will be able to release (enable) a new version of your code by clicking a button. In case of application failures, you would be able to disable it just as quickly.

There are many Feature Toggler libraries available as Open Source products or more advanced ones for which you will have to pay. Each works in the same way, in that they will give you access to managing functionalities in real-time.

The most popular Feature Togglers

  • Apache Zookeeper
  • LaunchDarkly
  • Rollout
  • Togglz
  • FeatureOps
  • fflip
  • ff4j

Let’s take a look at how Feature Togglers work. Most Feature Togglers consist of a list of flags (feature flags) that indicates each enabled feature.

1 2 shop.item.save = true shop.item.delete = false

With that flag, a Feature Toggler library can enable or disable functionality in your code. Usually, flags could be editable through the admin console provided by a library.

Another way to enable or disable your feature is to provide user role information to your FT library. You can enable certain features only for admins or testers, and disable it for regular users.

Note that if you make any changes in the system roles, you will also have to change it in Feature settings.

Some of the FT libraries provide custom checks to evaluate more complicated expressions. For example, we can enable our functionality only after the date of release. Alternatively, we can enable the functionality for a group of users connected only from a specified IP range (i.e. from your company office). If the library doesn’t provide you with the desired checks, then you can usually implement it yourself.

FF4J: Feature Flipper for Java

Feature Flipper for Java is an Open Source library that helps you bring Feature Togglers to your Java Spring Boot application. When carrying out documentation, use samples and source code that you can find on GitHub.

To start your adventure with FF4j, you have to add dependencies to your pom.xml file:

1 2 org.ff4j ff4j-spring-boot-starter ${ff4j.version} org.ff4j ff4j-web ${ff4j.version}

Then we have to specify FF4J context as a Spring component in our configuration file.

1 2 3 4 @Bean public FF4j ff4jCustom() { FF4j ff4j = new FF4j(); ff4j.setFeatureStore(new InMemoryFeatureStore()); ff4j.setPropertiesStore(new InMemoryPropertyStore()); ff4j.setEventRepository(new InMemoryEventRepository()); ff4j.audit(true); return ff4j; }

Creating the context method

Let’s take a look at what happened in creating the context method. We set three properties to the context: FeatureStore, PropertiesStore and EventRepository.

FeatureStore is a definition of storage where we want to store our feature information, in the above implementation, we set InMemoryFeatureStore, meaning we will lose our features when the application stops. To change that, we can integrate FF4J with databases such as MongoDB, PostreSQL and others. See here to learn more on how to integrate different Feature Stores.

The next important store is PropertyStore. Its store can help save your custom properties that could be used in your implementation. In this example, we can save the release date, IP address or expression to be evaluated in the feature toggling process. As in the Feature store, we can integrate it with our database.

The last store worth mentioning is the Event Repository, FF4J. By using it to save all events occurred in the Feature Toggler library – in the following example enabling/disabling feature, we can create a new feature or delete it. Furthermore, we can save those events in our database using the FF4J integration feature.

Enabling admin console

One of the most essential Feature Toggler elements is the admin console. Through this console, we can manage our features in real-time. FF4J provides a build-in web admin console. And to enable it, we have to define and register the FF4J Servlet:

1 2 3 4 5 6 @Bean @ConditionalOnMissingBean public FF4jDispatcherServlet defineFF4jServlet() { FF4jDispatcherServlet ff4jConsoleServlet = new FF4jDispatcherServlet(); ff4jConsoleServlet.setFf4j(ff4jCustom); return ff4jConsoleServlet; } @Bean public ServletRegistrationBean registerFF4jServlet(FF4jDispatcherServlet ff4jDispatcherServlet) { return new ServletRegistrationBean(ff4jDispatcherServlet, "/ff4j-web-console/*"); }

Now, FF4J console should be accessible on the /ff4j-web-console/ page. From that page, you can create your first feature. You can also see the admin console on the public demo site.

Now that we have configured the environment, we can start with feature toggling!

To use the FF4J toggling system, you have to inject an FF4J context to your bean by:

@Autowired FF4j ff4jCustom;

We can now check if desired feature has been enabled:

1 2 if(ff4jCustom.check("buy-item")){ return featureBuy(itemIds); }

As you can see, the application will skip the ‘featureBuy’ procedure, if the ‘buy-item’ feature will be disabled. That is the simplest way to use this library.

You can also avoid injecting a whole FF4J context to your bean, simply by using the @FF4JFeature annotation:

1 2 @FF4JFeature(value = "roleback-transaction") private boolean rolebackTransactionEnabled;

A ‘RolebackTransationEnabled’ flag will indicate if feature specified in value property is enabled.

The drawbacks of using feature flags directly in the code is the need for additional implementation. We need to add a flag check for each part of the implementation, which can affect the readability of the code. To fix that, refer to the FF4J implemented @Flip annotation.

@Flip annotation

@Flip annotation was designed to work with interfaces and switch its implementation by the reflection according to the feature flag state.

To use it, we need to create our interface with methods that we wish to flip.

1 2 public interface ItemService { @Flip(name = "save-item", alterClazz = FeatureItemService.class) Item save(final Item item); }

Annotation passes two arguments:

  • name– the name of flag configured in FF4J feature store
  • alterClazz/alterBean – name of class of bean implementing an interface with an implementation of method representing enabled feature (this is what would be run when we enable feature)

Now, let’s feed our application with the implementation of the above interface. We need two classes, one for method ‘save’ if a feature is disabled, and another one when the feature is enabled.

If the feature is disabled, we should inform the user about it. The easiest way is just to create an exception:

1 2 3 @Service public class ItemServiceImpl implements ItemService{ public Item save(final Item item){ throw new UnsupportedOperationException("Not implemented yet"); } }

Another class will consist of proper implementation of our new feature.

1 2 3 @Service public class FeatureItemService implements ItemService { @Autowired ItemRepository itemRepository; @Override public Item save(Item item) { return itemRepository.save(item); } }

The last thing we have to do is use our implementation of the interface in the application. We need to inject our bean ItemServiceImpl and use it where we want to. Then, FF4J will handle the rest, and use proper implementation.

We can also use more implementations of the same interface. But, one method can be implemented as an enabled element in one class.

LaunchDarkly

LaunchDarkly is next Feature Toggler library that can you use in your application. The main advantage of that solution is you don’t have to worry about technology requirements. LaunchDarkly is a system with SDK’s for many languages. Therefore, you can integrate your Java, JavaScript, .Net etc. application and manage your features in the same place.

The feature admin console is hosted on the LaunchDarkly page. To get access to it, you have to buy a licence or sign up to a 30-day trial.

Integrating it with a Java application is extremely simple. All you have to do is add a dependency to your maven project.

1 2 com.launchdarkly launchdarkly-java-server-sdk 5.0.0

Create LDClient in your application (you have to use your SDK key, it would be available on LaunchDarkly page after you sign up).

1 2 @Bean public LDClient ldClient() { return new LDClient(sdkKey); }

Now, you can simply use your client to check if the feature is enabled:

ldClient.boolVariation(name, user, false);

Note that, LDClient requires usage details from you. The system checks if a current logged user has permission to use a specific feature.

To pass user details to LaunchDarkly, you have to create an LDUser instance and give details to it, i.e. you can receive logged user details from the Spring Security context :

1 2 3 4 5 6 Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication != null) { UserDetails userDetails = (UserDetails)authentication.getPrincipal(); return new LDUser.Builder(UUID.randomUUID().toString()) .name(userDetails.getUsername()) .customString("groups", userDetails.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList())) .build(); } return null;

You can extend that implementation by adding integration with DB to get more specified User details.

With specified LDUser instance, LaunchDarkly will check if the current user with a role from property group has access to that future.

LaunchDarkly is not multifunctional as an FF4J library. Still, thanks to cross-platform support we can archive Feature Toggler for our system, no matter what stack we choose to implement it.

Conclusion

As you can see, using Feature Togglers is the easiest way to manage our functionalities in real-time. They have many advantages as real-time managing, permission checks, triggered enabling etc. but they often require an additional part of the code to use features in your application correctly.

Because of that, larger systems may become too complicated with Feature Togglers. The decision of using it is highly intertwined with the technologies we use, including the Feature library and system characteristics.

Explore our custom software development services



Author
Tomasz Sadło
Software Developer