diff --git a/providers/flipt/README.md b/providers/flipt/README.md
index 34a0ae50b..107a9abed 100644
--- a/providers/flipt/README.md
+++ b/providers/flipt/README.md
@@ -7,26 +7,34 @@
```xml
-
dev.openfeature.contrib.providers
flipt
- 0.0.2
+ 0.1.0
```
## Concepts
+
* Boolean evaluation gets feature boolean evaluation / enabled status.
* Non-boolean evaluation gets feature variant key.
## Usage
-Flipt OpenFeature Provider is using Flipt Java SDK.
+
+Flipt OpenFeature Provider uses Flipt's [Server Java SDK](https://github.com/flipt-io/flipt-server-sdks/tree/main/flipt-java).
### Usage Example
-```
+```java
+// create a Flipt client and provider
+FliptClientBuilder fliptClientBuilder = FliptClient.builder().url(apiUrl);
+FliptProviderConfig fliptProviderConfig = FliptProviderConfig.builder()
+ .fliptClientBuilder(fliptClientBuilder)
+ .build();
+
+// create OpenFeature provider
FeatureProvider featureProvider = new FliptProvider(fliptProviderConfig);
OpenFeatureAPI.getInstance().setProviderAndWait("sync", fliptProvider);
client = OpenFeatureAPI.getInstance().getClient("sync");
diff --git a/providers/flipt/pom.xml b/providers/flipt/pom.xml
index e05ef34f9..32f90396f 100644
--- a/providers/flipt/pom.xml
+++ b/providers/flipt/pom.xml
@@ -10,7 +10,7 @@
dev.openfeature.contrib.providers
flipt
- 0.0.2
+ 0.1.0
flipt
Flipt provider for Java
@@ -24,7 +24,7 @@
io.flipt
flipt-java
- 0.2.15
+ 1.0.1
@@ -40,12 +40,32 @@
test
+
+ com.fasterxml.jackson.core
+ jackson-core
+ 2.16.1
+ test
+
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ 2.16.1
+ test
+
+
+
+ com.fasterxml.jackson.core
+ jackson-annotations
+ 2.16.1
+ test
+
+
org.apache.logging.log4j
log4j-slf4j2-impl
2.22.1
test
-
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 bb01ba135..5d69576a6 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
@@ -1,9 +1,5 @@
package dev.openfeature.contrib.providers.flipt;
-import com.flipt.api.FliptApiClient;
-import com.flipt.api.resources.evaluation.types.BooleanEvaluationResponse;
-import com.flipt.api.resources.evaluation.types.EvaluationRequest;
-import com.flipt.api.resources.evaluation.types.VariantEvaluationResponse;
import dev.openfeature.sdk.EvaluationContext;
import dev.openfeature.sdk.EventProvider;
import dev.openfeature.sdk.ImmutableMetadata;
@@ -14,6 +10,10 @@
import dev.openfeature.sdk.Value;
import dev.openfeature.sdk.exceptions.GeneralError;
import dev.openfeature.sdk.exceptions.ProviderNotReadyError;
+import io.flipt.api.FliptClient;
+import io.flipt.api.evaluation.models.BooleanEvaluationResponse;
+import io.flipt.api.evaluation.models.EvaluationRequest;
+import io.flipt.api.evaluation.models.VariantEvaluationResponse;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
@@ -41,7 +41,7 @@ public class FliptProvider extends EventProvider {
@Setter(AccessLevel.PROTECTED)
@Getter
- private FliptApiClient fliptApiClient;
+ private FliptClient fliptClient;
@Setter(AccessLevel.PROTECTED)
@Getter
@@ -51,6 +51,7 @@ public class FliptProvider extends EventProvider {
/**
* Constructor.
+ *
* @param fliptProviderConfig FliptProviderConfig
*/
public FliptProvider(FliptProviderConfig fliptProviderConfig) {
@@ -59,6 +60,7 @@ public FliptProvider(FliptProviderConfig fliptProviderConfig) {
/**
* Initialize the provider.
+ *
* @param evaluationContext evaluation context
* @throws Exception on error
*/
@@ -69,7 +71,7 @@ public void initialize(EvaluationContext evaluationContext) throws Exception {
throw new GeneralError("already initialized");
}
super.initialize(evaluationContext);
- fliptApiClient = fliptProviderConfig.getFliptApiClientBuilder().build();
+ fliptClient = fliptProviderConfig.getFliptClientBuilder().build();
state = ProviderState.READY;
log.info("finished initializing provider, state: {}", state);
@@ -103,32 +105,32 @@ public ProviderEvaluation getBooleanEvaluation(String key, Boolean defa
Map contextMap = ContextTransformer.transform(ctx);
EvaluationRequest request = EvaluationRequest.builder().namespaceKey(fliptProviderConfig.getNamespace())
- .flagKey(key).entityId(ctx.getTargetingKey()).context(contextMap).build();
+ .flagKey(key).entityId(ctx.getTargetingKey()).context(contextMap).build();
BooleanEvaluationResponse response = null;
try {
- response = fliptApiClient.evaluation().boolean_(request);
+ response = fliptClient.evaluation().evaluateBoolean(request);
} catch (Exception e) {
log.error("Error evaluating boolean", e);
throw new GeneralError(e.getMessage());
}
return ProviderEvaluation.builder()
- .value(response.getEnabled())
- .reason(response.getReason().toString())
- .build();
+ .value(response.isEnabled())
+ .reason(response.getReason().toString())
+ .build();
}
@Override
public ProviderEvaluation getStringEvaluation(String key, String defaultValue, EvaluationContext ctx) {
ProviderEvaluation valueProviderEvaluation = getObjectEvaluation(key, new Value(defaultValue), ctx);
return ProviderEvaluation.builder()
- .value(valueProviderEvaluation.getValue().asString())
- .variant(valueProviderEvaluation.getVariant())
+ .value(valueProviderEvaluation.getValue().asString())
+ .variant(valueProviderEvaluation.getVariant())
.errorCode(valueProviderEvaluation.getErrorCode())
.reason(valueProviderEvaluation.getReason())
.flagMetadata(valueProviderEvaluation.getFlagMetadata())
- .build();
+ .build();
}
@Override
@@ -136,12 +138,12 @@ public ProviderEvaluation getIntegerEvaluation(String key, Integer defa
ProviderEvaluation valueProviderEvaluation = getObjectEvaluation(key, new Value(defaultValue), ctx);
Integer value = getIntegerValue(valueProviderEvaluation, defaultValue);
return ProviderEvaluation.builder()
- .value(value)
- .variant(valueProviderEvaluation.getVariant())
- .errorCode(valueProviderEvaluation.getErrorCode())
- .reason(valueProviderEvaluation.getReason())
- .flagMetadata(valueProviderEvaluation.getFlagMetadata())
- .build();
+ .value(value)
+ .variant(valueProviderEvaluation.getVariant())
+ .errorCode(valueProviderEvaluation.getErrorCode())
+ .reason(valueProviderEvaluation.getReason())
+ .flagMetadata(valueProviderEvaluation.getFlagMetadata())
+ .build();
}
private static Integer getIntegerValue(ProviderEvaluation valueProviderEvaluation, Integer defaultValue) {
@@ -158,12 +160,12 @@ public ProviderEvaluation getDoubleEvaluation(String key, Double default
ProviderEvaluation valueProviderEvaluation = getObjectEvaluation(key, new Value(defaultValue), ctx);
Double value = getDoubleValue(valueProviderEvaluation, defaultValue);
return ProviderEvaluation.builder()
- .value(value)
- .variant(valueProviderEvaluation.getVariant())
- .errorCode(valueProviderEvaluation.getErrorCode())
- .reason(valueProviderEvaluation.getReason())
- .flagMetadata(valueProviderEvaluation.getFlagMetadata())
- .build();
+ .value(value)
+ .variant(valueProviderEvaluation.getVariant())
+ .errorCode(valueProviderEvaluation.getErrorCode())
+ .reason(valueProviderEvaluation.getReason())
+ .flagMetadata(valueProviderEvaluation.getFlagMetadata())
+ .build();
}
private static Double getDoubleValue(ProviderEvaluation valueProviderEvaluation, Double defaultValue) {
@@ -185,22 +187,22 @@ public ProviderEvaluation getObjectEvaluation(String key, Value defaultVa
}
Map contextMap = ContextTransformer.transform(ctx);
EvaluationRequest request = EvaluationRequest.builder().namespaceKey(fliptProviderConfig.getNamespace())
- .flagKey(key).entityId(ctx.getTargetingKey()).context(contextMap).build();
+ .flagKey(key).entityId(ctx.getTargetingKey()).context(contextMap).build();
VariantEvaluationResponse response;
try {
- response = fliptApiClient.evaluation().variant(request);
+ response = fliptClient.evaluation().evaluateVariant(request);
} catch (Exception e) {
log.error("Error evaluating variant", e);
throw new GeneralError(e.getMessage());
}
- if (!response.getMatch()) {
+ if (!response.isMatch()) {
log.debug("non matching variant for {} : {}", key, response.getReason());
return ProviderEvaluation.builder()
- .value(defaultValue)
- .reason(DEFAULT.name())
- .build();
+ .value(defaultValue)
+ .reason(DEFAULT.name())
+ .build();
}
ImmutableMetadata.ImmutableMetadataBuilder flagMetadataBuilder = ImmutableMetadata.builder();
@@ -209,11 +211,11 @@ public ProviderEvaluation getObjectEvaluation(String key, Value defaultVa
}
return ProviderEvaluation.builder()
- .value(new Value(response.getVariantKey()))
- .variant(response.getVariantKey())
- .reason(TARGETING_MATCH.name())
- .flagMetadata(flagMetadataBuilder.build())
- .build();
+ .value(new Value(response.getVariantKey()))
+ .variant(response.getVariantKey())
+ .reason(TARGETING_MATCH.name())
+ .flagMetadata(flagMetadataBuilder.build())
+ .build();
}
@Override
diff --git a/providers/flipt/src/main/java/dev/openfeature/contrib/providers/flipt/FliptProviderConfig.java b/providers/flipt/src/main/java/dev/openfeature/contrib/providers/flipt/FliptProviderConfig.java
index 4efff5470..9d26bb3d7 100644
--- a/providers/flipt/src/main/java/dev/openfeature/contrib/providers/flipt/FliptProviderConfig.java
+++ b/providers/flipt/src/main/java/dev/openfeature/contrib/providers/flipt/FliptProviderConfig.java
@@ -1,17 +1,16 @@
package dev.openfeature.contrib.providers.flipt;
-import com.flipt.api.FliptApiClientBuilder;
+import io.flipt.api.FliptClient.FliptClientBuilder;
import lombok.Builder;
import lombok.Getter;
-
/**
* FliptProvider config.
*/
@Getter
@Builder
public class FliptProviderConfig {
- private FliptApiClientBuilder fliptApiClientBuilder;
+ private FliptClientBuilder fliptClientBuilder;
@Builder.Default
private String namespace = "default";
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 8bfa97395..3378f840f 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
@@ -1,8 +1,7 @@
package dev.openfeature.contrib.providers.flipt;
-import com.flipt.api.FliptApiClient;
-import com.flipt.api.FliptApiClientBuilder;
-import com.flipt.api.core.Environment;
+import io.flipt.api.FliptClient;
+import io.flipt.api.FliptClient.FliptClientBuilder;
import com.github.tomakehurst.wiremock.client.WireMock;
import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo;
import com.github.tomakehurst.wiremock.junit5.WireMockTest;
@@ -58,7 +57,7 @@ class FliptProviderTest {
@BeforeAll
void setUp(WireMockRuntimeInfo wmRuntimeInfo) {
- apiUrl = "http://localhost:" + wmRuntimeInfo.getHttpPort() + "/";
+ apiUrl = "http://localhost:" + wmRuntimeInfo.getHttpPort();
fliptProvider = buildFliptProvider();
OpenFeatureAPI.getInstance().setProviderAndWait("sync", fliptProvider);
client = OpenFeatureAPI.getInstance().getClient("sync");
@@ -71,22 +70,23 @@ public void shutdown() {
private void mockFliptAPI(String url, String resourceName, String flagKey) {
stubFor(
- post(urlEqualTo(url))
- .withHeader("Content-Type", equalTo("application/json"))
- .withRequestBody(WireMock.containing(flagKey))
- .willReturn(
- aResponse()
- .withStatus(200)
- .withHeader("Content-Type", "application/json")
- .withBody(readResourceFileContent(resourceName))));
+ post(urlEqualTo(url))
+ .withHeader("Content-Type", equalTo("application/json; charset=UTF-8"))
+ .withRequestBody(WireMock.containing(flagKey))
+ .willReturn(
+ aResponse()
+ .withStatus(200)
+ .withHeader("Content-Type", "application/json; charset=UTF-8")
+ .withBody(readResourceFileContent(resourceName))));
}
@SneakyThrows
private FliptProvider buildFliptProvider() {
- FliptApiClientBuilder fliptApiClientBuilder = FliptApiClient.builder().url(apiUrl).environment(Environment.custom(apiUrl));
+ FliptClientBuilder fliptClientBuilder = FliptClient.builder().url(apiUrl);
FliptProviderConfig fliptProviderConfig = FliptProviderConfig.builder()
- .fliptApiClientBuilder(fliptApiClientBuilder)
- .build();
+ .fliptClientBuilder(fliptClientBuilder)
+ .namespace("default")
+ .build();
return new FliptProvider(fliptProviderConfig);
}
@@ -112,7 +112,7 @@ void getStringVariantEvaluation() {
MutableContext evaluationContext = new MutableContext();
evaluationContext.setTargetingKey(TARGETING_KEY);
assertEquals(VARIANT_FLAG_VALUE, fliptProvider.getStringEvaluation(VARIANT_FLAG_NAME, "",
- evaluationContext).getValue());
+ evaluationContext).getValue());
assertEquals(VARIANT_FLAG_VALUE, client.getStringValue(VARIANT_FLAG_NAME, "", evaluationContext));
assertEquals("fallback_str", client.getStringValue("non-existing", "fallback_str", evaluationContext));
}
@@ -124,7 +124,7 @@ void getIntegerEvaluation() {
evaluationContext.setTargetingKey(TARGETING_KEY);
evaluationContext.add("userId", "int");
assertEquals(INT_FLAG_VALUE, fliptProvider.getIntegerEvaluation(INT_FLAG_NAME, 1,
- evaluationContext).getValue());
+ evaluationContext).getValue());
assertEquals(INT_FLAG_VALUE, client.getIntegerValue(INT_FLAG_NAME, 1, evaluationContext));
assertEquals(1, client.getIntegerValue("non-existing", 1, evaluationContext));
@@ -139,7 +139,7 @@ void getDoubleEvaluation() {
evaluationContext.setTargetingKey(TARGETING_KEY);
evaluationContext.add("userId", "double");
assertEquals(DOUBLE_FLAG_VALUE, fliptProvider.getDoubleEvaluation(DOUBLE_FLAG_NAME, 1.1,
- evaluationContext).getValue());
+ evaluationContext).getValue());
assertEquals(DOUBLE_FLAG_VALUE, client.getDoubleValue(DOUBLE_FLAG_NAME, 1.1, evaluationContext));
assertEquals(1.1, client.getDoubleValue("non-existing", 1.1, evaluationContext));
@@ -153,7 +153,8 @@ void getStringEvaluationByUser() {
MutableContext evaluationContext = new MutableContext();
evaluationContext.setTargetingKey(TARGETING_KEY);
evaluationContext.add("userId", "111");
- assertEquals(VARIANT_FLAG_VALUE, fliptProvider.getStringEvaluation(USERS_FLAG_NAME, "", evaluationContext).getValue());
+ assertEquals(VARIANT_FLAG_VALUE,
+ fliptProvider.getStringEvaluation(USERS_FLAG_NAME, "", evaluationContext).getValue());
assertEquals(VARIANT_FLAG_VALUE, client.getStringValue(USERS_FLAG_NAME, "", evaluationContext));
evaluationContext.add("userId", "2");
assertEquals("", client.getStringValue(USERS_FLAG_NAME, "", evaluationContext));
@@ -165,10 +166,11 @@ void getEvaluationMetadataTest() {
MutableContext evaluationContext = new MutableContext();
evaluationContext.setTargetingKey(TARGETING_KEY);
ProviderEvaluation stringEvaluation = fliptProvider.getStringEvaluation(VARIANT_FLAG_NAME, "",
- evaluationContext);
+ evaluationContext);
ImmutableMetadata flagMetadata = stringEvaluation.getFlagMetadata();
assertEquals("attachment-1", flagMetadata.getString("variant-attachment"));
- FlagEvaluationDetails nonExistingFlagEvaluation = client.getStringDetails("non-existing", "", evaluationContext);
+ FlagEvaluationDetails nonExistingFlagEvaluation = client.getStringDetails("non-existing", "",
+ evaluationContext);
assertEquals(null, nonExistingFlagEvaluation.getFlagMetadata().getBoolean("variant-attachment"));
}
@@ -179,11 +181,13 @@ void shouldThrowIfNotInitialized() {
assertEquals(ProviderState.NOT_READY, asyncInitfliptProvider.getState());
// ErrorCode.PROVIDER_NOT_READY should be returned when evaluated via the client
- assertThrows(ProviderNotReadyError.class, ()-> asyncInitfliptProvider.getBooleanEvaluation("fail_not_initialized", false, new ImmutableContext()));
- assertThrows(ProviderNotReadyError.class, ()-> asyncInitfliptProvider.getStringEvaluation("fail_not_initialized", "", new ImmutableContext()));
+ assertThrows(ProviderNotReadyError.class, () -> asyncInitfliptProvider
+ .getBooleanEvaluation("fail_not_initialized", false, new ImmutableContext()));
+ assertThrows(ProviderNotReadyError.class,
+ () -> asyncInitfliptProvider.getStringEvaluation("fail_not_initialized", "", new ImmutableContext()));
asyncInitfliptProvider.initialize(null);
- assertThrows(GeneralError.class, ()-> asyncInitfliptProvider.initialize(null));
+ assertThrows(GeneralError.class, () -> asyncInitfliptProvider.initialize(null));
asyncInitfliptProvider.shutdown();
}
@@ -197,8 +201,10 @@ void shouldThrowIfErrorEvent() {
asyncInitfliptProvider.emitProviderError(ProviderEventDetails.builder().build());
// ErrorCode.PROVIDER_NOT_READY should be returned when evaluated via the client
- assertThrows(GeneralError.class, ()-> asyncInitfliptProvider.getBooleanEvaluation("fail", false, new ImmutableContext()));
- assertThrows(GeneralError.class, ()-> asyncInitfliptProvider.getStringEvaluation("fail", "", new ImmutableContext()));
+ assertThrows(GeneralError.class,
+ () -> asyncInitfliptProvider.getBooleanEvaluation("fail", false, new ImmutableContext()));
+ assertThrows(GeneralError.class,
+ () -> asyncInitfliptProvider.getStringEvaluation("fail", "", new ImmutableContext()));
asyncInitfliptProvider.shutdown();
}
diff --git a/providers/flipt/version.txt b/providers/flipt/version.txt
index 4e379d2bf..6e8bf73aa 100644
--- a/providers/flipt/version.txt
+++ b/providers/flipt/version.txt
@@ -1 +1 @@
-0.0.2
+0.1.0