-
Notifications
You must be signed in to change notification settings - Fork 629
Description
Hello,
I have a spring application running using Spring Cloud Stream Function(Spring Native). I am consuming some data using cloud function. I generated a native docker image with spring-boot-maven-plugin.
Additionally, I read spring cloud stream properties from config-server. This is exactly where my problem starts. Actually, I have no problem reading properties from config-server. However, for native (AOT), it seems like I have to specify spring cloud stream binders at build time. But I want to get the binder configurations from config server during application startup as I have been doing before native.
Case 1:
If I configure the application to connect to the config-server while building the project, the code runs without any problem.
Related application.yml
spring:
application:
name: person-service
cloud:
config:
enabled: true
config:
import: optional:configserver:http://config-server
What I see in your code is that If I build as shown above (fetching from config server during build time), the following classes are generated for all binders correctly. Then, afterwards there is no problem in getting these classes from applicationContext in runtime and use them(DefaultBinderFactory - getBinderInstance- this.binderChildContextInitializers.get(configurationName).initialize(binderProducingContext)). But unfortunately, I don't have the chance to access config server in build time. I did this for testing purposes. I can't work like this in Production.
Case 2:
spring:
application:
name: person-service
cloud:
config:
enabled: false
Another option is to disable property reading from the config server at build time.
In this case, I enable config-server from docker-compose.yml to fetch the properties from the config server at runtime.
If I do it this way, the relevant classes for the binders are not generated that are supposed to be generated in build time. Then I get an error because these binders cannot be found in the runtime.
Case 1 - Classes Generated After Code Build (Config.Enabled = True)

Case 2 - Classes Generated After Code Build (Config.Enabled = False)

I am getting the error here. Because the binderChildContextInitializers instance in DefaultBinderFactory was not initialized with the relevant binders at build time. It seems like this is a must to fill the binderChildContextInitializers in native build.
Error :
org.springframework.context.ApplicationContextException: Failed to start bean 'inputBindingLifecycle'
at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:182) ~[spring-context-6.0.11.jar!/:6.0.11]
at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:357) ~[spring-context-6.0.11.jar!/:6.0.11]
at java.base/java.lang.Iterable.forEach(Iterable.java:75) ~[na:na]
at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:156) ~[spring-context-6.0.11.jar!/:6.0.11]
at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:124) ~[spring-context-6.0.11.jar!/:6.0.11]
at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:958) ~[spring-context-6.0.11.jar!/:6.0.11]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:611) ~[spring-context-6.0.11.jar!/:6.0.11]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.1.2.jar!/:3.1.2]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:734) ~[spring-boot-3.1.2.jar!/:3.1.2]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:436) ~[spring-boot-3.1.2.jar!/:3.1.2]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:312) ~[spring-boot-3.1.2.jar!/:3.1.2]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) ~[spring-boot-3.1.2.jar!/:3.1.2]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) ~[spring-boot-3.1.2.jar!/:3.1.2]
at org.cloud.framework.service.milestone.app.MilestoneServiceApplication.main(MilestoneServiceApplication.java:20) ~[classes!/:6.0.0-SNAPSHOT]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49) ~[milestone-service-6.0.0-SNAPSHOT.jar:6.0.0-SNAPSHOT]
at org.springframework.boot.loader.Launcher.launch(Launcher.java:95) ~[milestone-service-6.0.0-SNAPSHOT.jar:6.0.0-SNAPSHOT]
at org.springframework.boot.loader.Launcher.launch(Launcher.java:58) ~[milestone-service-6.0.0-SNAPSHOT.jar:6.0.0-SNAPSHOT]
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:65) ~[milestone-service-6.0.0-SNAPSHOT.jar:6.0.0-SNAPSHOT]
Caused by: java.lang.IllegalStateException: Requested binder 'commonBinder' did not match available binders: [kafka]
at org.springframework.cloud.stream.binder.DefaultBinderFactory.doGetBinderAOT(DefaultBinderFactory.java:206) ~[spring-cloud-stream-4.1.1-SNAPSHOT.jar!/:4.1.1-SNAPSHOT]
at org.springframework.cloud.stream.binder.DefaultBinderFactory.doGetBinder(DefaultBinderFactory.java:178) ~[spring-cloud-stream-4.1.1-SNAPSHOT.jar!/:4.1.1-SNAPSHOT]
at org.springframework.cloud.stream.binder.DefaultBinderFactory.getBinder(DefaultBinderFactory.java:167) ~[spring-cloud-stream-4.1.1-SNAPSHOT.jar!/:4.1.1-SNAPSHOT]
at org.springframework.cloud.stream.binding.BindingService.getBinder(BindingService.java:411) ~[spring-cloud-stream-4.1.1-SNAPSHOT.jar!/:4.1.1-SNAPSHOT]
at org.springframework.cloud.stream.binding.BindingService.bindConsumer(BindingService.java:108) ~[spring-cloud-stream-4.1.1-SNAPSHOT.jar!/:4.1.1-SNAPSHOT]
at org.springframework.cloud.stream.binding.AbstractBindableProxyFactory.createAndBindInputs(AbstractBindableProxyFactory.java:98) ~[spring-cloud-stream-4.1.1-SNAPSHOT.jar!/:4.1.1-SNAPSHOT]
at org.springframework.cloud.stream.binding.InputBindingLifecycle.doStartWithBindable(InputBindingLifecycle.java:67) ~[spring-cloud-stream-4.1.1-SNAPSHOT.jar!/:4.1.1-SNAPSHOT]
at java.base/java.util.LinkedHashMap$LinkedValues.forEach(LinkedHashMap.java:647) ~[na:na]
at org.springframework.cloud.stream.binding.AbstractBindingLifecycle.start(AbstractBindingLifecycle.java:57) ~[spring-cloud-stream-4.1.1-SNAPSHOT.jar!/:4.1.1-SNAPSHOT]
at org.springframework.cloud.stream.binding.InputBindingLifecycle.start(InputBindingLifecycle.java:38) ~[spring-cloud-stream-4.1.1-SNAPSHOT.jar!/:4.1.1-SNAPSHOT]
at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:179) ~[spring-context-6.0.11.jar!/:6.0.11]
... 21 common frames omitted
I kind of get that these should be initialized during build time but how can we get over this situation (fetching binders during application startup)? Recently, I have been opening pull requests for problems caused by Spring Native. If you direct me, I can make the development and open a pull request.