mirror of
https://github.com/2martens/tsw-timetable.git
synced 2026-10-17 07:57:55 +02:00
Moved generic value classes to separate module
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
plugins {
|
||||
id("twomartens.kotlin")
|
||||
id("twomartens.java")
|
||||
kotlin("kapt")
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package de.twomartens.timetable.model.base
|
||||
package de.twomartens.timetable.types
|
||||
|
||||
@JvmInline
|
||||
value class Hour private constructor(val value: Int) {
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package de.twomartens.timetable.model.base
|
||||
package de.twomartens.timetable.types
|
||||
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalDateTime
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package de.twomartens.timetable.model.base
|
||||
package de.twomartens.timetable.types
|
||||
|
||||
@JvmInline
|
||||
value class NonEmptyString(val name: String) {
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package de.twomartens.timetable.model.base
|
||||
package de.twomartens.timetable.types
|
||||
|
||||
@JvmInline
|
||||
value class PositiveInteger(val value: Int) {
|
||||
@@ -5,6 +5,7 @@ plugins {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(":common"))
|
||||
implementation(libs.mapstruct.base)
|
||||
implementation(libs.bundles.spring.boot.security)
|
||||
implementation(libs.jaxb.impl)
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
package de.twomartens.timetable.bahnApi.mapper
|
||||
|
||||
import de.twomartens.timetable.bahnApi.model.db.BahnTimetable
|
||||
import de.twomartens.timetable.model.base.NonEmptyString
|
||||
import de.twomartens.timetable.types.NonEmptyString
|
||||
import org.mapstruct.*
|
||||
import java.time.LocalDateTime
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package de.twomartens.timetable.bahnApi.model
|
||||
|
||||
import de.twomartens.timetable.bahnApi.model.db.ScheduledFetchTask
|
||||
import de.twomartens.timetable.model.base.HourAtDay
|
||||
import de.twomartens.timetable.types.HourAtDay
|
||||
import org.springframework.stereotype.Component
|
||||
import java.time.LocalDateTime
|
||||
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
package de.twomartens.timetable.bahnApi.model.db
|
||||
|
||||
import de.twomartens.timetable.bahnApi.model.Eva
|
||||
import de.twomartens.timetable.model.base.NonEmptyString
|
||||
import de.twomartens.timetable.types.NonEmptyString
|
||||
import org.bson.types.ObjectId
|
||||
import org.springframework.data.annotation.CreatedDate
|
||||
import org.springframework.data.annotation.Id
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ package de.twomartens.timetable.bahnApi.model.db
|
||||
|
||||
import de.twomartens.timetable.bahnApi.model.Eva
|
||||
import de.twomartens.timetable.bahnApi.model.dto.BahnStationStop
|
||||
import de.twomartens.timetable.model.base.NonEmptyString
|
||||
import de.twomartens.timetable.types.NonEmptyString
|
||||
import org.bson.types.ObjectId
|
||||
import org.springframework.data.annotation.CreatedDate
|
||||
import org.springframework.data.annotation.Id
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
package de.twomartens.timetable.bahnApi.model.db
|
||||
|
||||
import de.twomartens.timetable.bahnApi.model.Eva
|
||||
import de.twomartens.timetable.model.base.HourAtDay
|
||||
import de.twomartens.timetable.types.HourAtDay
|
||||
import org.bson.types.ObjectId
|
||||
import org.springframework.data.annotation.CreatedDate
|
||||
import org.springframework.data.annotation.Id
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ import jakarta.xml.bind.annotation.XmlRootElement
|
||||
@XmlRootElement(name = "stations")
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
data class BahnStations(
|
||||
@field:XmlElement(name = "station") var stations: List<BahnStation>
|
||||
@field:XmlElement(name = "station") var stations: List<BahnStation>
|
||||
) {
|
||||
constructor() : this(listOf())
|
||||
}
|
||||
|
||||
+15
-15
@@ -9,22 +9,22 @@ import java.time.LocalDateTime
|
||||
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
data class BahnStopEvent(
|
||||
@field:XmlAttribute(name = "pde") var plannedDistantEndpoint: String,
|
||||
@field:XmlAttribute(name = "cde") var changedDistantEndpoint: String,
|
||||
@field:XmlAttribute(name = "pt")
|
||||
@field:XmlJavaTypeAdapter(value = LocalDateTimeAdapter::class)
|
||||
var plannedTime: LocalDateTime?,
|
||||
@field:XmlAttribute(name = "ct")
|
||||
@field:XmlJavaTypeAdapter(value = LocalDateTimeAdapter::class)
|
||||
var changedTime: LocalDateTime?,
|
||||
@field:XmlAttribute(name = "ppth") var plannedPath: String,
|
||||
@field:XmlAttribute(name = "cpth") var changedPath: String,
|
||||
@field:XmlAttribute(name = "pp") var plannedPlatform: String,
|
||||
@field:XmlAttribute(name = "cp") var changedPlatform: String,
|
||||
@field:XmlAttribute(name = "wings") var wings: String,
|
||||
@field:XmlAttribute(name = "l") var line: String
|
||||
@field:XmlAttribute(name = "pde") var plannedDistantEndpoint: String,
|
||||
@field:XmlAttribute(name = "cde") var changedDistantEndpoint: String,
|
||||
@field:XmlAttribute(name = "pt")
|
||||
@field:XmlJavaTypeAdapter(value = LocalDateTimeAdapter::class)
|
||||
var plannedTime: LocalDateTime?,
|
||||
@field:XmlAttribute(name = "ct")
|
||||
@field:XmlJavaTypeAdapter(value = LocalDateTimeAdapter::class)
|
||||
var changedTime: LocalDateTime?,
|
||||
@field:XmlAttribute(name = "ppth") var plannedPath: String,
|
||||
@field:XmlAttribute(name = "cpth") var changedPath: String,
|
||||
@field:XmlAttribute(name = "pp") var plannedPlatform: String,
|
||||
@field:XmlAttribute(name = "cp") var changedPlatform: String,
|
||||
@field:XmlAttribute(name = "wings") var wings: String,
|
||||
@field:XmlAttribute(name = "l") var line: String
|
||||
) {
|
||||
constructor(): this("", "",
|
||||
constructor() : this("", "",
|
||||
null,
|
||||
null,
|
||||
"", "", "", "",
|
||||
|
||||
+6
-6
@@ -6,12 +6,12 @@ import jakarta.xml.bind.annotation.XmlAttribute
|
||||
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
data class BahnTripLabel(
|
||||
@field:XmlAttribute(name = "c") var category: String,
|
||||
// S: S-Bahn, N: Nahverkehr, F: Fernverkehr
|
||||
@field:XmlAttribute(name = "f") var filterFlags: String,
|
||||
@field:XmlAttribute(name = "n") var trainNumber: String,
|
||||
@field:XmlAttribute(name = "o") var owner: String,
|
||||
@field:XmlAttribute(name = "t") var tripType: BahnTripType
|
||||
@field:XmlAttribute(name = "c") var category: String,
|
||||
// S: S-Bahn, N: Nahverkehr, F: Fernverkehr
|
||||
@field:XmlAttribute(name = "f") var filterFlags: String,
|
||||
@field:XmlAttribute(name = "n") var trainNumber: String,
|
||||
@field:XmlAttribute(name = "o") var owner: String,
|
||||
@field:XmlAttribute(name = "t") var tripType: BahnTripType
|
||||
) {
|
||||
constructor() : this("", "", "", "", BahnTripType.p)
|
||||
}
|
||||
+2
-2
@@ -5,7 +5,7 @@ import de.twomartens.timetable.bahnApi.model.dto.BahnStation
|
||||
import de.twomartens.timetable.bahnApi.model.dto.BahnStations
|
||||
import de.twomartens.timetable.bahnApi.model.dto.BahnTimetable
|
||||
import de.twomartens.timetable.bahnApi.property.BahnApiProperties
|
||||
import de.twomartens.timetable.model.base.HourAtDay
|
||||
import de.twomartens.timetable.types.HourAtDay
|
||||
import org.springframework.http.HttpEntity
|
||||
import org.springframework.http.HttpHeaders
|
||||
import org.springframework.http.HttpMethod
|
||||
@@ -23,7 +23,7 @@ class BahnApiService(
|
||||
fun fetchStations(pattern: String): List<BahnStation> {
|
||||
val requestEntity = buildRequestEntity<BahnStations>()
|
||||
val response = restTemplate.exchange(
|
||||
"https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/station/${pattern}",
|
||||
"https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/station/${pattern}",
|
||||
HttpMethod.GET,
|
||||
requestEntity,
|
||||
BahnStations::class.java
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ import de.twomartens.timetable.bahnApi.model.dto.BahnStation
|
||||
import de.twomartens.timetable.bahnApi.model.dto.BahnTimetable
|
||||
import de.twomartens.timetable.bahnApi.repository.BahnStationRepository
|
||||
import de.twomartens.timetable.bahnApi.repository.BahnTimetableRepository
|
||||
import de.twomartens.timetable.model.base.HourAtDay
|
||||
import de.twomartens.timetable.types.HourAtDay
|
||||
import org.mapstruct.factory.Mappers
|
||||
import org.springframework.stereotype.Service
|
||||
|
||||
|
||||
+2
-2
@@ -5,9 +5,9 @@ import de.twomartens.timetable.bahnApi.model.FetchDates
|
||||
import de.twomartens.timetable.bahnApi.model.TaskFactory
|
||||
import de.twomartens.timetable.bahnApi.model.db.ScheduledFetchTask
|
||||
import de.twomartens.timetable.bahnApi.repository.ScheduledFetchTaskRepository
|
||||
import de.twomartens.timetable.model.base.Hour
|
||||
import de.twomartens.timetable.model.base.HourAtDay
|
||||
import de.twomartens.timetable.model.db.TswRoute
|
||||
import de.twomartens.timetable.types.Hour
|
||||
import de.twomartens.timetable.types.HourAtDay
|
||||
import mu.KotlinLogging
|
||||
import org.springframework.stereotype.Service
|
||||
import java.time.LocalDate
|
||||
|
||||
+1
-1
@@ -6,8 +6,8 @@ import de.twomartens.timetable.bahnApi.repository.ScheduledFetchTaskRepository
|
||||
import de.twomartens.timetable.bahnApi.tasks.DeleteScheduledTask
|
||||
import de.twomartens.timetable.bahnApi.tasks.FetchTimetableTask
|
||||
import de.twomartens.timetable.bahnApi.tasks.StoreTimetableTask
|
||||
import de.twomartens.timetable.model.base.HourAtDay
|
||||
import de.twomartens.timetable.property.TimeProperties
|
||||
import de.twomartens.timetable.types.HourAtDay
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler
|
||||
import org.springframework.stereotype.Service
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ package de.twomartens.timetable.bahnApi.tasks
|
||||
import de.twomartens.timetable.bahnApi.model.Eva
|
||||
import de.twomartens.timetable.bahnApi.service.BahnApiService
|
||||
import de.twomartens.timetable.bahnApi.service.TaskScheduler
|
||||
import de.twomartens.timetable.model.base.HourAtDay
|
||||
import de.twomartens.timetable.types.HourAtDay
|
||||
import mu.KotlinLogging
|
||||
import org.springframework.scheduling.annotation.Async
|
||||
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ package de.twomartens.timetable.bahnApi.tasks
|
||||
|
||||
import de.twomartens.timetable.bahnApi.model.dto.BahnTimetable
|
||||
import de.twomartens.timetable.bahnApi.service.BahnDatabaseService
|
||||
import de.twomartens.timetable.model.base.HourAtDay
|
||||
import de.twomartens.timetable.types.HourAtDay
|
||||
import mu.KotlinLogging
|
||||
import org.springframework.scheduling.annotation.Async
|
||||
|
||||
|
||||
+1
-1
@@ -10,5 +10,5 @@ import org.springframework.context.annotation.Configuration
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(RestTemplateTimeoutProperties::class, ServiceProperties::class,
|
||||
StatusProbeProperties::class, TimeProperties::class, BahnApiProperties::class)
|
||||
StatusProbeProperties::class, TimeProperties::class, BahnApiProperties::class)
|
||||
open class PropertyConfiguration
|
||||
+1
-1
@@ -1,9 +1,9 @@
|
||||
package de.twomartens.timetable.controller
|
||||
|
||||
import de.twomartens.timetable.bahnApi.service.ScheduledTaskService
|
||||
import de.twomartens.timetable.model.base.NonEmptyString
|
||||
import de.twomartens.timetable.model.db.UserId
|
||||
import de.twomartens.timetable.repository.TswRouteRepository
|
||||
import de.twomartens.timetable.types.NonEmptyString
|
||||
import io.swagger.v3.oas.annotations.Operation
|
||||
import io.swagger.v3.oas.annotations.Parameter
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package de.twomartens.timetable.model.db
|
||||
|
||||
import de.twomartens.timetable.model.base.PositiveInteger
|
||||
import de.twomartens.timetable.types.PositiveInteger
|
||||
|
||||
@JvmInline
|
||||
value class CoachCapacity(val capacity: PositiveInteger)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package de.twomartens.timetable.model.db
|
||||
|
||||
import de.twomartens.timetable.model.base.NonEmptyString
|
||||
import de.twomartens.timetable.types.NonEmptyString
|
||||
|
||||
@JvmInline
|
||||
value class CountryCode(val countryCode: NonEmptyString) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package de.twomartens.timetable.model.db
|
||||
|
||||
import de.twomartens.timetable.model.base.NonEmptyString
|
||||
import de.twomartens.timetable.types.NonEmptyString
|
||||
import kotlin.time.Duration
|
||||
|
||||
data class Depot(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package de.twomartens.timetable.model.db
|
||||
|
||||
import de.twomartens.timetable.model.base.NonEmptyString
|
||||
import de.twomartens.timetable.types.NonEmptyString
|
||||
import org.bson.types.ObjectId
|
||||
import org.springframework.data.annotation.CreatedDate
|
||||
import org.springframework.data.annotation.Id
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package de.twomartens.timetable.model.db
|
||||
|
||||
import de.twomartens.timetable.model.base.PositiveInteger
|
||||
import de.twomartens.timetable.types.PositiveInteger
|
||||
|
||||
@JvmInline
|
||||
value class FormationId(val id: PositiveInteger)
|
||||
@@ -1,6 +1,6 @@
|
||||
package de.twomartens.timetable.model.db
|
||||
|
||||
import de.twomartens.timetable.model.base.NonEmptyString
|
||||
import de.twomartens.timetable.types.NonEmptyString
|
||||
import kotlin.time.Duration
|
||||
|
||||
data class Portal(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package de.twomartens.timetable.model.db
|
||||
|
||||
import de.twomartens.timetable.model.base.NonEmptyString
|
||||
import de.twomartens.timetable.types.NonEmptyString
|
||||
|
||||
@JvmInline
|
||||
value class Section(val name: NonEmptyString)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package de.twomartens.timetable.model.db
|
||||
|
||||
import de.twomartens.timetable.model.base.NonEmptyString
|
||||
import de.twomartens.timetable.types.NonEmptyString
|
||||
|
||||
@JvmInline
|
||||
value class StationId(val id: NonEmptyString) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package de.twomartens.timetable.model.db
|
||||
|
||||
import de.twomartens.timetable.model.base.PositiveInteger
|
||||
import de.twomartens.timetable.types.PositiveInteger
|
||||
|
||||
@JvmInline
|
||||
value class TrackId(val id: PositiveInteger)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package de.twomartens.timetable.model.db
|
||||
|
||||
import de.twomartens.timetable.model.base.NonEmptyString
|
||||
import de.twomartens.timetable.types.NonEmptyString
|
||||
import org.bson.types.ObjectId
|
||||
import org.springframework.data.annotation.CreatedDate
|
||||
import org.springframework.data.annotation.Id
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package de.twomartens.timetable.model.db
|
||||
|
||||
import de.twomartens.timetable.model.base.NonEmptyString
|
||||
import de.twomartens.timetable.types.NonEmptyString
|
||||
import org.bson.types.ObjectId
|
||||
import org.springframework.data.annotation.CreatedDate
|
||||
import org.springframework.data.annotation.Id
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package de.twomartens.timetable.model.db
|
||||
|
||||
import de.twomartens.timetable.model.base.NonEmptyString
|
||||
import de.twomartens.timetable.types.NonEmptyString
|
||||
|
||||
@JvmInline
|
||||
value class UserId(val id: NonEmptyString)
|
||||
|
||||
+1
-1
@@ -1,8 +1,8 @@
|
||||
package de.twomartens.timetable.repository
|
||||
|
||||
import de.twomartens.timetable.model.base.NonEmptyString
|
||||
import de.twomartens.timetable.model.db.TswRoute
|
||||
import de.twomartens.timetable.model.db.UserId
|
||||
import de.twomartens.timetable.types.NonEmptyString
|
||||
import org.bson.types.ObjectId
|
||||
import org.springframework.data.mongodb.repository.MongoRepository
|
||||
|
||||
|
||||
+4
-4
@@ -6,8 +6,8 @@ import org.springframework.web.filter.ForwardedHeaderFilter
|
||||
|
||||
@Configuration
|
||||
open class FilterConfiguration {
|
||||
@Bean
|
||||
open fun forwardedFilter(): ForwardedHeaderFilter {
|
||||
return ForwardedHeaderFilter()
|
||||
}
|
||||
@Bean
|
||||
open fun forwardedFilter(): ForwardedHeaderFilter {
|
||||
return ForwardedHeaderFilter()
|
||||
}
|
||||
}
|
||||
+8
-8
@@ -8,13 +8,13 @@ import java.time.Clock
|
||||
|
||||
@Configuration
|
||||
open class InterceptorConfiguration {
|
||||
@Bean
|
||||
open fun loggingInterceptorRest(clock: Clock): LoggingInterceptorRest {
|
||||
return LoggingInterceptorRest(clock)
|
||||
}
|
||||
@Bean
|
||||
open fun loggingInterceptorRest(clock: Clock): LoggingInterceptorRest {
|
||||
return LoggingInterceptorRest(clock)
|
||||
}
|
||||
|
||||
@Bean
|
||||
open fun headerInterceptorRest(): HeaderInterceptorRest {
|
||||
return HeaderInterceptorRest()
|
||||
}
|
||||
@Bean
|
||||
open fun headerInterceptorRest(): HeaderInterceptorRest {
|
||||
return HeaderInterceptorRest()
|
||||
}
|
||||
}
|
||||
+15
-15
@@ -12,28 +12,28 @@ import org.springframework.context.annotation.Configuration
|
||||
|
||||
@SecurityScheme(name = "bearerAuth", type = SecuritySchemeType.HTTP, scheme = "bearer", bearerFormat = "JWT")
|
||||
@SecurityScheme(
|
||||
name = "oauth2",
|
||||
type = SecuritySchemeType.OAUTH2,
|
||||
flows = OAuthFlows(
|
||||
implicit = OAuthFlow(
|
||||
authorizationUrl = "https://id.2martens.de/realms/2martens/protocol/openid-connect/auth",
|
||||
tokenUrl = "https://id.2martens.de/realms/2martens/protocol/openid-connect/token"
|
||||
name = "oauth2",
|
||||
type = SecuritySchemeType.OAUTH2,
|
||||
flows = OAuthFlows(
|
||||
implicit = OAuthFlow(
|
||||
authorizationUrl = "https://id.2martens.de/realms/2martens/protocol/openid-connect/auth",
|
||||
tokenUrl = "https://id.2martens.de/realms/2martens/protocol/openid-connect/token"
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
@Configuration
|
||||
open class OpenApiConfiguration {
|
||||
@Bean
|
||||
open fun customOpenAPI(
|
||||
@Value("\${openapi.description}") apiDescription: String,
|
||||
@Value("\${openapi.version}") apiVersion: String, @Value("\${openapi.title}") apiTitle: String
|
||||
@Value("\${openapi.description}") apiDescription: String,
|
||||
@Value("\${openapi.version}") apiVersion: String, @Value("\${openapi.title}") apiTitle: String
|
||||
): OpenAPI {
|
||||
return OpenAPI()
|
||||
.info(
|
||||
Info()
|
||||
.title(apiTitle)
|
||||
.version(apiVersion)
|
||||
.description(apiDescription)
|
||||
)
|
||||
.info(
|
||||
Info()
|
||||
.title(apiTitle)
|
||||
.version(apiVersion)
|
||||
.description(apiDescription)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+9
-9
@@ -1,8 +1,8 @@
|
||||
package de.twomartens.timetable.support.configuration
|
||||
|
||||
import de.twomartens.timetable.property.RestTemplateTimeoutProperties
|
||||
import de.twomartens.timetable.support.interceptor.HeaderInterceptorRest
|
||||
import de.twomartens.timetable.support.interceptor.LoggingInterceptorRest
|
||||
import de.twomartens.timetable.property.RestTemplateTimeoutProperties
|
||||
import org.springframework.boot.web.client.RestTemplateBuilder
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
@@ -17,10 +17,10 @@ open class RestTemplateConfiguration {
|
||||
restTemplateTimeoutProperties: RestTemplateTimeoutProperties
|
||||
): RestTemplate {
|
||||
return RestTemplateBuilder()
|
||||
.additionalInterceptors(headerInterceptorRest, loggingInterceptor)
|
||||
.setConnectTimeout(restTemplateTimeoutProperties.connectionRestTemplateTimeoutInMillis)
|
||||
.setReadTimeout(restTemplateTimeoutProperties.readTimeoutRestTemplateInMillis)
|
||||
.build()
|
||||
.additionalInterceptors(headerInterceptorRest, loggingInterceptor)
|
||||
.setConnectTimeout(restTemplateTimeoutProperties.connectionRestTemplateTimeoutInMillis)
|
||||
.setReadTimeout(restTemplateTimeoutProperties.readTimeoutRestTemplateInMillis)
|
||||
.build()
|
||||
}
|
||||
|
||||
@Bean("restTemplateRestHealthIndicator")
|
||||
@@ -29,9 +29,9 @@ open class RestTemplateConfiguration {
|
||||
restTemplateTimeoutProperties: RestTemplateTimeoutProperties
|
||||
): RestTemplate {
|
||||
return RestTemplateBuilder()
|
||||
.additionalInterceptors(headerInterceptorRest)
|
||||
.setConnectTimeout(restTemplateTimeoutProperties.connectionRestHealthIndicatorTimeoutInMillis)
|
||||
.setReadTimeout(restTemplateTimeoutProperties.readTimeoutRestHealthIndicatorInMillis)
|
||||
.build()
|
||||
.additionalInterceptors(headerInterceptorRest)
|
||||
.setConnectTimeout(restTemplateTimeoutProperties.connectionRestHealthIndicatorTimeoutInMillis)
|
||||
.setReadTimeout(restTemplateTimeoutProperties.readTimeoutRestHealthIndicatorInMillis)
|
||||
.build()
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -18,8 +18,8 @@ open class StatusProbeConfiguration(private val clock: Clock) {
|
||||
@Bean
|
||||
open fun testStatusProbe(statusProbeLogger: StatusProbeLogger): StatusProbe {
|
||||
return CountBasedStatusProbe(
|
||||
1,
|
||||
clock, StatusProbeCriticality.K1, "testStatusProbe", statusProbeLogger
|
||||
1,
|
||||
clock, StatusProbeCriticality.K1, "testStatusProbe", statusProbeLogger
|
||||
)
|
||||
}
|
||||
}
|
||||
+13
-13
@@ -34,12 +34,12 @@ open class WebSecurityConfiguration {
|
||||
@Throws(Exception::class)
|
||||
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
|
||||
http
|
||||
.csrf { it.disable() }
|
||||
.authorizeHttpRequests { it.requestMatchers(*PERMITTED_PATHS.toTypedArray<String>()).permitAll() }
|
||||
.authorizeHttpRequests { it.requestMatchers(HttpMethod.OPTIONS).permitAll() }
|
||||
.authorizeHttpRequests { it.anyRequest().authenticated() }
|
||||
.oauth2ResourceServer { obj: OAuth2ResourceServerConfigurer<HttpSecurity?> -> obj.jwt(Customizer.withDefaults()) }
|
||||
.addFilterAfter(createPolicyEnforcerFilter(), BearerTokenAuthenticationFilter::class.java)
|
||||
.csrf { it.disable() }
|
||||
.authorizeHttpRequests { it.requestMatchers(*PERMITTED_PATHS.toTypedArray<String>()).permitAll() }
|
||||
.authorizeHttpRequests { it.requestMatchers(HttpMethod.OPTIONS).permitAll() }
|
||||
.authorizeHttpRequests { it.anyRequest().authenticated() }
|
||||
.oauth2ResourceServer { obj: OAuth2ResourceServerConfigurer<HttpSecurity?> -> obj.jwt(Customizer.withDefaults()) }
|
||||
.addFilterAfter(createPolicyEnforcerFilter(), BearerTokenAuthenticationFilter::class.java)
|
||||
return http.build()
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ open class WebSecurityConfiguration {
|
||||
override fun resolve(request: HttpRequest): PolicyEnforcerConfig {
|
||||
return try {
|
||||
val policyEnforcerConfig = JsonSerialization.readValue(
|
||||
javaClass.getResourceAsStream("/policy-enforcer.json"), PolicyEnforcerConfig::class.java
|
||||
javaClass.getResourceAsStream("/policy-enforcer.json"), PolicyEnforcerConfig::class.java
|
||||
)
|
||||
policyEnforcerConfig.credentials = mapOf(Pair("secret", clientSecret))
|
||||
if (request.method == HttpMethod.OPTIONS.name()) {
|
||||
@@ -72,12 +72,12 @@ open class WebSecurityConfiguration {
|
||||
|
||||
companion object {
|
||||
private val PERMITTED_PATHS: Collection<String> = listOf(
|
||||
"/timetable/v1/healthCheck",
|
||||
"/actuator/**",
|
||||
"/timetable/v1/doc/**",
|
||||
"/timetable/v1/api-docs/**",
|
||||
"/error",
|
||||
"/timetable/version",
|
||||
"/timetable/v1/healthCheck",
|
||||
"/actuator/**",
|
||||
"/timetable/v1/doc/**",
|
||||
"/timetable/v1/api-docs/**",
|
||||
"/error",
|
||||
"/timetable/version",
|
||||
)
|
||||
private val PATHS = buildPathConfigs()
|
||||
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ import org.springframework.web.bind.annotation.RestController
|
||||
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler
|
||||
|
||||
@ControllerAdvice(annotations = [RestController::class])
|
||||
class ExceptionController: ResponseEntityExceptionHandler() {
|
||||
class ExceptionController : ResponseEntityExceptionHandler() {
|
||||
@ExceptionHandler(HttpStatusException::class)
|
||||
fun handleException(e: HttpStatusException): ResponseEntity<ErrorMessage> {
|
||||
if (e.cause != null) {
|
||||
|
||||
+2
-1
@@ -65,7 +65,8 @@ class VersionHtmlController {
|
||||
JarFile(jarFileName).use { jarFile ->
|
||||
val entry = jarFile.getEntry(JarFile.MANIFEST_NAME)
|
||||
jarFile.getInputStream(entry).use { `in` ->
|
||||
return String(`in`.readAllBytes(), StandardCharsets.UTF_8).lines().toList() }
|
||||
return String(`in`.readAllBytes(), StandardCharsets.UTF_8).lines().toList()
|
||||
}
|
||||
}
|
||||
} catch (ignored: FileNotFoundException) {
|
||||
// do nothing if manifest file is not available
|
||||
|
||||
+1
-1
@@ -2,5 +2,5 @@ package de.twomartens.timetable.support.exception
|
||||
|
||||
import org.springframework.http.HttpStatus
|
||||
|
||||
class HttpStatusException(val status: HttpStatus, message: String, cause: Throwable?):
|
||||
class HttpStatusException(val status: HttpStatus, message: String, cause: Throwable?) :
|
||||
RuntimeException(message, cause)
|
||||
+1
-1
@@ -8,7 +8,7 @@ import java.io.ByteArrayInputStream
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
|
||||
class BufferingClientHttpResponseWrapper(private val response: ClientHttpResponse): ClientHttpResponse {
|
||||
class BufferingClientHttpResponseWrapper(private val response: ClientHttpResponse) : ClientHttpResponse {
|
||||
private var body: ByteArray? = null
|
||||
|
||||
@Throws(IOException::class)
|
||||
|
||||
+4
-4
@@ -44,8 +44,8 @@ class HeaderInterceptorRest : HeaderInterceptor(), HandlerInterceptor, ClientHtt
|
||||
// ClientHttpRequestInterceptor
|
||||
@Throws(IOException::class)
|
||||
override fun intercept(
|
||||
request: HttpRequest, body: ByteArray,
|
||||
execution: ClientHttpRequestExecution
|
||||
request: HttpRequest, body: ByteArray,
|
||||
execution: ClientHttpRequestExecution
|
||||
): ClientHttpResponse {
|
||||
request.headers.add(HEADER_FIELD_TRACE_ID, getTraceId())
|
||||
val requestType = getRequestType()
|
||||
@@ -63,8 +63,8 @@ class HeaderInterceptorRest : HeaderInterceptor(), HandlerInterceptor, ClientHtt
|
||||
|
||||
// HandlerInterceptor
|
||||
override fun preHandle(
|
||||
request: HttpServletRequest, response: HttpServletResponse,
|
||||
handler: Any
|
||||
request: HttpServletRequest, response: HttpServletResponse,
|
||||
handler: Any
|
||||
): Boolean {
|
||||
val traceId = extractTraceId(request)
|
||||
val requestType = extractRequestType(request)
|
||||
|
||||
+111
-111
@@ -35,14 +35,14 @@ class LoggingInterceptorRest(
|
||||
|
||||
@Throws(IOException::class, ServletException::class)
|
||||
override fun doFilter(
|
||||
request: ServletRequest, response: ServletResponse,
|
||||
chain: FilterChain
|
||||
request: ServletRequest, response: ServletResponse,
|
||||
chain: FilterChain
|
||||
) {
|
||||
val requestTime = ZonedDateTime.now(clock)
|
||||
val httpRequest = request as HttpServletRequest
|
||||
val requestWrapper = ContentCachingRequestWrapper(httpRequest)
|
||||
val responseWrapper = ContentCachingResponseWrapper(
|
||||
(response as HttpServletResponse)
|
||||
(response as HttpServletResponse)
|
||||
)
|
||||
var fullResponseBytes: ByteArray? = null
|
||||
var throwable: Throwable? = null
|
||||
@@ -51,8 +51,8 @@ class LoggingInterceptorRest(
|
||||
try {
|
||||
try {
|
||||
chain.doFilter(
|
||||
if (requestLogBehaviour != FieldLogBehaviour.NEVER) requestWrapper else httpRequest,
|
||||
responseWrapper
|
||||
if (requestLogBehaviour != FieldLogBehaviour.NEVER) requestWrapper else httpRequest,
|
||||
responseWrapper
|
||||
)
|
||||
if (responseLogBehaviour != FieldLogBehaviour.NEVER) {
|
||||
fullResponseBytes = responseWrapper.contentAsByteArray
|
||||
@@ -68,58 +68,58 @@ class LoggingInterceptorRest(
|
||||
try {
|
||||
val responseSize = responseWrapper.contentSize
|
||||
val responseHeaders = extractHeaders(
|
||||
headerNames = responseWrapper.headerNames.iterator()
|
||||
headerNames = responseWrapper.headerNames.iterator()
|
||||
) { responseWrapper.getHeaders(it).iterator() }
|
||||
if (
|
||||
(responseLogBehaviour == FieldLogBehaviour.ONLY_ON_ERROR && isError(httpStatusCode)
|
||||
|| responseLogBehaviour == FieldLogBehaviour.ALWAYS)
|
||||
&& fullResponseBytes != null
|
||||
(responseLogBehaviour == FieldLogBehaviour.ONLY_ON_ERROR && isError(httpStatusCode)
|
||||
|| responseLogBehaviour == FieldLogBehaviour.ALWAYS)
|
||||
&& fullResponseBytes != null
|
||||
) {
|
||||
responseBody = String(
|
||||
fullResponseBytes,
|
||||
determineResponseEncoding()
|
||||
fullResponseBytes,
|
||||
determineResponseEncoding()
|
||||
)
|
||||
}
|
||||
val query = if (httpRequest.queryString != null) "?${httpRequest.queryString}" else ""
|
||||
val requestUrl = URL("${httpRequest.requestURL}$query")
|
||||
val requestHeaders = extractHeaders(
|
||||
headerNames = httpRequest.headerNames.asIterator(),
|
||||
ignoreList = listOf("authorization")) {
|
||||
headerNames = httpRequest.headerNames.asIterator(),
|
||||
ignoreList = listOf("authorization")) {
|
||||
httpRequest.getHeaders(it).asIterator()
|
||||
}
|
||||
var requestBody: String? = null
|
||||
var businessType: String? = null
|
||||
if (requestLogBehaviour == FieldLogBehaviour.ONLY_ON_ERROR && isError(httpStatusCode)
|
||||
|| requestLogBehaviour == FieldLogBehaviour.ALWAYS
|
||||
|| requestLogBehaviour == FieldLogBehaviour.ALWAYS
|
||||
) {
|
||||
val fullRequestBytes = requestWrapper.contentAsByteArray
|
||||
requestBody = String(fullRequestBytes, determineRequestEncoding())
|
||||
businessType = determineBusinessType()
|
||||
}
|
||||
log(
|
||||
LogMessage(
|
||||
requestHeaders = requestHeaders,
|
||||
responseHeaders = responseHeaders,
|
||||
url = requestUrl,
|
||||
method = httpRequest.method,
|
||||
requestMimeType = typeToString(request.getContentType()),
|
||||
responseMimeType = typeToString(response.getContentType()),
|
||||
requestBody = requestBody,
|
||||
responseBody = responseBody,
|
||||
requestSize = httpRequest.contentLength,
|
||||
responseSize = responseSize,
|
||||
httpStatus = httpStatusCode,
|
||||
direction = DIRECTION_IN,
|
||||
requestTime = requestTime,
|
||||
responseTime = ZonedDateTime.now(clock),
|
||||
traceId = HeaderInterceptor.getTraceId(),
|
||||
requestType = HeaderInterceptor.getRequestType(),
|
||||
businessType = businessType,
|
||||
throwable = throwable
|
||||
)
|
||||
LogMessage(
|
||||
requestHeaders = requestHeaders,
|
||||
responseHeaders = responseHeaders,
|
||||
url = requestUrl,
|
||||
method = httpRequest.method,
|
||||
requestMimeType = typeToString(request.getContentType()),
|
||||
responseMimeType = typeToString(response.getContentType()),
|
||||
requestBody = requestBody,
|
||||
responseBody = responseBody,
|
||||
requestSize = httpRequest.contentLength,
|
||||
responseSize = responseSize,
|
||||
httpStatus = httpStatusCode,
|
||||
direction = DIRECTION_IN,
|
||||
requestTime = requestTime,
|
||||
responseTime = ZonedDateTime.now(clock),
|
||||
traceId = HeaderInterceptor.getTraceId(),
|
||||
requestType = HeaderInterceptor.getRequestType(),
|
||||
businessType = businessType,
|
||||
throwable = throwable
|
||||
)
|
||||
)
|
||||
val interceptorCloseables =
|
||||
request.getAttribute(HeaderInterceptorRest.CLASS_NAME) as HeaderInterceptor.InterceptorCloseables
|
||||
request.getAttribute(HeaderInterceptorRest.CLASS_NAME) as HeaderInterceptor.InterceptorCloseables
|
||||
interceptorCloseables.close()
|
||||
} catch (e: java.lang.RuntimeException) {
|
||||
log.error(e.toString(), e)
|
||||
@@ -133,8 +133,8 @@ class LoggingInterceptorRest(
|
||||
|
||||
@Throws(IOException::class)
|
||||
override fun intercept(
|
||||
request: HttpRequest,
|
||||
requestBytes: ByteArray, execution: ClientHttpRequestExecution
|
||||
request: HttpRequest,
|
||||
requestBytes: ByteArray, execution: ClientHttpRequestExecution
|
||||
): ClientHttpResponse {
|
||||
val requestTime = ZonedDateTime.now(clock)
|
||||
var responseSize = 0
|
||||
@@ -147,7 +147,7 @@ class LoggingInterceptorRest(
|
||||
var businessType: String? = null
|
||||
return try {
|
||||
val result = BufferingClientHttpResponseWrapper(
|
||||
execution.execute(request, requestBytes)
|
||||
execution.execute(request, requestBytes)
|
||||
)
|
||||
val responseBytes = StreamUtils.copyToByteArray(result.getBody())
|
||||
responseSize = responseBytes.size
|
||||
@@ -155,11 +155,11 @@ class LoggingInterceptorRest(
|
||||
responseMediaType = result.headers.getContentType()
|
||||
httpStatusCode = result.statusCode.value()
|
||||
if (responseLogBehaviour == FieldLogBehaviour.ONLY_ON_ERROR && isError(httpStatusCode)
|
||||
|| responseLogBehaviour == FieldLogBehaviour.ALWAYS
|
||||
|| responseLogBehaviour == FieldLogBehaviour.ALWAYS
|
||||
) {
|
||||
responseBody = String(
|
||||
responseBytes,
|
||||
determineRequestEncoding()
|
||||
responseBytes,
|
||||
determineRequestEncoding()
|
||||
)
|
||||
}
|
||||
result
|
||||
@@ -171,35 +171,35 @@ class LoggingInterceptorRest(
|
||||
val url = request.uri.toURL()
|
||||
val requestHeaders: Map<String, Collection<String>> = extractHeaders(request.headers)
|
||||
if (requestLogBehaviour == FieldLogBehaviour.ONLY_ON_ERROR && isError(httpStatusCode)
|
||||
|| requestLogBehaviour == FieldLogBehaviour.ALWAYS
|
||||
|| requestLogBehaviour == FieldLogBehaviour.ALWAYS
|
||||
) {
|
||||
requestBody = String(
|
||||
requestBytes,
|
||||
determineRequestEncoding()
|
||||
requestBytes,
|
||||
determineRequestEncoding()
|
||||
)
|
||||
businessType = determineBusinessType()
|
||||
}
|
||||
log(
|
||||
LogMessage(
|
||||
requestHeaders = requestHeaders,
|
||||
responseHeaders = responseHeaders,
|
||||
url = url,
|
||||
method = request.method.name(),
|
||||
requestMimeType = typeToString(request.headers.getContentType()),
|
||||
requestBody = requestBody,
|
||||
responseBody = responseBody,
|
||||
responseMimeType = typeToString(responseMediaType!!),
|
||||
requestSize = requestBytes.size,
|
||||
responseSize = responseSize,
|
||||
httpStatus = httpStatusCode,
|
||||
direction = DIRECTION_OUT,
|
||||
requestTime = requestTime,
|
||||
responseTime = ZonedDateTime.now(clock),
|
||||
businessType = businessType,
|
||||
throwable = throwable,
|
||||
traceId = HeaderInterceptorRest.extractTraceId(request),
|
||||
requestType = HeaderInterceptorRest.extractRequestType(request),
|
||||
)
|
||||
LogMessage(
|
||||
requestHeaders = requestHeaders,
|
||||
responseHeaders = responseHeaders,
|
||||
url = url,
|
||||
method = request.method.name(),
|
||||
requestMimeType = typeToString(request.headers.getContentType()),
|
||||
requestBody = requestBody,
|
||||
responseBody = responseBody,
|
||||
responseMimeType = typeToString(responseMediaType!!),
|
||||
requestSize = requestBytes.size,
|
||||
responseSize = responseSize,
|
||||
httpStatus = httpStatusCode,
|
||||
direction = DIRECTION_OUT,
|
||||
requestTime = requestTime,
|
||||
responseTime = ZonedDateTime.now(clock),
|
||||
businessType = businessType,
|
||||
throwable = throwable,
|
||||
traceId = HeaderInterceptorRest.extractTraceId(request),
|
||||
requestType = HeaderInterceptorRest.extractRequestType(request),
|
||||
)
|
||||
)
|
||||
} catch (e: java.lang.RuntimeException) {
|
||||
log.error(e.toString(), e)
|
||||
@@ -210,18 +210,18 @@ class LoggingInterceptorRest(
|
||||
private fun log(logMessage: LogMessage) {
|
||||
val stringMapMessage = StringMapMessage()
|
||||
addLogString(
|
||||
stringMapMessage, PARAM_REQUEST_HEADERS,
|
||||
toHeaderString(logMessage.requestHeaders)
|
||||
stringMapMessage, PARAM_REQUEST_HEADERS,
|
||||
toHeaderString(logMessage.requestHeaders)
|
||||
)
|
||||
addLogString(
|
||||
stringMapMessage, PARAM_RESPONSE_HEADERS,
|
||||
toHeaderString(logMessage.responseHeaders)
|
||||
stringMapMessage, PARAM_RESPONSE_HEADERS,
|
||||
toHeaderString(logMessage.responseHeaders)
|
||||
)
|
||||
addLogString(stringMapMessage, PARAM_URL_FULL, logMessage.url.toString())
|
||||
addLogString(stringMapMessage, PARAM_URL_DOMAIN, logMessage.url.host)
|
||||
addLogString(
|
||||
stringMapMessage, PARAM_URL_EXTENSION,
|
||||
extractExtension(logMessage.url.path)
|
||||
stringMapMessage, PARAM_URL_EXTENSION,
|
||||
extractExtension(logMessage.url.path)
|
||||
)
|
||||
addLogString(stringMapMessage, PARAM_URL_PATH, logMessage.url.path)
|
||||
addLogString(stringMapMessage, PARAM_URL_PORT, logMessage.url.port.toString())
|
||||
@@ -229,8 +229,8 @@ class LoggingInterceptorRest(
|
||||
addLogString(stringMapMessage, PARAM_URL_QUERY, logMessage.url.query)
|
||||
addLogString(stringMapMessage, PARAM_REQUEST_METHOD, logMessage.method)
|
||||
addLogString(
|
||||
stringMapMessage, PARAM_REQUEST_REFERER,
|
||||
getHeader(logMessage.requestHeaders, HttpHeaders.REFERER)
|
||||
stringMapMessage, PARAM_REQUEST_REFERER,
|
||||
getHeader(logMessage.requestHeaders, HttpHeaders.REFERER)
|
||||
)
|
||||
addLogString(stringMapMessage, PARAM_REQUEST_MIMETYPE, logMessage.requestMimeType)
|
||||
addLogString(stringMapMessage, PARAM_RESPONSE_MIMETYPE, logMessage.responseMimeType)
|
||||
@@ -240,21 +240,21 @@ class LoggingInterceptorRest(
|
||||
addLogString(stringMapMessage, PARAM_DIRECTION, logMessage.direction)
|
||||
addLogString(stringMapMessage, PARAM_PROTOCOL, PROTOCOL_NAME)
|
||||
addLogString(
|
||||
stringMapMessage, PARAM_REQUEST_TIME,
|
||||
logMessage.requestTime.format(DATE_TIME_FORMATTER)
|
||||
stringMapMessage, PARAM_REQUEST_TIME,
|
||||
logMessage.requestTime.format(DATE_TIME_FORMATTER)
|
||||
)
|
||||
addLogString(
|
||||
stringMapMessage, PARAM_RESPONSE_TIME,
|
||||
logMessage.responseTime.format(DATE_TIME_FORMATTER)
|
||||
stringMapMessage, PARAM_RESPONSE_TIME,
|
||||
logMessage.responseTime.format(DATE_TIME_FORMATTER)
|
||||
)
|
||||
addLogString(
|
||||
stringMapMessage,
|
||||
PARAM_DURATION,
|
||||
getDurationBetweenRequestAndResponseTime(logMessage).toNanos().toString()
|
||||
stringMapMessage,
|
||||
PARAM_DURATION,
|
||||
getDurationBetweenRequestAndResponseTime(logMessage).toNanos().toString()
|
||||
)
|
||||
addLogString(
|
||||
stringMapMessage, PARAM_USER_AGENT,
|
||||
getHeader(logMessage.requestHeaders, HttpHeaders.USER_AGENT)
|
||||
stringMapMessage, PARAM_USER_AGENT,
|
||||
getHeader(logMessage.requestHeaders, HttpHeaders.USER_AGENT)
|
||||
)
|
||||
addLogString(stringMapMessage, HeaderInterceptor.LOGGER_TRACE_ID, logMessage.traceId)
|
||||
addLogString(stringMapMessage, HeaderInterceptor.LOGGER_REQTYPE_ID, logMessage.requestType)
|
||||
@@ -270,9 +270,9 @@ class LoggingInterceptorRest(
|
||||
|
||||
private fun getHeader(headers: Map<String, Collection<String?>>, headerKey: String): String? {
|
||||
return headers.entries.asSequence()
|
||||
.filter { it.key.equals(headerKey, ignoreCase = true) }
|
||||
.flatMap { it.value.asSequence() }
|
||||
.firstOrNull()
|
||||
.filter { it.key.equals(headerKey, ignoreCase = true) }
|
||||
.flatMap { it.value.asSequence() }
|
||||
.firstOrNull()
|
||||
}
|
||||
|
||||
private fun addLogString(stringMapMessage: StringMapMessage, key: String, value: String?) {
|
||||
@@ -340,9 +340,9 @@ class LoggingInterceptorRest(
|
||||
const val PARAM_PROTOCOL = "network.protocol"
|
||||
|
||||
private fun extractHeaders(
|
||||
headerNames: Iterator<String>,
|
||||
ignoreList: List<String> = emptyList(),
|
||||
headerValuesSupplier: Function<String, Iterator<String>>
|
||||
headerNames: Iterator<String>,
|
||||
ignoreList: List<String> = emptyList(),
|
||||
headerValuesSupplier: Function<String, Iterator<String>>
|
||||
): Map<String, MutableCollection<String>> {
|
||||
val requestHeaders: MutableMap<String, MutableCollection<String>> = mutableMapOf()
|
||||
while (headerNames.hasNext()) {
|
||||
@@ -367,12 +367,12 @@ class LoggingInterceptorRest(
|
||||
|
||||
private fun toHeaderString(headerMap: Map<String, Collection<String>>): String {
|
||||
return headerMap.entries.asSequence()
|
||||
.flatMap { entry ->
|
||||
val key = entry.key
|
||||
entry.value.asSequence().map { Pair(key, it) }
|
||||
}
|
||||
.map { "${it.first}=${it.second}" }
|
||||
.joinToString(separator = ",")
|
||||
.flatMap { entry ->
|
||||
val key = entry.key
|
||||
entry.value.asSequence().map { Pair(key, it) }
|
||||
}
|
||||
.map { "${it.first}=${it.second}" }
|
||||
.joinToString(separator = ",")
|
||||
}
|
||||
|
||||
private fun typeToString(contentType: String?): String? {
|
||||
@@ -408,24 +408,24 @@ class LoggingInterceptorRest(
|
||||
}
|
||||
|
||||
private data class LogMessage(
|
||||
val requestHeaders: Map<String, Collection<String>>,
|
||||
val responseHeaders: Map<String, Collection<String>>,
|
||||
val url: URL,
|
||||
val method: String,
|
||||
val requestMimeType: String?,
|
||||
val responseMimeType: String?,
|
||||
val requestBody: String?,
|
||||
val responseBody: String?,
|
||||
val requestSize: Int,
|
||||
val responseSize: Int,
|
||||
val httpStatus: Int,
|
||||
val direction: String,
|
||||
val requestTime: ZonedDateTime,
|
||||
val responseTime: ZonedDateTime,
|
||||
val traceId: String?,
|
||||
val requestType: String?,
|
||||
val businessType: String?,
|
||||
val throwable: Throwable?
|
||||
val requestHeaders: Map<String, Collection<String>>,
|
||||
val responseHeaders: Map<String, Collection<String>>,
|
||||
val url: URL,
|
||||
val method: String,
|
||||
val requestMimeType: String?,
|
||||
val responseMimeType: String?,
|
||||
val requestBody: String?,
|
||||
val responseBody: String?,
|
||||
val requestSize: Int,
|
||||
val responseSize: Int,
|
||||
val httpStatus: Int,
|
||||
val direction: String,
|
||||
val requestTime: ZonedDateTime,
|
||||
val responseTime: ZonedDateTime,
|
||||
val traceId: String?,
|
||||
val requestType: String?,
|
||||
val businessType: String?,
|
||||
val throwable: Throwable?
|
||||
)
|
||||
|
||||
enum class FieldLogBehaviour {
|
||||
|
||||
+4
-4
@@ -11,8 +11,8 @@ import java.time.Duration
|
||||
import java.util.*
|
||||
|
||||
abstract class AbstractHealthIndicator(
|
||||
private val clock: Clock,
|
||||
private val preparable: Preparable
|
||||
private val clock: Clock,
|
||||
private val preparable: Preparable
|
||||
) : HealthIndicator {
|
||||
|
||||
private val logStatusDownMessage = "health indicator '${indicatorName()}' invoked with status '${Status.DOWN.code}'"
|
||||
@@ -67,8 +67,8 @@ abstract class AbstractHealthIndicator(
|
||||
|
||||
private fun indicatorName(): String {
|
||||
return this.javaClass.getSimpleName()
|
||||
.replace("HealthIndicator", "")
|
||||
.lowercase(Locale.getDefault())
|
||||
.replace("HealthIndicator", "")
|
||||
.lowercase(Locale.getDefault())
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
package de.twomartens.timetable.support.monitoring.actuator
|
||||
|
||||
import de.twomartens.timetable.support.interceptor.HeaderInterceptorRest
|
||||
import de.twomartens.timetable.property.ServiceProperties
|
||||
import de.twomartens.timetable.support.interceptor.HeaderInterceptorRest
|
||||
import org.springframework.boot.actuate.health.Health
|
||||
import org.springframework.boot.actuate.health.HealthIndicator
|
||||
import org.springframework.boot.actuate.health.Status
|
||||
|
||||
+3
-3
@@ -7,11 +7,11 @@ import java.time.Duration
|
||||
interface ScheduledStatusProbe {
|
||||
fun runScheduledTask()
|
||||
fun scheduleTask(
|
||||
threadPoolTaskScheduler: ThreadPoolTaskScheduler,
|
||||
schedulePeriod: Duration
|
||||
threadPoolTaskScheduler: ThreadPoolTaskScheduler,
|
||||
schedulePeriod: Duration
|
||||
) {
|
||||
val periodicTrigger = PeriodicTrigger(
|
||||
Duration.ofSeconds(schedulePeriod.toSeconds())
|
||||
Duration.ofSeconds(schedulePeriod.toSeconds())
|
||||
)
|
||||
threadPoolTaskScheduler.schedule(periodicTrigger) { runScheduledTask() }
|
||||
}
|
||||
|
||||
+14
-14
@@ -19,8 +19,8 @@ class StatusProbeLogger internal constructor(private val clock: Clock, private v
|
||||
}
|
||||
|
||||
fun logStatusChange(
|
||||
name: String, message: String?, status: Status, lastStatusChange: ZonedDateTime?,
|
||||
throwable: Throwable?
|
||||
name: String, message: String?, status: Status, lastStatusChange: ZonedDateTime?,
|
||||
throwable: Throwable?
|
||||
) {
|
||||
var probeIdent = getProbeIdent(name)
|
||||
if (probeIdent == null) {
|
||||
@@ -32,8 +32,8 @@ class StatusProbeLogger internal constructor(private val clock: Clock, private v
|
||||
|
||||
private fun getProbeIdent(name: String): ProbeIdent? {
|
||||
return statusProbeToStatus.keys.asSequence()
|
||||
.filter { it.name == name }
|
||||
.firstOrNull()
|
||||
.filter { it.name == name }
|
||||
.firstOrNull()
|
||||
}
|
||||
|
||||
private fun createLog(message: String?, lastStatusChange: ZonedDateTime?, throwable: Throwable?) {
|
||||
@@ -42,7 +42,7 @@ class StatusProbeLogger internal constructor(private val clock: Clock, private v
|
||||
val criticality = overallCriticality
|
||||
if (Status.UP == overallStatus) {
|
||||
commLog.info(
|
||||
MARKER, StringMapMessage()
|
||||
MARKER, StringMapMessage()
|
||||
.with(LABEL_CRITICALITY, criticality)
|
||||
.with(LABEL_STATUS, overallStatus)
|
||||
.with(LABEL_MESSAGE, cleanedMessage)
|
||||
@@ -50,7 +50,7 @@ class StatusProbeLogger internal constructor(private val clock: Clock, private v
|
||||
)
|
||||
} else {
|
||||
commLog.error(
|
||||
MARKER, StringMapMessage()
|
||||
MARKER, StringMapMessage()
|
||||
.with(LABEL_CRITICALITY, criticality)
|
||||
.with(LABEL_STATUS, overallStatus)
|
||||
.with(LABEL_MESSAGE, cleanedMessage)
|
||||
@@ -63,8 +63,8 @@ class StatusProbeLogger internal constructor(private val clock: Clock, private v
|
||||
private val overallCriticality: StatusProbeCriticality
|
||||
get() {
|
||||
val crits = statusProbeToStatus.keys.asSequence()
|
||||
.map { it.criticality }
|
||||
.toList()
|
||||
.map { it.criticality }
|
||||
.toList()
|
||||
return if (crits.contains(StatusProbeCriticality.K1)) StatusProbeCriticality.K1
|
||||
else if (crits.contains(StatusProbeCriticality.K2)) StatusProbeCriticality.K2
|
||||
else StatusProbeCriticality.K3
|
||||
@@ -77,9 +77,9 @@ class StatusProbeLogger internal constructor(private val clock: Clock, private v
|
||||
private val reason: String
|
||||
get() {
|
||||
val probesDown = statusProbeToStatus.entries.asSequence()
|
||||
.filter { it.value == Status.DOWN }
|
||||
.map { it.key }
|
||||
.toList()
|
||||
.filter { it.value == Status.DOWN }
|
||||
.map { it.key }
|
||||
.toList()
|
||||
val reasonK1 = getDownStatusProbes(probesDown, StatusProbeCriticality.K1)
|
||||
val reasonK2 = getDownStatusProbes(probesDown, StatusProbeCriticality.K2)
|
||||
val reasonK3 = getDownStatusProbes(probesDown, StatusProbeCriticality.K3)
|
||||
@@ -88,9 +88,9 @@ class StatusProbeLogger internal constructor(private val clock: Clock, private v
|
||||
|
||||
private fun getDownStatusProbes(probesDown: List<ProbeIdent>, criticality: StatusProbeCriticality): String {
|
||||
val downProbeNames = probesDown.asSequence()
|
||||
.filter { it.criticality == criticality }
|
||||
.map { it.name }
|
||||
.toList()
|
||||
.filter { it.criticality == criticality }
|
||||
.map { it.name }
|
||||
.toList()
|
||||
return if (downProbeNames.isNotEmpty()) {
|
||||
"$criticality failed: ${downProbeNames.joinToString(separator = ",")}\n"
|
||||
} else ""
|
||||
|
||||
+4
-4
@@ -8,8 +8,8 @@ import java.time.temporal.ChronoUnit
|
||||
|
||||
@ConfigurationProperties(prefix = "resttemplate.timeout")
|
||||
data class RestTemplateTimeoutProperties @ConstructorBinding constructor(
|
||||
@DurationUnit(ChronoUnit.MILLIS) val readTimeoutRestHealthIndicatorInMillis: Duration,
|
||||
@DurationUnit(ChronoUnit.MILLIS) val connectionRestHealthIndicatorTimeoutInMillis: Duration,
|
||||
@DurationUnit(ChronoUnit.MILLIS) val readTimeoutRestTemplateInMillis: Duration,
|
||||
@DurationUnit(ChronoUnit.MILLIS) val connectionRestTemplateTimeoutInMillis: Duration
|
||||
@DurationUnit(ChronoUnit.MILLIS) val readTimeoutRestHealthIndicatorInMillis: Duration,
|
||||
@DurationUnit(ChronoUnit.MILLIS) val connectionRestHealthIndicatorTimeoutInMillis: Duration,
|
||||
@DurationUnit(ChronoUnit.MILLIS) val readTimeoutRestTemplateInMillis: Duration,
|
||||
@DurationUnit(ChronoUnit.MILLIS) val connectionRestTemplateTimeoutInMillis: Duration
|
||||
)
|
||||
+4
-5
@@ -5,7 +5,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties
|
||||
import org.springframework.boot.context.properties.bind.ConstructorBinding
|
||||
import org.springframework.boot.convert.DurationUnit
|
||||
import org.springframework.cloud.context.config.annotation.RefreshScope
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import java.time.Duration
|
||||
import java.time.temporal.ChronoUnit
|
||||
|
||||
@@ -13,8 +12,8 @@ import java.time.temporal.ChronoUnit
|
||||
@ConfigurationProperties(prefix = "de.twomartens.timetable.statusprobe")
|
||||
@Schema(description = "Properties, to configure this Application")
|
||||
data class StatusProbeProperties @ConstructorBinding constructor(
|
||||
@DurationUnit(ChronoUnit.SECONDS) val scheduleDuration: Duration,
|
||||
@DurationUnit(ChronoUnit.MINUTES) val maxKafkaFailureDuration: Duration,
|
||||
val maxBlobFailureCount: Int,
|
||||
val maxFailurePercent: Int
|
||||
@DurationUnit(ChronoUnit.SECONDS) val scheduleDuration: Duration,
|
||||
@DurationUnit(ChronoUnit.MINUTES) val maxKafkaFailureDuration: Duration,
|
||||
val maxBlobFailureCount: Int,
|
||||
val maxFailurePercent: Int
|
||||
)
|
||||
|
||||
+2
-2
@@ -9,6 +9,6 @@ import java.time.ZoneId
|
||||
@RefreshScope
|
||||
@ConfigurationProperties(prefix = "time")
|
||||
@Schema(description = "Properties to configure time")
|
||||
data class TimeProperties @ConstructorBinding constructor(
|
||||
val defaultTimeZone: ZoneId
|
||||
data class TimeProperties @ConstructorBinding constructor(
|
||||
val defaultTimeZone: ZoneId
|
||||
)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
val projectname: String = providers.gradleProperty("projectname").get()
|
||||
rootProject.name = projectname
|
||||
|
||||
include("common")
|
||||
include("server")
|
||||
include("deploy")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user