Skip to content

Need For Specifiying All The Binders During Build Time In Sping Native #2804

@omercelikceng

Description

@omercelikceng

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)
image


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

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions