{"id":111814,"date":"2021-06-13T12:38:12","date_gmt":"2021-06-13T12:38:12","guid":{"rendered":"https:\/\/staging.wingify.com\/blog\/java-feature-flags\/"},"modified":"2021-06-13T12:38:12","modified_gmt":"2021-06-13T12:38:12","slug":"java-feature-flags","status":"publish","type":"post","link":"https:\/\/wingify.com\/blog\/java-feature-flags\/","title":{"rendered":"How to Implement Feature Flags in Java"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">In this article, we\u2019ll cover how to implement feature flags in Java using our\u00a0<a href=\"https:\/\/docs.developers.flagship.io\/docs\/sdk-overview\" target=\"_blank\" rel=\"noreferrer noopener\">Java SDK<\/a> and also discuss other open-source Java frameworks available on Github. If your are using the Spring framework, this article will suit you well.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Overview of the feature flag pattern<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Feature flags are a powerful software development tool that turns certain functionalities on and off without the need to deploy new code, and without any service disruptions.&nbsp;<a href=\"https:\/\/wingify.com\/blog\/feature-flags-use-cases\/\" target=\"_blank\" rel=\"noopener\">Feature flags can be used for a wide range of purposes<\/a>, from kill switch to targeted releases (ex: ring deployments, canary deployments), through feature testing. Thus, a feature flag ranges from a simple IF statement to more complex decision trees, which act upon different variables.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Wingify offers an <a href=\"https:\/\/wingify.com\/\" target=\"_blank\" rel=\"noopener\">enterprise-grade feature flag management platform<\/a> that keeps you in control of your release strategies.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">As its core, it provides a Decision API to assign and retrieve feature flag values for your users (e.g. what value a flag should be for a specific user), so you don\u2019t have to mess with complex configuration files or manage a dedicated infrastructure to <a href=\"https:\/\/wingify.com\/blog\/feature-flag-storage\/\" target=\"_blank\" rel=\"noopener\">store all the different flag values<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The \u201cDecision\u201d part in the name refers to built-in intelligence that is key to maintain flag values consistency between different user sessions or for instance when an anonymous users gets authenticated to your application.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">White this REST API is language-agnostic by design, we provide several server and client-side SDKs. Here, we\u2019ll discuss the Java SDK that includes preconfigured methods to implement the Decision API. Refer to our&nbsp;<a href=\"https:\/\/developers.flagship.io\/docs\/sdk\/java\/v1.0\" target=\"_blank\" rel=\"noopener\">developer documentation for more details<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Setting feature flags with&nbsp;Wingify&nbsp;Java SDK<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Using our cloud-based feature management service&nbsp;is a 2- step process. First, in your codebase, you wrap your features once with flags using methods from the Java SDK. Once this is done, you remotely configure your flags (values, segments\u2026) from the&nbsp;dashboard. Let\u2019s see both steps in details.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Setting up the Java SDK<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">Installation and initialization<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">First, you need to add the Java repository to your dependency manager. You can use Maven or Gradle build tools to do so:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;pre&gt;&lt;code class=\"language-maven line-numbers\"&gt;&lt;!--\n\/\/ Gradle\nmaven { url 'https:\/\/abtasty.jfrog.io\/artifactory\/flagship-java' }\n\n\/\/ Maven\n&lt;repositories&gt;\n    &lt;repository&gt;\n        &lt;id&gt;com.abtasty&lt;\/id&gt;\n        &lt;url&gt;https:\/\/abtasty.jfrog.io\/artifactory\/flagship-java&lt;\/url&gt;\n    &lt;\/repository&gt;\n&lt;\/repositories&gt;\n--&gt;&lt;\/code&gt;&lt;\/pre&gt;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then, import the Java SDK using either Maven or Gradle dependency management:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;pre&gt;&lt;code class=\"language-maven line-numbers\"&gt;&lt;!--\n\/\/ Gradle\nimplementation 'com.abtasty:flagship-java:1.0.0'\n\n\/\/ Maven\n&lt;dependency&gt;\n    &lt;groupId&gt;com.abtasty&lt;\/groupId&gt;\n    &lt;artifactId&gt;flagship-java&lt;\/artifactId&gt;\n    &lt;version&gt;1.0.0&lt;\/version&gt;\n&lt;\/dependency&gt;\n--&gt;&lt;\/code&gt;&lt;\/pre&gt;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">To initialize and start the SDK, simply call the start function of the class, in the most appropriate location for your application. You need to pass two parameters: your environment id and your API authentication key. Both values are available from the&nbsp;user interface (UI), once you are logged in.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;pre&gt;&lt;code class=\"language-java line-numbers\"&gt;&lt;!--\nFlagship.start(\"YOUR_ENV_ID\", \"YOUR_API_KEY\");\n--&gt;&lt;\/code&gt;&lt;\/pre&gt;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The start method also accepts a third argument to create a custom configuration, ex:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;pre&gt;&lt;code class=\"language-java line-numbers\"&gt;&lt;!--\nFlagship.start(\"YOUR_ENV_ID\", \"YOUR_API_KEY\", new FlagshipConfig()\n    .withFlagshipMode(Flagship.Mode.DECISION_API)\n    .withLogManager(new CustomLogManager())\n    .withLogLevel(LogManager.Level.ALL)\n    .withTimeout(200));\n--&gt;&lt;\/code&gt;&lt;\/pre&gt;<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"creating-a-new-visitor\">Creating a new visitor<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Next, you\u2019ll have to create a new visitor.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The visitor instance is a helper object that lets you manage the context and campaigns for a user identified by a unique ID.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The user context is a property dataset which defines the current user of your app. This dataset is sent and used by the Decision API as targeting criterias for campaign assignment.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For example, if you want to enable or disable a specific feature based on a VIP status, you would pass this attribute as a key-value pair in the user context so that the Decision API can enable or disable the corresponding feature flag for the user.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;pre&gt;&lt;code class=\"language-java line-numbers\"&gt;&lt;!--\nVisitor visitor = Flagship.newVisitor(\"YOUR_VISITOR_ID\", new HashMap&lt;String, Object&gt;() {{\n    put(\"isVip\", true);\n--&gt;&lt;\/code&gt;&lt;\/pre&gt;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The first parameter of the method is the Unique visitor identifier, while the second is the initial user context.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You can also update the visitor context when required. The following method from the Visitor instance allows you to set new context values matching the given keys.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;pre&gt;&lt;code class=\"language-java line-numbers\"&gt;&lt;!--\nVisitor visitor = Flagship.newVisitor(\"YOUR_VISITOR_ID\", new HashMap&lt;String, Object&gt;() {{\n    put(\"isVip\", false);\n}});\n\nvisitor.updateContext(\"isVip\", true);\n--&gt;&lt;\/code&gt;&lt;\/pre&gt;<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"managing-feature-flag-assignment\">Managing feature flag assignment<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The synchronizeModifications() method of the visitor instance automatically calls the Decision API to run feature flag assignments according to the current user context.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;pre&gt;&lt;code class=\"language-java line-numbers\"&gt;&lt;!--\nVisitor visitor = Flagship.newVisitor(\"YOUR_VISITOR_ID\")\nvisitor.updateContext(\"isVip\", true)\nvisitor.synchronizeModifications().whenComplete((instance, error) -&gt; {\n    \/\/ Asynchronous non blocking call\n    \/\/ Synchronization has been completed. Do stuff here...\n});\n--&gt;&lt;\/code&gt;&lt;\/pre&gt;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Once the campaign has been assigned and synchronized, all the modifications are stored in the SDK. You can retrieve these modifications using the getModification method from the Visitor instance. It retrieves a modification value by its key. If no modification matches the given key or if the stored value type and default value type do not match, default value will be returned.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;pre&gt;&lt;code class=\"language-java line-numbers\"&gt;&lt;!--\nVisitor visitor = Flagship.newVisitor(\"YOUR_VISITOR_ID\")\nvisitor.updateContext(\"isVip\", true)\nvisitor.synchronizeModifications().whenComplete((instance, error) -&gt; {\n    Boolean displayVipFeature = visitor.getModification(\"displayVipFeature\",  false);\n});\n--&gt;&lt;\/code&gt;&lt;\/pre&gt;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The getModification method accepts a third argument, that, if set to true will automatically report on our server that the current visitor has seen this specifc variation. It is also possible to call activateModification() later.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;pre&gt;&lt;code class=\"language-java line-numbers\"&gt;&lt;!--\nVisitor visitor = Flagship.newVisitor(\"YOUR_VISITOR_ID\")\nvisitor.updateContext(\"isVip\", true)\nvisitor.synchronizeModifications().whenComplete((instance, error) -&gt; {\n\n    Boolean displayVipFeature = visitor.getModification(\"displayVipFeature\", false, true); \/\/send an activation event.\n\n    \/\/ or\n\n    Boolean displayVipFeature = visitor.getModification(\"displayVipFeature\", false);\n    visitor.activateModification(\"displayVipFeature\");\n});\n--&gt;&lt;\/code&gt;&lt;\/pre&gt;<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"measuring-events-and-metrics\">Measuring events and metrics<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Our Universal Collect protocol provides a unified hit format to send data back to our server-side solution for reporting purposes. The format of the hit is based on the Google Analytics measurement protocol. By sending hits to our platform, you can measure the impact of a feature on different metrics such as pageviews, screenviews, transactions or generic events.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To send hits, you must call the sendHit method from the Visitor instance:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;pre&gt;&lt;code class=\"language-java line-numbers\"&gt;&lt;!--\n\/\/ Pageview hit\nPage page = new Page(\"https:\/\/www.my_domain_com\/my_page\")\nvisitor.sendHit(page);\n\n\/\/ Sreenview hit\nScreen screen = new Screen(\"screen location\")\n    .withResolution(200, 100)\n    .withLocale(\"fr_FR\")\n    .withIp(\"127.0.0.1\")\n    .withSessionNumber(2);\nvisitor.sendHit(screen);\n\n\/\/ Transaction hit\nTransaction transaction = new Transaction(\"#12345\", \"affiliation\")\n    .withCouponCode(\"code\")\n    .withCurrency(\"EUR\")\n    .withItemCount(1)\n    .withPaymentMethod(\"creditcard\")\n    .withShippingCosts(9.99f)\n    .withTaxes(19.99f)\n    .withTotalRevenue(199.99f)\n    .withShippingMethod(\"1day\");\nvisitor.sendHit(transaction);\n\n\/\/ Generic Event hit\nEvent event = new Event(Event.EventCategory.ACTION_TRACKING, \"action\")\n    .withEventLabel(\"label\")\n    .withEventValue(100);\nvisitor.sendHit(event);\n--&gt;&lt;\/code&gt;&lt;\/pre&gt;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">For more details, refer to our&nbsp;<a href=\"https:\/\/developers.flagship.io\/docs\/sdk\/java\/v1.0\" target=\"_blank\" rel=\"noopener\">Java SDK references<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"setting-up-flags-in-the-flagship.io-ui-interface\">Setting up flags in our&nbsp;UI interface<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The first step is to <a href=\"https:\/\/www.flagship.io\/sign-up\/\" target=\"_blank\" rel=\"noopener\">sign up <\/a>to our app.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You can refer to this short video that goes through all the process of a feature flag setup or read the detailed instructions below.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;p&gt;&lt;script src=\"https:\/\/fast.wistia.com\/embed\/medias\/a0r6tvay8z.jsonp\" async=\"\"&gt;&lt;\/script&gt;&lt;script src=\"https:\/\/fast.wistia.com\/assets\/external\/E-v1.js\" async=\"\"&gt;&lt;\/script&gt;&lt;\/p&gt;\n&lt;div class=\"wistia_responsive_padding\" style=\"padding: 56.25% 0 0 0; position: relative;\"&gt;\n&lt;div class=\"wistia_responsive_wrapper\" style=\"height: 100%; left: 0; position: absolute; top: 0; width: 100%;\"&gt;\n&lt;div class=\"wistia_embed wistia_async_a0r6tvay8z videoFoam=true\" style=\"height: 100%; position: relative; width: 100%;\"&gt;\n&lt;div class=\"wistia_swatch\" style=\"height: 100%; left: 0; opacity: 0; overflow: hidden; position: absolute; top: 0; transition: opacity 200ms; width: 100%;\"&gt;&lt;img style=\"filter: blur(5px); height: 100%; object-fit: contain; width: 100%;\" src=\"https:\/\/fast.wistia.com\/embed\/medias\/a0r6tvay8z\/swatch\" alt=\"\" aria-hidden=\"true\" \/&gt;&lt;\/div&gt;\n&lt;\/div&gt;\n&lt;\/div&gt;\n&lt;\/div&gt;<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"creating-your-feature-flag-use-case\">Creating your feature flag use case<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">To create a feature flag from the dashboard, apply the following steps:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Go to the dashboard.<\/li>\n\n\n\n<li>Click the + button.<\/li>\n\n\n\n<li>Choose an existing project or create a new one<\/li>\n\n\n\n<li>Click the \u201cAdd a use case\u201d button.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">You are presented with a list of different templates or use cases (ex: progressive rollout, <a href=\"https:\/\/wingify.com\/glossary\/ab-testing\/\" target=\"_blank\" rel=\"noopener\">A\/B test<\/a>\u2026)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Choose the \u201cFeature toggling\u201d template.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"entering-the-basic-information\">Entering the basic information<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">First, you need to enter the basic information of your feature flag use case:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The feature name: use the most representative name for your feature, because this is the one you\u2019ll need to remember in case you want to find it later.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The feature description: explain exactly what your feature deployment is about and what its purpose for your business is.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The primary\/secondary metric to follow (optional) which will serve as a point of reference to analyze performance. For more information, refer to Configuring KPIs.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"defining-flags\">Defining flags<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">This is where you configure the flags and their values based on your different scenarios. Think of it as the config file mentioned in the first method, but that you manage remotely from the cloud. Important: flag names you specify here should match the ones used in your codebase.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"defining-targeting\">Defining targeting<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">During this step, you can define which users will be assigned to your different flag values. This is a segmentation engine built into the platform that makes it easy to assign flags conditionally based on user traits (or attributes) that you have access to in your codebase.&nbsp;<a href=\"https:\/\/docs.abtasty.com\/feature-experimentation-and-rollout\" target=\"_blank\" rel=\"noreferrer noopener\">Refer to this article about feature flag targeting for more information<\/a>. The 3 following options are available:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>All Users if you want all your users to progressively see your feature.<\/li>\n\n\n\n<li>Users by ID if you want only users with a specific ID to see your feature.<\/li>\n\n\n\n<li>Key if you only want users matching this key value to see your feature.<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"enabling-your-feature\">Enabling your feature<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Once you have configured your feature, it is OFF by default to allow you to check that it is correctly configured. Back to the dashboard, you can activate your feature ON when you are ready!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>And that\u2019s it. Now, provided changes to your codebase have been deployed, you can activate\/deactivate feature flags, remotely change their values and have your Java Application react instantly to these changes.<\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Open-source feature flag frameworks for Java<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">For the sake of completeness, we list here open source alternatives if you are using Java. While there are pros and cons to each approach, the third-party vendor option is probably the most efficient method for large teams with evolving use cases that don\u2019t want to deal with the challenges of an in-house system.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Keep reading:&nbsp;<a href=\"https:\/\/wingify.com\/blog\/build-vs-buy\/\" target=\"_blank\" rel=\"noopener\">The Journey of Feature Flag Implementation (Build vs. Buy)<\/a>&nbsp;where we discuss the pros and cons of different options when it comes to choosing between to build, use an open-source project or buy a feature flag management solution.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">FF4J &#8211; Feature Flipping for Java<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/github.com\/ff4j\/ff4j\">FF4j<\/a>, is an implementation of the Feature Toggle pattern for Java. It provides a rich set of features:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Enable and disable features at runtime &#8211; no deployments.<\/li>\n\n\n\n<li>Enable features not only with flag values but also drive access with roles and groups.<\/li>\n\n\n\n<li>Implement custom predicates to evaluate if a feature is enabled.<\/li>\n\n\n\n<li>Keep your code clean and readable: Avoid nested if statements but use annotations.<\/li>\n\n\n\n<li>Each action (create, update, delete, toggles) can be traced and saved in the audit trail for troubleshooting.<\/li>\n\n\n\n<li>Administrate FF4j (including features and properties) with the web UI.<\/li>\n\n\n\n<li>Wide choice of databases technologies to store your features, properties and events.<\/li>\n\n\n\n<li>(Distributed) Cache Evaluating predicates may put pressure on DB (high hit ratio).<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">940 stars on Github.&nbsp;<a href=\"https:\/\/github.com\/ff4j\/ff4j\" target=\"_blank\" rel=\"noopener\">View repository<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"togglz---feature-flags-for-the-java-platform\">togglz &#8211; Feature Flags for the Java platform<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/www.togglz.org\/\" target=\"_blank\" rel=\"noopener\">Togglz<\/a> is another implementation of the Feature Toggles pattern for Java.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Modular setup. Select exactly the components of the framework you want to use. Besides the main dependency, install specific integration modules if you are planning to integrate Togglz into a web application (Servlet environment) or if you are using CDI, Spring, Spring Boot, JSF.<\/li>\n\n\n\n<li>Straight forward usage. Just call the isActive() method on the corresponding enum to check if a feature is active or not for the current user.<\/li>\n\n\n\n<li>Admin console. Togglz comes with an embedded admin console that allows you to enable or disable features and edit the user list associated with every feature.<\/li>\n\n\n\n<li>Activation strategies. They are responsible for deciding whether an enabled feature is active or not. Activation strategies can, for example, be used to activate features only for specific users, for specific client IPs or at a specified time.<\/li>\n\n\n\n<li>Custom Strategies. Besides the built-in default strategies, it\u2019s easy to add your own strategies. Togglz offers an extension point that allows you to implement a new strategy with only a single class.<\/li>\n\n\n\n<li>Feature groups. To make sure you don\u2019t get lost in all the different feature flags, Togglz allows you to define group for feature that are just used for a visual grouping in the admin console.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">940 stars on Github.&nbsp;<a href=\"https:\/\/github.com\/togglz\/togglz\" target=\"_blank\" rel=\"noopener\">View repository<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"unleash\">Unleash<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/github.com\/Unleash\/unleash\" target=\"_blank\" rel=\"noopener\">Unleash<\/a> is an open-source feature management platform. It provides an overview of all feature toggles\/flags across all your applications and services. You first need to setup an Unleash server that you self-host, and then use a client SDK to connect your application to the server. A Java Client SDK is available and provides features such as:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Boolean feature toggles (on\/off)<\/li>\n\n\n\n<li>Canary release (Gradual rollout)<\/li>\n\n\n\n<li>Targeted release<\/li>\n\n\n\n<li>Experimentation (A\/B testing)<\/li>\n\n\n\n<li>Kill switches<\/li>\n\n\n\n<li>Custom activation strategies<\/li>\n\n\n\n<li>Privacy first (GDPR) where end-user data never leaves your application<\/li>\n\n\n\n<li>Audit logs<\/li>\n\n\n\n<li>Addons integrating with other popular tools (Slack, Teams, Datadog, etc.)<\/li>\n\n\n\n<li>Dashboard to manage technical debt<\/li>\n\n\n\n<li>Flexible architecture and can be hosted anywhere<\/li>\n\n\n\n<li>Docker image available<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">3,828 stars on Github.&nbsp;<a href=\"https:\/\/github.com\/Unleash\/unleash\" target=\"_blank\" rel=\"noopener\">View repository<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Let&#8217;s see how to implement the feature flag pattern in Java using our Java SDK.<\/p>\n","protected":false},"author":1435,"featured_media":115643,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"post_read_time":0,"footnotes":""},"categories":[10777],"tags":[10780],"feature":[],"industry-type":[],"product":[],"role":[],"region":[],"class_list":["post-111814","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-feature-flags","tag-rollouts"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Implement Feature Flags in Java - Wingify Blog<\/title>\n<meta name=\"description\" content=\"Let&#039;s see how to implement the feature flag pattern in Java using our Java SDK.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/wingify.com\/blog\/java-feature-flags\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Implement Feature Flags in Java - Wingify Blog\" \/>\n<meta property=\"og:description\" content=\"Let&#039;s see how to implement the feature flag pattern in Java using our Java SDK.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/wingify.com\/blog\/java-feature-flags\/\" \/>\n<meta property=\"og:site_name\" content=\"Wingify Blog\" \/>\n<meta property=\"article:published_time\" content=\"2021-06-13T12:38:12+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/static.wingify.com\/gcp\/uploads\/sites\/3\/2026\/08\/Blog-og-image@2x-1.png\" \/>\n<meta name=\"author\" content=\"Anthony Brebion\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/static.wingify.com\/gcp\/uploads\/sites\/3\/2026\/08\/Blog-og-image@2x-1.png\" \/>\n<meta name=\"twitter:creator\" content=\"@Wingify\" \/>\n<meta name=\"twitter:site\" content=\"@Wingify\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Anthony Brebion\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/wingify.com\\\/blog\\\/java-feature-flags\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/wingify.com\\\/blog\\\/java-feature-flags\\\/\"},\"author\":{\"name\":\"Anthony Brebion\",\"@id\":\"https:\\\/\\\/wingify.com\\\/blog\\\/#\\\/schema\\\/person\\\/ef0688fa888868d2b6418dd5751e3929\"},\"headline\":\"How to Implement Feature Flags in Java\",\"datePublished\":\"2021-06-13T12:38:12+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/wingify.com\\\/blog\\\/java-feature-flags\\\/\"},\"wordCount\":1816,\"image\":{\"@id\":\"https:\\\/\\\/wingify.com\\\/blog\\\/java-feature-flags\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/static.wingify.com\\\/gcp\\\/uploads\\\/sites\\\/3\\\/2026\\\/09\\\/Release-Management-3.png\",\"keywords\":[\"Rollouts\"],\"articleSection\":[\"Feature Flags\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/wingify.com\\\/blog\\\/java-feature-flags\\\/\",\"url\":\"https:\\\/\\\/wingify.com\\\/blog\\\/java-feature-flags\\\/\",\"name\":\"Implement Feature Flags in Java - Wingify Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/wingify.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/wingify.com\\\/blog\\\/java-feature-flags\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/wingify.com\\\/blog\\\/java-feature-flags\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/static.wingify.com\\\/gcp\\\/uploads\\\/sites\\\/3\\\/2026\\\/09\\\/Release-Management-3.png\",\"datePublished\":\"2021-06-13T12:38:12+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/wingify.com\\\/blog\\\/#\\\/schema\\\/person\\\/ef0688fa888868d2b6418dd5751e3929\"},\"description\":\"Let's see how to implement the feature flag pattern in Java using our Java SDK.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/wingify.com\\\/blog\\\/java-feature-flags\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/wingify.com\\\/blog\\\/java-feature-flags\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/wingify.com\\\/blog\\\/java-feature-flags\\\/#primaryimage\",\"url\":\"https:\\\/\\\/static.wingify.com\\\/gcp\\\/uploads\\\/sites\\\/3\\\/2026\\\/09\\\/Release-Management-3.png\",\"contentUrl\":\"https:\\\/\\\/static.wingify.com\\\/gcp\\\/uploads\\\/sites\\\/3\\\/2026\\\/09\\\/Release-Management-3.png\",\"width\":2400,\"height\":2332,\"caption\":\"Release Management 3\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/wingify.com\\\/blog\\\/java-feature-flags\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/wingify.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Feature Flags\",\"item\":\"https:\\\/\\\/wingify.com\\\/blog\\\/feature-flags\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"How to Implement Feature Flags in Java\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/wingify.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/wingify.com\\\/blog\\\/\",\"name\":\"Wingify Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/wingify.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/wingify.com\\\/blog\\\/#\\\/schema\\\/person\\\/ef0688fa888868d2b6418dd5751e3929\",\"name\":\"Anthony Brebion\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/static.wingify.com\\\/gcp\\\/uploads\\\/sites\\\/3\\\/2026\\\/09\\\/1779458990830-150x150.jpg\",\"url\":\"https:\\\/\\\/static.wingify.com\\\/gcp\\\/uploads\\\/sites\\\/3\\\/2026\\\/09\\\/1779458990830-150x150.jpg\",\"contentUrl\":\"https:\\\/\\\/static.wingify.com\\\/gcp\\\/uploads\\\/sites\\\/3\\\/2026\\\/09\\\/1779458990830-150x150.jpg\",\"caption\":\"Anthony Brebion\"},\"description\":\"Anthony Brebion is a GTM &amp; RevOps Engineer at AB Tasty, with a background in digital marketing, SEO, and website optimization. He combines his marketing and technical expertise to build data-driven systems, automate workflows, and improve digital experiences. His areas of expertise include CRO, e-commerce optimization, marketing automation, and experimentation.\",\"sameAs\":[\"https:\\\/\\\/www.linkedin.com\\\/in\\\/anthonybrebion\\\/\"],\"url\":\"https:\\\/\\\/wingify.com\\\/blog\\\/author\\\/abrebion\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Implement Feature Flags in Java - Wingify Blog","description":"Let's see how to implement the feature flag pattern in Java using our Java SDK.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/wingify.com\/blog\/java-feature-flags\/","og_locale":"en_US","og_type":"article","og_title":"Implement Feature Flags in Java - Wingify Blog","og_description":"Let's see how to implement the feature flag pattern in Java using our Java SDK.","og_url":"https:\/\/wingify.com\/blog\/java-feature-flags\/","og_site_name":"Wingify Blog","article_published_time":"2021-06-13T12:38:12+00:00","og_image":[{"url":"https:\/\/static.wingify.com\/gcp\/uploads\/sites\/3\/2026\/08\/Blog-og-image@2x-1.png","type":"","width":"","height":""}],"author":"Anthony Brebion","twitter_card":"summary_large_image","twitter_image":"https:\/\/static.wingify.com\/gcp\/uploads\/sites\/3\/2026\/08\/Blog-og-image@2x-1.png","twitter_creator":"@Wingify","twitter_site":"@Wingify","twitter_misc":{"Written by":"Anthony Brebion","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/wingify.com\/blog\/java-feature-flags\/#article","isPartOf":{"@id":"https:\/\/wingify.com\/blog\/java-feature-flags\/"},"author":{"name":"Anthony Brebion","@id":"https:\/\/wingify.com\/blog\/#\/schema\/person\/ef0688fa888868d2b6418dd5751e3929"},"headline":"How to Implement Feature Flags in Java","datePublished":"2021-06-13T12:38:12+00:00","mainEntityOfPage":{"@id":"https:\/\/wingify.com\/blog\/java-feature-flags\/"},"wordCount":1816,"image":{"@id":"https:\/\/wingify.com\/blog\/java-feature-flags\/#primaryimage"},"thumbnailUrl":"https:\/\/static.wingify.com\/gcp\/uploads\/sites\/3\/2026\/09\/Release-Management-3.png","keywords":["Rollouts"],"articleSection":["Feature Flags"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/wingify.com\/blog\/java-feature-flags\/","url":"https:\/\/wingify.com\/blog\/java-feature-flags\/","name":"Implement Feature Flags in Java - Wingify Blog","isPartOf":{"@id":"https:\/\/wingify.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/wingify.com\/blog\/java-feature-flags\/#primaryimage"},"image":{"@id":"https:\/\/wingify.com\/blog\/java-feature-flags\/#primaryimage"},"thumbnailUrl":"https:\/\/static.wingify.com\/gcp\/uploads\/sites\/3\/2026\/09\/Release-Management-3.png","datePublished":"2021-06-13T12:38:12+00:00","author":{"@id":"https:\/\/wingify.com\/blog\/#\/schema\/person\/ef0688fa888868d2b6418dd5751e3929"},"description":"Let's see how to implement the feature flag pattern in Java using our Java SDK.","breadcrumb":{"@id":"https:\/\/wingify.com\/blog\/java-feature-flags\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/wingify.com\/blog\/java-feature-flags\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/wingify.com\/blog\/java-feature-flags\/#primaryimage","url":"https:\/\/static.wingify.com\/gcp\/uploads\/sites\/3\/2026\/09\/Release-Management-3.png","contentUrl":"https:\/\/static.wingify.com\/gcp\/uploads\/sites\/3\/2026\/09\/Release-Management-3.png","width":2400,"height":2332,"caption":"Release Management 3"},{"@type":"BreadcrumbList","@id":"https:\/\/wingify.com\/blog\/java-feature-flags\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/wingify.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Feature Flags","item":"https:\/\/wingify.com\/blog\/feature-flags\/"},{"@type":"ListItem","position":3,"name":"How to Implement Feature Flags in Java"}]},{"@type":"WebSite","@id":"https:\/\/wingify.com\/blog\/#website","url":"https:\/\/wingify.com\/blog\/","name":"Wingify Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/wingify.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/wingify.com\/blog\/#\/schema\/person\/ef0688fa888868d2b6418dd5751e3929","name":"Anthony Brebion","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/static.wingify.com\/gcp\/uploads\/sites\/3\/2026\/09\/1779458990830-150x150.jpg","url":"https:\/\/static.wingify.com\/gcp\/uploads\/sites\/3\/2026\/09\/1779458990830-150x150.jpg","contentUrl":"https:\/\/static.wingify.com\/gcp\/uploads\/sites\/3\/2026\/09\/1779458990830-150x150.jpg","caption":"Anthony Brebion"},"description":"Anthony Brebion is a GTM &amp; RevOps Engineer at AB Tasty, with a background in digital marketing, SEO, and website optimization. He combines his marketing and technical expertise to build data-driven systems, automate workflows, and improve digital experiences. His areas of expertise include CRO, e-commerce optimization, marketing automation, and experimentation.","sameAs":["https:\/\/www.linkedin.com\/in\/anthonybrebion\/"],"url":"https:\/\/wingify.com\/blog\/author\/abrebion\/"}]}},"_links":{"self":[{"href":"https:\/\/wingify.com\/blog\/wp-json\/wp\/v2\/posts\/111814","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wingify.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wingify.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wingify.com\/blog\/wp-json\/wp\/v2\/users\/1435"}],"replies":[{"embeddable":true,"href":"https:\/\/wingify.com\/blog\/wp-json\/wp\/v2\/comments?post=111814"}],"version-history":[{"count":0,"href":"https:\/\/wingify.com\/blog\/wp-json\/wp\/v2\/posts\/111814\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wingify.com\/blog\/wp-json\/wp\/v2\/media\/115643"}],"wp:attachment":[{"href":"https:\/\/wingify.com\/blog\/wp-json\/wp\/v2\/media?parent=111814"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wingify.com\/blog\/wp-json\/wp\/v2\/categories?post=111814"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wingify.com\/blog\/wp-json\/wp\/v2\/tags?post=111814"},{"taxonomy":"feature","embeddable":true,"href":"https:\/\/wingify.com\/blog\/wp-json\/wp\/v2\/feature?post=111814"},{"taxonomy":"industry-type","embeddable":true,"href":"https:\/\/wingify.com\/blog\/wp-json\/wp\/v2\/industry-type?post=111814"},{"taxonomy":"product","embeddable":true,"href":"https:\/\/wingify.com\/blog\/wp-json\/wp\/v2\/product?post=111814"},{"taxonomy":"role","embeddable":true,"href":"https:\/\/wingify.com\/blog\/wp-json\/wp\/v2\/role?post=111814"},{"taxonomy":"region","embeddable":true,"href":"https:\/\/wingify.com\/blog\/wp-json\/wp\/v2\/region?post=111814"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}
