mirror of
https://github.com/Dannecron/spring-boot-demo.git
synced 2025-12-26 00:32:34 +03:00
some refactoring
This commit is contained in:
@@ -9,6 +9,7 @@ import com.example.demo.services.database.city.CityServiceImpl
|
|||||||
import com.example.demo.services.database.product.ProductService
|
import com.example.demo.services.database.product.ProductService
|
||||||
import com.example.demo.services.database.product.ProductServiceImpl
|
import com.example.demo.services.database.product.ProductServiceImpl
|
||||||
import com.example.demo.services.kafka.Producer
|
import com.example.demo.services.kafka.Producer
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
import org.springframework.beans.factory.annotation.Autowired
|
import org.springframework.beans.factory.annotation.Autowired
|
||||||
import org.springframework.beans.factory.annotation.Value
|
import org.springframework.beans.factory.annotation.Value
|
||||||
import org.springframework.context.annotation.Bean
|
import org.springframework.context.annotation.Bean
|
||||||
@@ -20,9 +21,10 @@ class AppConfig(
|
|||||||
private val defaultProductSyncTopic: String
|
private val defaultProductSyncTopic: String
|
||||||
) {
|
) {
|
||||||
@Bean
|
@Bean
|
||||||
fun shopProvider(): ShopProvider{
|
fun objectMapper(): ObjectMapper = ObjectMapper()
|
||||||
return MockedShopProvider()
|
|
||||||
}
|
@Bean
|
||||||
|
fun shopProvider(): ShopProvider = MockedShopProvider()
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
fun productService(
|
fun productService(
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package com.example.demo.config
|
|||||||
|
|
||||||
import com.example.demo.services.kafka.Producer
|
import com.example.demo.services.kafka.Producer
|
||||||
import com.example.demo.services.kafka.ProducerImpl
|
import com.example.demo.services.kafka.ProducerImpl
|
||||||
import com.example.demo.services.kafka.dto.serializer.ProductSerializer
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
import org.apache.kafka.clients.producer.ProducerConfig
|
import org.apache.kafka.clients.producer.ProducerConfig
|
||||||
import org.apache.kafka.common.serialization.StringSerializer
|
import org.apache.kafka.common.serialization.StringSerializer
|
||||||
import org.springframework.beans.factory.annotation.Autowired
|
import org.springframework.beans.factory.annotation.Autowired
|
||||||
@@ -24,7 +24,7 @@ class ProducerConfig(
|
|||||||
|
|
||||||
configProps[ProducerConfig.BOOTSTRAP_SERVERS_CONFIG] = servers
|
configProps[ProducerConfig.BOOTSTRAP_SERVERS_CONFIG] = servers
|
||||||
configProps[ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG] = StringSerializer::class.java
|
configProps[ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG] = StringSerializer::class.java
|
||||||
configProps[ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG] = ProductSerializer::class.java
|
configProps[ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG] = StringSerializer::class.java
|
||||||
|
|
||||||
return DefaultKafkaProducerFactory(configProps)
|
return DefaultKafkaProducerFactory(configProps)
|
||||||
}
|
}
|
||||||
@@ -35,7 +35,11 @@ class ProducerConfig(
|
|||||||
)
|
)
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
fun producer(@Autowired kafkaTemplate: KafkaTemplate<String, Any>): Producer = ProducerImpl(
|
fun producer(
|
||||||
|
@Autowired kafkaTemplate: KafkaTemplate<String, Any>,
|
||||||
|
@Autowired objectMapper: ObjectMapper
|
||||||
|
): Producer = ProducerImpl(
|
||||||
kafkaTemplate,
|
kafkaTemplate,
|
||||||
|
objectMapper,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@ package com.example.demo.services.kafka
|
|||||||
|
|
||||||
import com.example.demo.models.Product
|
import com.example.demo.models.Product
|
||||||
import com.example.demo.services.kafka.dto.ProductDto
|
import com.example.demo.services.kafka.dto.ProductDto
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
import org.springframework.kafka.core.KafkaTemplate
|
import org.springframework.kafka.core.KafkaTemplate
|
||||||
import org.springframework.kafka.support.KafkaHeaders
|
import org.springframework.kafka.support.KafkaHeaders
|
||||||
import org.springframework.messaging.Message
|
import org.springframework.messaging.Message
|
||||||
@@ -10,11 +11,12 @@ import org.springframework.stereotype.Service
|
|||||||
|
|
||||||
@Service
|
@Service
|
||||||
class ProducerImpl(
|
class ProducerImpl(
|
||||||
private val kafkaTemplate: KafkaTemplate<String, Any>
|
private val kafkaTemplate: KafkaTemplate<String, Any>,
|
||||||
|
private val objectMapper: ObjectMapper
|
||||||
): Producer {
|
): Producer {
|
||||||
override fun produceProductInfo(topicName: String, product: Product) {
|
override fun produceProductInfo(topicName: String, product: Product) {
|
||||||
val message: Message<ProductDto> = MessageBuilder
|
val message: Message<String> = MessageBuilder
|
||||||
.withPayload(ProductDto(product))
|
.withPayload(objectMapper.writeValueAsString(ProductDto(product)))
|
||||||
.setHeader(KafkaHeaders.TOPIC, topicName)
|
.setHeader(KafkaHeaders.TOPIC, topicName)
|
||||||
.setHeader("X-Custom-Header", "some-custom-header")
|
.setHeader("X-Custom-Header", "some-custom-header")
|
||||||
.build()
|
.build()
|
||||||
|
|||||||
@@ -2,16 +2,25 @@ package com.example.demo.services.kafka.dto
|
|||||||
|
|
||||||
import com.example.demo.models.Product
|
import com.example.demo.models.Product
|
||||||
import com.example.demo.services.kafka.exceptions.InvalidArgumentException
|
import com.example.demo.services.kafka.exceptions.InvalidArgumentException
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty
|
||||||
import java.time.format.DateTimeFormatter
|
import java.time.format.DateTimeFormatter
|
||||||
|
|
||||||
data class ProductDto(
|
data class ProductDto(
|
||||||
|
@JsonProperty("id")
|
||||||
val id: Long,
|
val id: Long,
|
||||||
|
@JsonProperty("guid")
|
||||||
val guid: String,
|
val guid: String,
|
||||||
|
@JsonProperty("name")
|
||||||
val name: String,
|
val name: String,
|
||||||
|
@JsonProperty("description")
|
||||||
val description: String?,
|
val description: String?,
|
||||||
|
@JsonProperty("price")
|
||||||
val price: Long,
|
val price: Long,
|
||||||
|
@JsonProperty("createdAt")
|
||||||
val createdAt: String,
|
val createdAt: String,
|
||||||
|
@JsonProperty("updatedAt")
|
||||||
val updatedAt: String?,
|
val updatedAt: String?,
|
||||||
|
@JsonProperty("deletedAt")
|
||||||
val deletedAt: String?,
|
val deletedAt: String?,
|
||||||
) {
|
) {
|
||||||
@Throws(InvalidArgumentException::class)
|
@Throws(InvalidArgumentException::class)
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
package com.example.demo.services.kafka.dto.serializer
|
|
||||||
|
|
||||||
import com.example.demo.services.kafka.dto.ProductDto
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper
|
|
||||||
import org.apache.kafka.common.serialization.Serializer
|
|
||||||
import javax.sql.rowset.serial.SerialException
|
|
||||||
|
|
||||||
class ProductSerializer: Serializer<ProductDto> {
|
|
||||||
private val objectMapper = ObjectMapper()
|
|
||||||
|
|
||||||
override fun serialize(topic: String?, data: ProductDto?): ByteArray {
|
|
||||||
return objectMapper.writeValueAsBytes(
|
|
||||||
data ?: throw SerialException()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun close() {
|
|
||||||
// no logic
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,6 +2,7 @@ package com.example.demo.services.kafka
|
|||||||
|
|
||||||
import com.example.demo.models.Product
|
import com.example.demo.models.Product
|
||||||
import com.example.demo.services.kafka.dto.ProductDto
|
import com.example.demo.services.kafka.dto.ProductDto
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.mockito.kotlin.argumentCaptor
|
import org.mockito.kotlin.argumentCaptor
|
||||||
import org.mockito.kotlin.doReturn
|
import org.mockito.kotlin.doReturn
|
||||||
@@ -26,6 +27,9 @@ class ProducerImplTest {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private lateinit var producerImpl: ProducerImpl
|
private lateinit var producerImpl: ProducerImpl
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private lateinit var objectMapper: ObjectMapper
|
||||||
|
|
||||||
@MockBean
|
@MockBean
|
||||||
private lateinit var kafkaTemplate: KafkaTemplate<String, Any>
|
private lateinit var kafkaTemplate: KafkaTemplate<String, Any>
|
||||||
|
|
||||||
@@ -43,7 +47,7 @@ class ProducerImplTest {
|
|||||||
deletedAt = OffsetDateTime.now(),
|
deletedAt = OffsetDateTime.now(),
|
||||||
)
|
)
|
||||||
|
|
||||||
val captor = argumentCaptor<Message<ProductDto>>()
|
val captor = argumentCaptor<Message<String>>()
|
||||||
|
|
||||||
whenever(kafkaTemplate.send(captor.capture()))
|
whenever(kafkaTemplate.send(captor.capture()))
|
||||||
.doReturn(CompletableFuture<SendResult<String, Any>>())
|
.doReturn(CompletableFuture<SendResult<String, Any>>())
|
||||||
@@ -52,8 +56,10 @@ class ProducerImplTest {
|
|||||||
|
|
||||||
assertEquals(1, captor.allValues.count())
|
assertEquals(1, captor.allValues.count())
|
||||||
val actualArgument = captor.firstValue
|
val actualArgument = captor.firstValue
|
||||||
assertEquals(product.id, actualArgument.payload.id)
|
|
||||||
assertEquals(product.guid.toString(), actualArgument.payload.guid)
|
val actualProductDto = objectMapper.readValue(actualArgument.payload, ProductDto::class.java)
|
||||||
|
assertEquals(product.id, actualProductDto.id)
|
||||||
|
assertEquals(product.guid.toString(), actualProductDto.guid)
|
||||||
assertEquals(topic, actualArgument.headers[KafkaHeaders.TOPIC])
|
assertEquals(topic, actualArgument.headers[KafkaHeaders.TOPIC])
|
||||||
assertEquals("some-custom-header", actualArgument.headers["X-Custom-Header"])
|
assertEquals("some-custom-header", actualArgument.headers["X-Custom-Header"])
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user