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

Switch Vert.x, datasource, reactive datasource and Agroal to @ConfigMapping #33228

Merged
merged 7 commits into from
Aug 2, 2023

Conversation

gsmet
Copy link
Member

@gsmet gsmet commented May 9, 2023

@quarkus-bot

This comment has been minimized.

@quarkus-bot

This comment has been minimized.

@radcortez
Copy link
Member

Please, have a look at smallrye/smallrye-config#939. It would be great if we could try this properly before merging and releasing it in SR Config, so we can make any adjustments.

@gsmet
Copy link
Member Author

gsmet commented May 26, 2023

@radcortez I have been struggling with this for a while and I think I will need your help.
I had to convert the Redis extension because it is using some config classes from Vert.x.

Unfortunately, I have two issues converting this extension:

  • NetConfig has an Optional<ProxyConfig> proxyOptions() configuration property. It used to be an empty Optional when no proxy configuration was set, it is now defined (with the default values set). This causes problems as it enables the proxy configuration. I think this new behavior will cause some problems for a lot of extensions so I suppose we should try to go back to the existing behavior. Or we will have to find another way to cover that use case.
  • I wonder if @WithConverter works similarly to @ConvertWith when it comes to List because I also have this error:
[ERROR]   NonDefaultFileForDefaultClientImportPreloadingTest » Runtime java.lang.RuntimeException: io.quarkus.builder.BuildException: Build failure: Build failed due to errors
	[error]: Build step io.quarkus.redis.deployment.client.RedisClientProcessor#init threw an exception: java.lang.ClassCastException: class java.lang.String cannot be cast to class java.util.List (java.lang.String and java.util.List are in module java.base of loader 'bootstrap')
	at io.quarkus.redis.deployment.client.RedisClientProcessor.getRedisLoadScript(RedisClientProcessor.java:300)

I added some comments in the code, I will point them to you in subsequent GitHub comments.

I will start to test your Map default branch now and report back.

// TODO @radcortez, this apparently returns a String now instead of a List<String>
var scripts = config.loadScript();
Copy link
Member Author

Choose a reason for hiding this comment

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

This is the @WithConverter issue that leads to a class cast exception.

Copy link
Member

Choose a reason for hiding this comment

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

You need to map it like this:
Optional<List<@WithConverter(TrimmedStringConverter.class)String>> loadScript();

@WithConverter now applies in the exact nested element type.

Copy link
Member Author

@gsmet gsmet Jun 15, 2023

Choose a reason for hiding this comment

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

That's what I did and the class cast error is gone:

    @ConfigDocDefault("import.redis in DEV, TEST ; no-file otherwise")
    Optional<List<@WithConverter(TrimmedStringConverter.class) String>> loadScript();

But it looks like the converter is somehow not applied:

Caused by: io.quarkus.runtime.configuration.ConfigurationException: Unable to find file referenced in 'quarkus.redis.redis-load-script=import/my-import.redis,  sample.redis'. Remove property or add file to your path.
	at io.quarkus.redis.deployment.client.RedisClientProcessor.preloadRedisData(RedisClientProcessor.java:263)
	at io.quarkus.redis.deployment.client.RedisClientProcessor.init(RedisClientProcessor.java:185)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at io.quarkus.deployment.ExtensionLoader$3.execute(ExtensionLoader.java:909)
	at io.quarkus.builder.BuildContext.run(BuildContext.java:282)
	at org.jboss.threads.ContextHandler$1.runWith(ContextHandler.java:18)
	at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)
	at java.base/java.lang.Thread.run(Thread.java:829)
	at org.jboss.threads.JBossThread.run(JBossThread.java:501)

Copy link
Member

Choose a reason for hiding this comment

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

It needs to be defined as:
Optional<@WithConverter(TrimmedStringConverter.class) List<String>> loadScript();

Sorry for misleading in the previous commented. Just pushed a fix.

Copy link
Member Author

Choose a reason for hiding this comment

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

Mkay. TBH, that's odd, I would have expected the converter to be placed on its target rather than the container.

Copy link
Member

Choose a reason for hiding this comment

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

Yes, it is a little misleading. I'll need to improve that.

Copy link
Member

Choose a reason for hiding this comment

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


tcp.localAddress().ifPresent(net::setLocalAddress);
tcp.nonProxyHosts().ifPresent(net::setNonProxyHosts);
// TODO @radcortez proxyOptions() used to be empty when nothing was set and is not empty anymore
Copy link
Member Author

Choose a reason for hiding this comment

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

This is where the problem with Optional manifests itself.

Copy link
Member

Choose a reason for hiding this comment

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

The issue here is that it can work both ways. You may want an instance of the configuration with the defaults and use it, or completely disregard it. This was not introduced with the defaults for Maps work.

Looking into the mapping and business logic, what we are saying is:

"Use these defaults only if certain properties are defined"

This creates conditional elements where only certain things are set. This was indeed supported when the default was only set with @WithDefault, but caused issues when we wanted to override only the default (since in that case it would trigger the element creation)

We simplified this, by creating elements for defaults in every case, and it is up to the user to apply the business logic on how they want to handle it. You are going to find cases where you want always to find the defaults, and there are going to be cases where you only want to use them if other properties are set (like the Proxy case here).

I believe a more correct mapping to represent such case is something like:

    @ConfigMapping(prefix = "proxy")
    interface ProxyOptionalDefaults {
        ProxyConfig proxy();

        interface ProxyConfig {
            @WithParentName
            Optional<ProxyHost> host();

            @WithParentName
            ProxySettings settings();
        }

        interface ProxyHost {
            String host();
        }

        interface ProxySettings {
            @WithDefault("3128")
            int port();
        }
    }

@radcortez
Copy link
Member

@radcortez I have been struggling with this for a while and I think I will need your help.

I'll have a look.

@gsmet gsmet marked this pull request as draft May 26, 2023 14:16
@gsmet
Copy link
Member Author

gsmet commented May 26, 2023

@radcortez BTW, maybe I was unclear but the rest is working. The two remaining issues are the ones I mentioned about the Redis extension.

@radcortez
Copy link
Member

@radcortez BTW, maybe I was unclear but the rest is working. The two remaining issues are the ones I mentioned about the Redis extension.

No, I've got it :)

I've already replied to both.

@geoand
Copy link
Contributor

geoand commented Jul 28, 2023

🏆

@radcortez
Copy link
Member

And ready \o/. Thanks for your help on this @radcortez !

You did all the work. I've just fixed my own bugs :)

@quarkus-bot

This comment has been minimized.

@gsmet
Copy link
Member Author

gsmet commented Jul 29, 2023

@radcortez unfortunately, I lost your commit when I rebased and I remember it was just a line but couldn't figure it out. Could you again push your fix on top of the rebased branch? Sorry and thanks!

@radcortez
Copy link
Member

@radcortez unfortunately, I lost your commit when I rebased and I remember it was just a line but couldn't figure it out. Could you again push your fix on top of the rebased branch? Sorry and thanks!

Sure. Done!

@radcortez
Copy link
Member

Hum, now sure why but my commit is only showing in your branch and the PR did not update automatically.

@gsmet
Copy link
Member Author

gsmet commented Jul 31, 2023

That's very odd. Let me try to get the commit, rebase and force push.

@gsmet
Copy link
Member Author

gsmet commented Jul 31, 2023

It worked, let's see what CI has to say.

@quarkus-bot

This comment has been minimized.

Copy link
Member

@yrodiere yrodiere left a comment

Choose a reason for hiding this comment

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

LGTM overall, though I'd be lying if I said this was a pleasant read :x

Also, I added a few minor comments below.

Comment on lines -82 to +74
@ConfigItem
public int reconnectAttempts;
@WithDefault("0")
int reconnectAttempts();
Copy link
Member

Choose a reason for hiding this comment

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

Is there a reason for this new @WithDefault("0")? Isn't 0 the default for primitive integers anyway?

Just asking in case this is a workaround for a weird behavior I should be aware of...

Copy link
Member Author

Choose a reason for hiding this comment

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

See my answer above. For booleans, SmallRye Config was complaining so I made them explicit.

Comment on lines -124 to +114
@ConfigItem
public boolean tcpKeepAlive;
@WithDefault("false")
boolean tcpKeepAlive();
Copy link
Member

Choose a reason for hiding this comment

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

Same here, I'd expect false to be the default for primitive booleans... ?

Comment on lines -142 to +131
@ConfigItem
public boolean trustAll;
@WithDefault("false")
boolean trustAll();
Copy link
Member

Choose a reason for hiding this comment

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

Same here, I'd expect false to be the default for primitive booleans... ?

Comment on lines -18 to +31
@ConfigItem
public DataSourceJdbcRuntimeConfig jdbc;
DataSourceJdbcRuntimeConfig jdbc();

/**
* Additional named datasources.
*/
@ConfigDocSection
@ConfigDocMapKey("datasource-name")
@ConfigItem(name = ConfigItem.PARENT)
public Map<String, DataSourceJdbcOuterNamedRuntimeConfig> namedDataSources;
@WithParentName
@WithDefaults
Map<String, DataSourceJdbcOuterNamedRuntimeConfig> namedDataSources();
Copy link
Member

Choose a reason for hiding this comment

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

Any reason not to merge these into a single datasources() method?

If so, can you please add a comment here so I don't break your stuff next time I end up in this part of the code? :)

Copy link
Member Author

Choose a reason for hiding this comment

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

I think it doesn't fly because you have:

quarkus.datasource.jdbc....
quarkus.datasource."name".jdbc....

I didn't really try but I thought it would be hard to make it work.

Copy link
Member

Choose a reason for hiding this comment

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

Ok I suppose we'll send a PR about that later

Comment on lines +144 to +185
DevServicesConfig devServicesConfig = new DevServicesConfig() {

@Override
public boolean enabled() {
return enabled;
}

@Override
public Optional<String> imageName() {
return Optional.empty();
}

@Override
public OptionalInt port() {
return OptionalInt.empty();
}

@Override
public boolean shared() {
return false;
}

@Override
public String serviceName() {
return null;
}

@Override
public Map<String, String> containerEnv() {
return Map.of();
}
};

DevServiceConfiguration devServiceConfiguration = new DevServiceConfiguration() {

@Override
public DevServicesConfig devservices() {
return devServicesConfig;
}
};

return devServiceConfiguration;
Copy link
Member

Choose a reason for hiding this comment

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

Same here, I'd suggest mockito.

@quarkus-bot
Copy link

quarkus-bot bot commented Aug 1, 2023

Failing Jobs - Building e244bbe

Status Name Step Failures Logs Raw logs
✔️ JVM Tests - JDK 11
✔️ JVM Tests - JDK 17
JVM Tests - JDK 20 Build ⚠️ Check → Logs Raw logs

@radcortez radcortez linked an issue Aug 2, 2023 that may be closed by this pull request
@gsmet gsmet merged commit 9aa28e3 into quarkusio:main Aug 2, 2023
49 of 50 checks passed
@quarkus-bot quarkus-bot bot removed the triage/waiting-for-ci Ready to merge when CI successfully finishes label Aug 2, 2023
@quarkus-bot quarkus-bot bot added this to the 3.3 - main milestone Aug 2, 2023
@quarkus-bot quarkus-bot bot added the kind/enhancement New feature or request label Aug 2, 2023
fedinskiy added a commit to fedinskiy/quarkus-test-suite that referenced this pull request Aug 28, 2023
- Class CrashingXADataSource used methods[1], which were added in 3.3.0

[1] quarkusio/quarkus#33228
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Optimize config generation
4 participants