Skip to content

KAFKA-17150: Use Utils.loadClass instead of Class.forName to resolve aliases correctly - #16608

Merged
gharris1727 merged 3 commits into
apache:trunkfrom
gharris1727:kafka-17150-class-forname-aliases
Jul 17, 2024
Merged

KAFKA-17150: Use Utils.loadClass instead of Class.forName to resolve aliases correctly#16608
gharris1727 merged 3 commits into
apache:trunkfrom
gharris1727:kafka-17150-class-forname-aliases

Conversation

@gharris1727

Copy link
Copy Markdown
Contributor

There are a handful of places where we call Class.forName in the code base. Previously, the ConfigDef call-site required a patch to resolve aliased classes (a feature in Connect). A second call-site via AbstractHerder -> Utils.newInstance has appeared as a regression in the current release. We can apply the same fix to all other call sites for Class.forName to prevent this from happening accidentally again. If aliases are not in-use, this should be a no-op change.

I added a PluginsTest case that exercises all of the ways we could construct Converter objects and ensures that they don't throw a ClassNotFoundException. This test failed before making the fix.

Committer Checklist (excluded from commit message)

  • Verify design and implementation
  • Verify test coverage and CI build status
  • Verify documentation (including upgrade notes)

…aliases correctly

Signed-off-by: Greg Harris <greg.harris@aiven.io>
@gharris1727 gharris1727 added backport-candidate This pull request is a candidate to be backported to previous versions Blocker This pull request is identified as solving a blocker for a release. labels Jul 16, 2024
@gharris1727

Copy link
Copy Markdown
Contributor Author

Hi @C0urante @jlprat PTAL, thanks!

@gharris1727

Copy link
Copy Markdown
Contributor Author

Also @yashmayya @mimaison and anyone else interested in reviewing!

@gharris1727

gharris1727 commented Jul 16, 2024

Copy link
Copy Markdown
Contributor Author

Alternatives to this PR are:

@C0urante C0urante left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM pending CI to demonstrate that there are no (further) regressions. Great find, thanks Greg!

@chia7712 chia7712 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gharris1727 this patch is good to me. one small comment is left. PTAL

public static <T> Class<? extends T> loadClass(String klass, Class<T> base) throws ClassNotFoundException {
return Class.forName(klass, true, Utils.getContextOrKafkaClassLoader()).asSubclass(base);
ClassLoader contextOrKafkaClassLoader = Utils.getContextOrKafkaClassLoader();
// Use loadClass here instead of Class.forName because the name we use here may be an alias

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those comments about "alias" seem to valid for connector only, right? I mean the plugin-able configs in other module (core, storage, and tool) have no mechanism about "alias". If the answer is YES, maybe we can tweak the comments so as to avoid incorrect assumption that "all" plugin-able configs can use "alias".

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aliasing is a general concept, with one particular implementation in connect. I don't think the word alias is incorrect to use here. The comment also doesn't mention plugins at all.

You're right that the only time we use aliases is in connect, via the DelegatingClassLoader, so most of the time this change has no effect, loadedClass.getName().equals(klass) is true.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assumed the "alias" are applied to all plugin configs when reading those comments, so the origin comment is "we have some deprecated implementations having same alias as new one. Bababa..."

There is no strong reason to tweak the comments, because the root cause is probably my poor reading 😢

@chia7712 chia7712 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM and thanks for this good fix!

@jlprat

jlprat commented Jul 17, 2024

Copy link
Copy Markdown
Contributor

I'm retriggering CI as 2 jobs failed in the first run.

@jlprat

jlprat commented Jul 17, 2024

Copy link
Copy Markdown
Contributor

@gharris1727 The build wasn't working because of a spotless violation:

* What went wrong:

[2024-07-16T22:42:43.930Z] Execution failed for task ':connect:runtime:spotlessJavaCheck'.

[2024-07-16T22:42:43.930Z] > The following files had format violations:

[2024-07-16T22:42:43.930Z]       src/test/java/org/apache/kafka/connect/runtime/isolation/SynchronizationTest.java

[2024-07-16T22:42:43.930Z]           @@ -24,8 +24,8 @@

[2024-07-16T22:42:43.930Z]            import·org.apache.kafka.common.config.ConfigDef.Type;

[2024-07-16T22:42:43.930Z]            import·org.apache.kafka.common.utils.Utils;

[2024-07-16T22:42:43.930Z]            import·org.apache.kafka.connect.runtime.WorkerConfig;

[2024-07-16T22:42:43.930Z]           +import·org.apache.kafka.connect.storage.Converter;

[2024-07-16T22:42:43.930Z]            

[2024-07-16T22:42:43.930Z]           -import·org.apache.kafka.connect.storage.Converter;

[2024-07-16T22:42:43.930Z]            import·org.junit.jupiter.api.AfterEach;

[2024-07-16T22:42:43.930Z]            import·org.junit.jupiter.api.BeforeEach;

[2024-07-16T22:42:43.930Z]            import·org.junit.jupiter.api.Test;

[2024-07-16T22:42:43.930Z]   Run './gradlew :connect:runtime:spotlessApply' to fix these violations.

Signed-off-by: Greg Harris <greg.harris@aiven.io>
Signed-off-by: Greg Harris <greg.harris@aiven.io>
@C0urante

Copy link
Copy Markdown
Contributor

@gharris1727 FYI, I've opened gharris1727#1 to add an integration test for plugin aliases. You are welcome to include it in this PR, or if you'd prefer I can file a PR against trunk to add the test instead.

@gharris1727

Copy link
Copy Markdown
Contributor Author

@C0urante Thanks for implementing an integration test! I think one may be warranted here because it's regressed twice now, and an integration test would have caught this.

I'd prefer to unblock the release quickly, so please retarget that PR at upstream/trunk, thanks!

@gharris1727

Copy link
Copy Markdown
Contributor Author

Test failures look unrelated, and the tests pass for me locally.

@gharris1727
gharris1727 merged commit c97421c into apache:trunk Jul 17, 2024
gharris1727 added a commit that referenced this pull request Jul 18, 2024
…aliases correctly (#16608)

Signed-off-by: Greg Harris <greg.harris@aiven.io>
Reviewers: Chris Egerton <chrise@aiven.io>, Chia-Ping Tsai <chia7712@gmail.com>, Josep Prat <josep.prat@aiven.io>
abhi-ksolves pushed a commit to ksolves/kafka that referenced this pull request Jul 31, 2024
…aliases correctly (apache#16608)

Signed-off-by: Greg Harris <greg.harris@aiven.io>
Reviewers: Chris Egerton <chrise@aiven.io>, Chia-Ping Tsai <chia7712@gmail.com>, Josep Prat <josep.prat@aiven.io>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport-candidate This pull request is a candidate to be backported to previous versions Blocker This pull request is identified as solving a blocker for a release.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants