diff --git a/providers/go-feature-flag/pom.xml b/providers/go-feature-flag/pom.xml
index c1cb3458b..f24fea1e6 100644
--- a/providers/go-feature-flag/pom.xml
+++ b/providers/go-feature-flag/pom.xml
@@ -29,13 +29,13 @@
com.fasterxml.jackson.datatype
jackson-datatype-jsr310
- 2.13.4
+ 2.14.0
com.fasterxml.jackson.core
jackson-databind
- 2.13.4
+ 2.14.0
diff --git a/providers/go-feature-flag/src/main/java/dev/openfeature/contrib/providers/gofeatureflag/GoFeatureFlagProvider.java b/providers/go-feature-flag/src/main/java/dev/openfeature/contrib/providers/gofeatureflag/GoFeatureFlagProvider.java
index 0423441bb..d2b09c445 100644
--- a/providers/go-feature-flag/src/main/java/dev/openfeature/contrib/providers/gofeatureflag/GoFeatureFlagProvider.java
+++ b/providers/go-feature-flag/src/main/java/dev/openfeature/contrib/providers/gofeatureflag/GoFeatureFlagProvider.java
@@ -1,18 +1,9 @@
package dev.openfeature.contrib.providers.gofeatureflag;
import static java.net.HttpURLConnection.HTTP_BAD_REQUEST;
-
-import java.io.IOException;
-import java.time.Instant;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-import java.util.stream.Collectors;
-
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
-
import dev.openfeature.contrib.providers.gofeatureflag.bean.GoFeatureFlagRequest;
import dev.openfeature.contrib.providers.gofeatureflag.bean.GoFeatureFlagResponse;
import dev.openfeature.contrib.providers.gofeatureflag.bean.GoFeatureFlagUser;
@@ -40,6 +31,12 @@
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
+import java.io.IOException;
+import java.time.Instant;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
/**
* GoFeatureFlagProvider is the JAVA provider implementation for the feature flag solution GO Feature Flag.
@@ -120,7 +117,6 @@ public List getProviderHooks() {
return FeatureProvider.super.getProviderHooks();
}
-
@Override
public ProviderEvaluation getBooleanEvaluation(
String key, Boolean defaultValue, EvaluationContext evaluationContext
@@ -201,8 +197,7 @@ private ProviderEvaluation resolveEvaluationGoFeatureFlagProxy(
if (Reason.DISABLED.name().equalsIgnoreCase(goffResp.getReason())) {
// we don't set a variant since we are using the default value, and we are not able to know
// which variant it is.
- return ProviderEvaluation.builder().value(defaultValue).reason(Reason.DISABLED.toString())
- .build();
+ return ProviderEvaluation.builder().value(defaultValue).reason(Reason.DISABLED.name()).build();
}
if (ErrorCode.FLAG_NOT_FOUND.name().equalsIgnoreCase(goffResp.getErrorCode())) {
@@ -218,6 +213,7 @@ private ProviderEvaluation resolveEvaluationGoFeatureFlagProxy(
}
return ProviderEvaluation.builder()
+ .errorCode(mapErrorCode(goffResp.getErrorCode()))
.reason(goffResp.getReason())
.value(flagValue)
.variant(goffResp.getVariationType())
@@ -229,6 +225,21 @@ private ProviderEvaluation resolveEvaluationGoFeatureFlagProxy(
}
}
+ /**
+ * mapErrorCode is mapping the errorCode in string received by the API to our internal SDK ErrorCode enum.
+ *
+ * @param errorCode - string of the errorCode received from the API
+ * @return an item from the enum
+ */
+ private ErrorCode mapErrorCode(String errorCode) {
+ try {
+ return ErrorCode.valueOf(errorCode);
+ } catch (IllegalArgumentException e) {
+ return null;
+ }
+ }
+
+
/**
* convertValue is converting the object return by the proxy response in the right type.
*
diff --git a/providers/go-feature-flag/src/main/java/dev/openfeature/contrib/providers/gofeatureflag/bean/GoFeatureFlagUser.java b/providers/go-feature-flag/src/main/java/dev/openfeature/contrib/providers/gofeatureflag/bean/GoFeatureFlagUser.java
index a00b9f8ed..cb16f14f3 100644
--- a/providers/go-feature-flag/src/main/java/dev/openfeature/contrib/providers/gofeatureflag/bean/GoFeatureFlagUser.java
+++ b/providers/go-feature-flag/src/main/java/dev/openfeature/contrib/providers/gofeatureflag/bean/GoFeatureFlagUser.java
@@ -31,8 +31,10 @@ public static GoFeatureFlagUser fromEvaluationContext(EvaluationContext ctx) {
if (key == null || "".equals(key)) {
throw new InvalidTargetingKey();
}
-
Value anonymousValue = ctx.getValue(anonymousFieldName);
+ if (anonymousValue == null) {
+ anonymousValue = new Value(Boolean.FALSE);
+ }
boolean anonymous = anonymousValue.asBoolean();
Map custom = new HashMap<>(ctx.asObjectMap());
if (ctx.getValue(anonymousFieldName) != null) {
diff --git a/providers/go-feature-flag/src/test/java/dev/openfeature/contrib/providers/gofeatureflag/GoFeatureFlagProviderTest.java b/providers/go-feature-flag/src/test/java/dev/openfeature/contrib/providers/gofeatureflag/GoFeatureFlagProviderTest.java
index fcc8ec082..04db2d41d 100644
--- a/providers/go-feature-flag/src/test/java/dev/openfeature/contrib/providers/gofeatureflag/GoFeatureFlagProviderTest.java
+++ b/providers/go-feature-flag/src/test/java/dev/openfeature/contrib/providers/gofeatureflag/GoFeatureFlagProviderTest.java
@@ -1,9 +1,5 @@
package dev.openfeature.contrib.providers.gofeatureflag;
-import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
@@ -33,6 +29,8 @@
import okhttp3.mockwebserver.MockWebServer;
import okhttp3.mockwebserver.RecordedRequest;
+import static org.junit.jupiter.api.Assertions.*;
+
class GoFeatureFlagProviderTest {
// Dispatcher is the configuration of the mock server to test the provider.
final Dispatcher dispatcher = new Dispatcher() {
@@ -138,15 +136,17 @@ void should_resolve_a_valid_boolean_flag_with_TARGETING_MATCH_reason() throws In
GoFeatureFlagProvider g = new GoFeatureFlagProvider(GoFeatureFlagProviderOptions.builder().endpoint(this.baseUrl.toString()).timeout(1000).build());
ProviderEvaluation res = g.getBooleanEvaluation("bool_targeting_match", false, this.evaluationContext);
assertEquals(true, res.getValue());
+ assertNull(res.getErrorCode());
assertEquals(Reason.TARGETING_MATCH.toString(), res.getReason());
assertEquals("True", res.getVariant());
}
@Test
- void should_return_unknown_reason_if_not_exists_in_SDK() throws InvalidOptions {
+ void should_return_custom_reason_if_returned_by_relay_proxy() throws InvalidOptions {
GoFeatureFlagProvider g = new GoFeatureFlagProvider(GoFeatureFlagProviderOptions.builder().endpoint(this.baseUrl.toString()).timeout(1000).build());
ProviderEvaluation res = g.getBooleanEvaluation("unknown_reason", false, this.evaluationContext);
assertEquals(true, res.getValue());
+ assertNull(res.getErrorCode());
assertEquals("CUSTOM_REASON", res.getReason());
assertEquals("True", res.getVariant());
}
@@ -170,6 +170,7 @@ void should_resolve_a_valid_string_flag_with_TARGETING_MATCH_reason() throws Inv
GoFeatureFlagProvider g = new GoFeatureFlagProvider(GoFeatureFlagProviderOptions.builder().endpoint(this.baseUrl.toString()).timeout(1000).build());
ProviderEvaluation res = g.getStringEvaluation("string_key", "defaultValue", this.evaluationContext);
assertEquals("CC0000", res.getValue());
+ assertNull(res.getErrorCode());
assertEquals(Reason.TARGETING_MATCH.toString(), res.getReason());
assertEquals("True", res.getVariant());
}
@@ -193,6 +194,7 @@ void should_resolve_a_valid_integer_flag_with_TARGETING_MATCH_reason() throws In
GoFeatureFlagProvider g = new GoFeatureFlagProvider(GoFeatureFlagProviderOptions.builder().endpoint(this.baseUrl.toString()).timeout(1000).build());
ProviderEvaluation res = g.getIntegerEvaluation("integer_key", 1200, this.evaluationContext);
assertEquals(100, res.getValue());
+ assertNull(res.getErrorCode());
assertEquals(Reason.TARGETING_MATCH.toString(), res.getReason());
assertEquals("True", res.getVariant());
}
@@ -216,6 +218,7 @@ void should_resolve_a_valid_double_flag_with_TARGETING_MATCH_reason() throws Inv
GoFeatureFlagProvider g = new GoFeatureFlagProvider(GoFeatureFlagProviderOptions.builder().endpoint(this.baseUrl.toString()).timeout(1000).build());
ProviderEvaluation res = g.getDoubleEvaluation("double_key", 1200.25, this.evaluationContext);
assertEquals(100.25, res.getValue());
+ assertNull(res.getErrorCode());
assertEquals(Reason.TARGETING_MATCH.toString(), res.getReason());
assertEquals("True", res.getVariant());
}
@@ -234,6 +237,7 @@ void should_resolve_a_valid_value_flag_with_TARGETING_MATCH_reason() throws Inva
ProviderEvaluation res = g.getObjectEvaluation("object_key", null, this.evaluationContext);
Value want = new Value(new MutableStructure().add("test", "test1").add("test2", false).add("test3", 123.3).add("test4", 1));
assertEquals(want, res.getValue());
+ assertNull(res.getErrorCode());
assertEquals(Reason.TARGETING_MATCH.toString(), res.getReason());
assertEquals("True", res.getVariant());
}
@@ -244,6 +248,7 @@ void should_wrap_into_value_if_wrong_type() throws InvalidOptions {
ProviderEvaluation res = g.getObjectEvaluation("string_key", null, this.evaluationContext);
Value want = new Value("CC0000");
assertEquals(want, res.getValue());
+ assertNull(res.getErrorCode());
assertEquals(Reason.TARGETING_MATCH.toString(), res.getReason());
assertEquals("True", res.getVariant());
}
@@ -274,6 +279,7 @@ void should_throw_an_error_if_no_targeting_key() throws InvalidOptions {
new Value("false"),
new Value("test3"))));
assertEquals(want, res.getValue());
+ assertNull(res.getErrorCode());
assertEquals(Reason.TARGETING_MATCH.toString(), res.getReason());
assertEquals("True", res.getVariant());
}