Repository: Unleash/unleash-client-java
Pull request #201 (2023-06-14 11:05:34)

feat: expose impression data property
This exposes the impression data property on the FeatureToggle class through a getter - `hasImpressionData()` this will default to false if not present

sighphyre: Hmm, okay, my built in formatter has made changes. Applying the maven task doesn't make changes here, happy to undo the changes by hand if folks object

Patch:
diff --git a/src/main/java/io/getunleash/FakeUnleash.java b/src/main/java/io/getunleash/FakeUnleash.java
index 477d4087..5eabb9e1 100644
--- a/src/main/java/io/getunleash/FakeUnleash.java
+++ b/src/main/java/io/getunleash/FakeUnleash.java
@@ -3,7 +3,6 @@ package io.getunleash;
 import static java.util.Collections.emptyList;
 
 import io.getunleash.lang.Nullable;
-
 import java.util.*;
 import java.util.function.BiPredicate;
 import java.util.stream.Collectors;
@@ -23,22 +22,22 @@ public class FakeUnleash implements Unleash {
             return excludedFeatures.getOrDefault(toggleName, false);
         } else {
             return more().getFeatureToggleDefinition(toggleName)
-                .map(FeatureToggle::isEnabled)
-                .orElse(defaultSetting);
+                    .map(FeatureToggle::isEnabled)
+                    .orElse(defaultSetting);
         }
     }
 
     @Override
     public boolean isEnabled(
-        String toggleName,
-        UnleashContext context,
-        BiPredicate<String, UnleashContext> fallbackAction) {
+            String toggleName,
+            UnleashContext context,
+            BiPredicate<String, UnleashContext> fallbackAction) {
         return isEnabled(toggleName, fallbackAction);
     }
 
     @Override
     public boolean isEnabled(
-        String toggleName, BiPredicate<String, UnleashContext> fallbackAction) {
+            String toggleName, BiPredicate<String, UnleashContext> fallbackAction) {
         if (!features.containsKey(toggleName)) {
             return fallbackAction.test(toggleName, UnleashContext.builder().build());
         }
diff --git a/src/main/java/io/getunleash/FeatureToggle.java b/src/main/java/io/getunleash/FeatureToggle.java
index a76081c4..44c5ced7 100644
--- a/src/main/java/io/getunleash/FeatureToggle.java
+++ b/src/main/java/io/getunleash/FeatureToggle.java
@@ -12,20 +12,31 @@ public final class FeatureToggle {
     private final boolean enabled;
     private final List<ActivationStrategy> strategies;
     @Nullable private final List<VariantDefinition> variants;
+    private final boolean impressionData;
 
     public FeatureToggle(String name, boolean enabled, List<ActivationStrategy> strategies) {
-        this(name, enabled, strategies, emptyList());
+        this(name, enabled, strategies, emptyList(), false);
     }
 
     public FeatureToggle(
             String name,
             boolean enabled,
             List<ActivationStrategy> strategies,
-            @Nullable List<VariantDefinition> variants) {
+            List<VariantDefinition> variants) {
+        this(name, enabled, strategies, variants, false);
+    }
+
+    public FeatureToggle(
+            String name,
+            boolean enabled,
+            List<ActivationStrategy> strategies,
+            @Nullable List<VariantDefinition> variants,
+            @Nullable Boolean impressionData) {
         this.name = name;
         this.enabled = enabled;
         this.strategies = strategies;
         this.variants = variants;
+        this.impressionData = impressionData != null ? impressionData : false;
     }
 
     public String getName() {
@@ -48,6 +59,11 @@ public final class FeatureToggle {
         }
     }
 
+    @Nullable
+    public boolean hasImpressionData() {
+        return impressionData;
+    }
+
     @Override
     public String toString() {
         return "FeatureToggle{"
@@ -61,6 +77,8 @@ public final class FeatureToggle {
                 + '\''
                 + ", variants='"
                 + variants
+                + ", impressionData="
+                + impressionData
                 + '\''
                 + '}';
     }


Test patch:
diff --git a/src/test/java/io/getunleash/DefaultUnleashTest.java b/src/test/java/io/getunleash/DefaultUnleashTest.java
index 3faddf89..0f6b8e19 100644
--- a/src/test/java/io/getunleash/DefaultUnleashTest.java
+++ b/src/test/java/io/getunleash/DefaultUnleashTest.java
@@ -9,23 +9,17 @@ import ch.qos.logback.classic.Logger;
 import ch.qos.logback.classic.spi.ILoggingEvent;
 import ch.qos.logback.core.read.ListAppender;
 import io.getunleash.event.EventDispatcher;
-import io.getunleash.metric.MetricSender;
 import io.getunleash.metric.UnleashMetricService;
 import io.getunleash.repository.*;
 import io.getunleash.strategy.DefaultStrategy;
 import io.getunleash.strategy.Strategy;
-import io.getunleash.util.MetricSenderFactory;
 import io.getunleash.util.UnleashConfig;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-
-import io.getunleash.util.UnleashFeatureFetcherFactory;
-import io.getunleash.util.UnleashScheduledExecutor;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
-import org.mockito.ArgumentCaptor;
 import org.slf4j.LoggerFactory;
 
 class DefaultUnleashTest {
@@ -220,35 +214,36 @@ class DefaultUnleashTest {
     @Test
     public void synchronous_fetch_on_initialisation_fails_on_initialization() {
         UnleashConfig config =
-            UnleashConfig.builder()
-                .unleashAPI("http://wrong:4242")
-                .appName("wrong_upstream")
-                .apiKey("default:development:1234567890123456")
-                .instanceId("multiple_connection_exception")
-                .synchronousFetchOnInitialisation(true)
-                .build();
+                UnleashConfig.builder()
+                        .unleashAPI("http://wrong:4242")
+                        .appName("wrong_upstream")
+                        .apiKey("default:development:1234567890123456")
+                        .instanceId("multiple_connection_exception")
+                        .synchronousFetchOnInitialisation(true)
+                        .build();
 
         assertThatThrownBy(() -> new DefaultUnleash(config)).isInstanceOf(UnleashException.class);
     }
 
     @Test
-    public void asynchronous_fetch_on_initialisation_fails_silently_and_retries() throws InterruptedException {
+    public void asynchronous_fetch_on_initialisation_fails_silently_and_retries()
+            throws InterruptedException {
         FeatureFetcher fetcher = mock(FeatureFetcher.class);
         FeatureCollection expectedResponse = new FeatureCollection();
         FeatureToggleResponse.Status expectedStatus = FeatureToggleResponse.Status.CHANGED;
         when(fetcher.fetchFeatures())
-            .thenThrow(UnleashException.class)
-            .thenReturn(new ClientFeaturesResponse(expectedStatus, expectedResponse));
+                .thenThrow(UnleashException.class)
+                .thenReturn(new ClientFeaturesResponse(expectedStatus, expectedResponse));
 
         UnleashConfig config =
-            UnleashConfig.builder()
-                .unleashAPI("http://wrong:4242")
-                .appName("wrong_upstream")
-                .apiKey("default:development:1234567890123456")
-                .instanceId("multiple_connection_exception")
-                .fetchTogglesInterval(1)
-                .unleashFeatureFetcherFactory((UnleashConfig c) -> fetcher)
-                .build();
+                UnleashConfig.builder()
+                        .unleashAPI("http://wrong:4242")
+                        .appName("wrong_upstream")
+                        .apiKey("default:development:1234567890123456")
+                        .instanceId("multiple_connection_exception")
+                        .fetchTogglesInterval(1)
+                        .unleashFeatureFetcherFactory((UnleashConfig c) -> fetcher)
+                        .build();
 
         Unleash unleash = new DefaultUnleash(config);
         verify(fetcher, times(1)).fetchFeatures();
diff --git a/src/test/java/io/getunleash/repository/FeatureToggleRepositoryTest.java b/src/test/java/io/getunleash/repository/FeatureToggleRepositoryTest.java
index 318e3fe4..976ce177 100644
--- a/src/test/java/io/getunleash/repository/FeatureToggleRepositoryTest.java
+++ b/src/test/java/io/getunleash/repository/FeatureToggleRepositoryTest.java
@@ -173,9 +173,12 @@ public class FeatureToggleRepositoryTest {
         // setup fetcher
         when(toggleFetcher.fetchToggles()).thenThrow(RuntimeException.class);
 
-        assertThatThrownBy(() -> {
-            new FeatureToggleRepository(config, executor, toggleFetcher, toggleBackupHandler);
-        }).isInstanceOf(RuntimeException.class);
+        assertThatThrownBy(
+                        () -> {
+                            new FeatureToggleRepository(
+                                    config, executor, toggleFetcher, toggleBackupHandler);
+                        })
+                .isInstanceOf(RuntimeException.class);
     }
 
     @Test
diff --git a/src/test/java/io/getunleash/repository/JsonFeatureToggleParserTest.java b/src/test/java/io/getunleash/repository/JsonFeatureToggleParserTest.java
index e85b2361..378efd08 100644
--- a/src/test/java/io/getunleash/repository/JsonFeatureToggleParserTest.java
+++ b/src/test/java/io/getunleash/repository/JsonFeatureToggleParserTest.java
@@ -117,6 +117,21 @@ public class JsonFeatureToggleParserTest {
                 .isNull();
     }
 
+    @Test
+    public void should_deserialize_impression_data() throws IOException {
+        Reader content = getFileReader("/unleash-repo-v2-with-impression-data.json");
+        FeatureCollection featureCollection = JsonFeatureParser.fromJson(content);
+        ToggleCollection toggleCollection = featureCollection.getToggleCollection();
+
+        assertThat(toggleCollection.getFeatures()).hasSize(3);
+        assertThat(toggleCollection.getToggle("Test.impressionDataPresent").hasImpressionData())
+                .isTrue();
+        assertThat(toggleCollection.getToggle("Test.impressionDataSetToOff").hasImpressionData())
+                .isFalse();
+        assertThat(toggleCollection.getToggle("Test.impressionDataMissing").hasImpressionData())
+                .isFalse();
+    }
+
     private Reader getFileReader(String filename) throws IOException {
         InputStream in = this.getClass().getResourceAsStream(filename);
         InputStreamReader reader = new InputStreamReader(in);
diff --git a/src/test/resources/unleash-repo-v2-with-impression-data.json b/src/test/resources/unleash-repo-v2-with-impression-data.json
new file mode 100644
index 00000000..29776069
--- /dev/null
+++ b/src/test/resources/unleash-repo-v2-with-impression-data.json
@@ -0,0 +1,43 @@
+{
+    "version": 2,
+    "features": [
+        {
+            "name": "Test.impressionDataPresent",
+            "description": "It's true, we do have impression data",
+            "enabled": true,
+            "strategies": [
+                {
+                    "name": "default"
+                }
+            ],
+            "impressionData": true,
+            "variants": null,
+            "createdAt": "2019-01-24T10:38:10.370Z"
+        },
+        {
+            "name": "Test.impressionDataSetToOff",
+            "description": "Explicitly no impression data",
+            "enabled": true,
+            "strategies": [
+                {
+                    "name": "default"
+                }
+            ],
+            "impressionData": false,
+            "variants": null,
+            "createdAt": "2019-01-24T10:38:10.370Z"
+        },
+        {
+            "name": "Test.impressionDataMissing",
+            "description": "No field defined",
+            "enabled": true,
+            "strategies": [
+                {
+                    "name": "default"
+                }
+            ],
+            "variants": null,
+            "createdAt": "2019-01-24T10:38:10.370Z"
+        }
+    ]
+}