Skip to content
This repository has been archived by the owner on Feb 23, 2023. It is now read-only.

@ConfigurationProperties with @Validated - native build fails when annotations present on a record #1462

Closed
prettymama opened this issue Jan 22, 2022 · 5 comments
Assignees
Labels
status: duplicate A duplicate of another issue type: bug A general bug

Comments

@prettymama
Copy link

prettymama commented Jan 22, 2022

Suppose I have application.properties with this line

server.port = 8080

that I want to map with @ConfigurationProperties but instead of a class I place the annotation on a record (which is OK with Spring Boot)

@ConfigurationProperties("server")
@Validated
public record ServerConfiguration(@Min(1) int port) {}

The AOT processor tries to proxy it and fails as it cannot be done.

java.lang.IllegalArgumentException: Cannot subclass primitive, array or final types: class xxx.ServerConfiguration
        at net.bytebuddy.ByteBuddy.subclass(ByteBuddy.java:406)
        at net.bytebuddy.ByteBuddy.subclass(ByteBuddy.java:379)
        at net.bytebuddy.ByteBuddy.subclass(ByteBuddy.java:276)
        at org.springframework.aop.framework.ProxyGenerator.getProxyBytes(ProxyGenerator.java:80)
        at org.springframework.aot.nativex.ConfigurationContributor.generateBuildTimeClassProxy(ConfigurationContributor.java:193)
        at org.springframework.aot.nativex.ConfigurationContributor.generateBuildTimeClassProxies(ConfigurationContributor.java:170)
        at org.springframework.aot.nativex.ConfigurationContributor.processBuildTimeClassProxyRequests(ConfigurationContributor.java:142)
        at org.springframework.aot.nativex.ConfigurationContributor.contribute(ConfigurationContributor.java:74)
        at org.springframework.aot.build.BootstrapCodeGenerator.generate(BootstrapCodeGenerator.java:91)
        at org.springframework.aot.build.BootstrapCodeGenerator.generate(BootstrapCodeGenerator.java:71)
        at org.springframework.aot.build.GenerateBootstrapCommand.call(GenerateBootstrapCommand.java:107)
        at org.springframework.aot.build.GenerateBootstrapCommand.call(GenerateBootstrapCommand.java:42)
        at picocli.CommandLine.executeUserObject(CommandLine.java:1953)
        at picocli.CommandLine.access$1300(CommandLine.java:145)
        at picocli.CommandLine$RunLast.executeUserObjectOfLastSubcommandWithSameParent(CommandLine.java:2352)
        at picocli.CommandLine$RunLast.handle(CommandLine.java:2346)
        at picocli.CommandLine$RunLast.handle(CommandLine.java:2311)
        at picocli.CommandLine$AbstractParseResultHandler.execute(CommandLine.java:2179)
        at picocli.CommandLine.execute(CommandLine.java:2078)
        at org.springframework.aot.build.GenerateBootstrapCommand.main(GenerateBootstrapCommand.java:112)
java.lang.IllegalStateException: Problem creating proxy with configuration: org.springframework.aop.framework.ProxyConfiguration@6571616c
        at org.springframework.aop.framework.ProxyGenerator.getProxyBytes(ProxyGenerator.java:94)
        at org.springframework.aot.nativex.ConfigurationContributor.generateBuildTimeClassProxy(ConfigurationContributor.java:193)
        at org.springframework.aot.nativex.ConfigurationContributor.generateBuildTimeClassProxies(ConfigurationContributor.java:170)
        at org.springframework.aot.nativex.ConfigurationContributor.processBuildTimeClassProxyRequests(ConfigurationContributor.java:142)
        at org.springframework.aot.nativex.ConfigurationContributor.contribute(ConfigurationContributor.java:74)
        at org.springframework.aot.build.BootstrapCodeGenerator.generate(BootstrapCodeGenerator.java:91)
        at org.springframework.aot.build.BootstrapCodeGenerator.generate(BootstrapCodeGenerator.java:71)
        at org.springframework.aot.build.GenerateBootstrapCommand.call(GenerateBootstrapCommand.java:107)
        at org.springframework.aot.build.GenerateBootstrapCommand.call(GenerateBootstrapCommand.java:42)
        at picocli.CommandLine.executeUserObject(CommandLine.java:1953)
        at picocli.CommandLine.access$1300(CommandLine.java:145)
        at picocli.CommandLine$RunLast.executeUserObjectOfLastSubcommandWithSameParent(CommandLine.java:2352)
        at picocli.CommandLine$RunLast.handle(CommandLine.java:2346)
        at picocli.CommandLine$RunLast.handle(CommandLine.java:2311)
        at picocli.CommandLine$AbstractParseResultHandler.execute(CommandLine.java:2179)
        at picocli.CommandLine.execute(CommandLine.java:2078)
        at org.springframework.aot.build.GenerateBootstrapCommand.main(GenerateBootstrapCommand.java:112)
Caused by: java.lang.IllegalArgumentException: Cannot subclass primitive, array or final types: class xxx.ServerConfiguration
        at net.bytebuddy.ByteBuddy.subclass(ByteBuddy.java:406)
        at net.bytebuddy.ByteBuddy.subclass(ByteBuddy.java:379)
        at net.bytebuddy.ByteBuddy.subclass(ByteBuddy.java:276)
        at org.springframework.aop.framework.ProxyGenerator.getProxyBytes(ProxyGenerator.java:80)
        ... 16 more

Spring Boot: 2.6.2
Spring Native: 0.11.1
GraalVM: 21.3.0 CE

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Jan 22, 2022
@sdeleuze
Copy link
Contributor

sdeleuze commented Jan 31, 2022

Could you please try with:

  • record without @Validated
  • class with @Validated

To qualify more precisely the source of the error?

@sdeleuze sdeleuze added the status: waiting-for-feedback We need additional information before we can continue label Jan 31, 2022
@prettymama
Copy link
Author

class with @Validated works, I have it currently as a workaround.
record without @Validated builds and runs OK.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Jan 31, 2022
@prettymama prettymama changed the title @ConfigurationProperties - native build fails when annotation present on a record @ConfigurationProperties with @Validated - native build fails when annotations present on a record Feb 1, 2022
@sdeleuze sdeleuze added type: bug A general bug and removed status: waiting-for-triage An issue we've not yet triaged or decided on status: feedback-provided Feedback has been provided labels Feb 1, 2022
@sdeleuze sdeleuze added this to the 0.11.3 milestone Feb 1, 2022
@prettymama
Copy link
Author

I tried some experimentation and it seems that when the configuration is a bit more "complex" (multilayered), configuration values are not bound to properties.

e.g.
Configuration

servers:
  server: 
    port: 10001

Records:

@ConfigurationProperties("servers")
public record ServersConfiguration(ServerConfiguration server) {
  public record ServerConfiguration(int port) {
    public ServerConfiguration{
      System.out.println("Port: " + port);
    }
  }
}

In native image the Port: 10001 is not printed out, in JVM version it's OK.

Removing one layer:

server: 
  port: 10001
@ConfigurationProperties("server")
public record ServerConfiguration(int port) {
  public ServerConfiguration{
    System.out.println("Port: " + port);
  }
}

and the line is printed.

@sdeleuze sdeleuze self-assigned this Feb 10, 2022
@sdeleuze
Copy link
Contributor

Notice it works with:

@ConfigurationProperties("servers")
@ConstructorBinding
public record ServersConfiguration(ServerConfiguration server) {
  public record ServerConfiguration(int port) {
    public ServerConfiguration{
      System.out.println("Port: " + port);
    }
  }
}

I have asked a feedback to Boot team to refine Spring native handling for that use case.

@sdeleuze
Copy link
Contributor

The proxy issue is likely a duplicate of #969, I will create another one for the proper nested record detection.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
status: duplicate A duplicate of another issue type: bug A general bug
Development

No branches or pull requests

3 participants