Joker-5 commented on code in PR #15642: URL: https://github.com/apache/kafka/pull/15642#discussion_r1547690392
########## connect/runtime/src/test/java/org/apache/kafka/connect/integration/ConnectorValidationIntegrationTest.java: ########## @@ -69,6 +69,9 @@ public static void setup() { Map<String, String> workerProps = new HashMap<>(); workerProps.put(GROUP_ID_CONFIG, WORKER_GROUP_ID); + // Work around a circular-dependency in TestPlugins. + TestPlugins.pluginPath(); Review Comment: @vamossagar12 If we don't add this, methods which use `TestPlugins` will have erroneous behavior. In particular: ``` [2024-04-02 19:16:25,977] ERROR Could not set up plugin test jars (org.apache.kafka.connect.runtime.isolation.TestPlugins:258) java.lang.NullPointerException at org.apache.kafka.connect.runtime.isolation.TestPlugins$TestPlugin.values(TestPlugins.java:69) at org.apache.kafka.connect.runtime.isolation.TestPlugins.<clinit>(TestPlugins.java:251) at org.apache.kafka.connect.runtime.isolation.TestPlugins$TestPlugin.<clinit>(TestPlugins.java:128) at org.apache.kafka.connect.integration.ConnectorValidationIntegrationTest.testConnectorHasConverterWithNoSuitableConstructor(ConnectorValidationIntegrationTest.java:337) ... ``` I found the reason behind it: >TL;DR The whole error occurred because the circle: inner class(some field depend on outer class in the \<clinit> method) -> outer class(some line in static code block depend on inner class in the \<clinit> method) -> inner class 1. There's a `private final Predicate<String> removeRuntimeClasses` field in the inner class `org.apache.kafka.connect.runtime.isolation.TestPlugins.TestPlugin`. 2. Some enums such as `BAD_PACKAGING_MISSING_SUPERCLASS` in (1)'s field will depend on `private static final Predicate<String> REMOVE_CLASS_FILTER = s -> s.contains("NonExistentInterface")` in the outer class(`org.apache.kafka.connect.runtime.isolation.TestPlugins`). 3. When test mothod such as `testConnectorHasConverterWithNoSuitableConstructor` is running, JVM will call \<clinit> method to initialize the inner class(`org.apache.kafka.connect.runtime.isolation.TestPlugins.TestPlugin`). 4. But some enum use the field(`removeRuntimeClasses`) in the outer class(`private static final Predicate<String> REMOVE_CLASS_FILTER = s -> s.contains("NonExistentInterface")`), so at that time JVM has to call \<clinit> method to initialize the outer class(`org.apache.kafka.connect.runtime.isolation.TestPlugins`). 5. In the outer class, there's a static code block which used the inner class. But the inner class have not been initialized, the circular-dependency just happened, which result in that error log. ```java static { Throwable err = null; Map<String, Path> pluginJars = new HashMap<>(); try { for (TestPlugin testPlugin : TestPlugin.values()) { // see this line if (pluginJars.containsKey(testPlugin.resourceDir())) { log.debug("Skipping recompilation of " + testPlugin.resourceDir()); } pluginJars.put(testPlugin.resourceDir(), createPluginJar(testPlugin.resourceDir(), testPlugin.removeRuntimeClasses())); } } catch (Throwable e) { log.error("Could not set up plugin test jars", e); err = e; } PLUGIN_JARS = Collections.unmodifiableMap(pluginJars); INITIALIZATION_EXCEPTION = err; } ``` So that's why I added the code. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: jira-unsubscr...@kafka.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org