Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,15 @@ dependencies {
implementation("org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.5")
implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.5")
implementation("com.querydsl:querydsl-jpa:5.1.0:jakarta")

kapt("com.querydsl:querydsl-apt:5.1.0:jakarta") // annotationProcessor → kapt로 변경

implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("com.h2database:h2")
runtimeOnly("com.mysql:mysql-connector-j")
compileOnly("org.projectlombok:lombok")
annotationProcessor("org.projectlombok:lombok")

testImplementation("org.springframework.batch:spring-batch-test")
testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("org.jetbrains.kotlin:kotlin-test-junit5")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/com/retrip/map/MapApplication.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication

@SpringBootApplication
class MapApplication
class MapApplication()

fun main(args: Array<String>) {
runApplication<MapApplication>(*args)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.retrip.map.application.`in`.service

import com.retrip.map.application.`in`.usecase.LocationIndexUseCase
import com.retrip.map.application.out.repository.LocationElasticRepository
import com.retrip.map.infra.adapter.out.search.elasticsearch.entity.LocationDocument
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional

@Service
@Transactional
class LocationIndexService(
private val locationElasticRepository: LocationElasticRepository
) : LocationIndexUseCase {
override fun indexLocationDocuments(documents: List<LocationDocument>?) {
documents?.let { locationElasticRepository.saveAll(it) }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.retrip.map.application.`in`.usecase

import com.retrip.map.infra.adapter.out.search.elasticsearch.entity.LocationDocument

interface LocationIndexUseCase {
fun indexLocationDocuments(documents: List<LocationDocument>?)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.retrip.map.application.out.repository

import com.retrip.map.infra.adapter.out.search.elasticsearch.entity.LocationDocument
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository
import org.springframework.stereotype.Repository
import java.util.UUID

@Repository
interface LocationElasticRepository: ElasticsearchRepository<LocationDocument, UUID> {

}
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package com.retrip.map.application.out.repository

import com.retrip.map.application.`in`.response.LocationResponse
import com.retrip.map.domain.entity.Location
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import java.time.LocalDate
import java.util.UUID

interface LocationQueryRepository {
fun findLocations(id: UUID?, page: Pageable): Page<LocationResponse>
fun findLocationsByEditedAt( editedAt: LocalDate): List<Location>
}
2 changes: 2 additions & 0 deletions src/main/kotlin/com/retrip/map/domain/entity/Location.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ import jakarta.persistence.Column
import jakarta.persistence.Embedded
import jakarta.persistence.Entity
import jakarta.persistence.Id
import jakarta.persistence.Table
import jakarta.persistence.Version
import lombok.AccessLevel
import lombok.NoArgsConstructor
import lombok.Setter
import java.util.*

@Entity
@Table(name = "location")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Setter(value = AccessLevel.PROTECTED)
class Location(
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.retrip.map.infra.adapter.`in`.batch

import com.retrip.map.domain.entity.Location
import com.retrip.map.infra.adapter.out.search.elasticsearch.entity.LocationDocument
import org.springframework.batch.core.Job
import org.springframework.batch.core.Step
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing
import org.springframework.batch.core.job.builder.JobBuilder
import org.springframework.batch.core.repository.JobRepository
import org.springframework.batch.core.step.builder.StepBuilder
import org.springframework.beans.factory.annotation.Value
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.transaction.PlatformTransactionManager

@Configuration
//@EnableBatchProcessing
class MapBatchConfig(
@Value("\${spring.batch.job.name}")
private val jobName: String,
private val reader: MapReader,
private val processor: MapProcessor,
private val writer: MapWriter,
) {

@Bean
fun mapJob(
jobRepository: JobRepository,
mapStep: Step
): Job {
return JobBuilder(jobName, jobRepository)
.start(mapStep)
.build()

}

@Bean
fun mapStep(
jobRepository: JobRepository,
transactionManager: PlatformTransactionManager
): Step {
return StepBuilder("map-step", jobRepository)
.chunk<List<Location>, List<LocationDocument>>(10, transactionManager)
.reader(reader)
.processor(processor)
.writer(writer)
.build()
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.retrip.map.infra.adapter.`in`.batch

import com.retrip.map.domain.entity.Location
import com.retrip.map.infra.adapter.out.search.elasticsearch.entity.LocationDocument
import org.springframework.batch.item.ItemProcessor
import org.springframework.stereotype.Component

@Component
class MapProcessor()
: ItemProcessor<List<Location>, List<LocationDocument>> {
override fun process(item: List<Location>): List<LocationDocument>? {
return item.map { LocationDocument.of(it) }

}
}
18 changes: 18 additions & 0 deletions src/main/kotlin/com/retrip/map/infra/adapter/in/batch/MapReader.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.retrip.map.infra.adapter.`in`.batch

import com.retrip.map.application.out.repository.LocationQueryRepository
import com.retrip.map.domain.entity.Location
import org.springframework.batch.item.ItemReader
import org.springframework.stereotype.Component
import java.time.LocalDate

@Component
class MapReader(
val locationQueryRepository: LocationQueryRepository

): ItemReader<List<Location>> {
override fun read(): List<Location>? {
println("TEST")
return locationQueryRepository.findLocationsByEditedAt(LocalDate.now())
}
}
17 changes: 17 additions & 0 deletions src/main/kotlin/com/retrip/map/infra/adapter/in/batch/MapWriter.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.retrip.map.infra.adapter.`in`.batch

import com.retrip.map.application.`in`.usecase.LocationIndexUseCase
import com.retrip.map.infra.adapter.out.search.elasticsearch.entity.LocationDocument
import org.springframework.batch.item.Chunk
import org.springframework.batch.item.ItemWriter
import org.springframework.stereotype.Component

@Component
class MapWriter(
val locationIndexUseCase: LocationIndexUseCase
) : ItemWriter<List<LocationDocument>> {
override fun write(chunk: Chunk<out List<LocationDocument>?>) {
chunk.items.forEach { documents -> locationIndexUseCase.indexLocationDocuments(documents) }
println("TEST 완료")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ import com.querydsl.core.types.Projections
import com.querydsl.jpa.impl.JPAQueryFactory
import com.retrip.map.application.`in`.response.LocationResponse
import com.retrip.map.application.out.repository.LocationQueryRepository
import com.retrip.map.domain.entity.Location
import com.retrip.map.domain.entity.QLocation.location
import org.springframework.data.domain.Page
import org.springframework.data.domain.PageImpl
import org.springframework.data.domain.Pageable
import org.springframework.stereotype.Repository
import java.time.LocalDate
import java.util.*


Expand Down Expand Up @@ -49,6 +51,16 @@ class LocationQuerydslRepository(
return PageImpl(locations, page, count ?: 0)
}

override fun findLocationsByEditedAt(editedAt: LocalDate): List<Location> {
val startOfDay = editedAt.atStartOfDay()
val endOfDay = editedAt.plusDays(1).atStartOfDay()
return query.selectFrom(location)
.where(
location.editedAt.goe(startOfDay),
location.createdAt.lt(endOfDay)
).fetch()
}

private fun eqLocation(id: UUID?): Predicate? {
return id?.let { location.id.eq(it) }
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.retrip.map.infra.adapter.out.search.elasticsearch.entity

import com.retrip.map.domain.entity.Location
import com.retrip.map.domain.exception.LocationNotFoundException
import com.retrip.map.domain.exception.common.RequireException
import jakarta.persistence.Id
import org.springframework.data.elasticsearch.annotations.Document
import org.springframework.data.elasticsearch.annotations.Field
import org.springframework.data.elasticsearch.annotations.FieldType
import java.util.*

@Document(indexName = "locations")
data class LocationDocument(
@Id
val id: UUID,
@Field(type = FieldType.Text)
val name: String,
@Field(type = FieldType.Keyword)
val category: String,
@Field(type = FieldType.Keyword)
val description: String?,
@Field(type = FieldType.Keyword)
val telephone: String?,
@Field(type = FieldType.Keyword)
val address: String?,
@Field(type = FieldType.Keyword)
val roadAddress: String?,
@Field(type = FieldType.Double)
val latitude: Double?,
@Field(type = FieldType.Double)
val longitude: Double?
) {
companion object {
fun of(location: Location): LocationDocument {
return LocationDocument(
location.id ?: throw LocationNotFoundException(),
location.name?.value ?: throw RequireException(),
location.category?.value ?: throw RequireException(),
location.description?.value,
location.telephone,
location.address?.address,
location.address?.roadAddress,
location.geoPoint?.latitude,
location.geoPoint?.longitude,
)
}
}

}
40 changes: 40 additions & 0 deletions src/main/kotlin/com/retrip/map/infra/config/ElasticsearchConfig.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.retrip.map.infra.config

import co.elastic.clients.elasticsearch.ElasticsearchClient
import co.elastic.clients.json.jackson.JacksonJsonpMapper
import co.elastic.clients.transport.rest_client.RestClientTransport
import org.apache.http.HttpHost
import org.apache.http.auth.AuthScope
import org.apache.http.auth.UsernamePasswordCredentials
import org.apache.http.impl.client.BasicCredentialsProvider
import org.apache.http.ssl.SSLContexts
import org.elasticsearch.client.RestClient
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration
class ElasticsearchConfig {
@Bean
fun elasticsearchClient(): ElasticsearchClient {
val credentialsProvider = BasicCredentialsProvider()
credentialsProvider.setCredentials(
AuthScope.ANY,
UsernamePasswordCredentials("elastic", "61tkSdZs6lUk2Mfa+nq5")
)

val sslContext = SSLContexts.custom()
.loadTrustMaterial(null) { _, _ -> true } // 개발용
.build()

val restClient = RestClient.builder(HttpHost("localhost", 9200, "https"))
.setHttpClientConfigCallback { httpClientBuilder ->
httpClientBuilder
.setSSLContext(sslContext)
.setDefaultCredentialsProvider(credentialsProvider) // ✅ 여기 수정
}
.build()

val transport = RestClientTransport(restClient, JacksonJsonpMapper())
return ElasticsearchClient(transport)
}
}
1 change: 0 additions & 1 deletion src/main/resources/application.properties

This file was deleted.

23 changes: 23 additions & 0 deletions src/main/resources/application.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
spring:
application:
name: map
############# Data Source ######
datasource:
url: jdbc:mysql://localhost:3306/map?useSSL=false&serverTimezone=Asia/Seoul&allowPublicKeyRetrieval=true
username: root
password: test1234
driver-class-name: com.mysql.cj.jdbc.Driver
h2:
console:
enabled: true
path: /h2-console
############# Batch ############
batch:
job:
name: "retrip-map"
jdbc:
initialize-schema: always
jpa:
show-sql: true
hibernate:
ddl-auto: create