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:
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: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]