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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 66 additions & 52 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
plugins {
id 'org.springframework.boot' version '3.5.10'
id 'org.springframework.boot' version '4.0.2'
id 'io.spring.dependency-management' version '1.1.7'
id 'org.jetbrains.kotlin.jvm' version '2.2.21'
id 'org.jetbrains.kotlin.plugin.spring' version '2.2.21'
Expand All @@ -9,6 +9,27 @@ plugins {
id 'application'
}

ext {
set('springCloudVersion', '2025.1.1')
set('testcontainersVersion', '2.0.3')
set('springBootVersion', '4.0.2')
set('wiremockVersion', '3.13.2')
set('mockkVersion', '1.14.9')
set('querydslMongodbVersion', '5.1.0')
set('springmockkVersion', '4.0.2')
set('logbackVersion', '1.5.30')
set('springdocVersion', '3.0.1')
set('logbackAppenderVersion', '2.25.0-alpha')
set('postgresqlVersion', '42.7.10')
set('junitPlatformLauncherVersion', '6.0.3')
set('micrometerRegistryPrometheusVersion', '1.16.3')
set('springSecurityTestVersion', '7.0.3')
set('springResilience4jVersion', '5.0.1')
set('micrometerTracingBridgeOtelVersion', '1.6.3')
set('micrometerContextPropagationVersion', '1.2.1')
set('nettyResolverDnsNativeMacosVersion', '4.2.3.Final')
}

group = 'com.softeno'
version = '0.0.1-SNAPSHOT'

Expand All @@ -18,10 +39,6 @@ java {
}
}

ext {
set('springCloudVersion', '2025.0.1')
set('testcontainersVersion', '2.0.3')
}

configurations {
compileOnly {
Expand All @@ -35,86 +52,83 @@ repositories {

dependencies {
// spring project dependencies
implementation 'org.springframework.boot:spring-boot-starter-data-mongodb-reactive'
implementation 'org.springframework.boot:spring-boot-starter-webflux'
implementation 'com.fasterxml.jackson.module:jackson-module-kotlin'
implementation "org.springframework.boot:spring-boot-starter-data-mongodb-reactive:${springBootVersion}"
implementation "org.springframework.boot:spring-boot-starter-webflux:${springBootVersion}"
implementation "org.springframework.boot:spring-boot-starter-webclient:${springBootVersion}"
implementation "org.springframework.boot:spring-boot-starter-jackson:${springBootVersion}"
developmentOnly "org.springframework.boot:spring-boot-devtools:${springBootVersion}"
annotationProcessor "org.springframework.boot:spring-boot-configuration-processor:${springBootVersion}"
implementation 'io.projectreactor.kotlin:reactor-kotlin-extensions'
implementation 'org.jetbrains.kotlin:kotlin-reflect'
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-reactor'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-reactive'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-slf4j'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
implementation 'com.fasterxml.jackson.module:jackson-module-kotlin'

// test utils
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation "org.springframework.boot:spring-boot-starter-test:${springBootVersion}"
testImplementation "org.springframework.boot:spring-boot-starter-webflux-test:${springBootVersion}"
testImplementation "org.springframework.boot:spring-boot-webtestclient:${springBootVersion}"
testImplementation "org.springframework.boot:spring-boot-starter-jackson-test:${springBootVersion}"
testImplementation "io.mockk:mockk:${mockkVersion}"
testImplementation "com.ninja-squad:springmockk:${springmockkVersion}"
testRuntimeOnly "org.junit.platform:junit-platform-launcher:${junitPlatformLauncherVersion}"
testImplementation 'io.projectreactor:reactor-test'
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test'
testImplementation 'org.jetbrains.kotlin:kotlin-test-junit5'
testImplementation 'io.projectreactor:reactor-test'
testImplementation 'io.mockk:mockk:1.14.9'
testImplementation 'com.ninja-squad:springmockk:4.0.2'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

// security
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server'
implementation 'org.springframework.boot:spring-boot-starter-security'
testImplementation 'org.springframework.security:spring-security-test'
implementation "org.springframework.boot:spring-boot-starter-oauth2-client:${springBootVersion}"
implementation "org.springframework.boot:spring-boot-starter-oauth2-resource-server:${springBootVersion}"
implementation "org.springframework.boot:spring-boot-starter-security:${springBootVersion}"
testImplementation "org.springframework.security:spring-security-test:${springSecurityTestVersion}"

// testcontainers
testImplementation 'org.springframework.boot:spring-boot-testcontainers'
testImplementation 'org.testcontainers:mongodb'
testImplementation 'org.testcontainers:junit-jupiter'
testImplementation "org.springframework.boot:spring-boot-testcontainers:${springBootVersion}"
testImplementation "org.testcontainers:testcontainers-kafka:${testcontainersVersion}"
testImplementation "org.testcontainers:testcontainers-mongodb:${testcontainersVersion}"
testImplementation "org.testcontainers:testcontainers-junit-jupiter:${testcontainersVersion}"

// wiremock
testImplementation 'org.wiremock:wiremock-standalone:3.13.2'
testImplementation "org.wiremock:wiremock-standalone:${wiremockVersion}"

// guerydsl
implementation ('com.querydsl:querydsl-mongodb:5.1.0') {
implementation ("com.querydsl:querydsl-mongodb:${querydslMongodbVersion}") {
exclude group: 'org.mongodb', module: 'mongo-java-driver'
}
kapt group: 'com.querydsl', name: 'querydsl-apt', version: '5.1.0'

// rsocket
implementation 'org.springframework.boot:spring-boot-starter-rsocket'
kapt group: 'com.querydsl', name: 'querydsl-apt', version: "${querydslMongodbVersion}"

// graphql
implementation 'org.springframework.boot:spring-boot-starter-graphql'
testImplementation 'org.springframework.graphql:spring-graphql-test'
implementation "org.springframework.boot:spring-boot-starter-graphql:${springBootVersion}"
testImplementation "org.springframework.boot:spring-boot-starter-graphql-test:${springBootVersion}"

// kafka
implementation 'org.springframework.kafka:spring-kafka'
implementation 'io.projectreactor.kafka:reactor-kafka'
testImplementation 'org.springframework.kafka:spring-kafka-test'
implementation "org.springframework.boot:spring-boot-starter-kafka:${springBootVersion}"
testImplementation "org.springframework.kafka:spring-kafka-test:${springBootVersion}"

// circuit breaker
implementation 'org.springframework.cloud:spring-cloud-starter-circuitbreaker-reactor-resilience4j'
implementation "org.springframework.cloud:spring-cloud-starter-circuitbreaker-reactor-resilience4j:${springResilience4jVersion}"

// macOs ARM only
if (osdetector.classifier == "osx-aarch_64") {
runtimeOnly("io.netty:netty-resolver-dns-native-macos:4.2.3.Final:${osdetector.classifier}")
runtimeOnly("io.netty:netty-resolver-dns-native-macos:${nettyResolverDnsNativeMacosVersion}:${osdetector.classifier}")
}

// s3
implementation 'io.minio:minio:8.6.0'

// monitoring
implementation 'org.springframework.boot:spring-boot-starter-actuator'
runtimeOnly 'io.micrometer:micrometer-registry-prometheus'

// elk
implementation 'net.logstash.logback:logstash-logback-encoder:8.1'

// springdoc
implementation 'org.springdoc:springdoc-openapi-starter-common:2.8.15'
implementation 'org.springdoc:springdoc-openapi-starter-webflux-ui:2.8.15'
implementation "org.springdoc:springdoc-openapi-starter-common:${springdocVersion}"
implementation "org.springdoc:springdoc-openapi-starter-webflux-ui:${springdocVersion}"

// zipkin
implementation 'io.micrometer:micrometer-tracing-bridge-otel'
implementation 'io.opentelemetry:opentelemetry-exporter-zipkin'
implementation 'io.zipkin.reporter2:zipkin-sender-urlconnection'
// monitoring
runtimeOnly "io.micrometer:micrometer-registry-prometheus:${micrometerRegistryPrometheusVersion}"
implementation "org.springframework.boot:spring-boot-starter-actuator:${springBootVersion}"

// opentelemetry
implementation "org.springframework.boot:spring-boot-starter-opentelemetry:${springBootVersion}"
testImplementation "org.springframework.boot:spring-boot-starter-opentelemetry-test:${springBootVersion}"
implementation "io.opentelemetry.instrumentation:opentelemetry-logback-appender-1.0:${logbackAppenderVersion}"
implementation "io.micrometer:micrometer-tracing-bridge-otel:${micrometerTracingBridgeOtelVersion}"
implementation "io.micrometer:context-propagation:${micrometerContextPropagationVersion}"
}

dependencyManagement {
Expand Down
136 changes: 136 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
version: "3.7"
services:
kafka-broker:
image: bitnami/kafka:latest
container_name: kafka-broker
user: "${UID}"
hostname: kafka-broker
ports:
- "${IP:-0.0.0.0}:9094:9094"
- "${IP:-0.0.0.0}:9093:9093"
- "${IP:-0.0.0.0}:9092:9092"
environment:
KAFKA_CFG_LISTENERS: PLAINTEXT://:9092,CONTROLLER://:9093,EXTERNAL://:9094
KAFKA_CFG_ADVERTISED_LISTENERS: PLAINTEXT://kafka-broker:9092,EXTERNAL://kafka-broker:9094
KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP: CONTROLLER:PLAINTEXT,EXTERNAL:PLAINTEXT,PLAINTEXT:PLAINTEXT
ALLOW_PLAINTEXT_LISTENER: yes
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka-broker:9092,EXTERNAL://kafka-broker:9094
KAFKA_BROKER_ID: 0
KAFKA_CFG_NODE_ID: 0
KAFKA_CFG_PROCESS_ROLES: controller,broker
KAFKA_CFG_CONTROLLER_LISTENER_NAMES: CONTROLLER
KAFKA_CFG_CONTROLLER_QUORUM_VOTERS: 0@kafka-broker:9093
volumes:
- kafka-broker-data:/bitnami

init-kafka:
image: confluentinc/cp-kafka:latest
user: "${UID}"
depends_on:
- kafka-broker
entrypoint: [ '/bin/sh', '-c' ]
command: |
"
# blocks until kafka is reachable
kafka-topics --bootstrap-server kafka-broker:9092 --list
echo -e 'Creating kafka topics'

kafka-topics --bootstrap-server kafka-broker:9092 --create --if-not-exists --topic sample_topic_2 --replication-factor 1 --partitions 1
kafka-topics --bootstrap-server kafka-broker:9092 --create --if-not-exists --topic keycloak-events --replication-factor 1 --partitions 1
kafka-topics --bootstrap-server kafka-broker:9092 --create --if-not-exists --topic keycloak-admin-events --replication-factor 1 --partitions 1

echo -e 'Successfully created the following topics:'
kafka-topics --bootstrap-server kafka-broker:9092 --list
"

postgres-keycloak:
image: postgres:16.4
container_name: postgres-keycloak
user: "${UID}"
hostname: postgres-keycloak
volumes:
- postgres-data-keycloak:/var/lib/postgresql/data
environment:
POSTGRES_DB: keycloak
POSTGRES_USER: keycloak
POSTGRES_PASSWORD: keycloak
ports:
- "${IP:-0.0.0.0}:5433:5432"

keycloak:
image: xcodeassociated/keycloak-kafka:latest
user: "${UID}"
pull_policy: always
container_name: keycloak
hostname: keycloak
ports:
- "8090:8080"
depends_on:
- postgres-keycloak
- kafka-broker
environment:
KEYCLOAK_ADMIN: admin
KEYCLOAK_ADMIN_PASSWORD: admin
KAFKA_TOPIC: keycloak-events
KAFKA_CLIENT_ID: keycloak
KAFKA_BOOTSTRAP_SERVERS: kafka-broker:9092
KAFKA_EVENTS: "REGISTER,LOGIN,LOGOUT"
KAFKA_ADMIN_TOPIC: keycloak-admin-events
KC_DB_URL_HOST: postgres-keycloak
KC_DB_URL_DATABASE: keycloak
KC_DB_URL_PORT: 5432
KC_DB: postgres
KC_DB_USERNAME: keycloak
KC_DB_PASSWORD: keycloak
KC_DB_SCHEMA: public
KC_HOSTNAME_STRICT: false
KC_HTTP_ENABLED: true
command:
- start-dev
volumes:
- keycloak-data:/opt/keycloak/data/

mongo:
container_name: mongo_rs_primary
user: "${UID}"
hostname: mongo
image: mongo:6.0.4
ports:
- "${IP:-0.0.0.0}:27017:27017"
entrypoint: [ "/usr/bin/mongod", "--config", "/etc/mongod.conf", "--bind_ip_all", "--replSet", "rs0" ]
environment:
- MONGO_INITDB_ROOT_USERNAME=user
- MONGO_INITDB_ROOT_PASSWORD=password
- MONGO_INITDB_DATABASE=example_db
volumes:
- mongo-rs-primary-data:/data/db
- "./mongo-rs/config/mongodb/mongod.conf:/etc/mongod.conf"

volumes:
kafka-broker-data:
driver: local
driver_opts:
o: bind
type: none
device: ./kafka+keycloak/volumes/kafka-broker

postgres-data-keycloak:
driver: local
driver_opts:
o: bind
type: none
device: ./kafka+keycloak/volumes/postgres

keycloak-data:
driver: local
driver_opts:
o: bind
type: none
device: ./kafka+keycloak/volumes/keycloak

mongo-rs-primary-data:
driver: local
driver_opts:
o: bind
type: none
device: ./mongo-rs/volumes/mongodb
13 changes: 0 additions & 13 deletions http/async.http

This file was deleted.

Binary file removed http/data/picture.jpg
Binary file not shown.
20 changes: 0 additions & 20 deletions http/minio.http

This file was deleted.

5 changes: 0 additions & 5 deletions http/rsocket.sh

This file was deleted.

4 changes: 0 additions & 4 deletions http/server-events.http

This file was deleted.

21 changes: 21 additions & 0 deletions init_volumes.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/bin/bash

set -euo pipefail

DIRS=(
"kafka+keycloak/volumes/postgres"
"kafka+keycloak/volumes/keycloak"
"kafka+keycloak/volumes/kafka-broker"
"mongo-rs/volumes/mongodb"
)

for dir in "${DIRS[@]}"; do
if [ -d "$dir" ]; then
echo "Directory exists: $dir"
else
echo "Directory does not exist, creating: $dir"
mkdir -p "$dir"
fi
done

echo "done"
12 changes: 0 additions & 12 deletions notes/keycloak-admin-api/user-create.json

This file was deleted.

Loading