Using kotlin and spring boot, I have set simple kafka config codes.
@Configuration
class KafkaProducerConfig(
@Value("\${kafka.hosts}") private val hosts: String,
@Value("\${kafka.retry.interval}") private val interval: Int,
@Value("\${kafka.retry.max-attempts}") private val maxAttempts: Int,
) {
@Bean
fun myRetryTopic(kafkaTemplate: KafkaTemplate<String, RetryTarget>): RetryTopicConfiguration {
return RetryTopicConfigurationBuilder
.newInstance()
.fixedBackOff(interval)
.maxAttempts(maxAttempts)
.concurrency(1)
.includeTopics(listOf(KafkaTopicName.RETRY.name))
.create(kafkaTemplate)
}
@Bean
fun kafkaTemplate(): KafkaTemplate<String, RetryTarget> {
return KafkaTemplate<String, RetryTarget>(producerFactory())
}
fun producerFactory(): ProducerFactory<String, RetryTarget> {
val producerConfig: Map<String, Any> = hashMapOf(
ProducerConfig.BOOTSTRAP_SERVERS_CONFIG to hosts,
ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG to StringSerializer::class.java,
ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG to JsonSerializer::class.java,
)
return DefaultKafkaProducerFactory(producerConfig)
}
}
enum class KafkaTopicName {
RETRY,
}
data class TestRetryEvent(
val id: String,
): RetryTarget
interface RetryTarget
And web application entry code is below.
@SpringBootApplication(
scanBasePackages = ["com.test"],
exclude = [KafkaAutoConfiguration::class]
)
class WebApplication
fun main(args: Array<String>) {
if (Objects.equals(System.getenv("SHUTDOWN_IMMEDIATE"), "true")) {
exitProcess(0)
}
runApplication<WebApplication>(*args)
}
The problem is,
- This code works well in the new skeleton spring boot project.
- However, the same code throws error when it is in my working project.
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'kafkaTemplate' defined in class path resource [com/test/mine/adaptor/out/event/retry/kafka/KafkaProducerConfig.class]: Post-processing of merged bean definition failed
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:576)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:521)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1405)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1325)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:885)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:789)
... 19 common frames omitted
Caused by: java.lang.IllegalStateException: Failed to introspect Class [org.springframework.kafka.core.KafkaTemplate] from ClassLoader [jdk.internal.loader.ClassLoaders$AppClassLoader@2aae9190]
at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:483)
at org.springframework.util.ReflectionUtils.doWithLocalMethods(ReflectionUtils.java:320)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.buildPersistenceMetadata(PersistenceAnnotationBeanPostProcessor.java:444)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findPersistenceMetadata(PersistenceAnnotationBeanPostProcessor.java:415)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findInjectionMetadata(PersistenceAnnotationBeanPostProcessor.java:369)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessMergedBeanDefinition(PersistenceAnnotationBeanPostProcessor.java:352)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyMergedBeanDefinitionPostProcessors(AbstractAutowireCapableBeanFactory.java:1082)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:573)
... 29 common frames omitted
Caused by: java.lang.NoClassDefFoundError: org/apache/kafka/clients/consumer/ConsumerGroupMetadata
at java.base/java.lang.Class.getDeclaredMethods0(Native Method)
at java.base/java.lang.Class.privateGetDeclaredMethods(Class.java:3402)
at java.base/java.lang.Class.getDeclaredMethods(Class.java:2504)
at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:465)
... 36 common frames omitted
Caused by: java.lang.ClassNotFoundException: org.apache.kafka.clients.consumer.ConsumerGroupMetadata
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
... 40 common frames omitted
Process finished with exit code 1
I debugged by myself more than a day, but failed to catch the reason.
- Added consumer config with consumer group id and so on -> doesn't work
- Using @Primary to kafkaTemplate bean -> doesn't work
- Using KafkaTemplate<String, String>, not KafkaTemplate<String, RetryTarget> -> doesn't work
- and so on...
It would be a great help for me if you know the reason why the error is thrown.
I appreciate in advance.