diff --git a/providers/flipt/README.md b/providers/flipt/README.md
index 482df09af..1e95c5e99 100644
--- a/providers/flipt/README.md
+++ b/providers/flipt/README.md
@@ -19,7 +19,8 @@
## Concepts
* Boolean evaluation gets feature boolean evaluation / enabled status.
-* Non-boolean evaluation gets feature variant key.
+* Object evaluation gets variant attachment.
+* Other evaluations gets feature variant key.
## Usage
diff --git a/providers/flipt/pom.xml b/providers/flipt/pom.xml
index 6960ddc5c..29bb603a9 100644
--- a/providers/flipt/pom.xml
+++ b/providers/flipt/pom.xml
@@ -20,6 +20,15 @@
false
+
+
+ markphelps
+ Mark Phelps
+ Flipt Software
+ https://flipt.io/
+
+
+
io.flipt
@@ -33,6 +42,12 @@
2.0.16
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ 2.17.2
+
+
com.github.tomakehurst
wiremock-jre8
diff --git a/providers/flipt/src/main/java/dev/openfeature/contrib/providers/flipt/FliptProvider.java b/providers/flipt/src/main/java/dev/openfeature/contrib/providers/flipt/FliptProvider.java
index 5977f9689..98ff216ad 100644
--- a/providers/flipt/src/main/java/dev/openfeature/contrib/providers/flipt/FliptProvider.java
+++ b/providers/flipt/src/main/java/dev/openfeature/contrib/providers/flipt/FliptProvider.java
@@ -40,7 +40,11 @@ public class FliptProvider extends EventProvider {
@Getter
private FliptClient fliptClient;
- private AtomicBoolean isInitialized = new AtomicBoolean(false);
+ @Setter(AccessLevel.PROTECTED)
+ @Getter
+ private ProviderState state = ProviderState.NOT_READY;
+
+ private final AtomicBoolean isInitialized = new AtomicBoolean(false);
/**
* Constructor.
@@ -96,7 +100,8 @@ public ProviderEvaluation getBooleanEvaluation(String key, Boolean defa
@Override
public ProviderEvaluation getStringEvaluation(String key, String defaultValue, EvaluationContext ctx) {
- ProviderEvaluation valueProviderEvaluation = getObjectEvaluation(key, new Value(defaultValue), ctx);
+ ProviderEvaluation valueProviderEvaluation =
+ evaluateVariant(String.class, key, new Value(defaultValue), ctx);
return ProviderEvaluation.builder()
.value(valueProviderEvaluation.getValue().asString())
.variant(valueProviderEvaluation.getVariant())
@@ -108,7 +113,8 @@ public ProviderEvaluation getStringEvaluation(String key, String default
@Override
public ProviderEvaluation getIntegerEvaluation(String key, Integer defaultValue, EvaluationContext ctx) {
- ProviderEvaluation valueProviderEvaluation = getObjectEvaluation(key, new Value(defaultValue), ctx);
+ ProviderEvaluation valueProviderEvaluation =
+ evaluateVariant(Integer.class, key, new Value(defaultValue), ctx);
Integer value = getIntegerValue(valueProviderEvaluation, defaultValue);
return ProviderEvaluation.builder()
.value(value)
@@ -130,7 +136,8 @@ private static Integer getIntegerValue(ProviderEvaluation valueProviderEv
@Override
public ProviderEvaluation getDoubleEvaluation(String key, Double defaultValue, EvaluationContext ctx) {
- ProviderEvaluation valueProviderEvaluation = getObjectEvaluation(key, new Value(defaultValue), ctx);
+ ProviderEvaluation valueProviderEvaluation =
+ evaluateVariant(Double.class, key, new Value(defaultValue), ctx);
Double value = getDoubleValue(valueProviderEvaluation, defaultValue);
return ProviderEvaluation.builder()
.value(value)
@@ -152,6 +159,18 @@ private static Double getDoubleValue(ProviderEvaluation valueProviderEval
@Override
public ProviderEvaluation getObjectEvaluation(String key, Value defaultValue, EvaluationContext ctx) {
+ return evaluateVariant(Value.class, key, defaultValue, ctx);
+ }
+
+ private ProviderEvaluation evaluateVariant(Class clazz, String key, Value defaultValue,
+ EvaluationContext ctx) {
+ if (!ProviderState.READY.equals(state)) {
+ if (ProviderState.NOT_READY.equals(state)) {
+ throw new ProviderNotReadyError(PROVIDER_NOT_YET_INITIALIZED);
+ }
+ throw new GeneralError(UNKNOWN_ERROR);
+ }
+
Map contextMap = ContextTransformer.transform(ctx);
EvaluationRequest request = EvaluationRequest.builder().namespaceKey(fliptProviderConfig.getNamespace())
.flagKey(key).entityId(ctx.getTargetingKey()).context(contextMap).build();
@@ -172,17 +191,22 @@ public ProviderEvaluation getObjectEvaluation(String key, Value defaultVa
.build();
}
+ Value value = new Value(response.getVariantKey());
ImmutableMetadata.ImmutableMetadataBuilder flagMetadataBuilder = ImmutableMetadata.builder();
- if (response.getVariantAttachment() != null) {
+ if (response.getVariantAttachment() != null && !response.getVariantAttachment().isEmpty()) {
flagMetadataBuilder.addString("variant-attachment", response.getVariantAttachment());
+
+ if (clazz.isAssignableFrom(Value.class)) {
+ value = new Value(response.getVariantAttachment());
+ }
}
return ProviderEvaluation.builder()
- .value(new Value(response.getVariantKey()))
- .variant(response.getVariantKey())
- .reason(TARGETING_MATCH.name())
- .flagMetadata(flagMetadataBuilder.build())
- .build();
+ .value(value)
+ .variant(response.getVariantKey())
+ .reason(TARGETING_MATCH.name())
+ .flagMetadata(flagMetadataBuilder.build())
+ .build();
}
@Override
diff --git a/providers/flipt/src/test/java/dev/openfeature/contrib/providers/flipt/FliptProviderTest.java b/providers/flipt/src/test/java/dev/openfeature/contrib/providers/flipt/FliptProviderTest.java
index 6cd62eabc..fb3c3da53 100644
--- a/providers/flipt/src/test/java/dev/openfeature/contrib/providers/flipt/FliptProviderTest.java
+++ b/providers/flipt/src/test/java/dev/openfeature/contrib/providers/flipt/FliptProviderTest.java
@@ -14,6 +14,7 @@
import dev.openfeature.sdk.ProviderEvaluation;
import dev.openfeature.sdk.ProviderEventDetails;
import dev.openfeature.sdk.ProviderState;
+import dev.openfeature.sdk.Value;
import dev.openfeature.sdk.exceptions.GeneralError;
import dev.openfeature.sdk.exceptions.ProviderNotReadyError;
import lombok.SneakyThrows;
@@ -31,8 +32,7 @@
import static com.github.tomakehurst.wiremock.client.WireMock.post;
import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.*;
/**
* FliptProvider test, based on APIs mocking.
@@ -50,9 +50,10 @@ class FliptProviderTest {
public static final Double DOUBLE_FLAG_VALUE = 1.23;
public static final String USERS_FLAG_NAME = "users-flag";
public static final String TARGETING_KEY = "targeting_key";
+ public static final String OBJECT_FLAG_NAME = "object-flag";
+
private static FliptProvider fliptProvider;
private static Client client;
-
private String apiUrl;
@BeforeAll
@@ -101,7 +102,6 @@ void getBooleanEvaluation() {
mockFliptAPI("/evaluate/v1/boolean", "boolean.json", FLAG_NAME);
MutableContext evaluationContext = new MutableContext();
evaluationContext.setTargetingKey(TARGETING_KEY);
- assertEquals(true, fliptProvider.getBooleanEvaluation(FLAG_NAME, false, evaluationContext).getValue());
assertEquals(true, client.getBooleanValue(FLAG_NAME, false, evaluationContext));
assertEquals(false, client.getBooleanValue("non-existing", false, evaluationContext));
}
@@ -171,6 +171,24 @@ void getEvaluationMetadataTest() {
assertEquals("attachment-1", flagMetadata.getString("variant-attachment"));
FlagEvaluationDetails nonExistingFlagEvaluation = client.getStringDetails("non-existing", "",
evaluationContext);
- assertEquals(null, nonExistingFlagEvaluation.getFlagMetadata().getBoolean("variant-attachment"));
+ assertNull(nonExistingFlagEvaluation.getFlagMetadata().getBoolean("variant-attachment"));
+ }
+
+ @SneakyThrows
+ @Test
+ void getObjectEvaluationTest() {
+ mockFliptAPI("/evaluate/v1/variant", "variant-object.json", OBJECT_FLAG_NAME);
+ MutableContext evaluationContext = new MutableContext();
+ evaluationContext.setTargetingKey(TARGETING_KEY);
+ evaluationContext.add("userId", "object");
+
+ Value expectedValue = new Value("{\"key1\":\"value1\",\"key2\":42,\"key3\":true}");
+ Value emptyValue = new Value();
+
+ assertEquals(expectedValue, client.getObjectValue(OBJECT_FLAG_NAME, emptyValue, evaluationContext));
+ assertEquals(emptyValue, client.getObjectValue("non-existing", emptyValue, evaluationContext));
+
+ // non-object flag value
+ assertEquals(emptyValue, client.getObjectValue(VARIANT_FLAG_NAME, emptyValue, evaluationContext));
}
}
\ No newline at end of file
diff --git a/providers/flipt/src/test/resources/variant-object.json b/providers/flipt/src/test/resources/variant-object.json
new file mode 100644
index 000000000..abf764532
--- /dev/null
+++ b/providers/flipt/src/test/resources/variant-object.json
@@ -0,0 +1,6 @@
+{
+ "flagKey": "object-flag",
+ "match": true,
+ "variantKey": "object-variant",
+ "variantAttachment": "{\"key1\":\"value1\",\"key2\":42,\"key3\":true}"
+}
\ No newline at end of file