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

@Validation annotation on AbstractExtendedBindingProperties causes context initialisation to fail #3071

Open
jmannix-ot opened this issue Jan 22, 2025 · 9 comments

Comments

@jmannix-ot
Copy link

jmannix-ot commented Jan 22, 2025

Describe the issue
The fix for #2974 causes some of our applications to fail when initialising application context with the following error:

2025-01-22T09:58:17.344Z  WARN 45438 --- [kafka-binding-issue] [           main]
s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name
'kafkaBindingIssueApplication': Unsatisfied dependency expressed through field 'kafkaExtendedBindingProperties': Bean
named 'spring.cloud.stream.kafka
org.springframework.cloud.stream.binder.kafka.properties.KafkaExtendedBindingProperties' is expected to be of type
'org.springframework.cloud.stream.binder.kafka.properties.KafkaExtendedBindingProperties' but was actually of type
'jdk.proxy2.$Proxy63'

The underlying cause appears to be the addition of the @Validation annotation on AbstractExtendedBindingProperties. When validation is enabled for the application, this causes the KafkaExtendedBindingProperties bean to be wrapped in a JDK proxy which cannot be cast back to the original type.

We autowire KafkaExtendedBindingProperties in one of our libraries as part of code that automates Kafka configuration, so any application that uses the library fails to start after upgrading to this version of Spring Cloud Stream.

To Reproduce
I have included a small example project with a failing test to demonstrate the problem:
kafka-binding-issue.zip

Version of the framework
Spring Cloud Stream 4.2.0

@olegz
Copy link
Contributor

olegz commented Jan 22, 2025

I just looked at it and indeed it fails, but i do have a question. . .
Why are you injecting properties into your application?
By doing so you are creating a new instance of KafkaExtendedBindingProperties that has no bearing on your binder configuration since binder runs in a separate ApplicationContext to which you have no access. So, for example even if you were to succeed and change some property, binder would not see it.

@olegz
Copy link
Contributor

olegz commented Jan 23, 2025

Further more, if you had multiple binder scenario you would have as many instances of KafkaExtendedBindingProperties as there are binders.
This is not an API to be used by the client, rather internal mechanism to configure binders. If you want to visualize or manipulate bider configuration we have another mechanism for it - https://docs.spring.io/spring-cloud-stream/reference/spring-cloud-stream/binding_visualization_control.html#page-title

@jmannix-ot
Copy link
Author

I just looked at it and indeed it fails, but i do have a question. . . Why are you injecting properties into your application? By doing so you are creating a new instance of KafkaExtendedBindingProperties that has no bearing on your binder configuration since binder runs in a separate ApplicationContext to which you have no access. So, for example even if you were to succeed and change some property, binder would not see it.

What we do is call getBindings() on the injected KafkaExtendedBindingProperties, modify the configuration and then call setBindings() to update them. It has been working for us up till now!

@jmannix-ot
Copy link
Author

Further more, if you had multiple binder scenario you would have as many instances of KafkaExtendedBindingProperties as there are binders. This is not an API to be used by the client, rather internal mechanism to configure binders. If you want to visualize or manipulate bider configuration we have another mechanism for it - https://docs.spring.io/spring-cloud-stream/reference/spring-cloud-stream/binding_visualization_control.html#page-title

Would the BindingsLifecycleController approach allow us to modify KafkaConsumerProperties on the bindings e.g. dlqName?

@olegz
Copy link
Contributor

olegz commented Jan 23, 2025

Regardless of it working before, the approach is fundamentally wrong since even in a single binder scenario you would be getting another instance of the configuration class. So technically I don't se how it worked for you since as I mentioned before binders (single or multiple) run in a separate application context.

Can you elaborate on your use case a bit more? I feel like there may be a simpler solution to what you need but need to better understand your requirements for dynamically changing configuration

@jmannix-ot
Copy link
Author

Yep, so we have a library which wraps spring cloud stream and provides additional functionality for things like: retry, buffering and claim check pattern for Kafka. It also has its own, simplified configuration, which we use to generate the correct spring cloud stream configuration following our internal standards. During application initialisation, the library reads the bindings and updates them with its own auto-generated consumer configuration.

@olegz
Copy link
Contributor

olegz commented Jan 23, 2025

Ok, and I assume you have a single binder scenario, not multibinder (e.g., kafka instance1 for input and kafka instance2 for output)

@jmannix-ot
Copy link
Author

Yep, that's correct

@olegz
Copy link
Contributor

olegz commented Jan 24, 2025

Let me think about it. It may work for you now, but it will stop working once a new binder is introduced or other configuration changes are made. It appears this would be a new feature/enhancement.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants