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

Configuration custom converters fail on primitive type arrays since Quarkus v3.18 #46170

Closed
jdussouillez opened this issue Feb 10, 2025 · 1 comment · Fixed by #46171
Closed
Assignees
Labels
area/config kind/bug Something isn't working
Milestone

Comments

@jdussouillez
Copy link

jdussouillez commented Feb 10, 2025

Describe the bug

Since Quarkus v3.18.0 and above, custom converters for primitive type arrays make Quarkus fail at startup with a ClassNotFoundException exception ([B class not found, so byte[] class).

Here's a simple converter to read a String value as a byte array:

public class ByteArrayConfigConverter implements Converter<byte[]> {

    @Override
    public byte[] convert(final String s) {
        return s.getBytes(StandardCharsets.UTF_8);
    }
}

In Quarkus v3.17.8, Quarkus is starting correctly and the converter works. Since Quarkus v3.18.0 (still in latest 3.18.2), Quarkus is failing when starting up.

Expected behavior

Quarkus should start correctly.

Actual behavior

Quarkus startup fails with ClassNotFoundException.

ERROR [io.qua.run.Quarkus] (Quarkus Main Thread) Error running Quarkus: java.lang.ExceptionInInitializerError
	at io.quarkus.runner.ApplicationImpl.<clinit>(Unknown Source)
	at java.base/jdk.internal.misc.Unsafe.allocateInstance(Native Method)
	at java.base/java.lang.invoke.DirectMethodHandle.allocateInstance(DirectMethodHandle.java:501)
	at io.quarkus.runtime.Quarkus.run(Quarkus.java:76)
	at io.quarkus.runtime.Quarkus.run(Quarkus.java:48)
	at io.quarkus.runtime.Quarkus.run(Quarkus.java:137)
	at io.quarkus.runner.GeneratedMain.main(Unknown Source)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at io.quarkus.runner.bootstrap.StartupActionImpl$1.run(StartupActionImpl.java:116)
	at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: java.lang.RuntimeException: java.lang.ClassNotFoundException: [B
	at io.quarkus.runtime.configuration.AbstractConfigBuilder.withConverter(AbstractConfigBuilder.java:30)
	at io.quarkus.runtime.generated.StaticInitConfigCustomizer.configBuilder(Unknown Source)
	at io.smallrye.config.SmallRyeConfigBuilder.build(SmallRyeConfigBuilder.java:770)
	at io.quarkus.runtime.generated.Config.<clinit>(Unknown Source)
	... 11 more
Caused by: java.lang.ClassNotFoundException: [B
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526)
	at io.quarkus.bootstrap.classloading.QuarkusClassLoader.loadClass(QuarkusClassLoader.java:569)
	at io.quarkus.bootstrap.classloading.QuarkusClassLoader.loadClass(QuarkusClassLoader.java:517)
	at io.quarkus.bootstrap.classloading.QuarkusClassLoader.loadClass(QuarkusClassLoader.java:569)
	at io.quarkus.bootstrap.classloading.QuarkusClassLoader.loadClass(QuarkusClassLoader.java:517)
	at io.quarkus.runtime.configuration.AbstractConfigBuilder.withConverter(AbstractConfigBuilder.java:28)
	... 14 more

How to Reproduce?

Reproducer: https://github.com/jdussouillez/quarkus-custom-converter

  1. Run ./mvnw quarkus:dev => Failure
  2. Run ./mvnw quarkus:dev -Dquarkus.platform.version=3.17.8 => Works fine

Output of uname -a or ver

No response

Output of java -version

openjdk version "21.0.5" 2024-10-15 LTS

Quarkus version or git rev

v3.18.0 ... v3.18.2

Build tool (ie. output of mvnw --version or gradlew --version)

Apache Maven 3.9.9

Additional information

I guess it's a regression because it's not mention in 3.18 migration guide. And it's not mentionned in Microprofile config documentation.

A workaround for v3.18 is to use a record to wrap the byte[] field.

public record KeyConfig(byte[] key) {
}

// ...

public class KeyConfigConverter implements Converter<KeyConfig> {

    @Override
    public KeyConfig convert(final String s) {
        return new KeyConfig(s.getBytes(StandardCharsets.UTF_8));
    }
}

// ...

@ConfigProperty(name = "myapp.key.value")
protected KeyConfig keyConfig;
@jdussouillez jdussouillez added the kind/bug Something isn't working label Feb 10, 2025
Copy link

quarkus-bot bot commented Feb 10, 2025

/cc @radcortez (config)

@jdussouillez jdussouillez changed the title Configuration custom converters fails on primitive type arrays since Quarkus v3.18 Configuration custom converters fail on primitive type arrays since Quarkus v3.18 Feb 10, 2025
@geoand geoand self-assigned this Feb 10, 2025
geoand added a commit to geoand/quarkus that referenced this issue Feb 10, 2025
We essentially use Class.forName to load the class instead of the
ClassLoader directly, as the former knows how to deal with arrays

Fixes: quarkusio#46170
geoand added a commit to geoand/quarkus that referenced this issue Feb 10, 2025
We essentially use Class.forName to load the class instead of the
ClassLoader directly, as the former knows how to deal with arrays

Fixes: quarkusio#46170
geoand added a commit that referenced this issue Feb 10, 2025
Fix config converter loading issue when arrays are used
@quarkus-bot quarkus-bot bot added this to the 3.19 - main milestone Feb 10, 2025
@gsmet gsmet modified the milestones: 3.19 - main, 3.18.3 Feb 11, 2025
gsmet pushed a commit to gsmet/quarkus that referenced this issue Feb 11, 2025
We essentially use Class.forName to load the class instead of the
ClassLoader directly, as the former knows how to deal with arrays

Fixes: quarkusio#46170
(cherry picked from commit 909bf16)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/config kind/bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants