-
-
Notifications
You must be signed in to change notification settings - Fork 9k
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
[JENKINS-46386] - Detach ServletContext logic to a pluggable Provider #3065
[JENKINS-46386] - Detach ServletContext logic to a pluggable Provider #3065
Conversation
It should prevent classloading issues on agents for sure.
This pull request originates from a CloudBees employee. At CloudBees, we require that all pull requests be reviewed by other CloudBees employees before we seek to have the change accepted. If you want to learn more about our process please see this explanation. |
|
||
//TODO: This should use the annotation indexer at least. | ||
// Ideally it should be a part of the Jenkins singleton in order to play nicely with {@code JenkinsRule}. | ||
private static final CopyOnWriteMap<String, SystemPropertiesProvider> providers = new CopyOnWriteMap.Hash<>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the map symatics are not really unused - you could remove using the actual provider (object) to remove and use a standard CopyOnWrite collection.
Ontop of this you get different (random) iteration order (the CopyOnWriteMap makes no guarantees about ordering). so could get hard to reproduce bugs when you sometimes get a system property and other times get a ServletContext parameter...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, probably Map is not required. I just added it to support Removal, but there are more simple and efficient ways for sure
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, this is all restricted, and there is no removal, so KISS.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
left a comment about what looks like a bug inline.
ontop of this I wonder if anyone really uses this functionality. Would a flat properties file in JENKINS_HOME (CWD of the agent) not be much better and would work on agents and masters alike?
(OT) The fact the jenkins changes behaviour based on unversioned environment variables also troubles me (I still see people starting services with /etc/initi.d/servericec start
... which will not start with a clean environment but whatever the current user has polluted their env with to begin with
Yes, I confirm I use these settings to customize the Jenkins behavior from my custom Jenkins WAR packaging. More in the private chat.
I suggest filing a ticket |
I need to fix the test codebase. Yes, I will try compiling it on my machine next time... |
…INS-46386-systemPropertiesProvider
The broader issue is that #3067 lacked a test because
This is long filed in JIRA and I would rather prioritize a fix of that so we are not making speculative and untestable fixes. |
Yes, even on the wild the issue happens rarely. @KostyaSha got a reproducible scenario in YAD, but I was using the plugin easily for many containers without an issue. ATH does not catches it as well. @jglick are you fine with the current fix PoC in this PR? For sure, we need to make the classloading logic more efficient + maybe add some static analysis around the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A bit overengineered, and still does nothing to block us from making the broader category of mistakes in the future (nor is there any test proving that the fix works), but seems to be a step in the right direction.
*/ | ||
@Override | ||
@SuppressFBWarnings(value = "ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD", | ||
justification = "Currently Jenkins instance may have one ond only one context") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo
* The ServletContext to get the "init" parameters from. | ||
*/ | ||
@CheckForNull | ||
private static ServletContext theContext; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this static
?
* @see ServletContextSystemPropertiesProvider | ||
*/ | ||
@Restricted(NoExternalUse.class) | ||
public abstract class SystemPropertiesProvider { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This and ServletContextSystemPropertiesProvider
could have just have been nested classes of SystemProperties
, I think; would be more readable.
|
||
//TODO: This should use the annotation indexer at least. | ||
// Ideally it should be a part of the Jenkins singleton in order to play nicely with {@code JenkinsRule}. | ||
private static final CopyOnWriteMap<String, SystemPropertiesProvider> providers = new CopyOnWriteMap.Hash<>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, this is all restricted, and there is no removal, so KISS.
* Gets all registered providers. | ||
* @return Collection of registered providers. | ||
*/ | ||
public static Collection<SystemPropertiesProvider> all() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unused
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Restricted anyway
* @return Removed provider (if any) | ||
*/ | ||
@CheckForNull | ||
public static SystemPropertiesProvider removeProvider(@Nonnull Class<?> providerClass) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unused
@Before | ||
public void setUp() { | ||
// Does not matter what we call, the fields are static | ||
new ServletContextSystemPropertiesProvider().contextInitialized(new ServletContextEvent(j.jenkins.servletContext)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why would this not be called automatically by Jetty during JenkinsRule
setup?
Except:
as I noted. |
Needs fix, yes. Due to whatever reason, FindBugs behaves differently in CI |
After #3362 this fix is not actual, but it still makes sense to revive it once we need better extensibility |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this still relevant?
unlikely |
@oleg-nenashev also, it's conflicted. What do you think about closing it? |
Aside grumbling about priority switches and lots of almost-done work being abandoned, I am fine with that. Closing it |
It should prevent classloading issues on agents for sure. The implementation is a bit hackish, ideally providers should be somehow integrated into the
Jenkins
object singleton (though then we need to prevent variable usage before Jenkins' full initialization)No autotests so far, because it requires specification of a custom
web.xml
for the WAR file. Will tests the case manuallySee JENKINS-46386.
Proposed changelog entries
javax.servlet.ServletContextListener
classloading issues. Now the class is not being propagated to agentsSubmitter checklist
* Use the
Internal:
prefix if the change has no user-visible impact (API, test frameworks, etc.)Desired reviewers
@reviewbybees @KostyaSha