Skip to content

Latest commit

 

History

370 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Arc for Kotlin and Java

Arc.Kotlin is the JVM implementation of Arc — an opinionated CQRS application framework — for Kotlin and Java applications hosted by Spring Boot. Compile-time model-bound commands and queries, generated TypeScript clients, servlet hosting, optional persistence and Chronicle integrations, OpenAPI, and in-process test support: everything discovered by convention instead of hand-wired. It does not claim complete feature parity with Arc on .NET; the implemented and intentionally unsupported areas are tracked, row by row, with their evidence, in the parity reference.

Maven Central Kotlin Build Publish Discord License

Arc hosts application behavior, executes command and query pipelines over KSP-generated, reflection-free handlers, and generates TypeScript clients for them from the same compile-time metadata. Validation, authorization, identity, tenancy, observable queries, OpenAPI, and observability come from the same pipeline. Chronicle event sourcing, Spring Data JPA/MongoDB, and OpenAPI are optional integrations layered on top of a Core that has no dependency on any of them.

Arc.Kotlin is part of one deliberately simple Cratis ecosystem — AI-friendly by design, with free AI skills for building with the stack.

Start here

What Arc.Kotlin owns

Boundary Arc.Kotlin provides
Hosting Spring Boot servlet hosting: HTTP, Server-Sent Events, and optional WebSocket, registered by auto-configuration
Commands Model-bound @Command classes with regular, suspend, or Java CompletionStage handlers, validation, authorization, filters, and generated endpoints
Queries Model-bound @ReadModel static/companion queries, paging and sorting, GET and RFC QUERY, observable HTTP snapshots, SSE, and WebSocket
Validation Jakarta Bean Validation, reusable ConceptValidator/ModelValidator rules, shared fluent validators with generated client rules, and command/query pipelines
Identity and tenancy Pluggable AuthenticationHandler chains, identity details, role/policy authorization, and header/query/claim/subdomain/fixed/development tenant resolution
Generated contracts Strict-mode TypeScript command/query/model/enum proxies, optional .proxy.ts file suffix, validation metadata, identity details, and npm package/type mapping
Persistence integration Spring Data JPA and MongoDB read models, paging, observable snapshots, and optional Chronicle-backed event-sourced behavior
Evaluation and tooling OpenAPI 3.1, Micrometer observability, stable ARCKSP compile diagnostics, checked .api binary baselines, and in-process command/query/observable scenarios

Each row is a documented capability area, not a promise of raw-output compatibility with Arc .NET — see the parity reference for the exact, evidence-backed status of every specific behavior.

Arc.Kotlin does not require Chronicle

io.cratis:arc has no Chronicle dependency. Commands and queries can use Spring Data JPA, Spring Data MongoDB, or plain application services without an event log. Choose the persistence and integrations that fit each application.

The io.cratis:arc-chronicle-spring-boot-starter integration is optional and supplies event-sourced behavior when configured: returned events are staged and committed as part of the command pipeline, Chronicle read models resolve into command handlers, and reactors can execute commands as side effects. io.cratis:cratis is the preferred single dependency for an event-sourced application - it is a pure aggregator over Arc, its Spring Boot wiring, and this Chronicle integration. See the Chronicle integration guide.

Chronicle is Cratis's storage-agnostic event-sourcing database and runtime — MIT licensed and free to use. This repository consumes it through Chronicle.Kotlin, the JVM client and Spring Boot starter; see the Chronicle documentation for its own scope.

Relationship to Arc on .NET

Arc.Kotlin is a separate implementation of the same ideas as Arc, not a generated or mechanically mirrored port. The two frameworks share vocabulary — commands, queries, model binding, generated TypeScript proxies — but Arc.Kotlin is Kotlin-first and Java-first-class, targets Spring Boot exclusively, and makes JVM-native choices where the platforms differ (coroutines and CompletionStage instead of async/await, KSP compile-time diagnostics instead of Roslyn analyzers, Flow/Flow.Publisher instead of IObservable/ISubject).

Every claim about how closely a specific behavior matches Arc .NET is tracked with its supporting test, contract test, or sample in the parity reference. Treat any other comparison — in this README, in code comments, or in conversation — as informal unless it points at that document.

Start an Arc host

Add the plugin and the Spring Boot starter, then annotate a command:

// build.gradle.kts
plugins {
    id("io.cratis.arc") version "<version>"
    kotlin("plugin.spring") version "2.4.20"
    id("org.springframework.boot") version "4.1.1"
    id("io.spring.dependency-management") version "1.1.7"
}

cratisArc {
    moduleName.set("TaskApplication")
    dependencyVersion.set("<version>")
    endpoints {
        segmentsToSkip.set(2)   // drops the 2 "example.tasks" package segments from the route
    }
}

dependencies {
    implementation("io.cratis:arc-spring-boot-starter:<version>")
    implementation("org.springframework.boot:spring-boot-starter-webmvc")
}
# src/main/resources/application.properties
cratis.arc.endpoints.segments-to-skip-for-route=2
// src/main/kotlin/example/tasks/CreateTask.kt
package example.tasks

import io.cratis.arc.artifacts.Command
import io.cratis.arc.authorization.AllowAnonymous

data class TaskCreated(val title: String)

@Command
@AllowAnonymous
data class CreateTask(val title: String) {
    fun handle(): TaskCreated = TaskCreated(title)
}

An ordinary @SpringBootApplication main is the entire host. KSP generates a reflection-free handler and the route POST /api/create-task at build time; nothing is registered by hand. Continue with the Kotlin or Java tutorial for a complete command, query, and read model, and use GitHub Issues when observed behavior does not match the documentation.

Workspace and published packages

Project Published identity Responsibility
:Source io.cratis:arc Command, query, validation, authorization, authentication, identity, tenancy, introspection, result, JSON, and artifact contracts
:CodeGeneration:KSP io.cratis:arc-ksp Reflection-free command/query generation, manifests, concept and Jakarta validation metadata, stable ARCKSP diagnostics, and a checked ABI baseline
:GradlePlugin Gradle plugin io.cratis.arc (io.cratis:arc-gradle-plugin) JVM/KSP conventions, one-shot plus observable TypeScript proxy generation, and a checked ABI baseline
:Integrations:SpringBoot io.cratis:arc-spring-boot-starter Spring Boot auto-configuration and servlet HTTP, SSE, and optional WebSocket hosting
:Integrations:SpringDataJpa io.cratis:arc-spring-data-jpa Spring Data JPA paging, read-model, command transaction, and observable Flow adapters
:Integrations:SpringDataMongo io.cratis:arc-spring-data-mongodb Spring Data MongoDB paging, read-model, command transaction, and change-stream-backed observable Flow adapters
:Integrations:OpenApi io.cratis:arc-openapi-spring-boot-starter OpenAPI 3.1 generation and cached document routes
:Integrations:Observability io.cratis:arc-observability-spring-boot-starter Micrometer observations and optional OpenTelemetry correlation for Arc execution
:Integrations:Chronicle io.cratis:arc-chronicle-spring-boot-starter Optional tenant-aware Chronicle transactions, concurrency, read models, command side effects, and scenario support
:Integrations:Cratis io.cratis:cratis The one dependency for an event-sourced Cratis application - a pure aggregator over Arc, its Spring Boot wiring, and the Chronicle integration
:Testing io.cratis:arc-testing Reusable command, query, and observable-query scenarios with Kotlin and Java bridges; Chronicle adds an in-memory scenario extender
:ContractTests Unpublished Kotlin and Java generated-artifact, manifest, validation, and consumer contract fixtures
:Samples:Kotlin:SpringBoot Unpublished Runnable standalone Kotlin Spring Boot application
:Samples:Java:SpringBoot Unpublished Runnable standalone Java Spring Boot application
:Samples:Kotlin:ChronicleSpringBoot Unpublished Runnable tenant-aware Kotlin Arc + Chronicle application
:Samples:Java:ChronicleSpringBoot Unpublished Runnable tenant-aware ordinary-Java Arc + Chronicle application

Arc targets Spring Boot; Source (io.cratis:arc) is part of that product, not a separate host-independent Core product. Integrations depend inward on Source; samples consume public starters, and Chronicle remains optional. The compiled artifacts, metadata, and json packages — and every local type they transitively reference — must remain Spring-free; ./gradlew checkSpringBoundary enforces that boundary on every build. This is a compiler/build-tool boundary, not a promise of another host: see Non-Spring hosting for that explicit disposition.

Build

The build uses the checked-in Gradle 8.14.4 wrapper and requires JDK 17. Make a JDK 17 installation the active JAVA_HOME/PATH; no repository-specific absolute JDK path is required.

java -version
./gradlew build --no-configuration-cache

Run the documentation-only gate with:

./Documentation/verify-markdown.sh

Supply a release version with -Pversion=<version>; local builds default to 0.0.0-SNAPSHOT.

Running the samples

One command starts a backend, regenerates its TypeScript proxies, and, for the plain Arc samples, opens a React frontend against them. The Chronicle sample runs backend-only:

./Samples/run.sh                     # Kotlin, in memory, with the frontend on :5173
./Samples/run.sh --language java     # the same application written in Java
./Samples/run.sh --database mongodb  # store the task board in MongoDB instead
./Samples/run.sh --chronicle         # the Chronicle-backed sample, kernel and all
./Samples/run.sh --no-frontend       # backend only, for curl

The showcase mirrors the Arc .NET sample application: a live ticker, a message feed, all four query shapes from one read model, conditional queries, change streams, observable collections keyed by Int and by UUID, a protected read model with one deliberately anonymous query, and cross-cutting authorization through command and query filters. A toolbar switches the transport between WebSocket and Server-Sent Events, changes the connection count and transfer mode, and signs a user in and out — and every page keeps working, which is the point.

Both plain Arc hosts serve the routes the shared frontend consumes, so it runs against either unchanged. The Kotlin host additionally exposes runtime-contract endpoints, including calendar queries and batch task creation. ./Samples/run.sh --help lists every option; Samples/README.md explains what each page demonstrates. Anything a run starts — a database container, the Chronicle kernel, the frontend — is stopped again on exit.

Documentation map

Contributing

Arc.Kotlin is a framework/library repository, not an event-sourced application: changes to public APIs, KSP-generated output, the artifact manifest, and generated TypeScript proxies affect every downstream consumer and carry their own review discipline. Start with AGENTS.md and the project rules under .cratis/ai/rules/project, which cover branching, commit and pull-request conventions, where tests live, the manifest as a transport contract, and the exact gates a change needs to satisfy before merge.

Community and repository

Path Destination
Questions and discussion Cratis Discord
Bugs and feature requests GitHub Issues
Releases GitHub Releases
Documentation Documentation/
Arc on .NET github.com/Cratis/Arc · Docs
License LICENSE

The Cratis ecosystem

Arc.Kotlin is part of Cratis — free, MIT-licensed tools for building event-sourced and CQRS applications.

  • Chronicle — event-sourcing database and runtime. Orleans-based kernel, pluggable storage (MongoDB default; PostgreSQL, SQL Server, SQLite, in-memory), language-agnostic gRPC contracts. Docs
  • Chronicle clients — first-class .NET SDK, plus TypeScript, Kotlin/Java, and Elixir; Python coming soon (pre-alpha). AI agents connect through the Chronicle MCP server.
  • Arc — opinionated CQRS framework for ASP.NET Core with commands, queries, validation, authorization, and TypeScript proxy generation. Works without event sourcing. Docs
  • Arc.Kotlin (this repository) — the JVM implementation of Arc for Kotlin and Java applications hosted by Spring Boot.
  • Components — React components aligned with Arc patterns. Docs
  • CLI + Workbench — inspect and diagnose Chronicle from the terminal or the browser. Docs
  • Model-first layer (experimental) — Studio, Screenplay, Stage, Scene, Prologue
  • Supporting — Fundamentals, Specifications, Synopsis, Lens, Narrator, and free AI tooling (preview); Ensemble coming soon (pre-release)
  • Samples — runnable event sourcing and CQRS samples for the whole stack

Everything Cratis publishes today is MIT licensed and free to use.

Release notes and announcements: the Cratis blog.

About

Arc for Kotlin and Java applications hosted by Spring Boot

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages