From d4dbb04d7e0dfa8ad7f6ea76c0ae62bb2f06215a Mon Sep 17 00:00:00 2001 From: jarebudev <23311805+jarebudev@users.noreply.github.com> Date: Thu, 7 May 2026 20:16:02 +0100 Subject: [PATCH 1/2] fix: shutdown now clears hooks, evaluationContext and transactionContextPropagator as per spec 1.6.2 Signed-off-by: jarebudev <23311805+jarebudev@users.noreply.github.com> --- .../dev/openfeature/sdk/OpenFeatureAPI.java | 3 +++ .../sdk/ShutdownBehaviorSpecTest.java | 25 ++++++++++++++----- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/main/java/dev/openfeature/sdk/OpenFeatureAPI.java b/src/main/java/dev/openfeature/sdk/OpenFeatureAPI.java index 02c1edf25..f385af40d 100644 --- a/src/main/java/dev/openfeature/sdk/OpenFeatureAPI.java +++ b/src/main/java/dev/openfeature/sdk/OpenFeatureAPI.java @@ -355,6 +355,9 @@ public void shutdown() { try (AutoCloseableLock ignored = lock.writeLockAutoCloseable()) { providerRepository = new ProviderRepository(this); eventSupport = new EventSupport(); + clearHooks(); + setEvaluationContext(new ImmutableContext()); + setTransactionContextPropagator(new NoOpTransactionContextPropagator()); } } } diff --git a/src/test/java/dev/openfeature/sdk/ShutdownBehaviorSpecTest.java b/src/test/java/dev/openfeature/sdk/ShutdownBehaviorSpecTest.java index 2c6a6304e..e34f5cdce 100644 --- a/src/test/java/dev/openfeature/sdk/ShutdownBehaviorSpecTest.java +++ b/src/test/java/dev/openfeature/sdk/ShutdownBehaviorSpecTest.java @@ -1,5 +1,7 @@ package dev.openfeature.sdk; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.*; import dev.openfeature.sdk.fixtures.ProviderFixture; @@ -131,16 +133,27 @@ void mustShutdownAllProvidersOnShuttingDownApi() { } @Test - @DisplayName("once shutdown is complete, api must be ready to use again") - void apiIsReadyToUseAfterShutdown() { + @Specification( + number = "1.6.2", + text = + "The API's `shutdown` function MUST reset all state of the API, removing all hooks, event handlers, evaluation context, transaction context propagators, and providers.") + @DisplayName("shutdown must reset the state of the API") + void apiStateMustBeResetOnShuttingDownApi() { + + FeatureProvider provider = ProviderFixture.createMockedProvider(); + TransactionContextPropagator transactionContextPropagator = new NoOpTransactionContextPropagator(); + EvaluationContext evaluationContext = mock(EvaluationContext.class); - NoOpProvider p1 = new NoOpProvider(); - api.setProvider(p1); + api.setProvider(provider); + api.setEvaluationContext(evaluationContext); + api.setTransactionContextPropagator(transactionContextPropagator); api.shutdown(); - NoOpProvider p2 = new NoOpProvider(); - api.setProvider(p2); + assertNotEquals(provider, api.getProvider()); + assertTrue(api.getHooks().isEmpty()); + assertNotEquals(evaluationContext, api.getEvaluationContext()); + assertNotEquals(transactionContextPropagator, api.getTransactionContextPropagator()); } @Test From 258341674fe3dd696f14544e21c2035e9b8f9c7e Mon Sep 17 00:00:00 2001 From: jarebudev <23311805+jarebudev@users.noreply.github.com> Date: Thu, 7 May 2026 20:54:45 +0100 Subject: [PATCH 2/2] applied Gemini code review suggested change to verify that hooks are cleared Signed-off-by: jarebudev <23311805+jarebudev@users.noreply.github.com> --- .../java/dev/openfeature/sdk/ShutdownBehaviorSpecTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/dev/openfeature/sdk/ShutdownBehaviorSpecTest.java b/src/test/java/dev/openfeature/sdk/ShutdownBehaviorSpecTest.java index e34f5cdce..e79bb17a1 100644 --- a/src/test/java/dev/openfeature/sdk/ShutdownBehaviorSpecTest.java +++ b/src/test/java/dev/openfeature/sdk/ShutdownBehaviorSpecTest.java @@ -141,9 +141,10 @@ void mustShutdownAllProvidersOnShuttingDownApi() { void apiStateMustBeResetOnShuttingDownApi() { FeatureProvider provider = ProviderFixture.createMockedProvider(); - TransactionContextPropagator transactionContextPropagator = new NoOpTransactionContextPropagator(); + TransactionContextPropagator transactionContextPropagator = mock(TransactionContextPropagator.class); EvaluationContext evaluationContext = mock(EvaluationContext.class); + api.addHooks(mock(Hook.class)); api.setProvider(provider); api.setEvaluationContext(evaluationContext); api.setTransactionContextPropagator(transactionContextPropagator);