I have the following class. I have verified in the console, the constructor of this class is called(during bean creation) before resolving the topic placeholder value in Kafka listener:
public class MsgReceiver<MSG> extends AbstractMsgReceiver<MSG> implements
MessageReceiver<MSG> {
@SuppressWarnings("unused")
private String topic;
public MsgReceiver(String topic, MessageHandler<MSG> handler) {
super(handler);
this.topic = topic;
}
@KafkaListener(topics = "${my.messenger.kafka.topics.#{${topic}}.value}", groupId = "${my.messenger.kafka.topics.#{${topic}}.groupId}")
public void receiveMessage(@Headers Map<String, Object> headers, @Payload MSG payload) {
System.out.println("Received "+payload);
super.receiveMessage(headers, payload);
}
}
I have my application.yml as follows:
my:
messenger:
kafka:
address: localhost:9092
topics:
topic_1:
value: my_topic
groupId: 1
During bean creation, I pass "topic_1" which I want should dynamically be used inside Kafka listener topic placeholder. I tried as shown in the code itself, but it does not work. Please suggest how to do that.
Placeholders are resolved before SpEL is evaluated; you can't dynamically build a placeholder name using SpEL. Also, you can't reference fields like that; you have to do it indirectly via the bean name (and a public getter).
So, to do what you want, you have to add a getter and get the property dynamically from the environment after building the property name with SpEL.
There is a special token
__listener
which allows you to reference the current bean.Putting it all together...
Result...
and