After migrating a project from Spring Boot v2.7 to v3.0 (and thus from Spring Integration v5.5 to v6.0), the following warnings are printed out:
WARN 22084 --- [ restartedMain] ocalVariableTableParameterNameDiscoverer : Using deprecated '-debug' fallback for parameter name resolution. Compile the affected code with '-parameters' instead or avoid its introspection: com.foobar.MyClassA
WARN 22084 --- [ restartedMain] ocalVariableTableParameterNameDiscoverer : Using deprecated '-debug' fallback for parameter name resolution. Compile the affected code with '-parameters' instead or avoid its introspection: com.foobar.MyClassB
WARN 22084 --- [ restartedMain] ocalVariableTableParameterNameDiscoverer : Using deprecated '-debug' fallback for parameter name resolution. Compile the affected code with '-parameters' instead or avoid its introspection: com.foobar.MyClassC
WARN 22084 --- [ restartedMain] ocalVariableTableParameterNameDiscoverer : Using deprecated '-debug' fallback for parameter name resolution. Compile the affected code with '-parameters' instead or avoid its introspection: com.foobar.MyClassD
MyClassA
extends IntegrationFlowAdapter
, and is annotated with @Component
:
package com.foobar;
@Component
class MyClassA extends IntegrationFlowAdapter {
// …
}
MyClassB
is annotated with @ConfigurationProperties
:
package com.foobar;
@ConfigurationProperties("my-config")
class MyClassB {
// …
}
MyClassC
is annotated with @Configuration
:
package com.foobar;
@Configuration
class MyClassC {
// …
}
And this particular one not even extending anything, nor annotated:
package com.foobar;
class MyClassD {
// …
}
I didn’t see any relevant information in the Spring Boot and Spring Integration migration guides. There is a section about name resolution in the Spring Boot migration guide, but it is related to Gradle, and I’m using Maven. I’m not even sure what this name resolution is all about.
I’m puzzled with the class LocalVariableTableParameterNameDiscoverer
, and I’m not sure what migration task I’m supposed to do.
Morgan's answer provides the correct fix, but I want to show some code to explain why this happens.
Given the following @Configuration class:
@Configuration
public class AppConfig {
@Bean
public SomeBean someBean(FooBar foo, FooBar bar) {
return new SomeBean(foo, bar);
}
@Bean
public FooBar foo() {
return new FooBar();
}
@Bean
public FooBar bar() {
return new FooBar();
}
}
When creating the bean someBean
, Spring must know which beans to use for each of the two parameters of the someBean()
method. It does this by looking at the parameter names of the method (i.e. foo
and bar
) and compares it with the name of existing beans. The deprecated LocalVariableTableParameterNameDiscoverer is used to resolve the parameter names of the method.
However, the parameter names are only kept after the compilation of the Java classes if the -debug
flag is passed to the javac
compiler. By default, the Maven compiler plugin does pass this flag to javac. That's why LocalVariableTableParameterNameDiscoverer
can do its job and why the warning is emitted.
With the code above, one can try to change the configuration of the Maven compiler plugin not to pass the debug flag to javac:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<debug>false</debug>
</configuration>
</plugin>
</plugins>
</build>
After compiling and executing the app, the warning will be replaced by the error:
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'edu.self.nyg.example.app.FooBar' available: expected single matching bean but found 2: foo,bar
For parameters names to be retained after compilation without the use of the debug flag, the -parameters
flag must be used. This will allow Spring's StandardReflectionParameterNameDiscoverer to replace LocalVariableTableParameterNameDiscoverer
and correctly find the proper beans for the foo and bar parameters of someBean()
.
The use of -parameters
seems to be recommended, but to get rid of the warning one can also do the following if needed:
@Bean
public SomeBean someBean(
@Qualifier("foo") FooBar foo,
@Qualifier("bar") FooBar bar) {
return new SomeBean(foo, bar);
}
Note that it's ok to have both debug and parameters flags set to true, Spring will use StandardReflectionParameterNameDiscoverer
and won't emit a warning.