* Add new module optional-depender and a new failing test
* Variant plugin is a dependency of optional-depender
Optional-depender contains the following class
@OptionalExtension(requirePlugins = {"dependee"})
public class OptionalDependerExtension {
private static void foo(Dependee d) {
}
}
* [JENKINS-60449] Move plugin initialization at the end, keep only one extension refresh
* Improve logic to detect classloading issues
Inspect all declared constructors/methods/fields recursively to exclude
failing classes from Guice rather than have Guice explode.
This also fix the failing test, but the previous commit is still better
because it avoids an extra Jenkins.get().refreshExtensions() call.
* Only test resolveClass method if the classloader is not the bootstrap one
* add support for JSR250 @PostConstruct
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
* with PostConstruct method no need to explicitely invoke load() anymore
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
* introduce PersistentDescriptor to flag Descriptors
which expect load() to be invoked.
This prevent double execution for plugins which
have been designed on previous version of code and
don’t expect load to be automatically invoked.
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
* document PostConstruct method discovery logic
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
* Force reflective access to non-public @PostConstruct methods
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
* check @PostConstruct annotation both on method and on implemented interface with a matching method.
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
* typo
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
* [JENKINS-50336] Only keep extensions that could be loaded in memory
So that delta computations will re-attempt to load any extension that
previously failed or was skipped after a new plugin is installed.
After installing a plugin, need to refresh extensions in order to pick
up extensions that can be loaded thanks to this new plugin.
* [JENKINS-50336] @OptionalExtension annotated classes were not being picked up after dynamic load of variant
Recompute GuiceExtensionAnnotation list when refreshing extensions
In addition to cluttering the namespace, unused imports generate
compiler warnings, introducing noise and obscuring more important
compiler warnings. This change removes them.
Even though SezpozModule.configure catches and ignores the faulty component, Guice still dies:
… hudson.ExtensionFinder$GuiceFinder <init>
SEVERE: Failed to create Guice container from all the plugins
com.google.inject.internal.guava.collect.$ComputationException: java.lang.NoClassDefFoundError: org/eclipse/jgit/storage/file/FileRepository
at …
at com.google.inject.Guice.createInjector(Guice.java:73)
at hudson.ExtensionFinder$GuiceFinder.<init>(ExtensionFinder.java:279)
The motivation of this is to enable test code to inject components from Jenkins, which means we need a single Injector that can see all of those, including @TestExtension and regular @Extension. Then I realized that the current implementation is broken, as it creates two independent Injectors. This has other undesirable side effects like @TestExtension components not being able to inject @Extensions, etc.
I briefly experimented with hierarchical Injectors (where we first create Injector that loads @Extension then create another that loads @TestExtension as a child), but this was hard to get right as we have no control over which ExtensionFinder gets instantiated first --- we'd be at the mercy of SezPoz.
So the eventual approach is to allow a single GuiceFinder to recognize multiple annotations. This also works well with our using child injector for installing plugins without restart
An investigation on NECTAR-50 revealed that the dead lock prevention made in 02fbfd9ed5 and c5269550d5 are causing slow down by having too many threads go through scouting, which in turn calls into classloader (which is synchronized.) Reduce the overhead by reusing sezpoz index so that classloading overhead is minimal.