-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Support local bean reference in @KafkaListener #534
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
Conversation
3e8813b to
66c7dad
Compare
In the `@KafkaListener` bean post processor, allow property SpEL expressions to access properties and methods on the bean being post-processed.
66c7dad to
8f6ea73
Compare
| this.topic = topic; | ||
| } | ||
|
|
||
| @KafkaListener(topics = "#{__listenerBean__.topic}", groupId = "#{__listenerBean__.topic}.group") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't advertise the feature like SpEL evaluation context variable and therefore register the outer object under a #listener name? More convenient to use and familiar syntax for SpEL users: https://docs.spring.io/spring/docs/5.0.2.RELEASE/spring-framework-reference/core.html#expressions-ref-variables ?
What I feel fragile for is that funky beanRef on the annotation...
Just my feeling from the end-user perspective.
If you are not agree with me, I'll merge it as you did.
Thanks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That was my initial plan, but we don't have access to the SpEL evaluation context - it is a single instance that's cached in the StandardBeanExpressionResolver - it would require replacing all that resolution infrastructure with our own.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I checked the code there, bu I mean pretend like we have it as a SpEL variable , by the name of the object in scope you use already.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That works already, out of the box...
@Bean
public Listener listener1() {
return new Listener("topic1");
}with
@KafkaListener(topics = "#{listener1.topic}",
groupId = "#{listener1.topic}.group")
public void listen(...) {
...
}But we're trying to solve a different problem, where we don't know the bean name while writing the code...
@Bean
public Listener listener1() {
return new Listener("topic1");
}
@Bean
public Listener listener2() {
return new Listener("topic2");
}We somehow need a reference to the current bean, but not by the bean name. Yes, ideally, a variable #currentBean would be best but, for the reason I specified above, we can't do that without copying a lot of code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK. Let's go simpler discussion way!
I don't like the name for the object in scope as __listenerBean__. I would prefer #listener instead. This way it mimics the well-known SpEL variable syntax.
Also I don't like that new beanRef annotation attribute. Don't know yet why, but my feeling like I would stay away of it. Although I agree about the argument "unlikely event that you have an actual bean called" especially in this point release.
So, having all of this thinking in my head I only suggest to rename the default __listenerBean__ key to the #listener. And that's all.
Let me know if my point is still unclear!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can't use #listener because SpEL will think it's a real variable and fail to find it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd be ok with _listener or _listener_ as the default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah! Good point!
OK. One more attempt. The StandardBeanExpressionResolver has this:
/**
* Template method for customizing the expression evaluation context.
* <p>The default implementation is empty.
*/
protected void customizeEvaluationContext(StandardEvaluationContext evalContext) {
}
Looks like this is the place where we could inject a SpEL variable for the bean in the method:
protected void processListener(MethodKafkaListenerEndpoint<?, ?> endpoint, KafkaListener kafkaListener, Object bean,
Object adminTarget, String beanName) {
But I agree that is more coding, ThreadLocal, param propagation etc. And in the end technically we end up with the same logic for end user.
So, let me know if you would like to play with this or let's leave as is and merge!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd be ok with
_listeneror_listener_as the default.
Yeah... That really might be two _ in the beginning, but I'm some lost to read dot after two _...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok; I will change it; and do no more; I think we've spent enough time on this 😄
In the
@KafkaListenerbean post processor, allow property SpEL expressions toaccess properties and methods on the bean being post-processed.
See Stack Overflow.