Enhance Your AEM Projects with Feature Flags


In the dynamic world of Adobe Experience Manager (AEM) projects, managing large-scale changes and feature implementations can be a challenging task. Whether you’re working on a website redesign or integrating new features, the ability to control when and where these changes take effect is crucial. This is where feature flags come into play, offering a strategic approach to implementing and managing features without immediate deployment on your production systems.

What Are Feature Flags?

Feature flags, also known as feature toggles, are a configuration strategy that allows you to enable or disable specific features within your application or website without modifying the underlying code. They act as simple on-off switches, granting you fine-grained control over feature activation.

Advantages of Feature Flags in AEM Projects

  • Integration Features: AEM leverages feature flags to enable specific functionalities, such as enabling Smart Tags on AEM as a Cloud Service (AEMaaCS). Additionally, AEM’s feature flags can hide or reveal features reliant on components like the “Auto-start workflow option” on AEMaaCS SDK, which relies on Asset Compute. This level of control ensures that you can selectively activate features based on readiness and dependencies. In complex AEM projects with multiple domains or micro-sites, feature flags can be employed to enable or disable entire integrations for specific domains. This flexibility allows you to customize the feature set for different sites, aligning your digital ecosystem with your business needs.
  • When simple “run-mode sepecific” / “context-aware” configs won’t be enough to determine whether a feature flag should be enabled or not. For this, custom services can be developed against the Feature interface. This additional level of control allows for even more fine-grained decision-making when it comes to feature activation, enhancing the flexibility and customization capabilities of feature flags in AEM projects
  • Agile Compatibility:
    • Incremental Progress: Feature flags allow for incremental development even in projects that span multiple sprints. For example, you can work on a new chat feature for your AEM website, enabling it using a feature flag in a test environment. This enables quality assurance (QA) testing and ensures that each incremental piece of work is production-ready when completed.
    • Safety Net: When a feature is turned off using a feature flag, it ensures that, from the user’s perspective, nothing has changed. This provides a safety net, allowing you to continue development and testing without disrupting the user experience.
  • Business Control:
    • Strategic Release Management: Feature flags empower Product Owners to strategically manage when specific features go live on production systems. For instance, if you’re introducing a maintenance banner to your AEM website, the Product Owner can toggle the feature flag, deciding when to display it without the need for taking the site offline.
    • Reduced Development Pressure: By allowing the Product Owner to control feature releases, development teams are relieved of the pressure to meet strict delivery deadlines. The coordination of feature releases becomes more flexible, aligning with the overall product release schedule.
  • Tailored Experiences: Feature flags enable the creation of custom configurations for different websites or segments of your site. For instance, you can have multiple regional websites, each with unique design requirements. By including feature flags in these configurations, you can tailor the user experience for each site based on specific design elements or features.
  • Efficient Incident Management: In the event of unexpected incidents or critical bugs in live systems, feature flags offer a rapid response. For example, if a newly introduced search functionality is causing issues, the Product Owner or authorized users can disable the feature via a feature flag. This action doesn’t require developer intervention, eliminating the need for system updates or site downtime. The site can continue to operate seamlessly while the issue is addressed, minimizing user disruption.
  • Beta Testing for specific User Groups: Feature flags can be used to beta test new or upgraded features with specific users or user groups. For example, you can enable a feature flag for a select group of beta testers, allowing them to access and provide feedback on a new feature before rolling it out to the broader user base. This approach ensures that you can gather valuable insights and make improvements based on real user feedback, ultimately leading to a more polished and user-friendly final product. For example on enabling feature based on user-groups, please refer to blog by Arun Patidar

Configuring Feature Flag

Feature flag support has two essential components:

  1. The Feature Flag Itself: This is represented by the Feature interface and serves as the core element of feature flag management.
  2. The Feature-Enabled Application: This refers to the sling model, servlet, rendercondition etc whose behaviour is controlled by a feature flag. A feature flag acts as a boolean condition that determines how this application behaves.

Feature flags provide the flexibility to enable or disable features in either a dynamic or static manner.

In dynamic management, feature flags can be established by registering services that implement the org.apache.sling.featureflags.Feature interface. This approach enables real-time feature management based on a variety of contextual factors, which include:

  • Time of Day
  • Segmentation Data: If available, features can be adapted based on segmentation criteria like gender and age, delivering tailored experiences to distinct user groups.
  • Request Parameter
  • Request Header
  • Cookie Value: The value of cookies linked to a user’s session can influence the feature’s state, ensuring that feature behavior aligns with user preferences.
  • Business logic added to isEnabled() of Feature.

Alternatively, in a static configuration approach, feature flags can be set up via OSGi factory configuration using the factory PID org.apache.sling.featureflags.impl.ConfiguredFeature. This method allows for a more structured and predetermined management of feature flags, ensuring consistent feature behavior.

Sometimes, a simple run-mode-based flag might not suffice to determine the enabling or disabling of a feature flag. In such cases, custom services can be created that adhere to the Feature interface.

Dynamic Feature Flags

To enable a Feature service, you need to implement the org.apache.sling.featureflags.Feature interface. Within this service, you can define the logic to enable or disable the feature in the isEnabled(ExecutionContext ec) method. This method returns a boolean value: true indicates that the feature is enabled, and false signifies that it’s disabled based on the implemented logic. Additionally, you can assign a name and description to the feature, which aids in identifying it through the feature console.

Here’s an example of how to enable a Feature service:

import org.apache.sling.featureflags.Feature;
import org.apache.sling.featureflags.ExecutionContext;
import org.osgi.service.component.annotations.Component;

@Component(service = Feature.class, immediate = true)
public class CustomFeatureService implements Feature {
    @Override
    public String getDescription() {
        return "Custom Feature";
    }

    @Override
    public String getName() {
        return "custom-feature";
    }

    @Override
    public boolean isEnabled(ExecutionContext ec) {

        // Implement the logic to evaluate the feature flag to true or false
        // For instance, you can check contextual data from request (header/cookie) or system-level info (Time)
        // Get the current system time
        Calendar currentSystemTime = Calendar.getInstance();

        // Set the target date to December 31, 2023
        Calendar targetDate = Calendar.getInstance();
        targetDate.set(2023, Calendar.DECEMBER, 31, 0, 0, 0);

        // Compare the current time with the target date
        if (currentSystemTime.before(targetDate)) {
            // Feature is enabled because the current time is after December 31, 2023
            return true;
        } else {
            // Feature is disabled because the current time is not after December 31, 2023
            return false;
        }
    }
}

This approach allows for dynamic configuration, where the logic is evaluated to determine the flag’s value. The isEnabled function can make use of various information available within the ExecutionContext object provided to it (request, resource resolver, other features etc).

Static Feature FLag

You can also activate the feature through the factory PID org.apache.sling.featureflags.impl.ConfiguredFeature (Apache Sling Configured Feature).

To enable feature flags with run mode-specific configurations, you can utilize the file org.apache.sling.featureflags.impl.ConfiguredFeature~newfeature.cfg.json. Here’s an example:

{
  "enabled":true,
  "name":"newFeature",
  "description":"New Feature Configuration"
}
PropertyDescription
nameShort name of this feature. This name is used to refer to this feature when checking for it to be enabled or not. This property is required and defaults to a name derived from the feature’s class name and object identity. It is strongly recommended to define a useful and unique for the feature
descriptionDescription for the feature. The intent is to descibe the behaviour of the application if this feature would be enabled. It is recommended to define this property. The default value is the value of the name property.
enabledBoolean flag indicating whether the feature is enabled or not by this configuration

One possible limitation of setting up Feature Flags in this way is their strong connection to your build process, which can constrain your ability to manage them without going through the deployment process for AEM as a Cloud Service (AEMaaCS) or the update process via the OSGi console for AEM 6.5.

Leveraging Environment Variables for Feature Flag Configuration in AEM as a Cloud Service

AEMaaCS’s Cloud Manager provides you with the agility to modify your feature flags without the necessity of code redeployment. Simply employ these environment variables within your OSGi configurations.

Sample “Apache Sling Configured Feature” in AEM

{
  "enabled":"$[env:<New_Feature_Enabled>;default=false]",
  "name":"newFeature",
  "description":"New Feature Configuration"
}

Sample Variable configured via Cloud Manager

Verifying Feature Flag

You can check the activation status of the registered feature flags, both dynamic and static, by accessing the OSGI console at http://localhost:4502/system/console/features (OSGi Console > Sling > Features)

Using Feature Flag

Show or Hide Visual Elements in AEM’s User Interface

Feature flags serve as an effective way to control when specific UI elements, like dialog fields and tools menu items, should be displayed in the AEM user interface. One common use case is to introduce new authoring options that should only become visible once a particular feature is activated.

To achieve this, the ‘granite/ui/components/coral/foundation/renderconditions/feature‘ resource type is employed as part of the ‘granite:rendercondition’ attribute associated with the author dialog field linked to your feature. This configuration results in the field being hidden when the feature is disabled and displayed when it’s enabled.

Example: “Enable DM features” in Image Policy is only available when Dynamic Media is integrated. Out of the box, this condition is captured by the feature flag “com.adobe.dam.asset.scene7.feature.flag.”

Just as with this example, you have the flexibility to define any feature and set it up with your dialog field using a render condition to control when the field is visible or hidden. In following example, the “description” field is hidden based on out custom-feature

Using feature flag in sling models / servlets / workflow steps and other OSGi Services

You can utilize Sling Feature Flags to control functionality within Sling Models, servlets, and other OSGI services. This can be accomplished by leveraging the Features factory service. By referencing or injecting these services, you can use the following code as needed. Example: Here we are enabling premium content with Feature Flags

import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
import org.apache.sling.featureflags.Features;
import org.osgi.framework.Constants;
import org.apache.sling.api.servlets.HttpConstants;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;

import javax.servlet.ServletException;
import java.io.IOException;

@Component(
    service = SlingSafeMethodsServlet.class,
    immediate = true,
    property = {
        Constants.SERVICE_DESCRIPTION + "=Premium User Content Servlet",
        "sling.servlet.methods=" + HttpConstants.METHOD_GET,
        "sling.servlet.paths=" + "/services/premiumContentServlet"
    }
)
public class PremiumContentServlet extends SlingSafeMethodsServlet {

    @Reference
    private Features features;

    private static final long serialVersionUID = 1L;

    @Override
    protected void doGet(final SlingHttpServletRequest req, final SlingHttpServletResponse resp) throws ServletException, IOException {
        if (features.isEnabled("com.example.feature.premiumEnabled")) {
            // Render premium content or provide premium functionality
            resp.setContentType("text/plain");
            resp.getWriter().write("Welcome to Premium Content!");
        } else {
            resp.setContentType("text/plain");
            resp.getWriter().write("Premiun content is work-in-progress.");
        }
    }
}

Utilizing Feature Flags in Workflow Launchers

Feature flags provide a versatile mechanism for activating workflow launchers in AEM, offering the capability to trigger them based on specific conditions. Within this context, the following elements play a crucial role:

Features: This section allows you to specify a list of features that need to be enabled for the workflow launcher to activate.

Disabled Features: In this section, you can define a list of features that must be disabled to enable the workflow launcher.

For example, consider the out-of-the-box use of the “com.adobe.dam.asset.nui.feature.flag” feature flag in the context of the “Asset Processing on SDK” workflow. This flag is set to ‘false’ for the SDK and ‘true’ for the AEMaaCS server. By configuring the “Disabled Features” section with “com.adobe.dam.asset.nui.feature.flag,” the workflow is disabled when the flag is ‘true,’ effectively deactivating it on the AEMaaCS platform. Similarly, you can configure the “Features” section to activate the workflow launcher when the flag is ‘true.’

Here’s a table summarizing the behavior:

ConditionWorkflow Launcher
Disabled FeaturesFunctional when the flag is ‘false’
FeaturesFunctional when the flag is ‘true’

Utilizing Feature Flags in Sightly

Incorporating feature flags into Sightly requires retrieving the flag’s value from the relevant Sling Model and can be achieved as follows:

<sly data-sly-use.model="com.example.core.components.SomeComponentModel">
    <div data-sly-test="${model.isCustomFeatureEnabled}">
        <!-- Component markup -->
    </div>
</sly>

In this code snippet, the value of the feature flag is obtained from the associated Sling Model and then used to conditionally render the component markup based on the flag’s status.

Leave a comment