chore(cleanup): remove unused FallbackController and outdated GatewayDependencies.txt

- Deleted `FallbackController` as it is no longer required, with alternatives already in place.
- Removed `GatewayDependencies.txt` to clean up outdated and redundant dependency tracking files.
This commit is contained in:
Stefan Mogeritsch 2026-01-04 22:47:11 +01:00
parent a2faf2166a
commit 6e58af1b5b
26 changed files with 495 additions and 1078 deletions

5
.gemini/settings.json Normal file
View File

@ -0,0 +1,5 @@
{
"general": {
"previewFeatures": true
}
}

View File

@ -1,687 +0,0 @@
stefan-mo@Li-Desk-Mo:~/WsMeldestelle/Meldestelle$ ./gradlew :backend:infrastructure:gateway:dependencies --configuration compileClasspath
Type-safe project accessors is an incubating feature.
> Task :backend:infrastructure:gateway:dependencies
------------------------------------------------------------
Project ':backend:infrastructure:gateway'
------------------------------------------------------------
compileClasspath - Compile classpath for 'main'.
+--- org.jetbrains.kotlin:kotlin-stdlib:2.3.0
| +--- org.jetbrains:annotations:13.0 -> 23.0.0
| +--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.0 -> 2.3.0 (c)
| \--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.0 -> 2.3.0 (c)
+--- org.springframework.boot:spring-boot-dependencies:4.0.1
| +--- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.20.1 (c)
| +--- com.fasterxml.jackson.module:jackson-module-kotlin:2.20.1 (c)
| +--- org.jetbrains.kotlin:kotlin-stdlib:2.2.21 -> 2.3.0 (c)
| +--- org.springframework.security:spring-security-oauth2-jose:7.0.2 (c)
| +--- ch.qos.logback:logback-classic:1.5.22 (c)
| +--- ch.qos.logback:logback-core:1.5.22 (c)
| +--- org.springframework.boot:spring-boot-starter-actuator:4.0.1 (c)
| +--- org.springframework.boot:spring-boot-starter-data-redis:4.0.1 (c)
| +--- org.springframework.boot:spring-boot-starter-oauth2-resource-server:4.0.1 (c)
| +--- org.springframework.boot:spring-boot-starter-security:4.0.1 (c)
| +--- org.springframework.boot:spring-boot-starter-webflux:4.0.1 (c)
| +--- org.jetbrains.kotlinx:kotlinx-serialization-json:1.9.0 -> 1.7.3 (c)
| +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2 (c)
| +--- org.flywaydb:flyway-core:11.14.1 -> 11.19.1 (c)
| +--- org.flywaydb:flyway-database-postgresql:11.14.1 -> 11.19.1 (c)
| +--- com.zaxxer:HikariCP:7.0.2 (c)
| +--- jakarta.annotation:jakarta.annotation-api:3.0.0 (c)
| +--- org.jetbrains.kotlinx:kotlinx-coroutines-reactor:1.10.2 (c)
| +--- org.slf4j:slf4j-api:2.0.17 (c)
| +--- com.fasterxml.jackson.core:jackson-annotations:2.20 (c)
| +--- com.fasterxml.jackson.core:jackson-core:2.20.1 (c)
| +--- com.fasterxml.jackson.core:jackson-databind:2.20.1 (c)
| +--- org.jetbrains.kotlin:kotlin-reflect:2.2.21 -> 2.3.0 (c)
| +--- org.springframework.security:spring-security-core:7.0.2 (c)
| +--- org.springframework.security:spring-security-oauth2-core:7.0.2 (c)
| +--- org.springframework:spring-core:7.0.2 (c)
| +--- org.springframework.boot:spring-boot-starter:4.0.1 (c)
| +--- org.springframework.boot:spring-boot-starter-micrometer-metrics:4.0.1 (c)
| +--- org.springframework.boot:spring-boot-actuator-autoconfigure:4.0.1 (c)
| +--- org.springframework.boot:spring-boot-health:4.0.1 (c)
| +--- io.micrometer:micrometer-observation:1.16.1 (c)
| +--- io.micrometer:micrometer-jakarta9:1.16.1 (c)
| +--- org.springframework.boot:spring-boot-data-redis:4.0.1 (c)
| +--- org.springframework.boot:spring-boot-security-oauth2-resource-server:4.0.1 (c)
| +--- org.springframework.boot:spring-boot-security:4.0.1 (c)
| +--- org.springframework:spring-aop:7.0.2 (c)
| +--- org.springframework.boot:spring-boot-starter-jackson:4.0.1 (c)
| +--- org.springframework.boot:spring-boot-starter-reactor-netty:4.0.1 (c)
| +--- org.springframework.boot:spring-boot-webflux:4.0.1 (c)
| +--- org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:1.9.0 (c)
| +--- org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.10.2 (c)
| +--- io.projectreactor:reactor-core:3.8.1 (c)
| +--- org.jetbrains.kotlinx:kotlinx-coroutines-reactive:1.10.2 (c)
| +--- org.springframework.security:spring-security-crypto:7.0.2 (c)
| +--- org.springframework:spring-beans:7.0.2 (c)
| +--- org.springframework:spring-context:7.0.2 (c)
| +--- org.springframework:spring-expression:7.0.2 (c)
| +--- org.springframework:spring-web:7.0.2 (c)
| +--- commons-logging:commons-logging:1.3.5 (c)
| +--- org.jspecify:jspecify:1.0.0 (c)
| +--- org.springframework.boot:spring-boot-starter-logging:4.0.1 (c)
| +--- org.springframework.boot:spring-boot-autoconfigure:4.0.1 (c)
| +--- org.yaml:snakeyaml:2.5 (c)
| +--- org.springframework.boot:spring-boot-micrometer-metrics:4.0.1 (c)
| +--- org.springframework.boot:spring-boot-actuator:4.0.1 (c)
| +--- org.springframework.boot:spring-boot:4.0.1 (c)
| +--- io.micrometer:micrometer-commons:1.16.1 (c)
| +--- io.micrometer:micrometer-core:1.16.1 (c)
| +--- org.springframework.boot:spring-boot-data-commons:4.0.1 (c)
| +--- org.springframework.boot:spring-boot-transaction:4.0.1 (c)
| +--- io.lettuce:lettuce-core:6.8.1.RELEASE -> 7.2.1.RELEASE (c)
| +--- org.springframework.data:spring-data-redis:4.0.1 (c)
| +--- org.springframework.security:spring-security-oauth2-resource-server:7.0.2 (c)
| +--- org.springframework.security:spring-security-config:7.0.2 (c)
| +--- org.springframework.security:spring-security-web:7.0.2 (c)
| +--- org.springframework.boot:spring-boot-jackson:4.0.1 (c)
| +--- org.springframework.boot:spring-boot-reactor:4.0.1 (c)
| +--- org.springframework.boot:spring-boot-reactor-netty:4.0.1 (c)
| +--- org.springframework.boot:spring-boot-http-codec:4.0.1 (c)
| +--- org.springframework:spring-webflux:7.0.2 (c)
| +--- org.springframework.boot:spring-boot-configuration-processor:4.0.1 (c)
| +--- org.springframework.boot:spring-boot-starter-validation:4.0.1 (c)
| +--- io.projectreactor.addons:reactor-extra:3.6.0 (c)
| +--- com.google.code.gson:gson:2.13.2 (c)
| +--- org.apache.httpcomponents:httpcore:4.4.16 (c)
| +--- org.springframework.boot:spring-boot-starter-cache:4.0.1 (c)
| +--- org.jetbrains.kotlinx:kotlinx-serialization-core:1.9.0 (c)
| +--- io.netty:netty-common:4.2.9.Final (c)
| +--- io.netty:netty-handler:4.2.9.Final (c)
| +--- io.netty:netty-transport:4.2.9.Final (c)
| +--- io.netty:netty-resolver-dns:4.2.9.Final (c)
| +--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:2.2.21 -> 2.3.0 (c)
| +--- commons-codec:commons-codec:1.19.0 (c)
| +--- org.springframework.boot:spring-boot-restclient:4.0.1 (c)
| +--- org.reactivestreams:reactive-streams:1.0.4 (c)
| +--- org.apache.logging.log4j:log4j-to-slf4j:2.25.3 (c)
| +--- org.slf4j:jul-to-slf4j:2.0.17 (c)
| +--- org.springframework.boot:spring-boot-micrometer-observation:4.0.1 (c)
| +--- org.springframework.boot:spring-boot-persistence:4.0.1 (c)
| +--- org.springframework.data:spring-data-commons:4.0.1 (c)
| +--- org.springframework:spring-tx:7.0.2 (c)
| +--- org.springframework.data:spring-data-keyvalue:4.0.1 (c)
| +--- org.springframework:spring-oxm:7.0.2 (c)
| +--- org.springframework:spring-context-support:7.0.2 (c)
| +--- tools.jackson.core:jackson-databind:3.0.3 (c)
| +--- org.springframework.boot:spring-boot-web-server:4.0.1 (c)
| +--- io.projectreactor.netty:reactor-netty-http:1.3.1 (c)
| +--- org.springframework.boot:spring-boot-validation:4.0.1 (c)
| +--- org.springframework.boot:spring-boot-cache:4.0.1 (c)
| +--- org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.9.0 (c)
| +--- io.netty:netty-resolver:4.2.9.Final (c)
| +--- io.netty:netty-buffer:4.2.9.Final (c)
| +--- io.netty:netty-transport-native-unix-common:4.2.9.Final (c)
| +--- io.netty:netty-codec-base:4.2.9.Final (c)
| +--- io.netty:netty-codec-dns:4.2.9.Final (c)
| +--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:2.2.21 -> 2.3.0 (c)
| +--- org.springframework.boot:spring-boot-http-client:4.0.1 (c)
| +--- org.apache.logging.log4j:log4j-api:2.25.3 (c)
| +--- tools.jackson.core:jackson-core:3.0.3 (c)
| +--- io.netty:netty-codec-http:4.2.9.Final (c)
| +--- io.netty:netty-codec-http2:4.2.9.Final (c)
| +--- io.netty:netty-codec-http3:4.2.9.Final (c)
| +--- io.netty:netty-resolver-dns-native-macos:4.2.9.Final (c)
| +--- io.netty:netty-transport-native-epoll:4.2.9.Final (c)
| +--- io.projectreactor.netty:reactor-netty-core:1.3.1 (c)
| +--- org.apache.tomcat.embed:tomcat-embed-el:11.0.15 (c)
| +--- org.hibernate.validator:hibernate-validator:9.0.1.Final (c)
| +--- io.netty:netty-codec-compression:4.2.9.Final (c)
| +--- io.netty:netty-codec-classes-quic:4.2.9.Final (c)
| +--- io.netty:netty-resolver-dns-classes-macos:4.2.9.Final (c)
| +--- io.netty:netty-transport-classes-epoll:4.2.9.Final (c)
| +--- io.netty:netty-handler-proxy:4.2.9.Final (c)
| +--- jakarta.validation:jakarta.validation-api:3.1.1 (c)
| +--- org.jboss.logging:jboss-logging:3.6.1.Final (c)
| +--- com.fasterxml:classmate:1.7.1 (c)
| \--- io.netty:netty-codec-socks:4.2.9.Final (c)
+--- org.springframework.cloud:spring-cloud-dependencies:2025.1.0
| +--- org.springframework.cloud:spring-cloud-starter-circuitbreaker-resilience4j:5.0.0 (c)
| +--- org.springframework.cloud:spring-cloud-starter-gateway-server-webflux:5.0.0 (c)
| +--- org.springframework.cloud:spring-cloud-starter-consul-discovery:5.0.0 (c)
| +--- org.springframework.cloud:spring-cloud-starter:5.0.0 (c)
| +--- org.springframework.cloud:spring-cloud-circuitbreaker-resilience4j:5.0.0 (c)
| +--- io.github.resilience4j:resilience4j-circuitbreaker:2.3.0 (c)
| +--- io.github.resilience4j:resilience4j-timelimiter:2.3.0 (c)
| +--- org.springframework.cloud:spring-cloud-gateway-server-webflux:5.0.0 (c)
| +--- org.springframework.cloud:spring-cloud-starter-consul:5.0.0 (c)
| +--- org.springframework.cloud:spring-cloud-consul-discovery:5.0.0 (c)
| +--- org.springframework.cloud:spring-cloud-starter-loadbalancer:5.0.0 (c)
| +--- org.springframework.cloud:spring-cloud-context:5.0.0 (c)
| +--- org.springframework.cloud:spring-cloud-commons:5.0.0 (c)
| +--- io.github.resilience4j:resilience4j-spring-boot3:2.3.0 (c)
| +--- io.github.resilience4j:resilience4j-core:2.3.0 (c)
| +--- org.springframework.cloud:spring-cloud-consul-core:5.0.0 (c)
| +--- com.ecwid.consul:consul-api:1.4.5 (c)
| +--- org.springframework.cloud:spring-cloud-loadbalancer:5.0.0 (c)
| +--- io.github.resilience4j:resilience4j-spring6:2.3.0 (c)
| +--- io.github.resilience4j:resilience4j-annotations:2.3.0 (c)
| +--- io.github.resilience4j:resilience4j-consumer:2.3.0 (c)
| +--- io.github.resilience4j:resilience4j-ratelimiter:2.3.0 (c)
| +--- io.github.resilience4j:resilience4j-retry:2.3.0 (c)
| \--- io.github.resilience4j:resilience4j-micrometer:2.3.0 (c)
+--- project :core:core-utils
| +--- project :core:core-domain
| | +--- org.jetbrains.kotlinx:kotlinx-serialization-json:1.9.0 -> 1.7.3
| | | \--- org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:1.7.3 -> 1.9.0
| | | +--- org.jetbrains.kotlinx:kotlinx-serialization-bom:1.9.0
| | | | +--- org.jetbrains.kotlinx:kotlinx-serialization-core:1.9.0 (c)
| | | | +--- org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:1.9.0 (c)
| | | | +--- org.jetbrains.kotlinx:kotlinx-serialization-json:1.9.0 -> 1.7.3 (c)
| | | | \--- org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.9.0 (c)
| | | +--- org.jetbrains.kotlin:kotlin-stdlib:2.2.0 -> 2.3.0 (*)
| | | \--- org.jetbrains.kotlinx:kotlinx-serialization-core:1.9.0
| | | \--- org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.9.0
| | | +--- org.jetbrains.kotlinx:kotlinx-serialization-bom:1.9.0 (*)
| | | \--- org.jetbrains.kotlin:kotlin-stdlib:2.2.0 -> 2.3.0 (*)
| | +--- org.jetbrains.kotlinx:kotlinx-datetime:0.7.1
| | | \--- org.jetbrains.kotlinx:kotlinx-datetime-jvm:0.7.1
| | | \--- org.jetbrains.kotlin:kotlin-stdlib:2.1.20 -> 2.3.0 (*)
| | \--- org.jetbrains.kotlin:kotlin-stdlib:2.3.0 (*)
| +--- org.jetbrains.kotlinx:kotlinx-serialization-json:1.9.0 -> 1.7.3 (*)
| +--- org.jetbrains.kotlinx:kotlinx-datetime:0.7.1 (*)
| +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2
| | \--- org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.10.2
| | +--- org.jetbrains:annotations:23.0.0
| | +--- org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.10.2
| | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.10.2 (c)
| | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2 (c)
| | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-reactive:1.10.2 (c)
| | | \--- org.jetbrains.kotlinx:kotlinx-coroutines-reactor:1.10.2 (c)
| | \--- org.jetbrains.kotlin:kotlin-stdlib:2.1.0 -> 2.3.0 (*)
| +--- com.ionspin.kotlin:bignum:0.3.10
| | \--- com.ionspin.kotlin:bignum-jvm:0.3.10
| | \--- org.jetbrains.kotlin:kotlin-stdlib:2.0.0 -> 2.3.0 (*)
| +--- org.jetbrains.kotlin:kotlin-stdlib:2.3.0 (*)
| +--- project :platform:platform-dependencies
| | +--- project :platform:platform-bom
| | | +--- org.springframework.boot:spring-boot-dependencies:4.0.1 (*)
| | | +--- org.springframework.cloud:spring-cloud-dependencies:2025.1.0 (*)
| | | +--- org.jetbrains.kotlin:kotlin-bom:2.3.0
| | | | +--- org.jetbrains.kotlin:kotlin-stdlib:2.3.0 (c)
| | | | +--- org.jetbrains.kotlin:kotlin-reflect:2.3.0 (c)
| | | | +--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:2.3.0 (c)
| | | | \--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:2.3.0 (c)
| | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.10.2 (*)
| | | +--- com.ionspin.kotlin:bignum:0.3.10 (c)
| | | +--- org.springframework.cloud:spring-cloud-starter-consul-discovery -> 5.0.0 (c)
| | | +--- io.github.oshai:kotlin-logging-jvm:7.0.13 (c)
| | | +--- jakarta.annotation:jakarta.annotation-api:3.0.0 (c)
| | | +--- ch.qos.logback:logback-classic:1.5.22 (c)
| | | +--- org.jetbrains.exposed:exposed-core:0.61.0 (c)
| | | +--- org.jetbrains.exposed:exposed-dao:0.61.0 (c)
| | | +--- org.jetbrains.exposed:exposed-jdbc:0.61.0 (c)
| | | +--- org.jetbrains.exposed:exposed-kotlin-datetime:0.61.0 (c)
| | | +--- org.flywaydb:flyway-core:11.19.1 (c)
| | | +--- org.flywaydb:flyway-database-postgresql:11.19.1 (c)
| | | +--- com.zaxxer:HikariCP:7.0.2 (c)
| | | +--- org.jetbrains.kotlinx:kotlinx-serialization-json:1.9.0 -> 1.7.3 (c)
| | | +--- org.jetbrains.kotlinx:kotlinx-datetime:0.7.1 (c)
| | | +--- com.fasterxml.jackson.module:jackson-module-kotlin -> 2.20.1 (c)
| | | +--- com.fasterxml.jackson.datatype:jackson-datatype-jsr310 -> 2.20.1 (c)
| | | \--- io.lettuce:lettuce-core:7.2.1.RELEASE (c)
| | +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2 (*)
| | +--- org.jetbrains.kotlinx:kotlinx-serialization-json:1.9.0 -> 1.7.3 (*)
| | +--- org.jetbrains.kotlinx:kotlinx-datetime:0.7.1 (*)
| | +--- io.github.oshai:kotlin-logging-jvm:7.0.13
| | | \--- org.jetbrains.kotlin:kotlin-stdlib:2.1.21 -> 2.3.0 (*)
| | +--- org.jetbrains.kotlinx:kotlinx-coroutines-reactor:1.10.2
| | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2 (*)
| | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.10.2 (*)
| | | +--- io.projectreactor:reactor-core:3.4.1 -> 3.8.1
| | | | +--- org.reactivestreams:reactive-streams:1.0.4
| | | | \--- org.jspecify:jspecify:1.0.0
| | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-reactive:1.10.2
| | | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2 (*)
| | | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.10.2 (*)
| | | | +--- org.reactivestreams:reactive-streams:1.0.3 -> 1.0.4
| | | | \--- org.jetbrains.kotlin:kotlin-stdlib:2.1.0 -> 2.3.0 (*)
| | | \--- org.jetbrains.kotlin:kotlin-stdlib:2.1.0 -> 2.3.0 (*)
| | +--- ch.qos.logback:logback-classic:1.5.22
| | | +--- ch.qos.logback:logback-core:1.5.22
| | | \--- org.slf4j:slf4j-api:2.0.17
| | \--- org.jetbrains.kotlin:kotlin-stdlib:2.3.0 (*)
| +--- org.jetbrains.exposed:exposed-core:0.61.0
| | +--- org.jetbrains.kotlin:kotlin-stdlib:2.0.0 -> 2.3.0 (*)
| | +--- org.jetbrains.kotlin:kotlin-reflect:2.0.0 -> 2.3.0
| | | \--- org.jetbrains.kotlin:kotlin-stdlib:2.3.0 (*)
| | +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.1 -> 1.10.2 (*)
| | \--- org.slf4j:slf4j-api:2.0.9 -> 2.0.17
| +--- org.jetbrains.exposed:exposed-dao:0.61.0
| | +--- org.jetbrains.exposed:exposed-core:0.61.0 (*)
| | \--- org.jetbrains.kotlin:kotlin-stdlib:2.0.0 -> 2.3.0 (*)
| +--- org.jetbrains.exposed:exposed-jdbc:0.61.0
| | +--- org.jetbrains.exposed:exposed-core:0.61.0 (*)
| | \--- org.jetbrains.kotlin:kotlin-stdlib:2.0.0 -> 2.3.0 (*)
| +--- org.jetbrains.exposed:exposed-kotlin-datetime:0.61.0
| | +--- org.jetbrains.exposed:exposed-core:0.61.0 (*)
| | +--- org.jetbrains.kotlinx:kotlinx-datetime-jvm:0.6.2 -> 0.7.1 (*)
| | \--- org.jetbrains.kotlin:kotlin-stdlib:2.0.0 -> 2.3.0 (*)
| +--- org.flywaydb:flyway-core:11.19.1
| | \--- com.fasterxml.jackson.core:jackson-databind:2.19.1 -> 2.20.1
| | +--- com.fasterxml.jackson.core:jackson-annotations:2.20
| | +--- com.fasterxml.jackson.core:jackson-core:2.20.1
| | | \--- com.fasterxml.jackson:jackson-bom:2.20.1
| | | +--- com.fasterxml.jackson.core:jackson-annotations:2.20 (c)
| | | +--- com.fasterxml.jackson.core:jackson-core:2.20.1 (c)
| | | +--- com.fasterxml.jackson.core:jackson-databind:2.20.1 (c)
| | | +--- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.20.1 (c)
| | | \--- com.fasterxml.jackson.module:jackson-module-kotlin:2.20.1 (c)
| | \--- com.fasterxml.jackson:jackson-bom:2.20.1 (*)
| +--- org.flywaydb:flyway-database-postgresql:11.19.1
| | \--- org.flywaydb:flyway-core:11.19.1 (*)
| +--- com.zaxxer:HikariCP:7.0.2
| | \--- org.slf4j:slf4j-api:2.0.17
| +--- org.springframework.cloud:spring-cloud-starter-consul-discovery -> 5.0.0
| | +--- org.springframework.cloud:spring-cloud-starter-consul:5.0.0
| | | +--- org.springframework.cloud:spring-cloud-starter:5.0.0
| | | | +--- org.springframework.boot:spring-boot-starter:4.0.0 -> 4.0.1
| | | | | +--- org.springframework.boot:spring-boot-starter-logging:4.0.1
| | | | | | +--- ch.qos.logback:logback-classic:1.5.22 (*)
| | | | | | +--- org.apache.logging.log4j:log4j-to-slf4j:2.25.3
| | | | | | | +--- org.apache.logging.log4j:log4j-api:2.25.3
| | | | | | | | +--- org.jspecify:jspecify:1.0.0
| | | | | | | | +--- biz.aQute.bnd:biz.aQute.bnd.annotation:7.1.0
| | | | | | | | | +--- org.osgi:org.osgi.resource:1.0.0
| | | | | | | | | \--- org.osgi:org.osgi.service.serviceloader:1.0.0
| | | | | | | | +--- com.google.errorprone:error_prone_annotations:2.38.0 -> 2.41.0
| | | | | | | | +--- org.osgi:org.osgi.annotation.bundle:2.0.0
| | | | | | | | | \--- org.osgi:org.osgi.annotation.versioning:1.1.2
| | | | | | | | \--- org.osgi:org.osgi.annotation.versioning:1.1.2
| | | | | | | +--- org.slf4j:slf4j-api:2.0.17
| | | | | | | +--- org.jspecify:jspecify:1.0.0
| | | | | | | +--- biz.aQute.bnd:biz.aQute.bnd.annotation:7.1.0 (*)
| | | | | | | +--- com.google.errorprone:error_prone_annotations:2.38.0 -> 2.41.0
| | | | | | | +--- org.osgi:org.osgi.annotation.bundle:2.0.0 (*)
| | | | | | | \--- org.osgi:org.osgi.annotation.versioning:1.1.2
| | | | | | \--- org.slf4j:jul-to-slf4j:2.0.17
| | | | | | \--- org.slf4j:slf4j-api:2.0.17
| | | | | +--- org.springframework.boot:spring-boot-autoconfigure:4.0.1
| | | | | | \--- org.springframework.boot:spring-boot:4.0.1
| | | | | | +--- org.springframework:spring-core:7.0.2
| | | | | | | +--- commons-logging:commons-logging:1.3.5
| | | | | | | \--- org.jspecify:jspecify:1.0.0
| | | | | | \--- org.springframework:spring-context:7.0.2
| | | | | | +--- org.springframework:spring-aop:7.0.2
| | | | | | | +--- org.springframework:spring-beans:7.0.2
| | | | | | | | \--- org.springframework:spring-core:7.0.2 (*)
| | | | | | | \--- org.springframework:spring-core:7.0.2 (*)
| | | | | | +--- org.springframework:spring-beans:7.0.2 (*)
| | | | | | +--- org.springframework:spring-core:7.0.2 (*)
| | | | | | +--- org.springframework:spring-expression:7.0.2
| | | | | | | \--- org.springframework:spring-core:7.0.2 (*)
| | | | | | \--- io.micrometer:micrometer-observation:1.16.1
| | | | | | +--- org.jspecify:jspecify:1.0.0
| | | | | | \--- io.micrometer:micrometer-commons:1.16.1
| | | | | | \--- org.jspecify:jspecify:1.0.0
| | | | | +--- jakarta.annotation:jakarta.annotation-api:3.0.0
| | | | | \--- org.yaml:snakeyaml:2.5
| | | | +--- org.springframework.cloud:spring-cloud-context:5.0.0
| | | | | \--- org.springframework.security:spring-security-crypto:7.0.0 -> 7.0.2
| | | | +--- org.springframework.cloud:spring-cloud-commons:5.0.0
| | | | | \--- org.springframework.security:spring-security-crypto:7.0.0 -> 7.0.2
| | | | \--- org.bouncycastle:bcprov-jdk18on:1.81
| | | +--- org.springframework.cloud:spring-cloud-consul-core:5.0.0
| | | | +--- org.springframework.boot:spring-boot-starter-validation:4.0.0 -> 4.0.1
| | | | | +--- org.springframework.boot:spring-boot-starter:4.0.1 (*)
| | | | | \--- org.springframework.boot:spring-boot-validation:4.0.1
| | | | | +--- org.springframework.boot:spring-boot:4.0.1 (*)
| | | | | +--- org.apache.tomcat.embed:tomcat-embed-el:11.0.15
| | | | | \--- org.hibernate.validator:hibernate-validator:9.0.1.Final
| | | | | +--- jakarta.validation:jakarta.validation-api:3.1.1
| | | | | +--- org.jboss.logging:jboss-logging:3.6.1.Final
| | | | | \--- com.fasterxml:classmate:1.7.0 -> 1.7.1
| | | | \--- org.springframework.boot:spring-boot-restclient:4.0.0 -> 4.0.1
| | | | +--- org.springframework.boot:spring-boot:4.0.1 (*)
| | | | \--- org.springframework.boot:spring-boot-http-client:4.0.1
| | | | +--- org.springframework.boot:spring-boot:4.0.1 (*)
| | | | \--- org.springframework:spring-web:7.0.2
| | | | +--- org.springframework:spring-beans:7.0.2 (*)
| | | | +--- org.springframework:spring-core:7.0.2 (*)
| | | | \--- io.micrometer:micrometer-observation:1.16.1 (*)
| | | +--- com.ecwid.consul:consul-api:1.4.5
| | | +--- com.google.code.gson:gson:2.13.2
| | | | \--- com.google.errorprone:error_prone_annotations:2.41.0
| | | +--- org.apache.httpcomponents:httpclient:4.5.14
| | | | +--- org.apache.httpcomponents:httpcore:4.4.16
| | | | +--- commons-logging:commons-logging:1.2 -> 1.3.5
| | | | \--- commons-codec:commons-codec:1.11 -> 1.19.0
| | | \--- org.apache.httpcomponents:httpcore:4.4.16
| | +--- org.springframework.cloud:spring-cloud-consul-discovery:5.0.0
| | | \--- org.springframework.cloud:spring-cloud-consul-core:5.0.0 (*)
| | \--- org.springframework.cloud:spring-cloud-starter-loadbalancer:5.0.0
| | +--- org.springframework.cloud:spring-cloud-starter:5.0.0 (*)
| | +--- org.springframework.cloud:spring-cloud-loadbalancer:5.0.0
| | | +--- org.springframework.cloud:spring-cloud-commons:5.0.0 (*)
| | | +--- org.springframework.cloud:spring-cloud-context:5.0.0 (*)
| | | +--- io.projectreactor:reactor-core:3.8.0 -> 3.8.1 (*)
| | | \--- io.projectreactor.addons:reactor-extra:3.6.0
| | | \--- io.projectreactor:reactor-core:3.8.0 -> 3.8.1 (*)
| | +--- org.springframework.boot:spring-boot-starter-cache:4.0.0 -> 4.0.1
| | | +--- org.springframework.boot:spring-boot-starter:4.0.1 (*)
| | | \--- org.springframework.boot:spring-boot-cache:4.0.1
| | | +--- org.springframework.boot:spring-boot:4.0.1 (*)
| | | \--- org.springframework:spring-context-support:7.0.2
| | | +--- org.springframework:spring-beans:7.0.2 (*)
| | | +--- org.springframework:spring-context:7.0.2 (*)
| | | \--- org.springframework:spring-core:7.0.2 (*)
| | \--- com.stoyanr:evictor:1.0.0
| +--- io.github.oshai:kotlin-logging-jvm:7.0.13 (*)
| +--- jakarta.annotation:jakarta.annotation-api:3.0.0
| +--- com.fasterxml.jackson.module:jackson-module-kotlin -> 2.20.1
| | +--- com.fasterxml.jackson.core:jackson-databind:2.20.1 (*)
| | +--- com.fasterxml.jackson.core:jackson-annotations:2.20
| | +--- org.jetbrains.kotlin:kotlin-reflect:2.0.21 -> 2.3.0 (*)
| | \--- com.fasterxml.jackson:jackson-bom:2.20.1 (*)
| \--- com.fasterxml.jackson.datatype:jackson-datatype-jsr310 -> 2.20.1
| +--- com.fasterxml.jackson.core:jackson-annotations:2.20
| +--- com.fasterxml.jackson.core:jackson-core:2.20.1 (*)
| +--- com.fasterxml.jackson.core:jackson-databind:2.20.1 (*)
| \--- com.fasterxml.jackson:jackson-bom:2.20.1 (*)
+--- project :platform:platform-dependencies (*)
+--- project :backend:infrastructure:monitoring:monitoring-client
| \--- org.jetbrains.kotlin:kotlin-stdlib:2.3.0 (*)
+--- org.springframework.boot:spring-boot-starter-webflux -> 4.0.1
| +--- org.springframework.boot:spring-boot-starter:4.0.1 (*)
| +--- org.springframework.boot:spring-boot-starter-jackson:4.0.1
| | +--- org.springframework.boot:spring-boot-starter:4.0.1 (*)
| | \--- org.springframework.boot:spring-boot-jackson:4.0.1
| | +--- org.springframework.boot:spring-boot:4.0.1 (*)
| | \--- tools.jackson.core:jackson-databind:3.0.3
| | +--- com.fasterxml.jackson.core:jackson-annotations:2.20
| | +--- tools.jackson.core:jackson-core:3.0.3
| | | \--- tools.jackson:jackson-bom:3.0.3
| | | +--- com.fasterxml.jackson.core:jackson-annotations:2.20 (c)
| | | +--- tools.jackson.core:jackson-core:3.0.3 (c)
| | | \--- tools.jackson.core:jackson-databind:3.0.3 (c)
| | \--- tools.jackson:jackson-bom:3.0.3 (*)
| +--- org.springframework.boot:spring-boot-starter-reactor-netty:4.0.1
| | +--- org.springframework.boot:spring-boot-starter:4.0.1 (*)
| | +--- org.springframework.boot:spring-boot-reactor:4.0.1
| | | +--- org.springframework.boot:spring-boot:4.0.1 (*)
| | | \--- io.projectreactor:reactor-core:3.8.1 (*)
| | \--- org.springframework.boot:spring-boot-reactor-netty:4.0.1
| | +--- org.springframework.boot:spring-boot-web-server:4.0.1
| | | +--- org.springframework.boot:spring-boot:4.0.1 (*)
| | | \--- org.springframework:spring-web:7.0.2 (*)
| | +--- io.projectreactor.netty:reactor-netty-http:1.3.1
| | | +--- io.netty:netty-codec-http:4.2.7.Final -> 4.2.9.Final
| | | | +--- io.netty:netty-common:4.2.9.Final
| | | | +--- io.netty:netty-buffer:4.2.9.Final
| | | | | \--- io.netty:netty-common:4.2.9.Final
| | | | +--- io.netty:netty-transport:4.2.9.Final
| | | | | +--- io.netty:netty-common:4.2.9.Final
| | | | | +--- io.netty:netty-buffer:4.2.9.Final (*)
| | | | | \--- io.netty:netty-resolver:4.2.9.Final
| | | | | \--- io.netty:netty-common:4.2.9.Final
| | | | +--- io.netty:netty-codec-base:4.2.9.Final
| | | | | +--- io.netty:netty-common:4.2.9.Final
| | | | | +--- io.netty:netty-buffer:4.2.9.Final (*)
| | | | | \--- io.netty:netty-transport:4.2.9.Final (*)
| | | | +--- io.netty:netty-codec-compression:4.2.9.Final
| | | | | +--- io.netty:netty-common:4.2.9.Final
| | | | | +--- io.netty:netty-buffer:4.2.9.Final (*)
| | | | | +--- io.netty:netty-transport:4.2.9.Final (*)
| | | | | \--- io.netty:netty-codec-base:4.2.9.Final (*)
| | | | \--- io.netty:netty-handler:4.2.9.Final
| | | | +--- io.netty:netty-common:4.2.9.Final
| | | | +--- io.netty:netty-resolver:4.2.9.Final (*)
| | | | +--- io.netty:netty-buffer:4.2.9.Final (*)
| | | | +--- io.netty:netty-transport:4.2.9.Final (*)
| | | | +--- io.netty:netty-transport-native-unix-common:4.2.9.Final
| | | | | +--- io.netty:netty-common:4.2.9.Final
| | | | | +--- io.netty:netty-buffer:4.2.9.Final (*)
| | | | | \--- io.netty:netty-transport:4.2.9.Final (*)
| | | | \--- io.netty:netty-codec-base:4.2.9.Final (*)
| | | +--- io.netty:netty-codec-http2:4.2.7.Final -> 4.2.9.Final
| | | | +--- io.netty:netty-common:4.2.9.Final
| | | | +--- io.netty:netty-buffer:4.2.9.Final (*)
| | | | +--- io.netty:netty-transport:4.2.9.Final (*)
| | | | +--- io.netty:netty-codec-base:4.2.9.Final (*)
| | | | +--- io.netty:netty-handler:4.2.9.Final (*)
| | | | \--- io.netty:netty-codec-http:4.2.9.Final (*)
| | | +--- io.netty:netty-codec-http3:4.2.7.Final -> 4.2.9.Final
| | | | +--- io.netty:netty-common:4.2.9.Final
| | | | +--- io.netty:netty-buffer:4.2.9.Final (*)
| | | | +--- io.netty:netty-codec-base:4.2.9.Final (*)
| | | | +--- io.netty:netty-codec-http:4.2.9.Final (*)
| | | | +--- io.netty:netty-codec-compression:4.2.9.Final (*)
| | | | +--- io.netty:netty-handler:4.2.9.Final (*)
| | | | +--- io.netty:netty-transport-native-unix-common:4.2.9.Final (*)
| | | | +--- io.netty:netty-transport:4.2.9.Final (*)
| | | | +--- io.netty:netty-resolver:4.2.9.Final (*)
| | | | \--- io.netty:netty-codec-classes-quic:4.2.9.Final
| | | +--- io.netty:netty-resolver-dns:4.2.7.Final -> 4.2.9.Final
| | | | +--- io.netty:netty-common:4.2.9.Final
| | | | +--- io.netty:netty-buffer:4.2.9.Final (*)
| | | | +--- io.netty:netty-resolver:4.2.9.Final (*)
| | | | +--- io.netty:netty-transport:4.2.9.Final (*)
| | | | +--- io.netty:netty-codec-base:4.2.9.Final (*)
| | | | +--- io.netty:netty-codec-dns:4.2.9.Final
| | | | | +--- io.netty:netty-common:4.2.9.Final
| | | | | +--- io.netty:netty-buffer:4.2.9.Final (*)
| | | | | +--- io.netty:netty-transport:4.2.9.Final (*)
| | | | | \--- io.netty:netty-codec-base:4.2.9.Final (*)
| | | | \--- io.netty:netty-handler:4.2.9.Final (*)
| | | +--- io.netty:netty-resolver-dns-native-macos:4.2.7.Final -> 4.2.9.Final
| | | | \--- io.netty:netty-resolver-dns-classes-macos:4.2.9.Final
| | | | +--- io.netty:netty-common:4.2.9.Final
| | | | +--- io.netty:netty-resolver-dns:4.2.9.Final (*)
| | | | \--- io.netty:netty-transport-native-unix-common:4.2.9.Final (*)
| | | +--- io.netty:netty-transport-native-epoll:4.2.7.Final -> 4.2.9.Final
| | | | +--- io.netty:netty-common:4.2.9.Final
| | | | +--- io.netty:netty-buffer:4.2.9.Final (*)
| | | | +--- io.netty:netty-transport:4.2.9.Final (*)
| | | | +--- io.netty:netty-transport-native-unix-common:4.2.9.Final (*)
| | | | \--- io.netty:netty-transport-classes-epoll:4.2.9.Final
| | | | +--- io.netty:netty-common:4.2.9.Final
| | | | +--- io.netty:netty-buffer:4.2.9.Final (*)
| | | | +--- io.netty:netty-transport:4.2.9.Final (*)
| | | | \--- io.netty:netty-transport-native-unix-common:4.2.9.Final (*)
| | | +--- io.projectreactor.netty:reactor-netty-core:1.3.1
| | | | +--- io.netty:netty-handler:4.2.7.Final -> 4.2.9.Final (*)
| | | | +--- io.netty:netty-handler-proxy:4.2.7.Final -> 4.2.9.Final
| | | | | +--- io.netty:netty-common:4.2.9.Final
| | | | | +--- io.netty:netty-buffer:4.2.9.Final (*)
| | | | | +--- io.netty:netty-transport:4.2.9.Final (*)
| | | | | +--- io.netty:netty-codec-base:4.2.9.Final (*)
| | | | | +--- io.netty:netty-codec-socks:4.2.9.Final
| | | | | | +--- io.netty:netty-common:4.2.9.Final
| | | | | | +--- io.netty:netty-buffer:4.2.9.Final (*)
| | | | | | +--- io.netty:netty-transport:4.2.9.Final (*)
| | | | | | \--- io.netty:netty-codec-base:4.2.9.Final (*)
| | | | | +--- io.netty:netty-codec-http:4.2.9.Final (*)
| | | | | \--- io.netty:netty-handler:4.2.9.Final (*)
| | | | +--- io.netty:netty-resolver-dns:4.2.7.Final -> 4.2.9.Final (*)
| | | | +--- io.netty:netty-resolver-dns-native-macos:4.2.7.Final -> 4.2.9.Final (*)
| | | | +--- io.netty:netty-transport-native-epoll:4.2.7.Final -> 4.2.9.Final (*)
| | | | +--- io.projectreactor:reactor-core:3.8.1 (*)
| | | | \--- org.jspecify:jspecify:1.0.0
| | | +--- io.projectreactor:reactor-core:3.8.1 (*)
| | | \--- org.jspecify:jspecify:1.0.0
| | \--- org.springframework:spring-web:7.0.2 (*)
| \--- org.springframework.boot:spring-boot-webflux:4.0.1
| +--- org.springframework.boot:spring-boot:4.0.1 (*)
| +--- org.springframework.boot:spring-boot-http-codec:4.0.1
| | +--- org.springframework.boot:spring-boot:4.0.1 (*)
| | \--- org.springframework:spring-web:7.0.2 (*)
| \--- org.springframework:spring-webflux:7.0.2
| +--- org.springframework:spring-beans:7.0.2 (*)
| +--- org.springframework:spring-core:7.0.2 (*)
| +--- org.springframework:spring-web:7.0.2 (*)
| \--- io.projectreactor:reactor-core:3.8.1 (*)
+--- org.springframework.cloud:spring-cloud-starter-gateway-server-webflux -> 5.0.0
| +--- org.springframework.cloud:spring-cloud-starter:5.0.0 (*)
| +--- org.springframework.cloud:spring-cloud-gateway-server-webflux:5.0.0
| | +--- org.springframework.boot:spring-boot-starter:4.0.0 -> 4.0.1 (*)
| | +--- org.springframework.boot:spring-boot-starter-validation:4.0.0 -> 4.0.1 (*)
| | \--- io.projectreactor.addons:reactor-extra:3.6.0 (*)
| \--- org.springframework.boot:spring-boot-starter-webflux:4.0.0 -> 4.0.1 (*)
+--- org.springframework.cloud:spring-cloud-starter-consul-discovery -> 5.0.0 (*)
+--- org.springframework.boot:spring-boot-starter-actuator -> 4.0.1
| +--- org.springframework.boot:spring-boot-starter:4.0.1 (*)
| +--- org.springframework.boot:spring-boot-starter-micrometer-metrics:4.0.1
| | +--- org.springframework.boot:spring-boot-starter:4.0.1 (*)
| | \--- org.springframework.boot:spring-boot-micrometer-metrics:4.0.1
| | +--- org.springframework.boot:spring-boot:4.0.1 (*)
| | +--- org.springframework.boot:spring-boot-micrometer-observation:4.0.1
| | | +--- org.springframework.boot:spring-boot:4.0.1 (*)
| | | \--- io.micrometer:micrometer-observation:1.16.1 (*)
| | \--- io.micrometer:micrometer-core:1.16.1
| | +--- org.jspecify:jspecify:1.0.0
| | +--- io.micrometer:micrometer-commons:1.16.1 (*)
| | \--- io.micrometer:micrometer-observation:1.16.1 (*)
| +--- org.springframework.boot:spring-boot-actuator-autoconfigure:4.0.1
| | +--- org.springframework.boot:spring-boot-autoconfigure:4.0.1 (*)
| | \--- org.springframework.boot:spring-boot-actuator:4.0.1
| | \--- org.springframework.boot:spring-boot:4.0.1 (*)
| +--- org.springframework.boot:spring-boot-health:4.0.1
| | \--- org.springframework.boot:spring-boot:4.0.1 (*)
| +--- io.micrometer:micrometer-observation:1.16.1 (*)
| \--- io.micrometer:micrometer-jakarta9:1.16.1
| +--- org.jspecify:jspecify:1.0.0
| +--- io.micrometer:micrometer-core:1.16.1 (*)
| +--- io.micrometer:micrometer-commons:1.16.1 (*)
| \--- io.micrometer:micrometer-observation:1.16.1 (*)
+--- org.springframework.boot:spring-boot-starter-security -> 4.0.1
| +--- org.springframework.boot:spring-boot-starter:4.0.1 (*)
| +--- org.springframework.boot:spring-boot-security:4.0.1
| | +--- org.springframework.boot:spring-boot:4.0.1 (*)
| | +--- org.springframework.security:spring-security-config:7.0.2
| | | +--- org.springframework.security:spring-security-core:7.0.2
| | | | +--- org.springframework.security:spring-security-crypto:7.0.2
| | | | +--- org.springframework:spring-aop:7.0.2 (*)
| | | | +--- org.springframework:spring-beans:7.0.2 (*)
| | | | +--- org.springframework:spring-context:7.0.2 (*)
| | | | +--- org.springframework:spring-core:7.0.2 (*)
| | | | +--- org.springframework:spring-expression:7.0.2 (*)
| | | | \--- io.micrometer:micrometer-observation:1.16.1 (*)
| | | +--- org.springframework:spring-aop:7.0.2 (*)
| | | +--- org.springframework:spring-beans:7.0.2 (*)
| | | +--- org.springframework:spring-context:7.0.2 (*)
| | | \--- org.springframework:spring-core:7.0.2 (*)
| | \--- org.springframework.security:spring-security-web:7.0.2
| | +--- org.springframework.security:spring-security-core:7.0.2 (*)
| | +--- org.springframework:spring-core:7.0.2 (*)
| | +--- org.springframework:spring-aop:7.0.2 (*)
| | +--- org.springframework:spring-beans:7.0.2 (*)
| | +--- org.springframework:spring-context:7.0.2 (*)
| | +--- org.springframework:spring-expression:7.0.2 (*)
| | \--- org.springframework:spring-web:7.0.2 (*)
| \--- org.springframework:spring-aop:7.0.2 (*)
+--- org.springframework.boot:spring-boot-starter-oauth2-resource-server -> 4.0.1
| +--- org.springframework.boot:spring-boot-starter:4.0.1 (*)
| +--- org.springframework.boot:spring-boot-starter-security:4.0.1 (*)
| \--- org.springframework.boot:spring-boot-security-oauth2-resource-server:4.0.1
| +--- org.springframework.boot:spring-boot:4.0.1 (*)
| +--- org.springframework.security:spring-security-oauth2-jose:7.0.2
| | +--- org.springframework.security:spring-security-core:7.0.2 (*)
| | +--- org.springframework.security:spring-security-oauth2-core:7.0.2
| | | +--- org.springframework.security:spring-security-core:7.0.2 (*)
| | | +--- org.springframework:spring-core:7.0.2 (*)
| | | \--- org.springframework:spring-web:7.0.2 (*)
| | +--- org.springframework:spring-core:7.0.2 (*)
| | \--- com.nimbusds:nimbus-jose-jwt:10.4
| \--- org.springframework.security:spring-security-oauth2-resource-server:7.0.2
| +--- org.springframework.security:spring-security-core:7.0.2 (*)
| +--- org.springframework.security:spring-security-oauth2-core:7.0.2 (*)
| +--- org.springframework.security:spring-security-web:7.0.2 (*)
| \--- org.springframework:spring-core:7.0.2 (*)
+--- org.springframework.security:spring-security-oauth2-jose -> 7.0.2 (*)
+--- org.springframework.cloud:spring-cloud-starter-circuitbreaker-resilience4j -> 5.0.0
| +--- org.springframework.cloud:spring-cloud-starter:5.0.0 (*)
| +--- org.springframework.cloud:spring-cloud-circuitbreaker-resilience4j:5.0.0
| | +--- com.fasterxml.jackson.core:jackson-core:2.20.1 (*)
| | +--- com.fasterxml.jackson.core:jackson-databind:2.20.1 (*)
| | +--- org.springframework.cloud:spring-cloud-commons:5.0.0 (*)
| | +--- io.micrometer:micrometer-observation:1.16.0 -> 1.16.1 (*)
| | +--- io.github.resilience4j:resilience4j-circuitbreaker:2.3.0
| | | \--- io.github.resilience4j:resilience4j-core:2.3.0
| | | \--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.0 -> 2.3.0
| | | +--- org.jetbrains.kotlin:kotlin-stdlib:2.3.0 (*)
| | | \--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:2.3.0
| | | \--- org.jetbrains.kotlin:kotlin-stdlib:2.3.0 (*)
| | +--- io.github.resilience4j:resilience4j-timelimiter:2.3.0
| | | \--- io.github.resilience4j:resilience4j-core:2.3.0 (*)
| | +--- io.github.resilience4j:resilience4j-spring-boot3:2.3.0
| | | \--- io.github.resilience4j:resilience4j-spring6:2.3.0
| | | +--- io.github.resilience4j:resilience4j-annotations:2.3.0
| | | +--- io.github.resilience4j:resilience4j-consumer:2.3.0
| | | \--- io.github.resilience4j:resilience4j-framework-common:2.3.0
| | | +--- io.github.resilience4j:resilience4j-circuitbreaker:2.3.0 (*)
| | | +--- io.github.resilience4j:resilience4j-ratelimiter:2.3.0
| | | | \--- io.github.resilience4j:resilience4j-core:2.3.0 (*)
| | | +--- io.github.resilience4j:resilience4j-retry:2.3.0
| | | | \--- io.github.resilience4j:resilience4j-core:2.3.0 (*)
| | | +--- io.github.resilience4j:resilience4j-timelimiter:2.3.0 (*)
| | | \--- io.github.resilience4j:resilience4j-micrometer:2.3.0
| | | +--- io.micrometer:micrometer-core:1.10.0 -> 1.16.1 (*)
| | | \--- io.micrometer:micrometer-observation:1.10.0 -> 1.16.1 (*)
| | \--- org.springframework.boot:spring-boot-configuration-processor:4.0.0 -> 4.0.1
| +--- io.github.resilience4j:resilience4j-circuitbreaker:2.3.0 (*)
| \--- io.github.resilience4j:resilience4j-timelimiter:2.3.0 (*)
+--- io.github.oshai:kotlin-logging-jvm:7.0.13 (*)
+--- ch.qos.logback:logback-classic:1.5.22 (*)
+--- ch.qos.logback:logback-core:1.5.22
+--- com.fasterxml.jackson.module:jackson-module-kotlin -> 2.20.1 (*)
+--- com.fasterxml.jackson.datatype:jackson-datatype-jsr310 -> 2.20.1 (*)
\--- org.springframework.boot:spring-boot-starter-data-redis -> 4.0.1
+--- org.springframework.boot:spring-boot-starter:4.0.1 (*)
\--- org.springframework.boot:spring-boot-data-redis:4.0.1
+--- org.springframework.boot:spring-boot:4.0.1 (*)
+--- org.springframework.boot:spring-boot-data-commons:4.0.1
| +--- org.springframework.boot:spring-boot:4.0.1 (*)
| +--- org.springframework.boot:spring-boot-persistence:4.0.1
| | +--- org.springframework.boot:spring-boot:4.0.1 (*)
| | \--- org.springframework:spring-tx:7.0.2
| | +--- org.springframework:spring-beans:7.0.2 (*)
| | \--- org.springframework:spring-core:7.0.2 (*)
| \--- org.springframework.data:spring-data-commons:4.0.1
| +--- org.springframework:spring-core:7.0.2 (*)
| +--- org.springframework:spring-beans:7.0.2 (*)
| \--- org.slf4j:slf4j-api:2.0.17
+--- org.springframework.boot:spring-boot-transaction:4.0.1
| +--- org.springframework.boot:spring-boot:4.0.1 (*)
| +--- org.springframework.boot:spring-boot-persistence:4.0.1 (*)
| \--- org.springframework:spring-tx:7.0.2 (*)
+--- io.lettuce:lettuce-core:6.8.1.RELEASE -> 7.2.1.RELEASE
| +--- redis.clients.authentication:redis-authx-core:0.1.1-beta2
| | \--- org.slf4j:slf4j-api:1.7.36 -> 2.0.17
| +--- io.netty:netty-common:4.2.5.Final -> 4.2.9.Final
| +--- io.netty:netty-handler:4.2.5.Final -> 4.2.9.Final (*)
| +--- io.netty:netty-transport:4.2.5.Final -> 4.2.9.Final (*)
| +--- io.projectreactor:reactor-core:3.6.6 -> 3.8.1 (*)
| \--- io.netty:netty-resolver-dns:4.2.5.Final -> 4.2.9.Final (*)
\--- org.springframework.data:spring-data-redis:4.0.1
+--- org.springframework.data:spring-data-keyvalue:4.0.1
| +--- org.springframework.data:spring-data-commons:4.0.1 (*)
| +--- org.springframework:spring-context:7.0.2 (*)
| +--- org.springframework:spring-tx:7.0.2 (*)
| \--- org.slf4j:slf4j-api:2.0.17
+--- org.springframework:spring-tx:7.0.2 (*)
+--- org.springframework:spring-oxm:7.0.2
| +--- org.springframework:spring-beans:7.0.2 (*)
| \--- org.springframework:spring-core:7.0.2 (*)
+--- org.springframework:spring-aop:7.0.2 (*)
+--- org.springframework:spring-context-support:7.0.2 (*)
\--- org.slf4j:slf4j-api:2.0.17
(c) - A dependency constraint, not a dependency. The dependency affected by the constraint occurs elsewhere in the tree.
(*) - Indicates repeated occurrences of a transitive dependency subtree. Gradle expands transitive dependency subtrees only once per project; repeat occurrences only display the root of the subtree, followed by this annotation.
A web-based, searchable dependency report is available by adding the --scan option.
[Incubating] Problems report is available at: file:///home/stefan-mo/WsMeldestelle/Meldestelle/build/reports/problems/problems-report.html
Deprecated Gradle features were used in this build, making it incompatible with Gradle 10.
You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.
For more on this, please refer to https://docs.gradle.org/9.2.1/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.
BUILD SUCCESSFUL in 3s
1 actionable task: 1 executed

View File

@ -4,10 +4,10 @@
### 1. Kern-Spezifikationen ### 1. Kern-Spezifikationen
| Komponente | Version | Status | | Komponente | Version | Status |
| --- | --- | --- | | --- |----------| --- |
| **Kotlin** | `2.3.0` | Stabil (K2 Compiler standardmäßig aktiv) | | **Kotlin** | `2.3.0` | Stabil (K2 Compiler standardmäßig aktiv) |
| **Java (JDK)** | `25` | LTS (Long-Term Support) | | **Java (JDK)** | `25` | LTS (Long-Term Support) |
| **Gradle** | `9.2+` | Erforderlich für JDK 25 Support | | **Gradle** | `9.2.1` | Erforderlich für JDK 25 Support |
| **Android Plugin (AGP)** | `8.8.0+` | Empfohlen für Gradle 9.x Kompatibilität | | **Android Plugin (AGP)** | `8.8.0+` | Empfohlen für Gradle 9.x Kompatibilität |
--- ---
@ -52,7 +52,7 @@ Damit das Projekt Java 25 erkennt, muss der Wrapper auf dem neuesten Stand sein:
**Terminal-Befehl:** **Terminal-Befehl:**
```bash ```bash
./gradlew wrapper --gradle-version 9.2 --distribution-type all ./gradlew wrapper --gradle-version 9.2.1 --distribution-type all
``` ```

View File

@ -25,7 +25,7 @@ dependencies {
// === GATEWAY-SPEZIFISCHE ABHÄNGIGKEITEN === // === GATEWAY-SPEZIFISCHE ABHÄNGIGKEITEN ===
// Die WebFlux-Abhängigkeit wird jetzt korrekt durch das BOM bereitgestellt. // Die WebFlux-Abhängigkeit wird jetzt korrekt durch das BOM bereitgestellt.
// implementation(libs.spring.boot.starter.webflux) implementation(libs.spring.boot.starter.webflux)
// Kern-Gateway inkl. Security, Actuator, CircuitBreaker, Discovery // Kern-Gateway inkl. Security, Actuator, CircuitBreaker, Discovery
implementation(libs.bundles.gateway.core) implementation(libs.bundles.gateway.core)
@ -34,6 +34,12 @@ dependencies {
// Redis-Unterstützung für verteiltes Rate Limiting (RequestRateLimiter) // Redis-Unterstützung für verteiltes Rate Limiting (RequestRateLimiter)
implementation(libs.bundles.gateway.redis) implementation(libs.bundles.gateway.redis)
// === Tracing Dependencies (Micrometer Tracing) ===
// Ermöglicht verteiltes Tracing über Thread-Grenzen hinweg (ersetzt manuellen MDC-Filter)
implementation(libs.micrometer.tracing.bridge.brave)
// Optional: Zipkin Reporter, falls du Traces an Zipkin senden willst (bereits im monitoringClient enthalten, aber hier explizit schadet nicht)
// implementation(libs.zipkin.reporter.brave)
// === Test Dependencies === // === Test Dependencies ===
testImplementation(projects.platform.platformTesting) testImplementation(projects.platform.platformTesting)
testImplementation(libs.bundles.testing.jvm) testImplementation(libs.bundles.testing.jvm)

View File

@ -1,6 +1,7 @@
package at.mocode.infrastructure.gateway package at.mocode.infrastructure.gateway
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.beans.factory.getBean
import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication import org.springframework.boot.runApplication
import org.springframework.core.env.Environment import org.springframework.core.env.Environment
@ -11,7 +12,7 @@ class GatewayApplication
fun main(args: Array<String>) { fun main(args: Array<String>) {
val context = runApplication<GatewayApplication>(*args) val context = runApplication<GatewayApplication>(*args)
val logger = LoggerFactory.getLogger(GatewayApplication::class.java) val logger = LoggerFactory.getLogger(GatewayApplication::class.java)
val env = context.getBean(Environment::class.java) val env = context.getBean<Environment>()
val port = env.getProperty("server.port") ?: "8081" val port = env.getProperty("server.port") ?: "8081"
logger.info(""" logger.info("""

View File

@ -1,5 +1,6 @@
package at.mocode.infrastructure.gateway.config package at.mocode.infrastructure.gateway.config
import io.micrometer.tracing.Tracer
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.cloud.gateway.filter.GatewayFilterChain import org.springframework.cloud.gateway.filter.GatewayFilterChain
import org.springframework.cloud.gateway.filter.GlobalFilter import org.springframework.cloud.gateway.filter.GlobalFilter
@ -7,17 +8,21 @@ import org.springframework.core.Ordered
import org.springframework.stereotype.Component import org.springframework.stereotype.Component
import org.springframework.web.server.ServerWebExchange import org.springframework.web.server.ServerWebExchange
import reactor.core.publisher.Mono import reactor.core.publisher.Mono
import java.util.*
/** /**
* Gateway-Konfiguration für erweiterte Funktionalitäten wie Logging, Rate Limiting und Security. * Gateway-Konfiguration für erweiterte Funktionalitäten wie Logging, Rate Limiting und Security.
*/ */
/** /**
* Global Filter für Correlations-IDs zur Request-Verfolgung. * Globaler Filter, der sicherstellt, dass die Trace-ID (von Micrometer Tracing)
* auch als "X-Correlation-ID" im Response-Header zurückgegeben wird.
*
* Hinweis: Micrometer Tracing kümmert sich bereits automatisch um die Propagation
* der Trace-ID (b3 oder w3c) an nachgelagerte Services. Dieser Filter dient nur
* der Bequemlichkeit für Clients (z. B. Frontend), um die ID einfach auslesen zu können.
*/ */
@Component @Component
class CorrelationIdFilter : GlobalFilter, Ordered { class CorrelationIdFilter(private val tracer: Tracer) : GlobalFilter, Ordered {
private val logger = LoggerFactory.getLogger(CorrelationIdFilter::class.java) private val logger = LoggerFactory.getLogger(CorrelationIdFilter::class.java)
@ -26,26 +31,21 @@ class CorrelationIdFilter : GlobalFilter, Ordered {
} }
override fun filter(exchange: ServerWebExchange, chain: GatewayFilterChain): Mono<Void> { override fun filter(exchange: ServerWebExchange, chain: GatewayFilterChain): Mono<Void> {
val request = exchange.request // Die aktuelle Trace-ID aus dem Micrometer Tracer holen
val correlationId = request.headers.getFirst(CORRELATION_ID_HEADER) val currentSpan = tracer.currentSpan()
?: UUID.randomUUID().toString() val traceId = currentSpan?.context()?.traceId()
val mutatedRequest = request.mutate() if (traceId != null) {
.header(CORRELATION_ID_HEADER, correlationId) // Trace-ID als Response-Header hinzufügen
.build() exchange.response.headers.add(CORRELATION_ID_HEADER, traceId)
}
val mutatedExchange = exchange.mutate() return chain.filter(exchange)
.request(mutatedRequest)
.build()
// Response-Header nach der Verarbeitung hinzufügen
mutatedExchange.response.headers.add(CORRELATION_ID_HEADER, correlationId)
return chain.filter(mutatedExchange)
.doOnError { ex -> .doOnError { ex ->
logger.error("Error in CorrelationIdFilter for request {}: {}", request.uri, ex.message) logger.error("Error processing request {}: {}", exchange.request.uri, ex.message)
} }
} }
override fun getOrder(): Int = Ordered.HIGHEST_PRECEDENCE // Niedrige Priorität, damit Tracing-Kontext bereits initialisiert ist
override fun getOrder(): Int = Ordered.LOWEST_PRECEDENCE
} }

View File

@ -0,0 +1,51 @@
package at.mocode.infrastructure.gateway.config
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Primary
import reactor.core.publisher.Mono
import java.security.Principal
@Configuration
class RateLimitConfig {
/**
* Standard KeyResolver: IP-basiert.
* Nutzt X-Forwarded-For (für Proxies/LoadBalancer), wenn vorhanden, sonst die Remote-Adresse.
* Wird verwendet, wenn kein anderer KeyResolver explizit angefordert wird oder aktiv ist.
*/
@Bean
@Primary
fun ipAddressKeyResolver(): KeyResolver = KeyResolver { exchange ->
val forwardedFor = exchange.request.headers.getFirst("X-Forwarded-For")
?.split(',')?.firstOrNull()?.trim()
val ip = forwardedFor
?: exchange.request.remoteAddress?.address?.hostAddress
?: "unknown"
Mono.just(ip)
}
/**
* Erweiterter KeyResolver: Principal-basiert (User-ID).
* Versucht, den authentifizierten User (Principal) zu nutzen.
* Fallback auf IP-Adresse, falls der User nicht eingeloggt ist.
*
* Aktivierung über Property: gateway.ratelimit.principal-key-resolver.enabled=true
*/
@Bean
@ConditionalOnProperty(prefix = "gateway.ratelimit.principal-key-resolver", name = ["enabled"], havingValue = "true", matchIfMissing = false)
fun principalNameKeyResolver(): KeyResolver = KeyResolver { exchange ->
exchange.getPrincipal<Principal>()
.map { it.name }
.switchIfEmpty(
Mono.just(
exchange.request.headers.getFirst("X-Forwarded-For")?.split(",")?.first()?.trim()
?: exchange.request.headers.getFirst("X-Real-IP")
?: exchange.request.remoteAddress?.address?.hostAddress
?: "unknown"
)
)
}
}

View File

@ -1,31 +0,0 @@
package at.mocode.infrastructure.gateway.config
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import reactor.core.publisher.Mono
import java.security.Principal
@Configuration
class RateLimiterConfig {
/**
* KeyResolver basierend auf authentifiziertem Principal; Fallback auf Client-IP.
* Funktioniert out-of-the-box mit Keycloak (Resource Server), sofern Security aktiv ist.
*/
@Bean
@ConditionalOnProperty(prefix = "gateway.ratelimit.principal-key-resolver", name = ["enabled"], havingValue = "true", matchIfMissing = false)
fun principalNameKeyResolver(): KeyResolver = KeyResolver { exchange ->
exchange.getPrincipal<Principal>()
.map { it.name }
.switchIfEmpty(
Mono.just(
exchange.request.headers.getFirst("X-Forwarded-For")?.split(",")?.first()?.trim()
?: exchange.request.headers.getFirst("X-Real-IP")
?: exchange.request.remoteAddress?.address?.hostAddress
?: "unknown"
)
)
}
}

View File

@ -1,26 +0,0 @@
package at.mocode.infrastructure.gateway.config
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver
import org.springframework.context.annotation.Primary
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import reactor.core.publisher.Mono
@Configuration
class RateLimitingConfig {
/**
* Einfache IP-basierte KeyResolver-Implementierung für das RequestRateLimiter-Filter.
* Nutzt X-Forwarded-For, wenn vorhanden, sonst die Remote-Adresse.
*/
@Bean
@Primary
fun ipAddressKeyResolver(): KeyResolver = KeyResolver { exchange ->
val forwardedFor = exchange.request.headers.getFirst("X-Forwarded-For")
?.split(',')?.firstOrNull()?.trim()
val ip = forwardedFor
?: exchange.request.remoteAddress?.address?.hostAddress
?: "unknown"
Mono.just(ip)
}
}

View File

@ -1,27 +0,0 @@
package at.mocode.infrastructure.gateway.fallback
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import java.time.Instant
/**
* Alternative FallbackController (deaktiviert per Default), nur aktivierbar über
* property `gateway.customFallback.enabled=true`. Standardmäßig existiert bereits
* ein FallbackController unter `...gateway.controller.FallbackController`.
*/
@RestController
@ConditionalOnProperty(prefix = "gateway.customFallback", name = ["enabled"], havingValue = "true", matchIfMissing = false)
class FallbackController {
@RequestMapping("/fallback/ping")
fun pingFallback(): ResponseEntity<Map<String, Any>> =
ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).body(
mapOf(
"message" to "Ping service unavailable",
"timestamp" to Instant.now().toString()
)
)
}

View File

@ -1,7 +1,8 @@
package at.mocode.infrastructure.gateway.health package at.mocode.infrastructure.gateway.health
import org.springframework.boot.actuate.health.Health import org.springframework.boot.health.contributor.Health
import org.springframework.boot.actuate.health.ReactiveHealthIndicator import org.springframework.boot.health.contributor.ReactiveHealthIndicator
import org.springframework.cloud.client.ServiceInstance
import org.springframework.cloud.client.discovery.DiscoveryClient import org.springframework.cloud.client.discovery.DiscoveryClient
import org.springframework.core.env.Environment import org.springframework.core.env.Environment
import org.springframework.stereotype.Component import org.springframework.stereotype.Component
@ -9,7 +10,9 @@ import org.springframework.web.reactive.function.client.WebClient
import org.springframework.web.reactive.function.client.WebClientResponseException import org.springframework.web.reactive.function.client.WebClientResponseException
import reactor.core.publisher.Flux import reactor.core.publisher.Flux
import reactor.core.publisher.Mono import reactor.core.publisher.Mono
import reactor.core.scheduler.Schedulers
import java.time.Duration import java.time.Duration
import java.util.concurrent.TimeoutException
/** /**
* Gateway Health Indicator zur Überwachung der Downstream Services. * Gateway Health Indicator zur Überwachung der Downstream Services.
@ -40,46 +43,47 @@ class GatewayHealthIndicator(
) )
private val HEALTH_CHECK_TIMEOUT = Duration.ofSeconds(5) private val HEALTH_CHECK_TIMEOUT = Duration.ofSeconds(5)
private const val PARALLELISM = 8
} }
// KORREKTUR für Spring Boot 4: Die `health()`-Methode und ihr Rückgabetyp `Mono<Health>`
// erlauben keine Null-Werte mehr. Die Fragezeichen (?) wurden entfernt.
override fun health(): Mono<Health> { override fun health(): Mono<Health> {
val builder = Health.up() val builder = Health.up()
val details = mutableMapOf<String, Any>() val details = mutableMapOf<String, Any>()
return Mono.fromCallable { discoveryClient.services } return Mono.fromCallable { discoveryClient.services }
.flatMapMany { services -> .subscribeOn(Schedulers.boundedElastic())
.flatMapMany { services: List<String> ->
details["totalServices"] = services.size details["totalServices"] = services.size
Flux.fromIterable(services) Flux.fromIterable(services)
} }
.flatMap({ serviceName -> .flatMap({ serviceName: String ->
val instances = discoveryClient.getInstances(serviceName) Mono.fromCallable { discoveryClient.getInstances(serviceName) }
.subscribeOn(Schedulers.boundedElastic())
.flatMap { instances: List<ServiceInstance> ->
val instanceDetails = mapOf( val instanceDetails = mapOf(
"instanceCount" to instances.size, "instanceCount" to instances.size,
"instances" to instances.map { "${it.host}:${it.port}" } "instances" to instances.map { "${it.host}:${it.port}" }
) )
// Für Health-Check nur auf definierte Services gehen
val checkMono = when { val checkMono: Mono<String> = when {
CRITICAL_SERVICES.contains(serviceName) || OPTIONAL_SERVICES.contains(serviceName) -> CRITICAL_SERVICES.contains(serviceName) || OPTIONAL_SERVICES.contains(serviceName) ->
checkServiceHealthReactive(serviceName) checkServiceHealthReactive(serviceName, instances)
else -> Mono.just("SKIPPED") else -> Mono.just("SKIPPED")
} }
checkMono checkMono.map { status -> Triple(serviceName, status, instanceDetails) }
.map { status -> Triple(serviceName, status, instanceDetails) } }
}, 8) // begrenze Parallelität }, PARALLELISM)
.collectList() .collectList()
.map { results -> .flatMap { results: List<Triple<String, String, Map<String, Any>>> ->
val discoveredServices = mutableMapOf<String, Any>() val discoveredServices = mutableMapOf<String, Any>()
val criticalServiceStatus = mutableMapOf<String, String>() val criticalServiceStatus = mutableMapOf<String, String>()
val optionalServiceStatus = mutableMapOf<String, String>() val optionalServiceStatus = mutableMapOf<String, String>()
results.forEach { (serviceName, status, instanceDetails) -> results.forEach { (serviceName, status, instanceDetails) ->
discoveredServices[serviceName] = instanceDetails discoveredServices[serviceName] = instanceDetails
if (CRITICAL_SERVICES.contains(serviceName)) { when {
criticalServiceStatus[serviceName] = status CRITICAL_SERVICES.contains(serviceName) -> criticalServiceStatus[serviceName] = status
} else if (OPTIONAL_SERVICES.contains(serviceName)) { OPTIONAL_SERVICES.contains(serviceName) -> optionalServiceStatus[serviceName] = status
optionalServiceStatus[serviceName] = status
} }
} }
@ -99,38 +103,39 @@ class GatewayHealthIndicator(
details["status"] = "UP" details["status"] = "UP"
details["reason"] = when { details["reason"] = when {
isTestEnvironment -> "Gesundheitsprüfung erfolgreich (Testumgebung)" isTestEnvironment -> "Gesundheitsprüfung erfolgreich (Testumgebung)"
isDevEnvironment -> "Gesundheitsprüfung erfolgreich (Entwicklungsumgebung - nicht alle Services erforderlich)" isDevEnvironment -> "Gesundheitsprüfung erfolgreich (Entwicklungsumgebung)"
else -> "Alle kritischen Services sind verfügbar oder optional" else -> "Alle kritischen Services sind verfügbar"
} }
} }
builder.withDetails(details).build() Mono.just(builder.withDetails(details).build())
} }
.onErrorResume { ex -> .onErrorResume { ex ->
Mono.just( Mono.just(
Health.down(ex) Health.down(ex)
.withDetail("status", "DOWN") .withDetail("status", "DOWN")
.withDetail("reason", "Fehler beim Prüfen der nachgelagerten Services: ${ex.message}") .withDetail("reason", "Fehler bei der Service-Prüfung: ${ex.message}")
.build() .build()
) )
} }
} }
private fun checkServiceHealthReactive(serviceName: String): Mono<String> { private fun checkServiceHealthReactive(serviceName: String, instances: List<ServiceInstance>): Mono<String> {
return Mono.fromCallable { discoveryClient.getInstances(serviceName) }
.flatMap { instances ->
if (instances.isEmpty()) { if (instances.isEmpty()) {
Mono.just("NO_INSTANCES") return Mono.just("NO_INSTANCES")
} else { }
// Wir prüfen exemplarisch die erste Instanz
val instance = instances.first() val instance = instances.first()
val healthUrl = "http://${instance.host}:${instance.port}/actuator/health" val healthUrl = "http://${instance.host}:${instance.port}/actuator/health"
webClient.get()
return webClient.get()
.uri(healthUrl) .uri(healthUrl)
.retrieve() .retrieve()
.bodyToMono(Map::class.java) .bodyToMono(Map::class.java)
.timeout(HEALTH_CHECK_TIMEOUT) .timeout(HEALTH_CHECK_TIMEOUT)
.map { it["status"]?.toString() ?: "UNKNOWN" } .map { it["status"]?.toString() ?: "UNKNOWN" }
.map { status -> if (status == "UP") "UP" else "DOWN" } .map { status -> if (status.equals("UP", ignoreCase = true)) "UP" else "DOWN" }
.onErrorResume { ex -> .onErrorResume { ex ->
when (ex) { when (ex) {
is WebClientResponseException -> when (ex.statusCode.value()) { is WebClientResponseException -> when (ex.statusCode.value()) {
@ -138,10 +143,9 @@ class GatewayHealthIndicator(
503 -> Mono.just("DOWN") 503 -> Mono.just("DOWN")
else -> Mono.just("ERROR") else -> Mono.just("ERROR")
} }
is TimeoutException -> Mono.just("TIMEOUT")
else -> Mono.just("ERROR") else -> Mono.just("ERROR")
} }
} }
} }
}
}
} }

View File

@ -16,6 +16,7 @@ import org.springframework.security.web.server.util.matcher.ServerWebExchangeMat
import org.springframework.web.cors.CorsConfiguration import org.springframework.web.cors.CorsConfiguration
import org.springframework.web.cors.reactive.CorsConfigurationSource import org.springframework.web.cors.reactive.CorsConfigurationSource
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource
import reactor.core.publisher.Mono
import java.time.Duration import java.time.Duration
@Configuration @Configuration
@ -69,35 +70,53 @@ class SecurityConfig(
* Erstellt einen ReactiveJwtDecoder für die JWT-Validierung. * Erstellt einen ReactiveJwtDecoder für die JWT-Validierung.
* *
* Verwendet die JWK Set URI aus der Konfiguration, um die öffentlichen Schlüssel * Verwendet die JWK Set URI aus der Konfiguration, um die öffentlichen Schlüssel
* von Keycloak zu laden. Falls die URI nicht konfiguriert ist oder Keycloak * von Keycloak zu laden.
* nicht erreichbar ist, wird trotzdem ein Bean erstellt, um Startfehler zu vermeiden. *
* Resilience-Optimierung:
* Anstatt beim Start zu failen oder einen statischen NoOp-Decoder zu nutzen,
* verwenden wir einen delegierenden Decoder. Dieser versucht bei jedem Request,
* den echten Decoder (lazy) zu initialisieren, falls er noch nicht bereit ist.
* So kann Keycloak auch NACH dem Gateway starten.
*/ */
@Bean @Bean
fun reactiveJwtDecoder( fun reactiveJwtDecoder(
@Value($$"${spring.security.oauth2.resourceserver.jwt.jwk-set-uri:}") jwkSetUri: String @Value($$"${spring.security.oauth2.resourceserver.jwt.jwk-set-uri:}") jwkSetUri: String
): ReactiveJwtDecoder { ): ReactiveJwtDecoder {
return if (jwkSetUri.isNotBlank()) { return ResilienceReactiveJwtDecoder(jwkSetUri)
try {
NimbusReactiveJwtDecoder.withJwkSetUri(jwkSetUri).build()
} catch (e: Exception) {
// Log warning and return a no-op decoder to allow startup
logger.warn("Failed to configure JWT decoder with JWK Set URI: {} - {}", jwkSetUri, e.message)
logger.warn("JWT authentication will not work until Keycloak is available")
createNoOpJwtDecoder()
}
} else {
logger.info("No JWK Set URI configured, using no-op JWT decoder")
createNoOpJwtDecoder()
}
} }
/** /**
* Erstellt einen No-Op JWT Decoder für Fälle, in denen Keycloak nicht verfügbar ist. * Ein Wrapper um den NimbusReactiveJwtDecoder, der Initialisierungsfehler abfängt
* Dieser Decoder lehnt alle Token ab, erlaubt aber den Anwendungsstart. * und erst zur Laufzeit (lazy) versucht, die JWKs zu laden.
*/ */
private fun createNoOpJwtDecoder(): ReactiveJwtDecoder { class ResilienceReactiveJwtDecoder(private val jwkSetUri: String) : ReactiveJwtDecoder {
return ReactiveJwtDecoder { token -> private val logger = LoggerFactory.getLogger(ResilienceReactiveJwtDecoder::class.java)
throw IllegalStateException("JWT validation is not available - Keycloak may not be running") private var delegate: ReactiveJwtDecoder? = null
override fun decode(token: String): Mono<org.springframework.security.oauth2.jwt.Jwt> {
if (delegate == null) {
synchronized(this) {
if (delegate == null) {
try {
if (jwkSetUri.isBlank()) {
throw IllegalArgumentException("JWK Set URI is missing")
}
logger.info("Attempting to initialize JWT Decoder with URI: {}", jwkSetUri)
delegate = NimbusReactiveJwtDecoder.withJwkSetUri(jwkSetUri).build()
logger.info("JWT Decoder successfully initialized.")
} catch (e: Exception) {
logger.warn("Could not initialize JWT Decoder (Keycloak might be down): {}", e.message)
return Mono.error(IllegalStateException("Identity Provider currently unavailable. Please try again later."))
}
}
}
}
return delegate!!.decode(token)
.onErrorResume { e ->
// Falls der Decoder zwar da ist, aber z.B. Netzwerkfehler auftreten, loggen wir das
logger.debug("JWT decoding failed: {}", e.message)
Mono.error(e)
}
} }
} }

View File

@ -27,6 +27,11 @@ management:
web: web:
exposure: exposure:
include: health,info,prometheus include: health,info,prometheus
tracing:
sampling:
probability: 1.0 # 100% der Requests tracen (für Dev/Test sinnvoll, in Prod reduzieren)
propagation:
type: w3c # Standard W3C Trace Context (kompatibel mit OpenTelemetry)
# Gateway-spezifische Einstellungen # Gateway-spezifische Einstellungen
gateway: gateway:

View File

@ -1,61 +1,38 @@
// Optimized Spring Boot ping service for testing microservice architecture
// This service demonstrates circuit breaker patterns, service discovery, and monitoring
plugins { plugins {
alias(libs.plugins.kotlinJvm) alias(libs.plugins.kotlinJvm)
alias(libs.plugins.kotlinSpring) alias(libs.plugins.kotlinSpring)
alias(libs.plugins.kotlinJpa) alias(libs.plugins.kotlinJpa)
alias(libs.plugins.spring.boot) alias(libs.plugins.spring.boot)
// FINALE BEREINIGUNG: Das `dependencyManagement`-Plugin wird entfernt.
// alias(libs.plugins.spring.dependencyManagement)
} }
// Configure the main class for the executable JAR kotlin {
springBoot { compilerOptions {
mainClass.set("at.mocode.ping.service.PingServiceApplicationKt") // Aktiviert die experimentelle UUID API von Kotlin 2.3.0
freeCompilerArgs.add("-opt-in=kotlin.uuid.ExperimentalUuidApi")
}
} }
dependencies { dependencies {
// Die `platform`-Deklaration ist der einzig korrekte Weg. // === Project Dependencies ===
implementation(platform(projects.platform.platformBom))
// Platform und Core Dependencies
implementation(projects.platform.platformDependencies)
implementation(projects.backend.services.ping.pingApi) implementation(projects.backend.services.ping.pingApi)
implementation(projects.backend.infrastructure.monitoring.monitoringClient) implementation(projects.platform.platformDependencies)
// Spring Boot Service Complete Bundle // === Spring Boot & Cloud ===
// Provides: web, validation, actuator, security, oauth2-client, oauth2-resource-server,
// data-jpa, data-redis, micrometer-prometheus, tracing, zipkin
implementation(libs.bundles.spring.boot.service.complete) implementation(libs.bundles.spring.boot.service.complete)
// WICHTIG: Da wir JPA (blockierend) nutzen, brauchen wir Spring MVC (nicht WebFlux)
// Datenbank (PostgresQL) Driver
implementation(libs.postgresql.driver)
// Web-Server (Tomcat) explizit hinzufügen!
implementation(libs.spring.boot.starter.web) implementation(libs.spring.boot.starter.web)
implementation(libs.bundles.spring.cloud.gateway) // Für Discovery Client
// Jackson Kotlin Support Bundle // === Database & Persistence ===
implementation(libs.bundles.jackson.kotlin) implementation(libs.bundles.database.complete)
// Kotlin Reflection (now from version catalog) // === Resilience ===
implementation(libs.kotlin.reflect)
// Service Discovery
implementation(libs.spring.cloud.starter.consul.discovery)
// Caching (Caffeine for Spring Cloud LoadBalancer)
implementation(libs.caffeine)
implementation(libs.spring.web) // Provides spring-context-support
// Resilience4j Bundle (Circuit Breaker, Reactor, AOP)
implementation(libs.bundles.resilience) implementation(libs.bundles.resilience)
// OpenAPI Documentation // === Testing ===
implementation(libs.springdoc.openapi.starter.webmvc.ui)
// Test Dependencies
testImplementation(projects.platform.platformTesting)
testImplementation(libs.bundles.testing.jvm) testImplementation(libs.bundles.testing.jvm)
testImplementation(libs.spring.boot.starter.test) }
testImplementation(libs.spring.boot.starter.web)
tasks.test {
useJUnitPlatform()
} }

View File

@ -1,13 +1,13 @@
package at.mocode.ping.service package at.mocode.ping
import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication import org.springframework.boot.runApplication
import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.EnableAspectJAutoProxy import org.springframework.context.annotation.EnableAspectJAutoProxy
import org.springframework.web.servlet.config.annotation.CorsRegistry import org.springframework.web.reactive.config.CorsRegistry
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer
@SpringBootApplication @SpringBootApplication
// Scannt explizit alle Sub-Packages (infrastructure, application, domain)
@EnableAspectJAutoProxy @EnableAspectJAutoProxy
class PingServiceApplication { class PingServiceApplication {

View File

@ -0,0 +1,44 @@
package at.mocode.ping.application
import at.mocode.ping.domain.Ping
import at.mocode.ping.domain.PingRepository
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import kotlin.uuid.ExperimentalUuidApi
import kotlin.uuid.Uuid
/**
* Application Service.
* Implementiert den Use Case und orchestriert Domain & Repository.
* Hier darf Spring (@Service, @Transactional) verwendet werden, da es "Application Logic" ist.
*/
@Service
@OptIn(ExperimentalUuidApi::class)
class PingService(
private val repository: PingRepository
) : PingUseCase {
private val logger = LoggerFactory.getLogger(PingService::class.java)
@Transactional
override fun executePing(message: String): Ping {
logger.info("Executing ping with message: {}", message)
// Domain Logic: Erstelle neue Entity (generiert UUID v7 automatisch)
val ping = Ping(message = message)
// Persistence
return repository.save(ping)
}
@Transactional(readOnly = true)
override fun getPingHistory(): List<Ping> {
return repository.findAll()
}
@Transactional(readOnly = true)
override fun getPing(id: Uuid): Ping? {
return repository.findById(id)
}
}

View File

@ -0,0 +1,16 @@
package at.mocode.ping.application
import at.mocode.ping.domain.Ping
import kotlin.uuid.ExperimentalUuidApi
import kotlin.uuid.Uuid
/**
* Primary Port (Inbound Port).
* Definiert die fachlichen Operationen, die von außen (Controller) aufgerufen werden können.
*/
@OptIn(ExperimentalUuidApi::class)
interface PingUseCase {
fun executePing(message: String): Ping
fun getPingHistory(): List<Ping>
fun getPing(id: Uuid): Ping?
}

View File

@ -0,0 +1,16 @@
package at.mocode.ping.domain
import kotlin.uuid.ExperimentalUuidApi
import kotlin.uuid.Uuid
import java.time.Instant
/**
* Domain Entity für einen Ping.
* Unabhängig von Frameworks (Pure Kotlin).
*/
@OptIn(ExperimentalUuidApi::class)
data class Ping(
val id: Uuid = Uuid.generateV7(), // Kotlin 2.3.0 UUID v7
val message: String,
val timestamp: Instant = Instant.now()
)

View File

@ -0,0 +1,15 @@
package at.mocode.ping.domain
import kotlin.uuid.ExperimentalUuidApi
import kotlin.uuid.Uuid
/**
* Secondary Port (Outbound Port).
* Definiert, wie Pings gespeichert werden, ohne die Technologie (DB) zu kennen.
*/
@OptIn(ExperimentalUuidApi::class)
interface PingRepository {
fun save(ping: Ping): Ping
fun findAll(): List<Ping>
fun findById(id: Uuid): Ping?
}

View File

@ -0,0 +1,24 @@
package at.mocode.ping.infrastructure.persistence
import jakarta.persistence.Entity
import jakarta.persistence.Id
import jakarta.persistence.Table
import java.time.Instant
import java.util.UUID
/**
* JPA Entity (Infrastructure Detail).
* Spiegelt die Datenbank-Tabelle wider.
* Nutzt java.util.UUID für JPA-Kompatibilität (bis Hibernate kotlin.uuid nativ unterstützt).
*/
@Entity
@Table(name = "pings")
class PingJpaEntity(
@Id
val id: UUID,
val message: String,
val timestamp: Instant
) {
// Default constructor for JPA
protected constructor() : this(UUID.randomUUID(), "", Instant.now())
}

View File

@ -0,0 +1,49 @@
package at.mocode.ping.infrastructure.persistence
import at.mocode.ping.domain.Ping
import at.mocode.ping.domain.PingRepository
import org.springframework.stereotype.Component
import kotlin.uuid.ExperimentalUuidApi
import kotlin.uuid.Uuid
import kotlin.uuid.toJavaUuid
import kotlin.uuid.toKotlinUuid
/**
* Driven Adapter.
* Implementiert den Domain-Port `PingRepository` mithilfe von Spring Data JPA.
* Mappt zwischen Domain-Entity und JPA-Entity.
*/
@Component
@OptIn(ExperimentalUuidApi::class)
class PingRepositoryAdapter(
private val jpaRepository: SpringDataPingRepository
) : PingRepository {
override fun save(ping: Ping): Ping {
val jpaEntity = PingJpaEntity(
id = ping.id.toJavaUuid(),
message = ping.message,
timestamp = ping.timestamp
)
val saved = jpaRepository.save(jpaEntity)
return mapToDomain(saved)
}
override fun findAll(): List<Ping> {
return jpaRepository.findAll().map { mapToDomain(it) }
}
override fun findById(id: Uuid): Ping? {
return jpaRepository.findById(id.toJavaUuid())
.map { mapToDomain(it) }
.orElse(null)
}
private fun mapToDomain(entity: PingJpaEntity): Ping {
return Ping(
id = entity.id.toKotlinUuid(),
message = entity.message,
timestamp = entity.timestamp
)
}
}

View File

@ -0,0 +1,8 @@
package at.mocode.ping.infrastructure.persistence
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Repository
import java.util.UUID
@Repository
interface SpringDataPingRepository : JpaRepository<PingJpaEntity, UUID>

View File

@ -0,0 +1,96 @@
package at.mocode.ping.infrastructure.web
import at.mocode.ping.api.EnhancedPingResponse
import at.mocode.ping.api.HealthResponse
import at.mocode.ping.api.PingApi
import at.mocode.ping.api.PingResponse
import at.mocode.ping.application.PingUseCase
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker
import org.slf4j.LoggerFactory
import org.springframework.web.bind.annotation.*
import java.time.ZoneOffset
import java.time.format.DateTimeFormatter
import kotlin.random.Random
/**
* Driving Adapter (REST Controller).
* Nutzt den Application Port (PingUseCase).
*/
@RestController
@CrossOrigin(allowedHeaders = ["*"], allowCredentials = "true")
class PingController(
private val pingUseCase: PingUseCase
) : PingApi {
private val logger = LoggerFactory.getLogger(PingController::class.java)
private val formatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME
companion object {
const val PING_CIRCUIT_BREAKER = "pingCircuitBreaker"
}
@GetMapping("/ping/simple")
override suspend fun simplePing(): PingResponse {
// Ruft Use Case auf -> Speichert in DB
val domainPing = pingUseCase.executePing("Simple Ping")
return PingResponse(
status = "pong",
timestamp = domainPing.timestamp.atOffset(ZoneOffset.UTC).format(formatter),
service = "ping-service"
)
}
@GetMapping("/ping/enhanced")
@CircuitBreaker(name = PING_CIRCUIT_BREAKER, fallbackMethod = "fallbackPing")
override suspend fun enhancedPing(
@RequestParam(required = false, defaultValue = "false") simulate: Boolean
): EnhancedPingResponse {
val start = System.nanoTime()
if (simulate && Random.nextDouble() < 0.6) {
throw RuntimeException("Simulated service failure")
}
// Use Case Aufruf
val domainPing = pingUseCase.executePing("Enhanced Ping")
val elapsedMs = (System.nanoTime() - start) / 1_000_000
return EnhancedPingResponse(
status = "pong",
timestamp = domainPing.timestamp.atOffset(ZoneOffset.UTC).format(formatter),
service = "ping-service",
circuitBreakerState = "CLOSED",
responseTime = elapsedMs
)
}
// Fallback muss public sein für Resilience4j Proxy
fun fallbackPing(simulate: Boolean, ex: Exception): EnhancedPingResponse {
logger.warn("Circuit breaker fallback triggered: {}", ex.message)
return EnhancedPingResponse(
status = "fallback",
timestamp = java.time.OffsetDateTime.now().format(formatter),
service = "ping-service-fallback",
circuitBreakerState = "OPEN",
responseTime = 0
)
}
@GetMapping("/ping/health")
override suspend fun healthCheck(): HealthResponse {
return HealthResponse(
status = "up",
timestamp = java.time.OffsetDateTime.now().format(formatter),
service = "ping-service",
healthy = true
)
}
// Zusätzlicher Endpunkt um die DB zu prüfen (History)
@GetMapping("/ping/history")
fun getHistory() = pingUseCase.getPingHistory().map {
mapOf("id" to it.id.toString(), "message" to it.message, "time" to it.timestamp.toString())
}
}

View File

@ -1,40 +0,0 @@
package at.mocode.ping.service
import at.mocode.ping.api.EnhancedPingResponse
import at.mocode.ping.api.HealthResponse
import at.mocode.ping.api.PingApi
import at.mocode.ping.api.PingResponse
import org.springframework.web.bind.annotation.*
import java.time.OffsetDateTime
import java.time.format.DateTimeFormatter
@RestController
@CrossOrigin(
origins = ["http://localhost:8080", "http://localhost:8083", "http://localhost:4000"],
methods = [RequestMethod.GET, RequestMethod.POST, RequestMethod.PUT, RequestMethod.DELETE, RequestMethod.OPTIONS],
allowedHeaders = ["*"],
allowCredentials = "true"
)
class PingController(
private val pingService: PingServiceCircuitBreaker
) : PingApi {
// Contract endpoints
@GetMapping("/ping/simple")
override suspend fun simplePing(): PingResponse {
val now = OffsetDateTime.now().format(DateTimeFormatter.ISO_OFFSET_DATE_TIME)
return PingResponse(
status = "pong",
timestamp = now,
service = "ping-service"
)
}
@GetMapping("/ping/enhanced")
override suspend fun enhancedPing(
@RequestParam(required = false, defaultValue = "false") simulate: Boolean
): EnhancedPingResponse = pingService.ping(simulate)
@GetMapping("/ping/health")
override suspend fun healthCheck(): HealthResponse = pingService.healthCheck()
}

View File

@ -1,109 +0,0 @@
package at.mocode.ping.service
import at.mocode.ping.api.EnhancedPingResponse
import at.mocode.ping.api.HealthResponse
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
import kotlin.random.Random
/**
* Service demonstrating a Circuit Breaker pattern with Resilience
*
* This service simulates potential failures and uses circuit breaker
* to handle service degradation gracefully with fallback responses.
*/
@Service
class PingServiceCircuitBreaker {
private val logger = LoggerFactory.getLogger(PingServiceCircuitBreaker::class.java)
companion object {
const val PING_CIRCUIT_BREAKER = "pingCircuitBreaker"
private val formatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME //.ofPattern("yyyy-MM-dd HH:mm:ss")
}
/**
* Primary ping method with circuit breaker protection returning DTO directly
*
* @param simulateFailure - if true, randomly throws exceptions to test circuit breaker
*/
@CircuitBreaker(name = PING_CIRCUIT_BREAKER, fallbackMethod = "fallbackPing")
fun ping(simulateFailure: Boolean = false): EnhancedPingResponse {
val start = System.nanoTime()
logger.info("Executing ping service call...")
if (simulateFailure && Random.nextDouble() < 0.6) {
logger.warn("Simulating service failure for circuit breaker testing")
throw RuntimeException("Simulated service failure")
}
val currentTime = LocalDateTime.now().atOffset(java.time.ZoneOffset.UTC).format(formatter)
val elapsedMs = (System.nanoTime() - start) / 1_000_000
logger.info("Ping service call successful")
return EnhancedPingResponse(
status = "pong",
timestamp = currentTime,
service = "ping-service",
circuitBreakerState = "CLOSED",
responseTime = elapsedMs
)
}
/**
* Fallback method called when circuit breaker is OPEN
*
* @param simulateFailure - original parameter (ignored in fallback)
* @param exception - the exception that triggered the fallback
*/
fun fallbackPing(simulateFailure: Boolean = false, exception: Exception): EnhancedPingResponse {
val start = System.nanoTime()
// Die volle Exception nur loggen, nicht an den Client weitergeben.
logger.warn("Circuit breaker fallback triggered due to: {}", exception.toString())
val currentTime = LocalDateTime.now().atOffset(java.time.ZoneOffset.UTC).format(formatter)
val elapsedMs = (System.nanoTime() - start) / 1_000_000
return EnhancedPingResponse(
status = "fallback",
timestamp = currentTime,
service = "ping-service-fallback",
circuitBreakerState = "OPEN",
responseTime = elapsedMs
)
}
/**
* Health check method with circuit breaker protection returning DTO directly
*/
@CircuitBreaker(name = PING_CIRCUIT_BREAKER, fallbackMethod = "fallbackHealth")
fun healthCheck(): HealthResponse {
logger.info("Executing health check...")
val currentTime = LocalDateTime.now().atOffset(java.time.ZoneOffset.UTC).format(formatter)
return HealthResponse(
status = "pong",
timestamp = currentTime,
service = "ping-service",
healthy = true
)
}
/**
* Fallback for health check returning DTO
*/
fun fallbackHealth(exception: Exception): HealthResponse {
logger.warn("Health check fallback triggered: {}", exception.message)
val currentTime = LocalDateTime.now().atOffset(java.time.ZoneOffset.UTC).format(formatter)
return HealthResponse(
status = "down",
timestamp = currentTime,
service = "ping-service",
healthy = false
)
}
}

View File

@ -16,8 +16,9 @@ kotlinx-coroutines = "1.10.2"
# --- Spring Ecosystem --- # --- Spring Ecosystem ---
springBoot = "4.0.1" # KORREKTUR: Version auf Benutzerwunsch angepasst (war 4.0.1)
# Spring Cloud Version kompatibel zu Spring Boot 4.0.1 springBoot = "3.5.9"
# Spring Cloud Version kompatibel zu Spring Boot
springCloud = "2025.1.0" springCloud = "2025.1.0"
# springCloudGateway = "4.3.0" # springCloudGateway = "4.3.0"
springDependencyManagement = "1.1.7" springDependencyManagement = "1.1.7"
@ -153,8 +154,8 @@ spring-boot-starter-oauth2-resource-server = { module = "org.springframework.boo
spring-boot-starter-security = { module = "org.springframework.boot:spring-boot-starter-security" } spring-boot-starter-security = { module = "org.springframework.boot:spring-boot-starter-security" }
spring-boot-starter-webflux = { module = "org.springframework.boot:spring-boot-starter-webflux" } spring-boot-starter-webflux = { module = "org.springframework.boot:spring-boot-starter-webflux" }
spring-boot-starter-json = { module = "org.springframework.boot:spring-boot-starter-json" } spring-boot-starter-json = { module = "org.springframework.boot:spring-boot-starter-json" }
# KORREKTUR: Fehlende Definition für spring-boot-starter-aop hinzugefügt. # KORREKTUR: Explizite Versionierung über BOM-Referenz
spring-boot-starter-aop = { module = "org.springframework.boot:spring-boot-starter-aop" } spring-boot-starter-aop = { module = "org.springframework.boot:spring-boot-starter-aop", version.ref = "springBoot" }
spring-kafka = { module = "org.springframework.kafka:spring-kafka" } spring-kafka = { module = "org.springframework.kafka:spring-kafka" }
spring-security-oauth2-jose = { module = "org.springframework.security:spring-security-oauth2-jose" } spring-security-oauth2-jose = { module = "org.springframework.security:spring-security-oauth2-jose" }
spring-web = { module = "org.springframework:spring-web" } spring-web = { module = "org.springframework:spring-web" }