> ## Documentation Index
> Fetch the complete documentation index at: https://docs.reasonos.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Java & Kotlin

> Build JVM applications with auto-downloaded JDK and Kotlin toolchains and Maven Central dependencies.

`rbs` builds Java and Kotlin projects hermetically: it downloads an OpenJDK (Eclipse
Temurin) and, for Kotlin, the JetBrains compiler, resolves dependencies from Maven
Central, and produces self-contained launchers that bundle the JARs and the runtime.
No system JDK, no Gradle or Maven installation.

## Set up the toolchains

### Java

Declare the JDK in `WORKSPACE.rbs`:

```python theme={null}
load("@rbs//java/toolchain.rbs", "java_toolchain")

java_toolchain(name = "java", version = "17.0.11")
```

Supported versions are `17.0.11` (LTS, default) and `21.0.3`. Keep the toolchain name
`java` — the Java rules resolve it by that name. When cross-compiling, a host JDK is
downloaded as well so `javac` runs natively on the build machine.

### Kotlin

Kotlin compiles to JVM bytecode and needs a Java toolchain, so declare both — Java
first:

```python theme={null}
load("@rbs//java/toolchain.rbs", "java_toolchain")
load("@rbs//kotlin/toolchain.rbs", "kotlin_toolchain")

java_toolchain(name = "java", version = "17.0.11")
kotlin_toolchain(name = "kotlin", version = "2.0.21")
```

Supported Kotlin versions are `2.0.21` (default), `1.9.25`, `1.9.24`, and `1.9.23`.
Keep the toolchain names `java` and `kotlin` — the rules resolve them by those names.
Kotlin targets JVM 17 bytecode, and the Kotlin standard library is bundled into your
targets automatically.

## Declare Maven dependencies

External JVM dependencies come from Maven Central. Declare them in `WORKSPACE.rbs`
with `java_repository` (or the identical `kotlin_repository` alias):

```python theme={null}
load("@rbs//java/dependencies.rbs", "java_repository")

java_repository(
    name = "spring_boot_web",
    package = "org.springframework.boot:spring-boot-starter-web",
    version = "3.2.2",
)
```

Several at once, using `group:artifact:version` specs:

```python theme={null}
load("@rbs//java/dependencies.rbs", "java_repositories")

java_repositories(
    name = "deps",
    packages = [
        "com.google.guava:guava:32.1.2-jre",
        "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1",
    ],
)
```

`rbs` downloads the JAR and POM, follows the POM to resolve transitive dependencies
recursively, and records everything in the workspace lockfile for instant repeat
builds.

### Referencing dependencies in BUILD files

In `BUILD.rbs`, reference an external dependency with the `@external://` form: the
Maven coordinate with every `.`, `-`, and `:` replaced by `_`, followed by the
version:

```python theme={null}
deps = [
    "@external://org_springframework_boot_spring_boot_starter_web:3.2.2",
]
```

Local library targets are referenced the usual way: `:my_lib` within the package, or
`//path/to/pkg:my_lib` across packages.

### Kotlin convenience helpers

For common Kotlin libraries, `@rbs//kotlin/dependencies.rbs` provides one-line
helpers: `kotlin_stdlib()`, `kotlin_reflect()`, `kotlin_coroutines()`,
`kotlin_serialization()`, and `kotlin_all_dependencies()`. Default versions can be
pinned workspace-wide with `configure_kotlin_versions()`.

## Java rules

```python theme={null}
load("@rbs//java/rules.rbs", "java_binary", "java_library", "java_test", "java_lint")
```

### java\_library

Compiles sources into a JAR that other targets can depend on. External dependencies
propagate transitively to dependents.

```python theme={null}
java_library(
    name = "springboot_lib",
    srcs = [
        "src/main/java/com/example/springboot/Application.java",
        "src/main/java/com/example/springboot/GreetingService.java",
    ],
    deps = [
        "@external://org_springframework_boot_spring_boot_starter_web:3.2.2",
    ],
)
```

| Attribute      | Type        | Description                                                                                     |
| -------------- | ----------- | ----------------------------------------------------------------------------------------------- |
| `srcs`         | string list | Java source files.                                                                              |
| `deps`         | label list  | Compile-and-runtime dependencies — local targets or `@external://…` packages.                   |
| `runtime_deps` | label list  | Dependencies needed only at runtime (kept off the compile classpath, propagated to dependents). |
| `resources`    | string list | Resource files copied into the JAR.                                                             |

### java\_binary

Builds an executable application: compiles the sources, packages a JAR with a
`Main-Class` manifest, and emits a launcher that runs it on the bundled JDK.

```python theme={null}
java_binary(
    name = "app",
    srcs = ["src/main/java/com/example/springboot/Application.java"],
    main = "com.example.springboot.Application",
    resources = ["src/main/resources/application.properties"],
    deps = [
        "@external://org_springframework_boot_spring_boot_starter_web:3.2.2",
    ],
    javaopts = ["-Djava.awt.headless=true"],
)
```

| Attribute      | Type        | Description                                                                                                                       |
| -------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------- |
| `srcs`         | string list | Java source files.                                                                                                                |
| `deps`         | label list  | Compile-and-runtime dependencies.                                                                                                 |
| `runtime_deps` | label list  | Runtime-only dependencies.                                                                                                        |
| `main`         | string      | Fully-qualified main class. Defaults to the class name of the first source file — set it explicitly when your code uses packages. |
| `resources`    | string list | Resource files.                                                                                                                   |
| `javaopts`     | string list | JVM options passed at launch.                                                                                                     |

```bash theme={null}
rbs build //:app
rbs run :app
```

### java\_test

Defines a JUnit 5 test target. The JUnit 5 framework (Jupiter, Platform Launcher and
Console) and the JaCoCo coverage agent are added automatically — you only declare the
code under test. Tests run through the JUnit Platform Console Launcher, so `args`
takes its selectors.

```python theme={null}
java_test(
    name = "greeting_service_test",
    srcs = [
        "src/main/java/com/example/springboot/GreetingService.java",
        "src/test/java/com/example/springboot/GreetingServiceTest.java",
    ],
    deps = [
        "@external://org_springframework_boot_spring_boot_starter_web:3.2.2",
    ],
    args = ["--select-class=com.example.springboot.GreetingServiceTest"],
)
```

| Attribute               | Type        | Description                                                                                |
| ----------------------- | ----------- | ------------------------------------------------------------------------------------------ |
| `srcs`                  | string list | Test sources (and the sources under test, if not in a dep).                                |
| `deps`                  | label list  | Dependencies. JUnit 5 is auto-included.                                                    |
| `runtime_deps`          | label list  | Runtime-only dependencies.                                                                 |
| `test_main`             | string      | Test entry point (defaults to the JUnit Platform Console Launcher).                        |
| `args`                  | string list | Console Launcher arguments: `--select-class`, `--select-package`, `--include-classname`, … |
| `javaopts`              | string list | JVM options.                                                                               |
| `resources`             | string list | Resource files.                                                                            |
| `min_line_coverage`     | int         | Minimum line coverage %. The test fails below this threshold.                              |
| `min_branch_coverage`   | int         | Minimum branch coverage %. The test fails below this threshold.                            |
| `min_function_coverage` | int         | Minimum method coverage %. The test fails below this threshold.                            |

### java\_lint

A lightweight, dependency-free linter for basic hygiene (tabs, trailing whitespace).

```python theme={null}
java_lint(
    name = "app_lint",
    srcs = ["src/main/java/com/example/springboot/Application.java"],
)
```

| Attribute    | Type        | Description                               |
| ------------ | ----------- | ----------------------------------------- |
| `srcs`       | string list | Java files to check.                      |
| `max_issues` | int         | Stop after this many issues (default 50). |

## Kotlin rules

```python theme={null}
load("@rbs//kotlin/rules.rbs", "kotlin_binary", "kotlin_library", "kotlin_test", "kotlin_lint")
```

The Kotlin rules mirror the Java rules — same attributes, same dependency mechanism,
same JUnit 5 / JaCoCo auto-inclusion for tests. Kotlin and Java targets can depend on
each other freely since both produce JARs.

### kotlin\_library and kotlin\_binary

```python theme={null}
kotlin_library(
    name = "greeter",
    srcs = ["Greeter.kt"],
)

kotlin_binary(
    name = "hello",
    srcs = ["Main.kt"],
    deps = [":greeter"],
    main = "MainKt",
)

kotlin_binary(
    name = "async_hello",
    srcs = ["AsyncMain.kt"],
    deps = [
        ":greeter",
        "@external://org_jetbrains_kotlinx_kotlinx_coroutines_core:1.8.1",
    ],
    main = "AsyncMainKt",
)
```

`kotlin_library` takes `srcs`, `deps`, `runtime_deps`, and `resources`;
`kotlin_binary` adds `main` and `javaopts` — the same shapes as their Java
counterparts.

<Tip>
  Kotlin top-level `main` functions compile to a class named after the file: `Main.kt`
  becomes `MainKt`. If `main` is unset, the name is derived from the first source file;
  set it explicitly (fully qualified) when your code declares a package.
</Tip>

### kotlin\_test

Identical to `java_test` (including `test_main`, Console Launcher `args`, and the
`min_*_coverage` thresholds), with JUnit 5 and the JaCoCo agent auto-included:

```python theme={null}
kotlin_test(
    name = "greeter_test",
    srcs = ["Greeter.kt", "GreeterTest.kt"],
    args = ["--select-class=GreeterTest"],
)
```

### Linting Kotlin

Two options exist:

* `kotlin_lint` (from `kotlin/rules.rbs`) — fast built-in checks: whitespace, line
  length (`max_line_length`, default 120), wildcard imports, and a Spring Boot
  `open class` check. Attributes: `srcs`, `max_issues`, `max_line_length`.
* `kt_lint` (from `@rbs//kotlin/lint.rbs`) — runs real ktlint and/or detekt.
  Register the linters in `WORKSPACE.rbs` with `register_kotlin_linters()`, then:

```python theme={null}
load("@rbs//kotlin/lint.rbs", "kt_lint")

kt_lint(
    name = "lint",
    srcs = glob(["**/*.kt"]),
    ktlint = True,     # default
    detekt = False,    # default
    fix = False,       # auto-fix mode
)
```

## Testing

Enable the shared JVM test dependencies once in `WORKSPACE.rbs` — this pre-installs
JUnit 5 and the JaCoCo agent from Maven Central:

```python theme={null}
load("@rbs//java/toolchain.rbs", "java_toolchain", "java_test_deps")

java_toolchain(name = "java", version = "17.0.11")
java_test_deps()
```

Then run tests with the standard commands (they work identically for `java_test` and
`kotlin_test`):

```bash theme={null}
rbs test :greeting_service_test   # one target
rbs test //...                    # every test in the workspace
rbs test :greeting_service_test -w  # watch mode: re-run on file changes
rbs coverage :greeting_service_test # run with JaCoCo coverage
```

Coverage thresholds declared on the target are enforced by `rbs coverage` — a target
below its threshold fails.

## Protocol Buffers

Java and Kotlin both have proto bindings — `java_proto_library` (from
`@rbs//java/proto.rbs`) and `kotlin_proto_library` (from `@rbs//kotlin/proto.rbs`) —
which generate code from a `proto_library` and auto-include the protobuf runtime (and
gRPC libraries with `enable_grpc = True`). See
[Other languages](/languages/other-languages) for the shared proto toolchain setup and
a full example.

## Editor support

<Note>
  Java and Kotlin language support in the ReasonOS editor is provisioned automatically
  when JVM sources are detected in your workspace — no build-file configuration needed.
  See the editor language support documentation for details.
</Note>
