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

Failed to extract parameter names exception thrown when binding with non-enumerable property source #38201

Closed
jorgerod opened this issue Nov 3, 2023 · 6 comments
Assignees
Labels
type: regression A regression from a previous release
Milestone

Comments

@jorgerod
Copy link

jorgerod commented Nov 3, 2023

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.

class LogCorrelationEnvironmentPostProcessor implements EnvironmentPostProcessor {
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
if (ClassUtils.isPresent("io.micrometer.tracing.Tracer", application.getClassLoader())) {
environment.getPropertySources().addLast(new LogCorrelationPropertySource(this, environment));
}
}
/**
* Log correlation {@link PropertySource}.
*/
private static class LogCorrelationPropertySource extends PropertySource<Object> {

In Spring boot 3.1.5 it works fine.

I attach a small example to reproduce it.

sb3-rest-webmvc.zip

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Nov 3, 2023
@scottfrederick
Copy link
Contributor

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

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.

@scottfrederick scottfrederick added the for: team-attention An issue we'd like other members of the team to review label Nov 3, 2023
@scottfrederick
Copy link
Contributor

@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?

@philwebb
Copy link
Member

philwebb commented Nov 4, 2023

@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.

@jorgerod
Copy link
Author

jorgerod commented Nov 6, 2023

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

@philwebb philwebb added type: regression A regression from a previous release and removed status: waiting-for-triage An issue we've not yet triaged labels Nov 6, 2023
@philwebb philwebb added this to the 3.2.x milestone Nov 6, 2023
@philwebb philwebb removed the for: team-attention An issue we'd like other members of the team to review label Nov 8, 2023
@sergey-morenets
Copy link

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>

@wilkinsona
Copy link
Member

wilkinsona commented Nov 13, 2023

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.

@philwebb philwebb self-assigned this Nov 13, 2023
@philwebb philwebb changed the title Failed to bind properties in ConfigurationProperties Failed to extract parameter names exception is thrown when binding with non-enumerable property source Nov 13, 2023
@philwebb philwebb changed the title Failed to extract parameter names exception is thrown when binding with non-enumerable property source Failed to extract parameter names exception thrown when binding with non-enumerable property source Nov 13, 2023
@philwebb philwebb modified the milestones: 3.2.x, 3.2.0 Nov 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: regression A regression from a previous release
Projects
None yet
Development

No branches or pull requests

6 participants