Skip to content

Commit bdbe98d

Browse files
committed
fix: [go-feature-flag] Fix NullPointerException on checking anonymous user
1 parent 75f0e3f commit bdbe98d

File tree

3 files changed

+39
-8
lines changed

3 files changed

+39
-8
lines changed

Diff for: providers/go-feature-flag/src/main/java/dev/openfeature/contrib/providers/gofeatureflag/bean/GoFeatureFlagUser.java

+13-6
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,25 @@ public class GoFeatureFlagUser {
2828
*/
2929
public static GoFeatureFlagUser fromEvaluationContext(EvaluationContext ctx) {
3030
String key = ctx.getTargetingKey();
31-
if (key == null || "".equals(key)) {
31+
if (key == null || key.isEmpty()) {
3232
throw new TargetingKeyMissingError();
3333
}
34-
Value anonymousValue = ctx.getValue(anonymousFieldName);
35-
if (anonymousValue == null) {
36-
anonymousValue = new Value(Boolean.FALSE);
37-
}
38-
boolean anonymous = anonymousValue.asBoolean();
34+
boolean anonymous = isAnonymousUser(ctx);
3935
Map<String, Object> custom = new HashMap<>(ctx.asObjectMap());
4036
if (ctx.getValue(anonymousFieldName) != null) {
4137
custom.remove(anonymousFieldName);
4238
}
4339
return GoFeatureFlagUser.builder().anonymous(anonymous).key(key).custom(custom).build();
4440
}
41+
42+
/**
43+
* isAnonymousUser is checking if the user in the evaluationContext is anonymous.
44+
*
45+
* @param ctx - EvaluationContext from open-feature
46+
* @return true if the user is anonymous, false otherwise
47+
*/
48+
public static boolean isAnonymousUser(EvaluationContext ctx) {
49+
Value value = ctx.getValue(anonymousFieldName);
50+
return value != null && value.asBoolean();
51+
}
4552
}

Diff for: providers/go-feature-flag/src/main/java/dev/openfeature/contrib/providers/gofeatureflag/hook/DataCollectorHook.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.fasterxml.jackson.core.JsonProcessingException;
44
import dev.openfeature.contrib.providers.gofeatureflag.GoFeatureFlagProvider;
5+
import dev.openfeature.contrib.providers.gofeatureflag.bean.GoFeatureFlagUser;
56
import dev.openfeature.contrib.providers.gofeatureflag.exception.InvalidOptions;
67
import dev.openfeature.contrib.providers.gofeatureflag.hook.events.Event;
78
import dev.openfeature.contrib.providers.gofeatureflag.hook.events.Events;
@@ -73,7 +74,7 @@ public void after(HookContext ctx, FlagEvaluationDetails details, Map hints) {
7374
Event event = Event.builder()
7475
.key(ctx.getFlagKey())
7576
.kind("feature")
76-
.contextKind(ctx.getCtx().getValue("anonymous").asBoolean() ? "anonymousUser" : "user")
77+
.contextKind(GoFeatureFlagUser.isAnonymousUser(ctx.getCtx()) ? "anonymousUser" : "user")
7778
.defaultValue(false)
7879
.variation(details.getVariant())
7980
.value(details.getValue())
@@ -88,7 +89,7 @@ public void error(HookContext ctx, Exception error, Map hints) {
8889
Event event = Event.builder()
8990
.key(ctx.getFlagKey())
9091
.kind("feature")
91-
.contextKind(ctx.getCtx().getValue("anonymous").asBoolean() ? "anonymousUser" : "user")
92+
.contextKind(GoFeatureFlagUser.isAnonymousUser(ctx.getCtx()) ? "anonymousUser" : "user")
9293
.creationDate(System.currentTimeMillis())
9394
.defaultValue(true)
9495
.variation("SdkDefault")

Diff for: providers/go-feature-flag/src/test/java/dev/openfeature/contrib/providers/gofeatureflag/GoFeatureFlagProviderTest.java

+23
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,29 @@ void should_publish_events() {
750750
assertEquals(6, publishEventsRequestsReceived, "we have call 6 time more, so we should consider only those new calls");
751751
}
752752

753+
@SneakyThrows
754+
@Test
755+
void should_publish_events_context_without_anonymous() {
756+
this.evaluationContext = new MutableContext("d45e303a-38c2-11ed-a261-0242ac120002");
757+
GoFeatureFlagProvider g = new GoFeatureFlagProvider(GoFeatureFlagProviderOptions.builder()
758+
.endpoint(this.baseUrl.toString())
759+
.timeout(1000)
760+
.enableCache(true)
761+
.flushIntervalMs(50L)
762+
.build());
763+
String providerName = this.testName;
764+
OpenFeatureAPI.getInstance().setProviderAndWait(providerName, g);
765+
Client client = OpenFeatureAPI.getInstance().getClient(providerName);
766+
client.getBooleanDetails("fail_500", false, this.evaluationContext);
767+
Thread.sleep(100L);
768+
assertEquals(1, publishEventsRequestsReceived, "We should have 1 event waiting to be publish");
769+
client.getBooleanDetails("bool_targeting_match", false, this.evaluationContext);
770+
client.getBooleanDetails("bool_targeting_match", false, this.evaluationContext);
771+
client.getBooleanDetails("bool_targeting_match", false, this.evaluationContext);
772+
Thread.sleep(100);
773+
assertEquals(3, publishEventsRequestsReceived, "We pass the flush interval, we should have 3 events");
774+
}
775+
753776
private String readMockResponse(String filename) throws Exception {
754777
URL url = getClass().getClassLoader().getResource("mock_responses/" + filename);
755778
assert url != null;

0 commit comments

Comments
 (0)