Spring Boot Togglz Usage — Part Two
In this article, we will introduce the feature flags in the properties file and control bean instantiation and initialization.
Join the DZone community and get the full member experience.
Join For FreeTogglz is a feature flag toggle pattern library to enable or disable a feature in the application. For getting started on togglz, please refer to the introduction article.
In this article, we will discuss having the feature flags in the properties file, also on different ways feature controlling bean instantiation and initialization and feature rest API.
Prerequisites
We need spring boot project with togglz dependencies like togglz-spring-boot-starter, togglz-spring-web, togglz-spring-security. Simple date utility rest API has been created for getting the server timezone and converting the time to your timezone.
value="/timezoneconversions") (
public String convertTimezone( ("timezone") String timezone) {
if (!this.manager.isActive(FeatureOptions.TIMEZONECONVERSION)) {
return "Feature is not active";
}
System.out.println(this.manager.getFeatureState(FeatureOptions.TIMEZONECONVERSION));
System.out.println(this.manager.getCurrentFeatureUser().getName());
Calendar currentdate = Calendar.getInstance();
DateFormat formatter= new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
formatter.setTimeZone(TimeZone.getTimeZone(timezone));
String convertedDate = formatter.format(currentdate.getTime());
formatter.setTimeZone(TimeZone.getTimeZone(timezone));
return convertedDate;
}
value="/currenttimezone") (
public String getServerTimezone() {
if (this.manager.isActive(FeatureOptions.CURRENTTZFEATURE)) {
return TimeZone.getDefault().getDisplayName();
} else {
return "Feature not active";
}
}
The logic to create the current Timezone was using java SDK library and convert the time to the requested timezone using Calendar instance is quite straight-forward logic.
Now, let's add the feature flags in the application.properties to toggle the features by creating a property for each feature( like togglz.features.<featurename>.enabled). Below properties are given for the current timezone feature and timezone conversion. It has been created with a User strategy for toggling the feature. So the suffix is added to strategy for the timezone conversion as a user and user list also given for the feature.
xxxxxxxxxx
togglz.features.CURRENTTZFEATURE.enabled=false
togglz.features.TIMEZONECONVERSION.enabled=true
togglz.features.TIMEZONECONVERSION.strategy=username
togglz.features.TIMEZONECONVERSION.param.users=user
We need to create an equivalent feature flag in the Feature implementation class.
x
public enum FeatureOptions implements Feature {
"Current TZ Feature") (
CURRENTTZFEATURE,
"Time zone conversion") (
TIMEZONECONVERSION,
public boolean isActive() {
System.out.println("greetings feature check");
return FeatureContext.getFeatureManager().isActive(this);
}
}
Then the Feature Manager injected into the class using constructor injection, with the help of Feature Manager to identify whether the feature is active or not.
Spring-security-web protects the whole web application for authentication. (Luckily spring boot creates a dynamic password for the default user login which is displayed in server console). Feature Manager when checked for the Timezone conversion feature is active by getting the logged-in user comparing the feature user given in properties file. We need to provide the User Provider bean to the context for the togglz to verify the user toggle strategy.
xxxxxxxxxx
public FeatureProvider featureProvider() {
return new EnumBasedFeatureProvider(FeatureOptions.class);
}
public UserProvider getUserProvider() {
System.out.println("**getting the user provider");
return new UserProvider() {
public FeatureUser getCurrentUser() {
System.out.println("**inside the current user" + SecurityContextHolder.getContext().getAuthentication().toString());
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String username = ((UserDetails) principal).getUsername();
return new SimpleFeatureUser(username, true);
}
};
}
In the bean factory method, the feature manager can be injected as a parameter. Then feature manager can be used to check the feature is active.
xxxxxxxxxx
public CustomerBean customerBean(FeatureManager featureManager) {
if (featureManager.isActive(FeatureOptions.CUSTOMERBEANFEATURE)) {
System.out.println("customer bean feature activte");
return new CustomerBean(featureManager);
}
return null;
}
Bean initialization can be controlled by the feature flag with feature manager injection and checking whether the feature is active.
xxxxxxxxxx
public CustomerBean(FeatureManager featureManager) {
if (featureManager.isActive(FeatureOptions.CUSTOMERBEANFEATURE)) {
System.out.println("customer bean feature activated");
}
System.out.println("customer bean created");
}
The context listener "onApplicationEvent" method invoked after the togglz context setup, In this method with the help of feature manager, checks feature is active before invoking the bean factory method ( getBean method).
xxxxxxxxxx
public class SpringTogglzListener extends TogglzApplicationContextBinderApplicationListener {
DefaultListableBeanFactory beanFactory;
ApplicationContext applicationContext;
public void onApplicationEvent(ApplicationEvent event) {
System.out.println("Wow! Togglz application context binder initialized!!!");
FeatureManager featureManager = (FeatureManager) beanFactory.getBean(FeatureManager.class);
System.out.println(featureManager.isActive(FeatureOptions.PRODUCTBEANFEATURE));
if (featureManager.isActive(FeatureOptions.PRODUCTBEANFEATURE))
System.out.println(beanFactory.getBean("productBean"));
}
}
Here the bean factory method is annotated with Lazy annotation as shown below. So when it is requested for the first time, then only the bean will be created.
true) (
public ProductBean productBean() {
System.out.println("product bean started..");
return new ProductBean();
}
Complete source code is available in GitHub.
Opinions expressed by DZone contributors are their own.
Comments