Kora Project Dependencies — Module Catalog
Kora sub-skill — obey the kora-v2 meta rules on every task: R0 ground the workspace on Kora 2.0 refs before starting (framework source at tag
2.0.0.RC1+kora-examplesatmigration/2.0;kora-docsis 1.x only) · R1 read this sub-skill before writing code · R2 Kora 2.0 APIs only — no Spring/Micronaut/Quarkus, no Kora 1.x APIs, no invented annotations or config keys · R3 journal any incorrect Kora usage. Add comments/Javadoc only if asked.
Group: io.koraframework — except the experimental/ tree, which is io.koraframework.experimental
BOM: io.koraframework:kora-bom:2.0.0.RC1 — on Maven Central, the only 2.0.x there
JDK: bytecode floor 25 | Kotlin: 2.4.10 | KSP: 2.3.11 | Gradle: 9.5.1
Critical: always import the
kora-bomplatform, and never put a version on anio.koraframework:*artifact — the BOM does it. The one deliberate exception is the Kotlinksp("io.koraframework:symbol-processors:$koraVersion")line, because the BOM is not applied to thekspconfiguration.
Read this first when:
- Selecting which Kora modules to include in a build
- Setting up the BOM in
build.gradle/build.gradle.kts - Configuring annotation processors (Java) or KSP (Kotlin)
- Resolving "Required dependency not found" or transitive version conflicts
- Translating 1.x coordinates (
ru.tinkoff.kora:kora-parent,json-module,cache-redis, …) - Scaffolding a new project (see Project Generator)
NOT when: writing DI code (→ kora-di-compile), HTTP controllers
(→ kora-http-server), repositories
(→ kora-database-jdbc), or Kafka handlers
(→ kora-kafka-consumer).
Quick Start — BOM Setup
Pin the version in gradle.properties and resolve from Maven Central:
koraVersion=2.0.0.RC1
repositories {
mavenCentral()
}
2.0.0.RC1 is published on Central and is the only 2.0.x release of kora-bom there, so nothing
else is needed. 2.0.0-SNAPSHOT is the master development line — never pin it in a new project;
tracking it deliberately also requires
maven { url = "https://central.sonatype.com/repository/maven-snapshots" }.
Java (build.gradle) — the koraBom configuration
A platform on implementation does not reach Java's annotationProcessor classpath, so Java
declares a koraBom configuration and wires it with extendsFrom. Miss that and
annotation-processors fails to resolve.
plugins {
id "java"
id "application"
}
repositories {
mavenCentral()
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(25)
vendor = JvmVendorSpec.ADOPTIUM
}
}
configurations {
koraBom
annotationProcessor.extendsFrom(koraBom)
compileOnly.extendsFrom(koraBom)
implementation.extendsFrom(koraBom)
api.extendsFrom(koraBom)
testImplementation.extendsFrom(koraBom)
testAnnotationProcessor.extendsFrom(koraBom)
}
dependencies {
koraBom platform("io.koraframework:kora-bom:$koraVersion")
annotationProcessor "io.koraframework:annotation-processors"
implementation "io.koraframework:http-server-undertow"
implementation "io.koraframework:json-common"
implementation "io.koraframework:config-hocon"
implementation "io.koraframework:logging-logback"
testAnnotationProcessor "io.koraframework:annotation-processors"
testImplementation "io.koraframework:test-junit5"
}
Kotlin (build.gradle.kts) — BOM straight on implementation
Kotlin does not create a koraBom configuration and does not use extendsFrom. The
processor carries an explicit version instead.
plugins {
id("application")
kotlin("jvm") version "2.4.10"
id("com.google.devtools.ksp") version "2.3.11"
}
repositories {
mavenCentral()
}
dependencies {
implementation(platform("io.koraframework:kora-bom:${property("koraVersion")}"))
ksp("io.koraframework:symbol-processors:${property("koraVersion")}")
implementation("io.koraframework:http-server-undertow")
implementation("io.koraframework:json-common")
implementation("io.koraframework:config-hocon")
implementation("io.koraframework:logging-logback")
testImplementation("io.koraframework:test-junit5")
}
kotlin {
jvmToolchain {
languageVersion.set(JavaLanguageVersion.of(25))
vendor.set(JvmVendorSpec.ADOPTIUM)
}
}
Both shapes are deliberate. Do not port one into the other's language.
Depth: references/bom-usage-reference.md,
references/annotation-processors-reference.md
JDK — two separate requirements
- Toolchain (compiles your code): Kora 2.0 artifacts are built at JVM 25 and
kora-bomdeclaresjava.version = 25, so 25 is the floor. The reference examples use exactly 25. - The JVM running Gradle:
io.koraframework:openapi-generatorlands on the buildscript classpath, which Gradle resolves with its own JVM — the toolchain has no say. Below 25 the build dies during configuration withDependency requires at least JVM runtime version 25. This build uses a Java 21 JVM.Check withJAVA_HOME=<jdk> ./gradlew projects.
Which number: 25 is the hard floor; the migration guides recommend the latest GA feature
release instead of a frozen number — check https://openjdk.org/projects/jdk/ on the day and
re-derive. --enable-preview is not a Kora requirement; add it only if your own code uses a preview
API.
Project Generator
scripts/generate_project.py scaffolds a compile-ready 2.0 project (build script, @KoraApp, HOCON
config, sample controller/repository/Kafka handlers) for a chosen set of modules.
# List available module keys
python3 scripts/generate_project.py --list-modules
# Preview without writing anything
python3 scripts/generate_project.py --name my-service --package com.example \
--lang java --modules http-server,jdbc-postgres,metrics --dry-run
# Java REST API + PostgreSQL
python3 scripts/generate_project.py \
--name my-service --package com.example --lang java \
--modules http-server,jdbc-postgres,metrics
# Kotlin Kafka service
python3 scripts/generate_project.py \
--name kafka-service --package com.example --lang kotlin \
--modules kafka,metrics
Output is 2.0-native: io.koraframework coordinates, the kora-bom platform, the Java vs Kotlin BOM
shapes above, @KoraApp from io.koraframework.common.annotation, UndertowPublicHttpServerModule,
@Repository extends JdbcRepository with io.koraframework.database.jdbc.annotation.EntityJdbc, and
a config using httpServer.port / httpServer.system.port / jdbc { … } with telemetry explicitly
enabled. Re-running over an existing directory rewrites the generated files in place.
Details: scripts/generate_project.py
Core Modules (almost every service)
| Artifact | Module interface | Purpose |
|---|---|---|
io.koraframework:config-hocon |
HoconConfigModule |
HOCON config (or config-yaml → YamlConfigModule) |
io.koraframework:json-common |
JsonModule |
JSON (de)serialization for DTOs, HTTP, Kafka |
io.koraframework:logging-logback |
LogbackModule |
SLF4J via Logback |
io.koraframework:annotation-processors |
— | Java annotation processor (mandatory, Java) |
io.koraframework:symbol-processors |
— | KSP symbol processor (mandatory, Kotlin) |
Depth: references/core-modules-reference.md
Module Catalog
Every artifact below is published from the Kora 2.0 settings.gradle. The complete list — including
the per-domain processors and the internal, unpublished modules — is in
references/artifact-catalog.md. Do not invent a coordinate:
if it is not in that file, it does not exist.
HTTP
| Artifact | Module interface | Notes |
|---|---|---|
http-server-undertow |
UndertowPublicHttpServerModule |
Public server on httpServer; extends the system server module, so httpServer.system (metrics, readiness, liveness) comes with it |
http-client-ok |
OkHttpClientModule |
OkHttp transport |
http-client-jdk |
JdkHttpClientModule |
JDK HttpClient transport |
http-client-apache |
ApacheHttpClientModule |
Apache HttpClient 5 transport |
No separate auth artifact: server auth is HttpServerPrincipalExtractor (http-server-common),
client auth is HttpClientTokenProvider (http-client-common). There is no ProbesModule — probes
are system-server endpoints. http-client-async was removed with no replacement.
Skills: kora-http-server, kora-http-client, kora-http-server-auth, kora-http-client-auth
Database
| Artifact | Module interface | Notes |
|---|---|---|
database-jdbc |
JdbcDatabaseModule |
JDBC repositories; config section is jdbc (was db) |
database-cassandra |
CassandraDatabaseModule |
Ships org.apache.cassandra:java-driver-core |
database-flyway |
FlywayJdbcDatabaseModule |
Ships flyway-core only — add your dialect artifact |
database-liquibase |
LiquibaseJdbcDatabaseModule |
Liquibase migrations |
JDBC drivers are not in the BOM. database-r2dbc and database-vertx were removed —
repository contracts are synchronous, there is no reactive replacement.
Skills: kora-database-jdbc, kora-database-cassandra, kora-database-migration
Messaging
| Artifact | Module interface | Notes |
|---|---|---|
kafka |
KafkaModule |
One artifact for @KafkaPublisher and @KafkaListener |
jms |
JmsConsumerModule |
JMS consumers; the JMS provider is your own dependency |
There are no kafka-producer / kafka-consumer artifacts.
Skills: kora-kafka-producer, kora-kafka-consumer
Telemetry
| Artifact | Module interface | Notes |
|---|---|---|
micrometer-module |
MetricsModule |
Micrometer metrics; Prometheus scrape on the system server (/metrics) |
opentelemetry-tracing-exporter-grpc |
OpentelemetryGrpcExporterModule |
OTLP/gRPC trace exporter |
opentelemetry-tracing-exporter-http |
OpentelemetryHttpExporterModule |
OTLP/HTTP trace exporter |
Adding the artifact is not enough. telemetry.metrics.enabled and telemetry.logging.enabled
default to false in 2.0 — turn them on per component (httpServer { telemetry.metrics.enabled = true }).
Skills: kora-telemetry-metrics, kora-telemetry-tracing, kora-telemetry-logging
gRPC and SOAP
| Artifact | Module interface |
|---|---|
grpc-server |
GrpcServerModule |
grpc-client |
GrpcClientModule |
soap-client |
SoapClientModule |
gRPC test transports are your own dependency and must match the gRPC version the module brings
(1.83.1) or server construction fails with AbstractMethodError.
Skills: kora-grpc-server, kora-grpc-client, kora-soap-client
OpenAPI
| Artifact | Where | Notes |
|---|---|---|
openapi-generator |
buildscript { dependencies { classpath … } } |
Codegen for the org.openapi.generator plugin, generatorName = "kora". Forces the Gradle JVM to 25+ |
openapi-management |
implementation |
OpenApiManagementModule — spec + Swagger UI / Scalar |
Only four modes remain: java-client, java-server, kotlin-client, kotlin-server.
Skills: kora-openapi-generator-server, kora-openapi-generator-client, kora-openapi-management
AOP
| Artifact | Module interface | Annotations |
|---|---|---|
resilient-kora |
ResilientModule |
@CircuitBreakable, @Retryable, @Timeout, @RateLimited, @Fallback — all take a spec interface, not a string |
cache-caffeine |
CaffeineCacheModule |
@Cacheable, @CachePut, @CacheInvalidate, @CacheInvalidateAll (in-process) |
cache-redis-lettuce |
LettuceRedisCacheModule |
Same annotations over Lettuce/Redis |
cache-redis-common |
RedisCacheModule |
Transport-neutral — supplies no client; on its own the graph fails to build |
scheduling-jdk |
SchedulingJdkModule |
@ScheduleAtFixedRate, @ScheduleWithFixedDelay, @ScheduleOnce |
scheduling-quartz |
QuartzModule |
@ScheduleWithCron, @ScheduleWithTrigger |
validation-module |
ValidationModule |
@Valid, @Validate (Kora's own constraints, not Jakarta) |
cache-redis does not exist in 2.0. Resilience is Kora's own — no Resilience4j on the classpath.
@Log / @Mdc live in the logging modules, not a separate AOP artifact.
Skills: kora-aop-resilient, kora-aop-caching, kora-aop-scheduling-jdk, kora-aop-scheduling-quartz, kora-aop-validation, kora-aop-logging
S3 and Camunda
| Artifact | Group | Notes |
|---|---|---|
s3-client-aws |
io.koraframework |
AwsS3ClientModule — AWS SDK wrapper. No @S3, no models |
s3-client-kora |
io.koraframework.experimental |
KoraS3ClientModule + the declarative @S3 client |
camunda-engine-bpmn |
io.koraframework.experimental |
Camunda 7 embedded BPMN |
camunda-rest-undertow |
io.koraframework.experimental |
Camunda 7 REST API |
camunda-zeebe-worker |
io.koraframework.experimental |
Camunda 8 Zeebe worker (ZeebeWorkerModule) |
The S3 group split is the classic trap: s3-client-aws is not experimental, s3-client-kora
is. They are alternatives, not a pair, and each needs an HTTP client transport module alongside it.
s3-client-minio does not exist in 2.0.
Skill: kora-s3
Mapping
MapStruct and Konvert discovery already ships inside the aggregate processors
(mapstruct-java-extension in annotation-processors; mapstruct-ksp-extension and
konvert-ksp-extension in symbol-processors). Do not list them yourself — add only the third-party
halves (org.mapstruct:mapstruct + its processor, or io.mcarle:konvert-api + ksp("io.mcarle:konvert")).
mapstruct-extension is a 1.x name and does not exist. Kotlin needs no kapt in 2.0.
Skill: kora-mapstruct
Testing
| Artifact | Purpose |
|---|---|
test-junit5 |
@KoraAppTest JUnit 5 extension; brings JUnit 5 |
Mockito, MockK and kotlin-reflect are compileOnly in test-junit5 — add your own. Black-box
tests are test-junit5 plus Testcontainers; there is no test-blackbox artifact.
Skills: kora-testing-junit-java, kora-testing-junit-kotlin, kora-testing-blackbox
Coming from Kora 1.x
| 1.x | 2.0 |
|---|---|
ru.tinkoff.kora:* |
io.koraframework:* |
ru.tinkoff.kora.experimental:* |
io.koraframework.experimental:* — except s3-client-aws, now plain io.koraframework |
kora-parent |
kora-bom |
json-module |
json-common |
cache-redis |
cache-redis-lettuce |
mapstruct-extension |
mapstruct-java-extension / mapstruct-ksp-extension (already inside the aggregate processors) |
http-client-async |
removed — use http-client-jdk / -ok / -apache |
database-r2dbc, database-vertx |
removed — no replacement |
s3-client-minio |
removed — s3-client-aws or s3-client-kora |
UndertowHttpServerModule |
UndertowPublicHttpServerModule |
Those artifacts still have directories on Maven Central, along with other 1.x/alpha leftovers
(declarative-logging-annotation-processor, declarative-logging-symbol-processor,
scheduling-ksp, experimental/s3-client). The listing is cumulative; none of them is in the
2.0.0.RC1 BOM.
Worse, io.koraframework:kora-parent and io.koraframework:cache-redis are published at
2.0.0.alpha5/2.0.0.alpha6. A blind ru.tinkoff.kora → io.koraframework replace that keeps the
old artifact id can therefore resolve — silently pinning a pre-release BOM instead of failing.
Rename the artifact, not just the group, and never take "the build resolved" as proof.
A rename is not the whole migration: config keys moved too (db → jdbc,
publicApiHttpPort → port, privateApiHttpPort → system.port) and telemetry now defaults to
off. See references/core-modules-reference.md.
Externally Versioned Dependencies (not in the BOM)
Pin these yourself. Every one of them fails at runtime, not at compile time.
dependencies {
// JDBC driver — database-jdbc ships Hikari, never a driver
implementation "org.postgresql:postgresql:42.7.7"
// Flyway dialect — database-flyway ships flyway-core only
implementation "org.flywaydb:flyway-database-postgresql:13.1.0"
testImplementation "io.koraframework:test-junit5"
testImplementation "org.testcontainers:junit-jupiter:1.21.4"
// test-junit5 declares these compileOnly — bring your own, new enough for Java 25 Byte Buddy
testImplementation "org.mockito:mockito-core:5.23.0" // Java
testImplementation "io.mockk:mockk:1.14.11" // Kotlin
// gRPC test transports must match the gRPC version grpc-server brings
testImplementation "io.grpc:grpc-inprocess:1.83.1"
}
Two coordinate moves that silently orphan a pinned version: Jackson is now
tools.jackson.core (Jackson 3), and the Cassandra driver is
org.apache.cassandra:java-driver-core.
Testcontainers 2.x renamed its modules — postgresql → testcontainers-postgresql,
kafka → testcontainers-kafka, cassandra → testcontainers-cassandra. Kora does not constrain
Testcontainers; the reference examples stay on 1.21.4 with the old names. A 2.x version with 1.x
module names does not resolve.
Depth: references/compatibility-matrix.md
Typical Combinations
REST API (HTTP server + JSON + metrics)
dependencies {
koraBom platform("io.koraframework:kora-bom:$koraVersion")
annotationProcessor "io.koraframework:annotation-processors"
implementation "io.koraframework:http-server-undertow"
implementation "io.koraframework:json-common"
implementation "io.koraframework:micrometer-module"
implementation "io.koraframework:logging-logback"
implementation "io.koraframework:config-hocon"
}
JDBC service (PostgreSQL + Flyway)
dependencies {
koraBom platform("io.koraframework:kora-bom:$koraVersion")
annotationProcessor "io.koraframework:annotation-processors"
implementation "io.koraframework:database-jdbc"
implementation "io.koraframework:database-flyway"
implementation "org.postgresql:postgresql:42.7.7"
implementation "org.flywaydb:flyway-database-postgresql:13.1.0"
implementation "io.koraframework:logging-logback"
implementation "io.koraframework:config-hocon"
testImplementation "io.koraframework:test-junit5"
}
Kafka service (JSON)
dependencies {
koraBom platform("io.koraframework:kora-bom:$koraVersion")
annotationProcessor "io.koraframework:annotation-processors"
implementation "io.koraframework:kafka"
implementation "io.koraframework:json-common"
implementation "io.koraframework:logging-logback"
implementation "io.koraframework:config-hocon"
}
Full multi-module example: assets/build.gradle-full.template
Common Pitfalls
| Symptom | Cause | Fix |
|---|---|---|
annotation-processors fails to resolve (Java) |
koraBom not extendsFrom annotationProcessor |
Wire the configuration — a platform on implementation does not reach the processor classpath |
symbol-processors fails to resolve (Kotlin) |
Versionless ksp("io.koraframework:symbol-processors") |
The BOM does not apply to ksp — give the dependency an explicit version |
Cannot resolve external dependency … because no repositories are defined |
The build has no repositories block |
Add repositories { mavenCentral() } — RC1 resolves from Central alone |
Could not find io.koraframework:…:2.0.0-SNAPSHOT |
Snapshot line without the snapshot repo | Pin 2.0.0.RC1 instead, or add maven { url = "https://central.sonatype.com/repository/maven-snapshots" } |
"cache-redis/kora-parent must still work — I can see the directory on Maven Central" |
The Central listing is cumulative and full of 1.x/alpha leftovers | Check what kora-bom:2.0.0.RC1 constrains, or the artifact's maven-metadata.xml, not the directory |
| A group-only rename builds fine, but modules resolve oddly | io.koraframework:kora-parent resolves at 2.0.0.alpha5/alpha6 — the build silently pinned a pre-release BOM |
Rename the artifact too: kora-bom. "It resolved" is not evidence the coordinate is right |
Could not find ru.tinkoff.kora:… |
1.x coordinate | See Coming from Kora 1.x |
Could not find io.koraframework:json-module / cache-redis / kora-parent |
Artifact does not exist in 2.0 | json-common / cache-redis-lettuce / kora-bom |
Could not find io.koraframework.experimental:s3-client-aws |
Wrong group | s3-client-aws is plain io.koraframework; only s3-client-kora is experimental |
Dependency requires at least JVM runtime version 25 at configuration time |
Gradle itself runs on an older JDK | Run Gradle on JDK 25+; the toolchain alone does not fix it |
FlywayException: Unsupported Database: PostgreSQL 16.x |
database-flyway ships flyway-core only |
Add org.flywaydb:flyway-database-postgresql at the resolved flyway-core version |
AbstractMethodError … buildClientTransportServers in tests |
gRPC test transport pinned to an older version | Align grpc-inprocess/grpc-netty with 1.83.1 |
Java 25 (69) is not supported by the current version of Byte Buddy |
Old Mockito/MockK; often hidden inside Application graph failed to initialize with N errors |
Raise mockito-core / mockk; pin mockito-core next to mockito-kotlin |
Could not find org.testcontainers:postgresql |
Testcontainers 2.x with 1.x module names | testcontainers-postgresql etc., or stay on 1.21.4 |
Hundreds of package ru.tinkoff.kora… does not exist in build/generated/ |
Stale generator output after the group rename | ./gradlew clean then build with --no-build-cache; never edit generated code |
Metrics missing though micrometer-module is present |
telemetry.metrics.enabled defaults to false |
Enable it per component |
| Service starts green but probes/metrics/LB hit nothing | Stale publicApiHttpPort/privateApiHttpPort — unrecognised keys are ignored, so each server uses its own default (8080 public, 8085 system) |
httpServer.port / httpServer.system.port. SystemHttpServerConfig overrides port() to 8085, so the servers do not collide on 8080 |
| Module added but nothing wired | *Module interface not extended |
Extend it on the @KoraApp interface |
KspTask no longer compiles |
KSP 2 removed the type | tasks.matching { it.name.startsWith("ksp") } |
References
| Document | Description |
|---|---|
references/artifact-catalog.md |
Every published artifact, by group, plus renames/removals |
references/bom-usage-reference.md |
BOM setup for Java and Kotlin, multi-module, version verification |
references/annotation-processors-reference.md |
Processors + KSP 2, aggregate vs per-domain, generated-code locations |
references/compatibility-matrix.md |
JDK derivation, Kotlin/KSP/Gradle, third-party and externally-versioned deps |
references/core-modules-reference.md |
Core modules, 2.0 config keys, a minimal @KoraApp |
See Also
kora-project-setup-java— Java Gradle scaffoldingkora-project-setup-kotlin— Kotlin Gradle scaffoldingkora-di-compile— compile-time DI (@KoraApp,@Component,@Module)kora-config-hocon— typed@ConfigSourceconfiguration