diff --git a/application/build.gradle.kts b/application/build.gradle.kts index 798de8e..bd2212e 100644 --- a/application/build.gradle.kts +++ b/application/build.gradle.kts @@ -16,7 +16,6 @@ dependencies { implementation("org.springframework:spring-aspects") runtimeOnly("io.micrometer:micrometer-registry-prometheus") - annotationProcessor("org.springframework.boot:spring-boot-configuration-processor") } tasks.withType { @@ -40,7 +39,7 @@ testing { implementation(project()) implementation("org.springframework.boot:spring-boot-starter-test") implementation("org.springframework.kafka:spring-kafka-test") - implementation("org.testcontainers:kafka:1.19.1") + implementation(integrationTestLibs.kafkaTestContainers) } } } diff --git a/application/src/main/kotlin/org/gxf/servicetemplate/observability/ObservabilityConfiguration.kt b/application/src/main/kotlin/org/gxf/servicetemplate/observability/ObservabilityConfiguration.kt deleted file mode 100644 index 231ceea..0000000 --- a/application/src/main/kotlin/org/gxf/servicetemplate/observability/ObservabilityConfiguration.kt +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-FileCopyrightText: Contributors to the GXF project -// -// SPDX-License-Identifier: Apache-2.0 - -package org.gxf.servicetemplate.observability - -import io.micrometer.observation.ObservationRegistry -import io.micrometer.observation.aop.ObservedAspect -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration - - -@Configuration(proxyBeanMethods = false) -internal class ObservabilityConfiguration { - - @Bean - fun observedAspect(observationRegistry: ObservationRegistry): ObservedAspect { - return ObservedAspect(observationRegistry) - } -} diff --git a/build.gradle.kts b/build.gradle.kts index 2ecc9e7..daa19f2 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,12 +6,12 @@ import io.spring.gradle.dependencymanagement.internal.dsl.StandardDependencyMana import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { - id("org.springframework.boot") version "3.1.5" apply false - id("io.spring.dependency-management") version "1.1.3" apply false - kotlin("jvm") version "1.9.10" apply false - kotlin("plugin.spring") version "1.9.10" apply false - kotlin("plugin.jpa") version "1.9.10" apply false - id("com.github.davidmc24.gradle.plugin.avro") version "1.8.0" apply false + id("org.springframework.boot") version "3.2.1" apply false + id("io.spring.dependency-management") version "1.1.4" apply false + kotlin("jvm") version "1.9.22" apply false + kotlin("plugin.spring") version "1.9.22" apply false + kotlin("plugin.jpa") version "1.9.22" apply false + id("com.github.davidmc24.gradle.plugin.avro") version "1.9.1" apply false id("org.sonarqube") version "4.4.1.3373" id("eclipse") } @@ -50,7 +50,7 @@ subprojects { extensions.configure { toolchain { - languageVersion.set(JavaLanguageVersion.of(17)) + languageVersion.set(JavaLanguageVersion.of(21)) } } @@ -63,7 +63,7 @@ subprojects { tasks.withType { kotlinOptions { freeCompilerArgs = listOf("-Xjsr305=strict") - jvmTarget = "17" + jvmTarget = "21" } } diff --git a/components/avro/build.gradle.kts b/components/avro/build.gradle.kts index 2780174..8d25323 100644 --- a/components/avro/build.gradle.kts +++ b/components/avro/build.gradle.kts @@ -7,5 +7,5 @@ plugins { } dependencies { - api("org.apache.avro:avro:1.11.3") + api(libs.avro) } diff --git a/components/kafka/build.gradle.kts b/components/kafka/build.gradle.kts index eae6d35..1621699 100644 --- a/components/kafka/build.gradle.kts +++ b/components/kafka/build.gradle.kts @@ -6,13 +6,13 @@ dependencies { implementation(project(":components:avro")) implementation("org.springframework.boot:spring-boot-autoconfigure") - implementation("org.springframework.boot:spring-boot-starter-logging") + implementation(libs.logging) implementation("org.springframework:spring-aop") implementation("org.springframework.kafka:spring-kafka") - implementation("com.gxf.utilities:kafka-avro:0.2") - implementation("com.gxf.utilities:kafka-azure-oauth:0.2") + implementation(libs.kafkaAvro) + implementation(libs.kafkaAzureOAuth) testImplementation("org.springframework:spring-test") diff --git a/components/kafka/src/main/kotlin/org/gxf/servicetemplate/kafka/GxfKafkaConsumer.kt b/components/kafka/src/main/kotlin/org/gxf/servicetemplate/kafka/GxfKafkaConsumer.kt index bf04cc0..bd31cdd 100644 --- a/components/kafka/src/main/kotlin/org/gxf/servicetemplate/kafka/GxfKafkaConsumer.kt +++ b/components/kafka/src/main/kotlin/org/gxf/servicetemplate/kafka/GxfKafkaConsumer.kt @@ -4,14 +4,10 @@ package org.gxf.servicetemplate.kafka +import io.github.oshai.kotlinlogging.KotlinLogging import org.gxf.service.Measurement -import io.micrometer.observation.annotation.Observed import org.apache.kafka.clients.consumer.ConsumerRecord -import org.slf4j.Logger -import org.slf4j.LoggerFactory import org.springframework.kafka.annotation.KafkaListener -import org.springframework.kafka.annotation.RetryableTopic -import org.springframework.retry.annotation.Backoff import org.springframework.stereotype.Service import java.net.SocketTimeoutException import java.time.LocalDateTime @@ -20,21 +16,13 @@ import java.time.ZoneOffset @Service class GxfKafkaConsumer { - companion object { - private val logger: Logger = LoggerFactory.getLogger(this::class.java) - } + private val logger = KotlinLogging.logger { } - @Observed(name = "consumer.consumed") @KafkaListener(topics = ["avroTopic"], id = "gxf-kafka-consumer") - @RetryableTopic( - backoff = Backoff(value = 3000L), - attempts = "2", - include = [SocketTimeoutException::class] - ) fun consume(record: ConsumerRecord) { - logger.info("Consuming: ${record.value().deviceId}") + logger.info { "Consuming: ${record.value().deviceId}" } if ((LocalDateTime.now().toEpochSecond(ZoneOffset.UTC) % 2) == 0L) { - logger.info("Timeout!: ${record.value().deviceId}") + logger.info { "Timeout!: ${record.value().deviceId}" } throw SocketTimeoutException() } } diff --git a/components/kafka/src/main/kotlin/org/gxf/servicetemplate/kafka/GxfKafkaProducer.kt b/components/kafka/src/main/kotlin/org/gxf/servicetemplate/kafka/GxfKafkaProducer.kt index fd360f7..b5585a0 100644 --- a/components/kafka/src/main/kotlin/org/gxf/servicetemplate/kafka/GxfKafkaProducer.kt +++ b/components/kafka/src/main/kotlin/org/gxf/servicetemplate/kafka/GxfKafkaProducer.kt @@ -4,9 +4,8 @@ package org.gxf.servicetemplate.kafka +import io.github.oshai.kotlinlogging.KotlinLogging import org.gxf.service.Measurement -import org.slf4j.Logger -import org.slf4j.LoggerFactory import org.springframework.kafka.core.KafkaTemplate import org.springframework.scheduling.annotation.Scheduled import org.springframework.stereotype.Service @@ -19,14 +18,12 @@ class GxfKafkaProducer( private val measurementGenerator: MeasurementGenerator ) { - companion object { - private val logger: Logger = LoggerFactory.getLogger(this::class.java) - } + private val logger = KotlinLogging.logger { } @Scheduled(cron = "* * * * * *") fun producer() { val deviceId = Random.nextLong() - logger.info("Producing: ${deviceId}") + logger.info { "Producing: ${deviceId}" } kafkaTemplate.send("avroTopic", measurementGenerator.generateMeasurement(deviceId)) } } diff --git a/components/kafka/src/main/kotlin/org/gxf/servicetemplate/kafka/configuration/KafkaConfiguration.kt b/components/kafka/src/main/kotlin/org/gxf/servicetemplate/kafka/configuration/KafkaConfiguration.kt index 764349e..1e35c56 100644 --- a/components/kafka/src/main/kotlin/org/gxf/servicetemplate/kafka/configuration/KafkaConfiguration.kt +++ b/components/kafka/src/main/kotlin/org/gxf/servicetemplate/kafka/configuration/KafkaConfiguration.kt @@ -10,6 +10,7 @@ import org.gxf.service.Measurement import org.apache.kafka.common.serialization.StringDeserializer import org.apache.kafka.common.serialization.StringSerializer import org.springframework.boot.autoconfigure.kafka.KafkaProperties +import org.springframework.boot.ssl.SslBundles import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory @@ -17,7 +18,7 @@ import org.springframework.kafka.core.* @Configuration -class KafkaConfiguration(val kafkaProperties: KafkaProperties) { +class KafkaConfiguration(val kafkaProperties: KafkaProperties, private val sslBundles: SslBundles) { @Bean fun kafkaListenerContainerFactory(consumerFactory: ConsumerFactory): ConcurrentKafkaListenerContainerFactory = @@ -31,7 +32,7 @@ class KafkaConfiguration(val kafkaProperties: KafkaProperties) { @Bean fun consumerFactory(): ConsumerFactory = DefaultKafkaConsumerFactory( - kafkaProperties.buildConsumerProperties(), + kafkaProperties.buildConsumerProperties(sslBundles), StringDeserializer(), AvroDeserializer(Measurement.getDecoder()) ) @@ -39,7 +40,7 @@ class KafkaConfiguration(val kafkaProperties: KafkaProperties) { @Bean fun producerFactory(): ProducerFactory = DefaultKafkaProducerFactory( - kafkaProperties.buildProducerProperties(), + kafkaProperties.buildProducerProperties(sslBundles), StringSerializer(), AvroSerializer(Measurement.getEncoder()) ) diff --git a/components/kafka/src/test/kotlin/org/gxf/servicetemplate/kafka/MeasurementGeneratorTest.kt b/components/kafka/src/test/kotlin/org/gxf/servicetemplate/kafka/MeasurementGeneratorTest.kt index 5ee4150..cc53649 100644 --- a/components/kafka/src/test/kotlin/org/gxf/servicetemplate/kafka/MeasurementGeneratorTest.kt +++ b/components/kafka/src/test/kotlin/org/gxf/servicetemplate/kafka/MeasurementGeneratorTest.kt @@ -4,9 +4,7 @@ package org.gxf.servicetemplate.kafka -import org.gxf.servicetemplate.kafka.MeasurementGenerator -import org.junit.jupiter.api.Assertions.* - +import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test class MeasurementGeneratorTest { diff --git a/components/mqtt/build.gradle.kts b/components/mqtt/build.gradle.kts index fe7ffbd..1fd21c1 100644 --- a/components/mqtt/build.gradle.kts +++ b/components/mqtt/build.gradle.kts @@ -3,9 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 dependencies { - implementation("org.springframework.boot:spring-boot-starter-logging") + implementation(libs.logging) implementation("org.springframework.integration:spring-integration-mqtt") - // Fixes: https://github.com/spring-projects/spring-integration/issues/3051 - implementation("org.springframework.integration:spring-integration-jmx") } diff --git a/components/mqtt/src/main/kotlin/org/gxf/servicetemplate/mqtt/MqttMessageConsumer.kt b/components/mqtt/src/main/kotlin/org/gxf/servicetemplate/mqtt/MqttMessageConsumer.kt index 19e903e..eae55b8 100644 --- a/components/mqtt/src/main/kotlin/org/gxf/servicetemplate/mqtt/MqttMessageConsumer.kt +++ b/components/mqtt/src/main/kotlin/org/gxf/servicetemplate/mqtt/MqttMessageConsumer.kt @@ -4,8 +4,7 @@ package org.gxf.servicetemplate.mqtt -import org.slf4j.Logger -import org.slf4j.LoggerFactory +import io.github.oshai.kotlinlogging.KotlinLogging import org.springframework.context.annotation.Bean import org.springframework.integration.dsl.IntegrationFlow import org.springframework.integration.dsl.integrationFlow @@ -20,19 +19,17 @@ class MqttMessageConsumer( private val clientFactory: MqttPahoClientFactory ) { - companion object { - val logger: Logger = LoggerFactory.getLogger(this::class.java) - } + private val logger = KotlinLogging.logger { } // Test with: mosquitto_pub -h localhost -t topic1 -m 23 -u admin -P password @Bean fun messageSourceFlow(): IntegrationFlow = - integrationFlow(MqttPahoMessageDrivenChannelAdapter("gxf-listener", clientFactory, "measurement" )) { + integrationFlow(MqttPahoMessageDrivenChannelAdapter("gxf-listener", clientFactory, "measurement")) { handle { message: Message<*> -> processMqttMessage(message) } } private fun processMqttMessage(m: Message<*>) { - logger.info("mqtt: ${m.headers.timestamp} - ${m.payload}") + logger.info { "mqtt: ${m.headers.timestamp} - ${m.payload}" } } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e411586..a595206 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/settings.gradle.kts b/settings.gradle.kts index a1450cf..3c78b41 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -8,3 +8,26 @@ include("application") include("components:avro") include("components:kafka") include("components:mqtt") + +dependencyResolutionManagement { + versionCatalogs { + create("libs") { + library("logging", "io.github.oshai", "kotlin-logging-jvm").version("6.0.1") + + version("mapstruct", "1.5.5.Final") + library("mapstruct", "org.mapstruct", "mapstruct").versionRef("mapstruct") + library("mapstructannotation", "org.mapstruct", "mapstruct-processor").versionRef("mapstruct") + + library("avro", "org.apache.avro", "avro").version("1.11.3") + + version("gxfUtils", "0.2") + library("kafkaAvro", "com.gxf.utilities", "kafka-avro").versionRef("gxfUtils") + library("kafkaAzureOAuth", "com.gxf.utilities", "kafka-azure-oauth").versionRef("gxfUtils") + } + create("integrationTestLibs") { + version("testContainers", "1.19.3") + library("kafkaTestContainers", "org.testcontainers", "kafka").versionRef("testContainers") + + } + } +}