Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SetContextClassLoader utility class #6575

Merged
merged 9 commits into from
Aug 2, 2022

Conversation

basil
Copy link
Member

@basil basil commented May 14, 2022

Promoting https://github.com/jenkinsci/ldap-plugin/blob/3731881c37d1c66f8f43101b7f8b0cdd5f1eba56/src/main/java/jenkins/security/plugins/ldap/SetContextClassLoader.java into a core utility class.

Example usages

Production code: jenkinsci/xcode-plugin#114
Test code: jenkinsci/jaxb-plugin#34

Proposed changelog entries

Introduced SetContextClassLoader utility class to assist in plugin class loading.

Proposed upgrade guidelines

N/A

Submitter checklist

  • (If applicable) Jira issue is well described
  • Changelog entries and upgrade guidelines are appropriate for the audience affected by the change (users or developer, depending on the change) and are in the imperative mood. Examples
    • Fill-in the Proposed changelog entries section only if there are breaking changes or other changes which may require extra steps from users during the upgrade
  • Appropriate autotests or explanation to why this change has no tests
  • New public classes, fields, and methods are annotated with @Restricted or have @since TODO Javadoc, as appropriate.
  • For dependency updates: links to external changelogs and, if possible, full diffs

Desired reviewers

@mention

Maintainer checklist

Before the changes are marked as ready-for-merge:

  • There are at least 2 approvals for the pull request and no outstanding requests for change
  • Conversations in the pull request are over OR it is explicit that a reviewer does not block the change
  • Changelog entries in the PR title and/or Proposed changelog entries are accurate, human-readable, and in the imperative mood
  • Proper changelog labels are set so that the changelog can be generated automatically
  • If the change needs additional upgrade steps from users, upgrade-guide-needed label is set and there is a Proposed upgrade guidelines section in the PR title. (example)
  • If it would make sense to backport the change to LTS, a Jira issue must exist, be a Bug or Improvement, and be labeled as lts-candidate to be considered (see query).

@basil basil added the developer Changes which impact plugin developers label May 14, 2022
@basil basil added the squash-merge-me Unclean or useless commit history, should be merged only with squash-merge label May 14, 2022
Comment on lines 57 to 62
public SetContextClassLoader(Class<?> clazz) {
t = Thread.currentThread();
orig = t.getContextClassLoader();
// It is too bad that Reflection.getCallerClass() is a private API.
t.setContextClassLoader(clazz.getClassLoader());
}
Copy link
Member Author

Choose a reason for hiding this comment

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

Once we're on Java 11, we could perhaps remove the clazz argument and get the calling class via the StackWalker API.

Copy link
Member

Choose a reason for hiding this comment

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

FWIW I would much prefer the explicit Class argument as currently written here. It is hardly bothersome to pass, and sometimes you may actually want something other than the calling class: a class from a library, a plugin you depend upon, etc. Magically inferring an argument according to the caller is a poor practice in terms of legibility and predictability; for example, it means that supposedly safe refactorings like pull up method may quietly lead to different behavior.

Copy link
Member Author

Choose a reason for hiding this comment

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

Well you can have your opinion and I can have mine. I actually think a no-argument version is preferable since you can cut and paste code from one class to another without having to worry about updating the calling class argument to reflect the new home of the code.

@basil
Copy link
Member Author

basil commented May 14, 2022

I think I am going leave this as draft/on-hold until we require Java 11. I would love to have a clean API from day 1 (with zero arguments), but that only seems possible with Java 11 features like StackWalker. I would rather avoid introducing multiple one-argument constructors only to have to deprecate them later.

@basil basil added the on-hold This pull request depends on another event/release, and it cannot be merged right now label May 14, 2022
@basil basil marked this pull request as draft May 14, 2022 18:37
@basil basil closed this May 16, 2022
Comment on lines 57 to 62
public SetContextClassLoader(Class<?> clazz) {
t = Thread.currentThread();
orig = t.getContextClassLoader();
// It is too bad that Reflection.getCallerClass() is a private API.
t.setContextClassLoader(clazz.getClassLoader());
}
Copy link
Member

Choose a reason for hiding this comment

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

FWIW I would much prefer the explicit Class argument as currently written here. It is hardly bothersome to pass, and sometimes you may actually want something other than the calling class: a class from a library, a plugin you depend upon, etc. Magically inferring an argument according to the caller is a poor practice in terms of legibility and predictability; for example, it means that supposedly safe refactorings like pull up method may quietly lead to different behavior.

core/src/main/java/jenkins/util/SetContextClassLoader.java Outdated Show resolved Hide resolved
@basil basil reopened this Jul 31, 2022
@basil basil removed the on-hold This pull request depends on another event/release, and it cannot be merged right now label Jul 31, 2022
@basil basil marked this pull request as ready for review July 31, 2022 01:00
@basil basil requested a review from jglick July 31, 2022 01:17
* @since TODO
*/
public SetContextClassLoader() {
this(StackWalker.getInstance().getCallerClass());
Copy link
Member

Choose a reason for hiding this comment

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

Comment on lines +64 to +65
public SetContextClassLoader() {
this(StackWalker.getInstance().getCallerClass());
Copy link
Member

Choose a reason for hiding this comment

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

Still -0 on including the no-arg overload as in #6575 (comment): StackWalker and similar idioms should be avoided in production code.

Copy link
Member

Choose a reason for hiding this comment

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

(an Object argument delegating to the Class overload would be fine, for calls from non-static contexts)

@basil
Copy link
Member Author

basil commented Aug 1, 2022

This PR is now ready for merge. We will merge it after approximately 24 hours if there is no negative feedback. Please see the merge process documentation for more information about the merge process. Thanks!

@basil basil added the ready-for-merge The PR is ready to go, and it will be merged soon if there is no negative feedback label Aug 1, 2022
@jglick
Copy link
Member

jglick commented Aug 1, 2022

BTW there are a few internal places that could use the new utility as a demonstration: ClassicPluginStrategy, ContextResettingExecutorService, TimerTest, PluginManagerTest

@basil
Copy link
Member Author

basil commented Aug 1, 2022

Two examples of usages of the new utility were provided in the PR description as a demonstration. There are a lot more that could be done.

@basil basil merged commit f77a28b into jenkinsci:master Aug 2, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
developer Changes which impact plugin developers ready-for-merge The PR is ready to go, and it will be merged soon if there is no negative feedback squash-merge-me Unclean or useless commit history, should be merged only with squash-merge
Projects
None yet
4 participants