open-feature / java-sdk

Java implementation of the OpenFeature SDK
https://openfeature.dev
Apache License 2.0
84 stars 38 forks source link

RejectedExecutionException thrown when calling setProvider after shutdown #552

Closed thomaspoignant closed 1 year ago

thomaspoignant commented 1 year ago

While writing a unit test I found a bug when calling OpenFeatureAPI.getInstance().shutdown(); and calling back setProvider() we have an exception thrown (java.util.concurrent.RejectedExecutionException).

I don't know if this is expected, but this exception is not super explicit anyway.

How to reproduce

public class ProviderTests2 {
    @Test
    void testXXX() {
        NoOpProvider p = new NoOpProvider();
        OpenFeatureAPI.getInstance().setProvider(p);
        var client = OpenFeatureAPI.getInstance().getClient();
        OpenFeatureAPI.getInstance().shutdown();

        NoOpProvider p2 = new NoOpProvider();
        OpenFeatureAPI.getInstance().setProvider(p2);
    }
}

The second setProvider is throwing this exception:

/Users/thomas.poignant/Library/Java/JavaVirtualMachines/corretto-11.0.18/Contents/Home/bin/java -ea -Didea.test.cyclic.buffer.size=1048576 -javaagent:/Users/thomas.poignant/Library/Application Support/JetBrains/Toolbox/apps/IDEA-U/ch-0/231.9011.34/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=57732:/Users/thomas.poignant/Library/Application Support/JetBrains/Toolbox/apps/IDEA-U/ch-0/231.9011.34/IntelliJ IDEA.app/Contents/bin -Dfile.encoding=UTF-8 -classpath /Users/thomas.poignant/.m2/repository/org/junit/platform/junit-platform-launcher/1.10.0/junit-platform-launcher-1.10.0.jar:/Users/thomas.poignant/Library/Application Support/JetBrains/Toolbox/apps/IDEA-U/ch-0/231.9011.34/IntelliJ IDEA.app/Contents/lib/idea_rt.jar:/Users/thomas.poignant/Library/Application Support/JetBrains/Toolbox/apps/IDEA-U/ch-0/231.9011.34/IntelliJ IDEA.app/Contents/plugins/junit/lib/junit5-rt.jar:/Users/thomas.poignant/Library/Application Support/JetBrains/Toolbox/apps/IDEA-U/ch-0/231.9011.34/IntelliJ IDEA.app/Contents/plugins/junit/lib/junit-rt.jar:/Users/thomas.poignant/dev/thomaspoignant/go-feature-flag/openfeature/provider_tests/java-integration-tests/target/test-classes:/Users/thomas.poignant/dev/thomaspoignant/go-feature-flag/openfeature/provider_tests/java-integration-tests/target/classes:/Users/thomas.poignant/.m2/repository/org/junit/jupiter/junit-jupiter-engine/5.10.0/junit-jupiter-engine-5.10.0.jar:/Users/thomas.poignant/.m2/repository/org/junit/platform/junit-platform-engine/1.10.0/junit-platform-engine-1.10.0.jar:/Users/thomas.poignant/.m2/repository/org/opentest4j/opentest4j/1.3.0/opentest4j-1.3.0.jar:/Users/thomas.poignant/.m2/repository/org/junit/platform/junit-platform-commons/1.10.0/junit-platform-commons-1.10.0.jar:/Users/thomas.poignant/.m2/repository/org/junit/jupiter/junit-jupiter-api/5.10.0/junit-jupiter-api-5.10.0.jar:/Users/thomas.poignant/.m2/repository/org/apiguardian/apiguardian-api/1.1.2/apiguardian-api-1.1.2.jar:/Users/thomas.poignant/.m2/repository/dev/openfeature/sdk/1.4.1/sdk-1.4.1.jar:/Users/thomas.poignant/.m2/repository/org/slf4j/slf4j-api/2.0.7/slf4j-api-2.0.7.jar:/Users/thomas.poignant/.m2/repository/dev/openfeature/contrib/providers/go-feature-flag/0.2.11/go-feature-flag-0.2.11.jar:/Users/thomas.poignant/.m2/repository/com/fasterxml/jackson/datatype/jackson-datatype-jsr310/2.15.2/jackson-datatype-jsr310-2.15.2.jar:/Users/thomas.poignant/.m2/repository/com/fasterxml/jackson/core/jackson-annotations/2.15.2/jackson-annotations-2.15.2.jar:/Users/thomas.poignant/.m2/repository/com/fasterxml/jackson/core/jackson-core/2.15.2/jackson-core-2.15.2.jar:/Users/thomas.poignant/.m2/repository/com/fasterxml/jackson/core/jackson-databind/2.15.2/jackson-databind-2.15.2.jar:/Users/thomas.poignant/.m2/repository/com/squareup/okhttp3/okhttp/4.11.0/okhttp-4.11.0.jar:/Users/thomas.poignant/.m2/repository/com/squareup/okio/okio/3.2.0/okio-3.2.0.jar:/Users/thomas.poignant/.m2/repository/com/squareup/okio/okio-jvm/3.2.0/okio-jvm-3.2.0.jar:/Users/thomas.poignant/.m2/repository/org/jetbrains/kotlin/kotlin-stdlib/1.6.20/kotlin-stdlib-1.6.20.jar:/Users/thomas.poignant/.m2/repository/org/jetbrains/kotlin/kotlin-stdlib-common/1.6.20/kotlin-stdlib-common-1.6.20.jar:/Users/thomas.poignant/.m2/repository/org/jetbrains/annotations/13.0/annotations-13.0.jar:/Users/thomas.poignant/.m2/repository/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.6.20/kotlin-stdlib-jdk8-1.6.20.jar:/Users/thomas.poignant/.m2/repository/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.6.20/kotlin-stdlib-jdk7-1.6.20.jar:/Users/thomas.poignant/.m2/repository/com/google/guava/guava/32.1.1-jre/guava-32.1.1-jre.jar:/Users/thomas.poignant/.m2/repository/com/google/guava/failureaccess/1.0.1/failureaccess-1.0.1.jar:/Users/thomas.poignant/.m2/repository/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar:/Users/thomas.poignant/.m2/repository/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar:/Users/thomas.poignant/.m2/repository/org/checkerframework/checker-qual/3.33.0/checker-qual-3.33.0.jar:/Users/thomas.poignant/.m2/repository/com/google/errorprone/error_prone_annotations/2.18.0/error_prone_annotations-2.18.0.jar:/Users/thomas.poignant/.m2/repository/com/google/j2objc/j2objc-annotations/2.8/j2objc-annotations-2.8.jar com.intellij.rt.junit.JUnitStarter -ideVersion5 -junit5 org.gofeatureflag.integrationtests.ProviderTests2
SLF4J: No SLF4J providers were found.
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See https://www.slf4j.org/codes.html#noProviders for further details.

java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@8317c52[Not completed, task = java.util.concurrent.Executors$RunnableAdapter@5f683daf[Wrapped task = dev.openfeature.sdk.ProviderRepository$$Lambda$360/0x000000080016cc40@78ffe6dc]] rejected from java.util.concurrent.ThreadPoolExecutor@325f903d[Shutting down, pool size = 1, active threads = 1, queued tasks = 0, completed tasks = 2]

    at java.base/java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2055)
    at java.base/java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:825)
    at java.base/java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1355)
    at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:118)
    at dev.openfeature.sdk.ProviderRepository.initializeProvider(ProviderRepository.java:104)
    at dev.openfeature.sdk.ProviderRepository.setProvider(ProviderRepository.java:69)
    at dev.openfeature.sdk.OpenFeatureAPI.setProvider(OpenFeatureAPI.java:100)
    at org.gofeatureflag.integrationtests.ProviderTests2.testXXX(ProviderTests2.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)

Process finished with exit code 255
Kavindu-Dodan commented 1 year ago

@thomaspoignant I assume you are using a SDK version <= 1.4.1 ? We had a static field in event handler implementation which caused this. It was fixed with https://github.com/open-feature/java-sdk/pull/545

I will go ahead with the 1.4.2 release - https://github.com/open-feature/java-sdk/pull/527 which contain the fix

Kavindu-Dodan commented 1 year ago

Caused by the static event handler usage which was fixed with https://github.com/open-feature/java-sdk/pull/545

Please update SDK version to https://github.com/open-feature/java-sdk/releases/tag/v1.4.2

thomaspoignant commented 1 year ago

Yes I was using 1.4.1. Let me try with the new version and I will close the issue.

thomaspoignant commented 1 year ago

@Kavindu-Dodan I have the exact same problem with the version v1.4.2.

Kavindu-Dodan commented 1 year ago

@thomaspoignant root cause is the singleton OF API ^1. Once the shutdown is called, eventing mechanism is no longer available.

I will revisit shutdown spec section and fix this

Kavindu-Dodan commented 1 year ago

@thomaspoignant Fix is ready and contains your bug recreation code as a test - https://github.com/open-feature/java-sdk/pull/556 :)

Kavindu-Dodan commented 1 year ago

@thomaspoignant please update to the newest release v1.4.3 ^1 which contains the fix for this bug