Repo that showcases the potential issue: https://github.com/gtiwari333/spring-micrometer-BeanDefinitionRegistryPostProcessor. You can run the BeansApp.main to see the errors.
It uses spring boot 3.2.2 with web and micrometer dependencies.
I'm trying to use BeanDefinitionRegistryPostProcessor to creating Beans dynamically and pass RestTemplate and Tracer to those beans. See https://github.com/gtiwari333/spring-micrometer-BeanDefinitionRegistryPostProcessor/blob/master/src/main/java/beanns/BeansApp.java#L33
The following where I'm not injecting any dependency to bean creation works just fine and also logs the trace ids.
@Bean
DynamicBeanDefinitionRegistrar r() { //trace ids print on log
return new DynamicBeanDefinitionRegistrar();
}
2024-02-17T14:44:04.428-06:00 INFO 17523 --- [nio-8080-exec-1] [65d11a947b2a2d475bfddc28892c8eaa-38a9ea6685ba5d7f] beanns.Ctrl : Test called ..
2024-02-17T14:44:04.443-06:00 INFO 17523 --- [ scheduling-1] [65d11a947b2a2d475bfddc28892c8eaa-5bfddc28892c8eaa] beanns.Ctrl : 200 OK Hello
2024-02-17T14:44:08.448-06:00 INFO 17523 --- [nio-8080-exec-2] [65d11a98485278c1db46c3e73f6b49b6-3f2b7e848c98066a] beanns.Ctrl : Test called ..
2024-02-17T14:44:08.450-06:00 INFO 17523 --- [ scheduling-1] [65d11a98485278c1db46c3e73f6b49b6-db46c3e73f6b49b6] beanns.Ctrl : 200 OK Hello
Issue 1: the trace ids doesn't print on log after I try to inject RestTemplate to reg method
@Bean
DynamicBeanDefinitionRegistrar r(RestTemplate t) {
return new DynamicBeanDefinitionRegistrar();
}
Issue 2: It throws java.lang.NoSuchMethodException: org.springframework.boot.actuate.autoconfigure.tracing.BravePropagationConfigurations$PropagationWithBaggage.<init>() when I try to inject io.micrometer.tracing.Tracer bean.
It appears its trying to create a bean of BravePropagationConfigurations$PropagationWithBaggage by calling empty
constructor, and it doesn't have the default constructor.
@Bean
DynamicBeanDefinitionRegistrar r(Tracer tr) { //
return new DynamicBeanDefinitionRegistrar();
}
Partial Exception:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'reg' defined in beanns.BeansApp: Unsatisfied dependency expressed through method 'reg' parameter 0: Error creating bean with name 'braveTracerBridge' defined in class path resource [org/springframework/boot/actuate/autoconfigure/tracing/BraveAutoConfiguration.class]: Unsatisfied dependency expressed through method 'braveTracerBridge' parameter 0: Error creating bean with name 'braveTracer' defined in class path resource [org/springframework/boot/actuate/autoconfigure/tracing/BraveAutoConfiguration.class]: Unsatisfied dependency expressed through method 'braveTracer' parameter 0: Error creating bean with name 'braveTracing' defined in class path resource [org/springframework/boot/actuate/autoconfigure/tracing/BraveAutoConfiguration.class]: Unsatisfied dependency expressed through method 'braveTracing' parameter 4: Error creating bean with name 'braveCurrentTraceContext' defined in class path resource [org/springframework/boot/actuate/autoconfigure/tracing/BraveAutoConfiguration.class]: Unsatisfied dependency expressed through method 'braveCurrentTraceContext' parameter 0: Error creating bean with name 'org.springframework.boot.actuate.autoconfigure.tracing.BravePropagationConfigurations$PropagationWithBaggage': Failed to instantiate [org.springframework.boot.actuate.autoconfigure.tracing.BravePropagationConfigurations$PropagationWithBaggage]: No default constructor found
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:798) ~[spring-beans-6.1.3.jar:6.1.3]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343) ~[spring-boot-3.2.2.jar:3.2.2]
at beanns.BeansApp.main(BeansApp.java:24) ~[classes/:na]
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'braveTracerBridge' defined in class path resource [org/springframework/boot/actuate/autoconfigure/tracing/BraveAutoConfiguration.class]: Unsatisfied dependency expressed through method 'braveTracerBridge' parameter 0: Error creating bean with name 'braveTracer' defined in class path resource [org/springframework/boot/actuate/autoconfigure/tracing/BraveAutoConfiguration.class]: Unsatisfied dependency expressed through method 'braveTracer' parameter 0: Error creating bean with name 'braveTracing' defined in class path resource [org/springframework/boot/actuate/autoconfigure/tracing/BraveAutoConfiguration.class]: Unsatisfied dependency expressed through method 'braveTracing' parameter 4: Error creating bean with name 'braveCurrentTraceContext' defined in class path resource [org/springframework/boot/actuate/autoconfigure/tracing/BraveAutoConfiguration.class]: Unsatisfied dependency expressed through method 'braveCurrentTraceContext' parameter 0: Error creating bean with name 'org.springframework.boot.actuate.autoconfigure.tracing.BravePropagationConfigurations$PropagationWithBaggage': Failed to instantiate [org.springframework.boot.actuate.autoconfigure.tracing.BravePropagationConfigurations$PropagationWithBaggage]: No default constructor found
... 19 common frames omitted
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'braveTracer' defined in class path resource [org/springframework/boot/actuate/autoconfigure/tracing/BraveAutoConfiguration.class]: Unsatisfied dependency expressed through method 'braveTracer' parameter 0: Error creating bean with name 'braveTracing' defined in class path resource [org/springframework/boot/actuate/autoconfigure/tracing/BraveAutoConfiguration.class]: Unsatisfied dependency expressed through method 'braveTracing' parameter 4: Error creating bean with name 'braveCurrentTraceContext' defined in class path resource [org/springframework/boot/actuate/autoconfigure/tracing/BraveAutoConfiguration.class]: Unsatisfied dependency expressed through method 'braveCurrentTraceContext' parameter 0: Error creating bean with name 'org.springframework.boot.actuate.autoconfigure.tracing.BravePropagationConfigurations$PropagationWithBaggage': Failed to instantiate [org.springframework.boot.actuate.autoconfigure.tracing.BravePropagationConfigurations$PropagationWithBaggage]: No default constructor found
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:798) ~[spring-beans-6.1.3.jar:6.1.3]
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:785) ~[spring-beans-6.1.3.jar:6.1.3]
... 33 common frames omitted
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'braveTracing' defined in class path resource [org/springframework/boot/actuate/autoconfigure/tracing/BraveAutoConfiguration.class]: Unsatisfied dependency expressed through method 'braveTracing' parameter 4: Error creating bean with name 'braveCurrentTraceContext' defined in class path resource [org/springframework/boot/actuate/autoconfigure/tracing/BraveAutoConfiguration.class]: Unsatisfied dependency expressed through method 'braveCurrentTraceContext' parameter 0: Error creating bean with name 'org.springframework.boot.actuate.autoconfigure.tracing.BravePropagationConfigurations$PropagationWithBaggage': Failed to instantiate [org.springframework.boot.actuate.autoconfigure.tracing.BravePropagationConfigurations$PropagationWithBaggage]: No default constructor found
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:798) ~[spring-beans-6.1.3.jar:6.1.3]
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:785) ~[spring-beans-6.1.3.jar:6.1.3]
... 47 common frames omitted
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'braveCurrentTraceContext' defined in class path resource [org/springframework/boot/actuate/autoconfigure/tracing/BraveAutoConfiguration.class]: Unsatisfied dependency expressed through method 'braveCurrentTraceContext' parameter 0: Error creating bean with name 'org.springframework.boot.actuate.autoconfigure.tracing.BravePropagationConfigurations$PropagationWithBaggage': Failed to instantiate [org.springframework.boot.actuate.autoconfigure.tracing.BravePropagationConfigurations$PropagationWithBaggage]: No default constructor found
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:798) ~[spring-beans-6.1.3.jar:6.1.3]
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:785) ~[spring-beans-6.1.3.jar:6.1.3]
... 61 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.boot.actuate.autoconfigure.tracing.BravePropagationConfigurations$PropagationWithBaggage': Failed to instantiate [org.springframework.boot.actuate.autoconfigure.tracing.BravePropagationConfigurations$PropagationWithBaggage]: No default constructor found
... 75 common frames omitted
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.boot.actuate.autoconfigure.tracing.BravePropagationConfigurations$PropagationWithBaggage]: No default constructor found
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:84) ~[spring-beans-6.1.3.jar:6.1.3]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1310) ~[spring-beans-6.1.3.jar:6.1.3]
... 100 common frames omitted
Caused by: java.lang.NoSuchMethodException: org.springframework.boot.actuate.autoconfigure.tracing.BravePropagationConfigurations$PropagationWithBaggage.<init>()
at java.base/java.lang.Class.getConstructor0(Class.java:3761) ~[na:na]
at java.base/java.lang.Class.getDeclaredConstructor(Class.java:2930) ~[na:na]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:80) ~[spring-beans-6.1.3.jar:6.1.3]
... 101 common frames omitted
Comment From: gtiwari333
I found the fix that I was looking for. https://github.com/gtiwari333/spring-micrometer-BeanDefinitionRegistryPostProcessor/pull/1/files
It looks BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry was getting called with uninitialized dependencies such as Tracer and RestTemplate. For both dependencies, Spring tried to create a bean by calling default constructor since they were un-initialized. RestTemplate without the ObservationRegistry is created - which caused no tracing to be passed. Tracer failed because there's no default constructor.
Now the question is, should Spring try to create the bean for RestTemplate and Tracer?
@Bean
BeanRegistry reg(RestTemplate t) {
BeanRegistry reg(Tracer tr) {
Comment From: mhalbritter
In the JavaDoc of BeanFactoryPostProcessor:
A BeanFactoryPostProcessor may interact with and modify bean definitions, but never bean instances. Doing so may cause premature bean instantiation, violating the container and causing unintended side effects. If bean instance interaction is required, consider implementing BeanPostProcessor instead.
That's exactly what happens here. By injecting RestTemplate and Tracer for a BeanFactoryPostProcessor you force the init of those beans very early, and bad stuff happens.