Hi

I found a bug when testing version 3.2.0-RC2 when binding in a configuration properties.

My configuration properties:

import com.jayway.jsonpath.JsonPath;
import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "app.prop1")
public class MyProperties {
    String name;
    JsonPath jsonPaths;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public JsonPath getJsonPaths() {
        return jsonPaths;
    }
}

Stacktrace:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::            (v3.2.0-RC2)

2023-11-03T14:59:22.056+01:00  INFO 18415 --- [           main] [                                                 ] c.e.s.Sb3RestWebmvcApplication           : Starting Sb3RestWebmvcApplication using Java 17.0.8 with PID 18415 (/home/jorgerma/dev_tmp/sb3-rest-webmvc/target/classes started by jorgerma in /home/jorgerma/dev_tmp/sb3-rest-webmvc)
2023-11-03T14:59:22.059+01:00  INFO 18415 --- [           main] [                                                 ] c.e.s.Sb3RestWebmvcApplication           : No active profile set, falling back to 1 default profile: "default"
2023-11-03T14:59:22.884+01:00  INFO 18415 --- [           main] [                                                 ] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port 8080 (http)
2023-11-03T14:59:22.894+01:00  INFO 18415 --- [           main] [                                                 ] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2023-11-03T14:59:22.895+01:00  INFO 18415 --- [           main] [                                                 ] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/10.1.15]
2023-11-03T14:59:22.939+01:00  INFO 18415 --- [           main] [                                                 ] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2023-11-03T14:59:22.940+01:00  INFO 18415 --- [           main] [                                                 ] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 843 ms
2023-11-03T14:59:23.168+01:00  WARN 18415 --- [           main] [                                                 ] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.boot.context.properties.ConfigurationPropertiesBindException: Error creating bean with name 'app.prop1-com.example.sb3restwebmvc.config.MyProperties': Could not bind properties to 'MyProperties' : prefix=app.prop1, ignoreInvalidFields=false, ignoreUnknownFields=true
2023-11-03T14:59:23.169+01:00  INFO 18415 --- [           main] [                                                 ] i.o.sdk.trace.SdkTracerProvider          : Calling shutdown() multiple times.
2023-11-03T14:59:23.172+01:00  INFO 18415 --- [           main] [                                                 ] o.apache.catalina.core.StandardService   : Stopping service [Tomcat]
2023-11-03T14:59:23.175+01:00  WARN 18415 --- [           main] [                                                 ] o.a.c.loader.WebappClassLoaderBase       : The web application [ROOT] appears to have started a thread named [BatchSpanProcessor_WorkerThread-1] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
 java.base@17.0.8/jdk.internal.misc.Unsafe.park(Native Method)
 java.base@17.0.8/java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:252)
 java.base@17.0.8/java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:1672)
 java.base@17.0.8/java.util.concurrent.ArrayBlockingQueue.poll(ArrayBlockingQueue.java:435)
 app//io.opentelemetry.sdk.trace.export.BatchSpanProcessor$Worker.run(BatchSpanProcessor.java:253)
 java.base@17.0.8/java.lang.Thread.run(Thread.java:833)
2023-11-03T14:59:23.187+01:00  INFO 18415 --- [           main] [                                                 ] .s.b.a.l.ConditionEvaluationReportLogger : 

Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
2023-11-03T14:59:23.201+01:00 ERROR 18415 --- [           main] [                                                 ] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

Failed to bind properties under 'app.prop1.json-paths' to com.jayway.jsonpath.JsonPath:

    Reason: java.lang.IllegalStateException: Failed to extract parameter names for private com.jayway.jsonpath.JsonPath(java.lang.String,com.jayway.jsonpath.Predicate[])

Action:

Update your application's configuration

Reviewing the problem in more detail, this error occurs when LogCorrelationPropertySource is in the context, otherwise, the operation is correct.

https://github.com/spring-projects/spring-boot/blob/ab2c7d05234a6b056af3d1461e4ae5cb6f131967/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/LogCorrelationEnvironmentPostProcessor.java#L36-L49

In Spring boot 3.1.5 it works fine.

I attach a small example to reproduce it.

sb3-rest-webmvc.zip

Comment From: scottfrederick

The root cause of the problem is this change in Spring Framework: https://github.com/spring-projects/spring-framework/issues/29559

When running the application with Spring Boot 3.1.5, you should see this warning:

2023-11-03T13:05:19.329-05:00  WARN 2920468 --- [           main] [                                                 ] ocalVariableTableParameterNameDiscoverer : Using deprecated '-debug' fallback for parameter name resolution. Compile the affected code with '-parameters' instead or avoid its introspection: com.jayway.jsonpath.JsonPath

It appears that json-path is not compiled with -parameters, which is required after this change in Framework if you want to use constructor binding. I'm not sure if there's anything that Boot or Framework can do about this. I'll mark this for team attention so we can discuss futher.

Comment From: scottfrederick

@jorgerod While we're considering this, can you provide an example of how you set the JsonPath properties in application.properties or application.yaml in a real-world case?

Comment From: philwebb

@jorgerod Or is the getJsonPath method public for another purpose and you never intend to bind anything to it? If so, #34616 would help but we might also be able to ignore the parameters exception.

Comment From: jorgerod

Hi @philwebb, @scottfrederick

Exactly, getJsonPath is a public method and there is no purpose to bind anything to it.

In that simplified case, I could rename the getJsonPath method and there would be no problem.

However, my real case is that my configuration properties extends another third party class where the getJsonPath method is and I can't change it.

The root cause of the problem is this change in Spring Framework: spring-projects/spring-framework#29559

When running the application with Spring Boot 3.1.5, you should see this warning:

``` 2023-11-03T13:05:19.329-05:00 WARN 2920468 --- [ main] [ ] ocalVariableTableParameterNameDiscoverer : Using deprecated '-debug' fallback for parameter name resolution. Compile the affected code with '-parameters' instead or avoid its introspection: com.jayway.jsonpath.JsonPath

In my run I don't see that warning message. I have run it with java 17 and maven 3.8.4

Comment From: sergey-morenets

Hi @jorgerod @philwebb

I confirm that I also don't see mentioned warning in the console. And if I add "-parameters" to Java compiler configuration then error is gone:

            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <release>21</release>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <compilerArgs>
                        <arg>-parameters</arg>
                    </compilerArgs>
                </configuration>
            </plugin>

Comment From: wilkinsona

The presence of LogCorrelationPropertySource makes a difference as it isn't an enumerable property source. Not being enumerable prevents the binder from making certain optimizations, resulting in the attempt to create a JsonPath instance that fails as no information about the constructor parameter names is available.

The above may also explain why the warning isn't shown with 3.1. To be shown, there needs to be a non-enumerable property source in the environment and there isn't one by default in 3.1 (LogCorrelationPropertySource is new in 3.2). I see the warning with 3.1 and this main class:

package com.example.sb3restwebmvc;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.core.env.PropertySource;

@SpringBootApplication
public class Sb3RestWebmvcApplication {

    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(Sb3RestWebmvcApplication.class);
        app.addInitializers((context) -> {
            context.getEnvironment().getPropertySources().addLast(new PropertySource<String>("breakage") {
                @Override
                public Object getProperty(String name) {
                    return null;
                }

            });
        });
        app.run(args);
    }

}

This main class will also reproduce the failure in 3.2 without the spring-boot-starter-actuator and micrometer-tracing-bridge-otel dependencies.