Feature flags are a common technique, often combined with continuous deployment and delivery and they allow us to rollback a specific feature, to create A/B tests or to rollout a specific feature for a specific test group, a specific amount of users or dedicated systems.

In the following short examples I’d like you to demonstrate how easy it is to implement feature flags with the Togglz framework with a few steps in a Java EE environment.

Project Dependencies

Togglz has a rich set of libraries for different integration points slf4j, cdi, spring, seam, servlet, shiro and others.

The main dependencies from my pom.xml are togglz-core, togglz-console, togglz-jsf and togglz-cdi are used in the following tutorial to add the administration console, facelet and CDI integration:

<properties > <project.build.sourceEncoding > UTF-8 </project.build.sourceEncoding > <togglz.version > 2.0.0.RC1 </togglz.version > </properties > <dependencies > <dependency > <groupId > org.togglz </groupId > <artifactId > togglz-core </artifactId > <version > ${togglz.version} </version > </dependency > <dependency > <groupId > org.togglz </groupId > <artifactId > togglz-console </artifactId > <version > ${togglz.version} </version > </dependency > <dependency > <groupId > org.togglz </groupId > <artifactId > togglz-jsf </artifactId > <version > ${togglz.version} </version > </dependency > <dependency > <groupId > org.togglz </groupId > <artifactId > togglz-cdi </artifactId > <version > ${togglz.version} </version > </dependency > <dependency > <groupId > org.glassfish.main.extras </groupId > <artifactId > glassfish-embedded-all </artifactId > <version > 3.1.2.2 </version > <scope > provided </scope > </dependency > </dependencies >

My full pom has some additional settings to integrate the embedded GlassFish Plugin, set the source/target level to Java 7 and add directives for the Maven War Plugin – please feel free to have a look at the source, fork, clone .. see below in the section “Tutorial Sources“..

Creating Feature Flags

A feature flag is implemented as an enum that implements org.togglz.core.Feature.

We may add a description for each feature using @Label, and adding a method isActive allows us to use this enum everywhere in our code.

This makes it easy to remove a feature switch from our code later because we only need to search for references to the specific enum.

package com.hascode.tutorial.fflag.feature ; import org.togglz.core.Feature ; import org.togglz.core.annotation.Label ; import org.togglz.core.context.FeatureContext ; public enum UserFeatures implements Feature { @ Label ( "Displays basic information for a given user" ) DISPLAY_SIMPLE_USER_PROFILE, @ Label ( "Displays extended information for a given user" ) DISPLAY_EXTENDED_USER_PROFILE ; public boolean isActive ( ) { return FeatureContext. getFeatureManager ( ) . isActive ( this ) ; } }

Feature Flag Configuration

Since we’ve added CDI integration, we’re able to instanciate our feature-flag configuration by creating an @ApplicationScoped class that implements org.togglz.core.manager.TogglzConfig.

Togglz offers different implementations for StateRepository – you may store your state in a database using JDBCStateRepository in a file using FileStateRepository – or for the purpose of a quick tutorial, using an in-memory repository, InMemoryStateRepository.

We’re using the ServletUserProvider here, initialized with the feature-admin role needed to access the administration area for the feature configuration.

package com.hascode.tutorial.fflag.config ; import javax.enterprise.context.ApplicationScoped ; import org.togglz.core.Feature ; import org.togglz.core.manager.TogglzConfig ; import org.togglz.core.repository.StateRepository ; import org.togglz.core.repository.mem.InMemoryStateRepository ; import org.togglz.core.user.UserProvider ; import org.togglz.servlet.user.ServletUserProvider ; import com.hascode.tutorial.fflag.feature.UserFeatures ; @ApplicationScoped public class FeatureFlagConfiguration implements TogglzConfig { private static final String featureAdminRole = "feature-admin" ; @Override public Class <? extends Feature > getFeatureClass ( ) { return UserFeatures. class ; } @Override public StateRepository getStateRepository ( ) { return new InMemoryStateRepository ( ) ; } @Override public UserProvider getUserProvider ( ) { return new ServletUserProvider ( featureAdminRole ) ; } }

If you want to take a quick look without adding authentication and roles to your application, just the following workaround, but please don’t forget to remove it for a production system!

@ApplicationScoped public class FeatureFlagConfiguration implements TogglzConfig { @Override public UserProvider getUserProvider ( ) { return new UserProvider ( ) { @Override public FeatureUser getCurrentUser ( ) { return new SimpleFeatureUser ( "admin" , true ) ; } } ; } }

To make CDI work, we need to add an empty file named beans.xml in src/main/webapp/WEB-INF!

Managing Feature Flags / Admin Console

When starting the application – in my project you simply need to run mvn to boot an embedded GlassFish with the application deployed – you’re able to load the administration console at the URL /contextPath/togglz/index.

Activation/Deactivation

In my case that means that the console is accessible at http://localhost:8080/togglz-feature-flag-tutorial/togglz/index

The console displays available features and their current state as seen in the following screenshot:

Activation Strategies

The following dialog allows you to activate a feature and chose a specific activation strategy:

none: The feature is simply activated

The feature is simply activated Client IP: Activated for clients with a specific IP

Activated for clients with a specific IP Gradual rollout: You may select the percentage of users e.g. selecting 25% activates the feature for every fourth user

You may select the percentage of users e.g. selecting 25% activates the feature for every fourth user Release date: You may specify the release date in the format yyyy-MM-dd

You may specify the release date in the format yyyy-MM-dd ScriptEngine: You may execute a script language e.g. ECMAScript – I must admit that I’ve never tried this one..

You may execute a script language e.g. ECMAScript – I must admit that I’ve never tried this one.. Server IP: Restrict the feature to a specific server IP .. e.g. activate for 2 of 6 servers by adding their IP address

Restrict the feature to a specific server IP .. e.g. activate for 2 of 6 servers by adding their IP address Username: Restrict to specific users .. you could – for example activate a specific feature for the users test-user and test-admin or something similar

This is what the administration console looks like with all features enabled .. greeen ….

Java Server Faces / Facelet Integration

Now we want to take a look at Togglz’ JSF Integration.. first of all we’re adding configuration for the JSF Servlet and add *.xhtml as the file pattern to activate it.

This is our web.xml in src/main/webapp/WEB-INF:

<?xml version = "1.0" encoding = "UTF-8" ?> <web-app version = "3.0" xmlns = "http://java.sun.com/xml/ns/javaee" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation = "http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" > <servlet > <servlet-name > Faces Servlet </servlet-name > <servlet-class > javax.faces.webapp.FacesServlet </servlet-class > </servlet > <servlet-mapping > <servlet-name > Faces Servlet </servlet-name > <url-pattern > *.xhtml </url-pattern > </servlet-mapping > </web-app >

And this is a simple facelet, index.xhtml added to the directory src/main/webapp.

As you can see, we’re able to test if a feature is enabled using #{features['FEATURE_NAME']} that returns a boolean.

In the following example, I’m displaying/hiding a panelGroup depending an the feature state:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns = "http://www.w3.org/1999/xhtml" xmlns:h = "http://java.sun.com/jsf/html" xmlns:f = "http://java.sun.com/jsf/core" xmlns:ui = "http://java.sun.com/jsf/facelets" > <h:head > <title > hasCode.com - Togglz Feature Flag Tutorial </title > </h:head > <h:body > <h1 > Features enabled </h1 > <h:panelGroup rendered = "#{features['DISPLAY_SIMPLE_USER_PROFILE']}" > Display simple user profile <hr /> </h:panelGroup > <h:panelGroup rendered = "#{features['DISPLAY_EXTENDED_USER_PROFILE']}" > Display extended user profile </h:panelGroup > </h:body > </html >

When you now start the application using mvn, the facelet is accessible at http://localhost:8080/togglz-feature-flag-tutorial/index.xhtml.

Programmatic Feature Flag Check

This is the way that we’ll be testing a flag most times – by simply using the enum and the isActive method.

In the following example, I’m adding a feature flag check to a servlet that prints a string depending on the features enabled:

package com.hascode.tutorial.fflag.servlet ; import java.io.IOException ; import javax.servlet.ServletException ; import javax.servlet.annotation.WebServlet ; import javax.servlet.http.HttpServlet ; import javax.servlet.http.HttpServletRequest ; import javax.servlet.http.HttpServletResponse ; import com.hascode.tutorial.fflag.feature.UserFeatures ; @WebServlet ( urlPatterns = "/fftest" ) public class FeatureFlagTestServlet extends HttpServlet { private static final long serialVersionUID = 1L ; @Override protected void doGet ( final HttpServletRequest req, final HttpServletResponse resp ) throws ServletException, IOException { StringBuilder sb = new StringBuilder ( ) ; sb. append ( "Available features are:

" ) ; if ( UserFeatures. DISPLAY_SIMPLE_USER_PROFILE . isActive ( ) ) { sb. append ( " \t - Display simple user profiles is enabled

" ) ; } if ( UserFeatures. DISPLAY_EXTENDED_USER_PROFILE . isActive ( ) ) { sb. append ( " \t - Display extended user profiles is enabled

" ) ; } resp. getWriter ( ) . append ( sb. toString ( ) ) ; } }

Finally the servlet output, accessible at http://localhost:8080/togglz-feature-flag-tutorial/fftest should output something like this if both features are enabled:

Tutorial Sources

Please feel free to download the tutorial sources from my Bitbucket repository, fork it there or clone it using Git:

git clone https: // bitbucket.org / hascode / jee-feature-flags.git

Resources

Tags: cdi, feature flag, java ee, java server faces, jsf, servlet, togglz