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

NullPointerException in MetaConfigFinder in CDI situations #2207

Closed
ljnelson opened this issue Jul 22, 2020 · 4 comments · Fixed by #2269
Closed

NullPointerException in MetaConfigFinder in CDI situations #2207

ljnelson opened this issue Jul 22, 2020 · 4 comments · Fixed by #2269
Assignees
Labels
bug Something isn't working config MP P3

Comments

@ljnelson
Copy link
Member

I don't want this to get lost; I'm not yet sure what the culprit is.

From within a unit test (in the datasource-hikaricp project) that I'm working on, when I do:

Server.builder();

…this causes the CDI container to start coming up. One of the portable extensions I'm working on (trying to fix #2115) was calling ConfigProvider.getConfig() in its constructor, which might be responsible for #2115's issue. I moved this call to effectively be at AfterBeanDiscovery time and tried this unit test in the Hikari package to make sure I didn't break anything.

When I did this and recompiled things and then ran the HikariCP datasource extension's simple unit test, I couldn't get past the Server.builder() step, which failed with the following partial (suppressed) stack:

java.lang.NullPointerException
	at io.helidon.config.MetaConfigFinder.findClasspath(MetaConfigFinder.java:159)
	at io.helidon.config.MetaConfigFinder.lambda$findSource$5(MetaConfigFinder.java:115)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
	at java.base/java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1601)
	at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:127)
	at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:502)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:488)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
	at java.base/java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:150)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:543)
	at io.helidon.config.MetaConfigFinder.findSource(MetaConfigFinder.java:117)
	at io.helidon.config.MetaConfigFinder.findMetaConfigSource(MetaConfigFinder.java:85)
	at io.helidon.config.MetaConfigFinder.findMetaConfig(MetaConfigFinder.java:55)
	at io.helidon.config.MetaConfig.metaConfig(MetaConfig.java:107)
	at io.helidon.config.mp.MpConfigProviderResolver.buildConfig(MpConfigProviderResolver.java:87)
	at io.helidon.config.mp.MpConfigProviderResolver.getConfig(MpConfigProviderResolver.java:74)
	at io.helidon.config.mp.MpConfigProviderResolver.getConfig(MpConfigProviderResolver.java:54)
	at org.eclipse.microprofile.config.ConfigProvider.getConfig(ConfigProvider.java:91)

The actual error was here:

java.lang.ExceptionInInitializerError
	at io.helidon.microprofile.cdi.ContainerInstanceHolder.fromBuildTimeInitializer(ContainerInstanceHolder.java:58)
	at io.helidon.microprofile.cdi.ContainerInstanceHolder.get(ContainerInstanceHolder.java:50)
	at io.helidon.microprofile.cdi.HelidonContainer.instance(HelidonContainer.java:48)
	at io.helidon.microprofile.server.Server$Builder.<clinit>(Server.java:134)
	at io.helidon.microprofile.server.Server.builder(Server.java:91)

Calling ConfigProvider.getConfig() will be something that users will attempt to do from within their own portable extensions as well.

I'm sure I'm making a mistake somewhere but I don't know where or how.

@ljnelson
Copy link
Member Author

ljnelson commented Jul 23, 2020

(Notes to self.)

ConfigProvider.getConfig() is called as the CDI container is being initialized. This appears to work fine and builds a new Config and registers it appropriately under the non-null ClassLoader that is the context classloader.

Then, during portable extension time, ConfigProvider.getConfig() is called again. This should end up loading the Config that was registered earlier, but oddly the context classloader at this point is null! Consequently, ConfigProviderResolver starts building a new one…and I haven't gotten further than this yet. So I need to find out who is responsible for nulling out the context classloader for the current thread.

💡 or it may be that…Weld deploys beans via the fork/join pool. It may be that a fork/join thread does not have a context classloader? Hmm.

{time passes}

See https://bugs.openjdk.java.net/browse/JDK-8184335 for reference. Is the system classloader null? Is it even possible for that to be a thing?

{time passes}

Ah, no, the system classloader is set just fine. But sure enough, the fork/join pool thread responsible for deploying beans has null as its context classloader.

@ljnelson
Copy link
Member Author

@ljnelson
Copy link
Member Author

ljnelson commented Aug 18, 2020

Hmm; my initial impression was that I could somehow {waves hands} just drop in some kind of AbstractExecutorServices implementation that simply wouldn't set the context classloader to null. But it turns out that unlike some other services in Weld, the kind of AbstractExecutorServices implementation used is not really customizable as it is limited to a fixed set, of which none of the members are entirely suitable.

Or maybe not:

https://github.com/weld/core/blob/b7745266bc674d145cddd19d26c5d6f0f3966193/impl/src/main/java/org/jboss/weld/bootstrap/WeldStartup.java#L311-L320

See also:

https://github.com/weld/core/blob/b7745266bc674d145cddd19d26c5d6f0f3966193/environments/se/core/src/main/java/org/jboss/weld/environment/se/Weld.java#L779-L785

And:

https://github.com/weld/core/blob/b7745266bc674d145cddd19d26c5d6f0f3966193/impl/src/main/java/org/jboss/weld/bootstrap/WeldStartup.java#L226

…which I think will let me plug in my own service.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working config MP P3
Projects
Archived in project
2 participants