|
| 1 | +Project-specific development guidelines |
| 2 | + |
| 3 | +Scope |
| 4 | +- This document captures only information that is particular to this repository (sdk-java). It assumes familiarity with Gradle, JUnit 5, Docker, and multi-module builds. |
| 5 | + |
| 6 | +Build and configuration |
| 7 | +- JDK/Toolchains |
| 8 | + - Java toolchain: 17 for compile/run (auto-provisioned via org.gradle.toolchains.foojay-resolver-convention in settings.gradle.kts). CI also validates with Java 21. |
| 9 | + - You do NOT need a locally installed JDK 17 if your Gradle has toolchains enabled; Gradle will download it. |
| 10 | +- Gradle wrapper |
| 11 | + - Always use the provided wrapper: ./gradlew ... |
| 12 | + - Wrapper version: see gradle/wrapper/gradle-wrapper.properties (8.x). CI uses the wrapper as well. |
| 13 | +- Root build highlights (build.gradle.kts) |
| 14 | + - Versioning via Gradle Version Catalog: gradle/libs.versions.toml. The SDK version is libs.versions.restate. |
| 15 | + - Spotless is enforced across all projects (Google Java Format for Java, ktfmt for Kotlin, license headers from config/license-header). The check task depends on checkLicense from the license-report plugin. |
| 16 | + - Dokka is applied to most subprojects for Kotlin docs; aggregated Javadocs live in :sdk-aggregated-javadocs. |
| 17 | + - Publishing is wired via io.github.gradle-nexus.publish-plugin. Sonatype credentials must be provided as MAVEN_CENTRAL_USERNAME and MAVEN_CENTRAL_TOKEN environment variables when publishing. |
| 18 | +- Subprojects layout |
| 19 | + - Core libraries: common, client, client-kotlin, sdk-common, sdk-core, sdk-serde-*, sdk-request-identity, sdk-api*, sdk-http-vertx, sdk-lambda, sdk-spring-boot*, starters, meta modules (sdk-*-http/lambda), examples, test-services. |
| 20 | + - Java/Kotlin conventions are centralized in buildSrc: |
| 21 | + - java-conventions.gradle.kts: toolchain 17, JUnit Platform, Spotless with googleJavaFormat. |
| 22 | + - kotlin-conventions.gradle.kts: toolchain 17, JUnit Platform, Spotless with ktfmt, license headers. |
| 23 | + |
| 24 | +Testing |
| 25 | +- Frameworks and dependencies |
| 26 | + - JUnit 5 Platform is enabled globally (tasks.withType<Test> { useJUnitPlatform() }). |
| 27 | + - AssertJ is available broadly via the version catalog and commonly applied in modules. |
| 28 | + - Some integration tests use Testcontainers and the Restate runtime. The sdk-testing module provides a JUnit 5 extension and utilities (RestateTest, RestateRunner) to spin up Restate and auto-register in-process services. |
| 29 | +- Running tests |
| 30 | + - All modules: ./gradlew test |
| 31 | + - Single module: ./gradlew :common:test (replace :common with the desired module) |
| 32 | + - Single class or method: ./gradlew :common:test --tests 'dev.restate.common.SomethingTest' or --tests 'dev.restate.common.SomethingTest.methodName' |
| 33 | + - CI pulls the Restate Docker image explicitly and tests on Java 17 and 21 (see .github/workflows/tests.yml). Locally, if you run integration tests that leverage @RestateTest, ensure Docker is running; Testcontainers will pull the required image on demand. |
| 34 | +- Restate integration testing (sdk-testing) |
| 35 | + - Annotate your JUnit 5 test class with @RestateTest to bootstrap a Restate runtime in a container and register your services. |
| 36 | + - Example sketch: |
| 37 | + @RestateTest(containerImage = "ghcr.io/restatedev/restate:main") |
| 38 | + class CounterTest { /* fields annotated with @BindService, inject @RestateClient, etc. */ } |
| 39 | + - The default image is docker.io/restatedev/restate:latest; CI uses ghcr.io/restatedev/restate:main. You can override via containerImage or add env via environment() in the annotation. |
| 40 | + - Under the hood, RestateRunner uses Testcontainers and opens ports 8080 (ingress) and 9070 (admin). Docker must be available. |
| 41 | +- Adding tests |
| 42 | + - Java tests: place under src/test/java and name *Test.java (JUnit 5). Kotlin tests under src/test/kotlin. |
| 43 | + - Dependencies are already configured in most modules (e.g., common includes testImplementation(libs.junit.jupiter) and testImplementation(libs.assertj)). If adding tests to a module without these, add them in that module's build.gradle.kts. |
| 44 | + - For Restate-based tests, add a dependency on sdk-testing if not already present and use the annotations provided in dev.restate.sdk.testing.*. |
| 45 | +- Example test run (verified locally) |
| 46 | + - A simple JUnit 5 test was created temporarily in :common and executed via: |
| 47 | + ./gradlew :common:test --no-daemon |
| 48 | + - The build succeeded. The temporary test file was then removed to avoid polluting the repo. |
| 49 | + |
| 50 | +Development and debugging tips |
| 51 | +- Formatting and license headers |
| 52 | + - Run formatting checks: ./gradlew spotlessCheck |
| 53 | + - Apply formatting and headers: ./gradlew spotlessApply |
| 54 | + - Any newly added source files must include the license header from config/license-header (Spotless can apply it). |
| 55 | +- Dependency and license compliance |
| 56 | + - The check task depends on checkLicense, which uses allowed-licenses.json and normalizer config under config/. If you add new dependencies, ensure license reporting stays green. |
| 57 | +- Version management |
| 58 | + - Add/upgrade dependencies in gradle/libs.versions.toml. Prefer using the version catalog aliases (libs.*) in module build files. The overall SDK version is controlled by versions.restate. |
| 59 | +- Docs |
| 60 | + - Aggregated Javadoc: ./gradlew :sdk-aggregated-javadocs:javadoc |
| 61 | + - Kotlin docs: ./gradlew dokkaHtmlMultiModule |
| 62 | +- Docker-based tests |
| 63 | + - If integration tests fail locally while CI is green, verify Docker daemon availability and that the Restate image is accessible. You may pre-pull CI's image: docker pull ghcr.io/restatedev/restate:main |
| 64 | +- IDE setup |
| 65 | + - Use Gradle import. The toolchain resolver will fetch JDK 17 automatically. Ensure your IDE respects the Gradle JVM and uses language level 17 for compilation. |
| 66 | + |
| 67 | +Troubleshooting |
| 68 | +- Classpath conflicts when running Dokka: The root buildscript pins Jackson modules to 2.17.1 specifically to avoid Dokka bringing unshaded variants that break other plugins. Keep these overrides if upgrading Dokka. |
| 69 | +- If tests that rely on Testcontainers hang on startup, check network/firewall settings and whether Testcontainers can communicate with Docker. You can enable more verbose logs with TESTCONTAINERS_LOG_LEVEL=DEBUG. |
| 70 | + |
| 71 | +Housekeeping |
| 72 | +- Do not commit temporary tests used for local verification; keep the tree clean. |
| 73 | +- Before publishing or opening PRs, run: ./gradlew clean build |
0 commit comments