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

eclipselink cdi with helidon 2.0.1 and custom config not working #2115

Closed
bhushan2901 opened this issue Jul 1, 2020 · 15 comments
Closed

eclipselink cdi with helidon 2.0.1 and custom config not working #2115

bhushan2901 opened this issue Jul 1, 2020 · 15 comments
Assignees
Labels
bug Something isn't working P3

Comments

@bhushan2901
Copy link

Environment Details

  • Helidon Version: 2.0.1
    *Helidon MP
  • JDK version: 11
  • OS: MAC
  • Docker version (if applicable):

Problem Description

I am using ecpliselink cdi in our project when I upgraded from 1.4.4 to 2.0.1 it started throwing below error

Internal Exception: org.jboss.weld.exceptions.UnsatisfiedResolutionException: WELD-001334: Unsatisfied dependencies for type DataSource with qualifiers @default @nAmed

in my project I am using custom file configuration. (all the configuration regarding DB i.e. javax.sql.DataSource.* is in config.properties)

Config.builder().sources(file("conf/config.properties"),
classpath("META-INF/microprofile-config.properties")).build();

When i moved javax.sql.DataSource.* properties to microprofile-config.properties it works fine.

Is there anything I am doing wrong or is this regression ?
I am following below documents for custom configuration. https://helidon.io/docs/v2/#/mp/guides/03_config#config/06_advanced-configuration.adoc

and https://helidon.io/docs/v2/#/mp/guides/15_migration for migration.

Thanks,
Bhushan.

@ljnelson
Copy link
Member

ljnelson commented Jul 1, 2020

Hello; this problem doesn't have anything to do with Eclipselink, right? Just DataSource configuration?

Secondly, I can't tell from the limited information here whether your ConfigBuilder#build() invocation is resulting in a Config that is then being used as the "main" MicroProfile Config Config instance. Perhaps you could post more code or information?

@bhushan2901
Copy link
Author

bhushan2901 commented Jul 1, 2020

yes this may not be problem with eclipselink actually not sure as i dont know the details about how config is being used in CDI.

below is how i start the server :
server = Server.builder().config(buildConfig()).build().start();
final org.eclipse.microprofile.config.Config config = ConfigProvider.getConfig();
System.out.println(config.getValue("javax.sql.DataSource.test.connectionFactoryClassName", String.class));
System.out.println(config.getValue("javax.sql.DataSource.test.URL", String.class));
System.out.println(config.getValue("javax.sql.DataSource.test.user", String.class));
System.out.println(config.getValue("javax.sql.DataSource.test.password", String.class));

private static Config buildConfig() {
return Config.builder().sources(file("conf/config.properties"),
classpath("META-INF/microprofile-config.properties")).build();
}

this dosent work but the console shows correct properties.

whereas when i add below system properties it works perfectly fine.
System.setProperty("javax.sql.DataSource.test.connectionFactoryClassName", "org.h2.jdbcx.JdbcDataSource");
System.setProperty("javax.sql.DataSource.test.URL", "jdbc:h2:mem:test;INIT=RUNSCRIPT FROM 'src/test/resources/sql.init'");
System.setProperty("javax.sql.DataSource.test.user", "sa");
System.setProperty("javax.sql.DataSource.test.password", "");
server = Server.builder().config(buildConfig()).build().start();

@ljnelson
Copy link
Member

ljnelson commented Jul 2, 2020

One further question to help me out. Could you see if your Config class—the one on which you're calling .builder()—is an instance of org.eclipse.microprofile.config.Config?

@bhushan2901
Copy link
Author

No , Config.builder().sources(file("conf/config.properties"),
classpath("META-INF/microprofile-config.properties")).build(); is io.helidon.config.Config

I also tried below. with io.helidon.config.Config class. this did print correct values from property file but still got "Internal Exception: org.jboss.weld.exceptions.UnsatisfiedResolutionException: WELD-001334: Unsatisfied dependencies for type DataSource with qualifiers " exception.

private static Config buildConfig() {
return Config.builder().sources(file("conf/config.properties"),
classpath("META-INF/microprofile-config.properties")).build();
}
Config cfg = buildConfig();
System.out.println(cfg.get("javax.sql.DataSource.test.connectionFactoryClassName"));
System.out.println(cfg.get("javax.sql.DataSource.test.URL"));
System.out.println(cfg.get("javax.sql.DataSource.test.user"));
System.out.println(cfg.get("javax.sql.DataSource.test.password"));
s_server = Server.builder().config(cfg).build().start();

@barchetta barchetta added the P3 label Jul 2, 2020
@barchetta barchetta added the bug Something isn't working label Jul 2, 2020
@ljnelson
Copy link
Member

ljnelson commented Jul 2, 2020

I apologize; I am still confused by your comment. It appears that you tried the same thing twice. Could you please provide a reproducer?

Note that the JPA integration makes use of org.eclipse.microprofile.config.ConfigProvider.getConfig(). We need to determine whether the Config you're supplying—whether it is a Helidon Config or a MicroProfile Config Config—is getting registered properly such that org.eclipse.microprofile.config.ConfigProvider.getConfig() will pick it up.

(Finally, the most portable (from a MicroProfile perspective) solution is not to use this programmatic setup at all, but to write a ConfigSourceProvider following the MicroProfile Config documentation. If one of these is found then the ConfigSources it returns will be used and honored.)

@bhushan2901
Copy link
Author

Hi @ljnelson sorry for confusion i just updated the comment #2115 (comment)

Also to confirm, using both org.eclipse.microprofile.config.Config and io.helidon.config.Config I am able to get the correct values.

@ljnelson
Copy link
Member

ljnelson commented Jul 2, 2020

Assuming you're right, then, the problem will lie in MpConfigProviderResolver.java and/or its interaction with org.eclipse.microprofile.config.ConfigProvider. It will take me quite some time to become familiar with the first class; kindly bear with me.

@ljnelson
Copy link
Member

ljnelson commented Jul 22, 2020

(More notes to myself.)

This excerpt from an exploratory test case I'm writing emulates what's going on when you build the server in the way that you've described, and the JPA extension subsequently calls org.eclipse.microprofile.config.ConfigProvider.getConfig() to pick up the currently built/registered MicroProfile Config object as it should (the specified way to get an org.eclipse.microprofile.config.Config object from within code somewhere if you're not injecting it):

        assertThat(ConfigProviderResolver.instance(), sameInstance(ConfigProviderResolver.instance()));
        // This emulates what you're doing via Server.Builder.config(...) in your code above
        final org.eclipse.microprofile.config.Config mpConfig = ConfigProviderResolver.instance()
            .getBuilder()
            .withSources(MpConfigSources.create(Config.builder() // Helidon Config builder
                                                .sources(ConfigSources.file(Thread.currentThread()
                                                                            .getContextClassLoader()
                                                                            .getResource(this.getClass()
                                                                                         .getSimpleName()
                                                                                         + "/test.yaml")
                                                                            .getPath()))
                                                .build()))
            .build();
        final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        ConfigProviderResolver.instance().registerConfig(mpConfig, classLoader);
        // This emulates what the JPA extension is doing
        final org.eclipse.microprofile.config.Config mpConfig2 = ConfigProvider.getConfig(classLoader);
        // My theory is that these two objects are not identical, but they should be
        assertThat(mpConfig, sameInstance(mpConfig2));

The final assertion fails (my assumption), suggesting that something about Helidon's implementation of ConfigProviderResolver's registerConfig(org.eclipse.microprofile.config.Config, ClassLoader) method is not making that registered object available to ConfigProvider's static getConfig(ClassLoader) method. I need to confirm if this assumption codified in the assertion above is in fact required to be true of MicroProfile Config implementations (such as Helidon's).

{time passes}

See here:

https://github.com/eclipse/microprofile-config/blob/adf90d7f1e674b265d6fa812f9667b1b573c8b8c/api/src/main/java/org/eclipse/microprofile/config/ConfigProvider.java#L94-L106

That would suggest to me that assert ConfigProviderResolver.instance().getConfig(cl) == ConfigProvider.getConfig(cl); must never fail for the same ClassLoader input (i.e. that my test case assertion is correct). Now to check Helidon's implementation of ConfigProviderResolver to see where this might be breaking.

@ljnelson
Copy link
Member

(More notes.)

While my assertion above naively should hold, there is apparently no explicit requirement that it do so. Moving on to explore how these two different MicroProfile Config objects differ. One is a delegate/wrapper object; the other is not, but both should behave the same and should contain the same information.

@ljnelson
Copy link
Member

Both objects do in fact return values from test.yaml, so so far this very isolated test does not reproduce the problematic behavior.

@ljnelson
Copy link
Member

ljnelson commented Jul 22, 2020

Thinking now that perhaps this is at fault:

https://github.com/oracle/helidon/blob/32994ed45be94d3fae1bc22ac3aad0245c8daa13/integrations/cdi/datasource/src/main/java/io/helidon/integrations/datasource/cdi/AbstractDataSourceExtension.java#L57-L65

Line 64 may be too early for the Helidon MicroProfile Config implementation, i.e. depending on the order in which CDI decides to instantiate portable extensions this one might be instantiated before others that have a role in making the built Config object available to the ConfigProvider. I need to be careful here since moving this may impact native image support (I am naïve in this area).

@ljnelson
Copy link
Member

Moving this later results in a NullPointerException in some file called MetaConfigFinder.java:

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)

Still digging.

@ljnelson
Copy link
Member

I believe that at least some of root issues can be traced to something I'm seeing in #2207. It in turn is indirectly related to WELD-2494.

@ljnelson
Copy link
Member

This should have been closed earlier; my apologies. Please see #2207 for the root issue and #2269 for the resolution.

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

No branches or pull requests

3 participants