javaspringreactor-kafka

Spring circular dependency,


I have two beans:

@Configuration
public class KafkaConfiguration {

    @Bean
    @ConfigurationProperties(prefix = "spring.kafka.consumer")
    public Map<String, Object> kafkaProperties() {
        return new HashMap<>();
    }

    @Bean
    public ReceiverOptions<String, Object> kafkaReceiverOptions(Map<String, Object> kafkaProperties) {
        return ReceiverOptions.create(kafkaProperties);
    }

}

and second:

@Slf4j
@Component
public class SpringReactorKafkaConsumer {

    private final ReceiverOptions<String, Object> kafkaReceiverOptions;

    public SpringReactorKafkaConsumer(ReceiverOptions<String, Object> kafkaReceiverOptions) {
        this.kafkaReceiverOptions = kafkaReceiverOptions;
    }

    @PostConstruct
    public void consume() {

    }

}

After starting my program I have a log:

┌─────┐
    |  springReactorKafkaConsumer defined in file [...adapter/kafka/consumer/SpringReactorKafkaConsumer.class]
↑     ↓
|  kafkaReceiverOptions defined in class path resource [...configuration/KafkaConfiguration.class]
└─────┘

But I don't really see why? KafkaReceiverOptions does not depend on SpringReactorKafkaConsumer


Solution

  • I'm 99% sure that Map<String, Object> kafkaProperties is completely different from what you're expecting. It's not your kafkaProperties bean, but a map of all bean-names to their instances.

    Change it to @Qualifier("kafkaProperties") Map<String, Object> kafkaProperties.

    Spring lets you autowire collections. You can depend upon List<Foo>, and Spring will construct a List containing all beans extending/implementing Foo. That doesn't mean that an actual bean exists of type List<Foo>.

    You're being stung by this feature in way that's contrary to what you're trying to express.

    For this reason, I personally avoid registering any type of collection as a bean. It can sometimes be too ambiguous. I'd create something like a KafkaProperties class, and register that as a bean instead of the Map.