Setup Java Spring Boot

This documentation was generated with the assistance of AI. Please report any inaccuracies.

End-to-end bootstrap for a new (or older, partially set-up) Spring Boot service repository built on Domain-Driven Design and hexagonal (ports and adapters) architecture, realised as a multi-module build: a Maven reactor for Java, or for Kotlin either a Maven reactor or a Gradle Kotlin DSL multi-project build. It interviews the user once, resolves every Spring Boot version and dependency id against the live Spring Initializr API, records the answers — including the language, build tool, Kotlin version, whether the project is open source, its visibility, its CI choices, its Sonar mode, and whether it ships a Hilla frontend — in a springboot-stack.yml manifest, and then delegates all file generation to seven sub-skills (eight when frontend: hilla).

Purpose

iru-setup-java-springboot is the top-level entry point for starting a Spring Boot microservice from nothing, or for updating a repository that already has an older or partial setup. It announces which of the two it is doing ("from scratch" or "updating an existing repository", with an inventory of what is absent, present, or partial) and then lets each sub-skill ask Update / Keep as is / Replace per pre-existing artifact it owns. It is the interviewer and orchestrator of the Spring Boot family: no other skill in that family asks the user anything about the stack, because this one asks everything exactly once and writes the answers to a manifest the others read back.

Four things distinguish it from iru-setup-java-library-repository, the catalog’s other bootstrap orchestrator:

  • It imposes an architecture. The module layout (domain, application, infrastructure/, api/, boot, coverage), the direction dependencies may point, and the rule that every dependency version lives in exactly one place — the root pom.xml on Maven, gradle/libs.versions.toml on Gradle — are not options; they are what the skill exists to enforce.

  • It supports Java and Kotlin. Step 3 asks the implementation language (Java recommended unless the repository already has Kotlin) and, for Kotlin only, the build tool (Gradle Kotlin DSL recommended for a new repository, Maven for an existing Maven one). Java is always Maven; Java on Gradle and Groovy-DSL Gradle builds are rejected. Kotlin uses detekt/ktlint and Dokka instead of Checkstyle/PMD/SpotBugs and Javadoc, no Lombok or MapStruct, and a Kotlin version resolved from the one the chosen Boot version manages rather than from memory. The choices are recorded as project.language, project.buildTool and project.kotlinVersion, and every sub-skill branches on them.

  • It resolves the stack from a live API rather than from memory. Spring Boot renames starter artifacts across major versions (in Boot 4.x spring-boot-starter-web became spring-boot-starter-webmvc, the Testcontainers modules became testcontainers-<engine>, and every starter gained a spring-boot-starter-<x>-test companion), so the skill reads https://start.spring.io/metadata/client for the current version list and dependency catalogue, and fetches a reference pom.xml from https://start.spring.io/pom.xml for the exact artifact names. If that API is unreachable it stops rather than guessing.

  • It produces a deployable service, not a publishable library. There is no Maven Central publishing or GPG signing; instead there is a container image, OpenTofu infrastructure-as-code for AWS or Google Cloud, and deploy and undeploy workflows.

Java 21 is the enforced minimum, in maven.compiler.release, java.version, and a maven-enforcer-plugin requireJavaVersion rule on Maven, or the JDK toolchain on Gradle — even though Spring Initializr’s own default javaVersion is currently lower.

Plugin

Shipped by the iru-springboot plugin of the ai-catalog marketplace (install with /plugin install iru-springboot@ai-catalog; see Plugins).

Invocation

/iru-setup-java-springboot

Optionally with args (key/value lines) to pre-resolve some questions and skip the matching interview step, whether invoked directly or driven by another orchestrator such as Setup Repository:

mode: new
open-source: yes
sonar: cloud
sonar-organization: example-github
sonar-project-key: example_orders-service
sonar-host-url: https://sonarcloud.io
frontend: none
accessibility: enforce
visibility: public
ci: yes
ci-tests: full
pages: yes
rolling-deployments: yes
deployment-strategy: canary
advance: hybrid
on-existing: ask

Inputs

Most inputs are collected interactively; the table below also covers the keys accepted via args (Step 0), which pre-resolve the matching question instead of asking it.

Argument Required Description Default

args: language

No

java or kotlin. Pre-resolves Step 3’s language question (Java recommended unless Kotlin is already present in the repository). build-tool: gradle with no language implies Kotlin.

Asked via AskUserQuestion when not supplied

args: build-tool

No

maven or gradle. gradle is valid only with Kotlin (Gradle Kotlin DSL); Java is always Maven, and gradle with language: java is rejected with a question offering Kotlin + Gradle or Java + Maven. Asked only for Kotlin.

maven for Java; asked for Kotlin (Gradle recommended for a new repository)

args: mode

No

new or existing. mode from args wins; otherwise a root pom.xml, settings.gradle.kts or build.gradle.kts (or any other artifact this run owns) means existing. Step 0 prints a "Setup mode" statement (from scratch vs updating, with an absent/present/partial inventory) and forwards mode to every sub-skill. Only a genuinely incompatible root build (a Gradle build for a Java service, a Groovy-DSL Gradle build, a Maven/Gradle tool switch, or a single-module build with its own root sources) triggers a Stop / Continue anyway question, even when mode: existing was supplied.

Detected from the repository when not supplied

args: open-source

No

yes or no. Answers Step 3b’s open-source question, which drives the visibility and Sonar recommendations.

Asked via AskUserQuestion when not supplied

args: sonar (+ sonar-organization / sonar-project-key / sonar-host-url)

No

cloud, self-hosted, or none. SonarCloud is recommended only when the repository is public and open source; otherwise none is recommended (SonarCloud requires a paid plan for private projects), with self-hosted offered as the alternative. With ci: no, none is recommended since nothing would send reports automatically. The organization/project-key/host-URL keys apply only when sonar is cloud or self-hosted.

Asked via AskUserQuestion when not supplied

args: frontend

No

none or hilla. hilla adds Setup Java Spring Boot Hilla as an eighth sub-skill in Step 8, scaffolding a Vaadin/Hilla React frontend into the boot module.

none

args: accessibility

No

enforce, report, off, or none — the automated accessibility level of the frontend’s UI tests. Meaningful only with frontend: hilla (neither asked nor recorded otherwise); iru-setup-java-springboot-hilla writes it to .ui-quality.yml. The Hilla frontend follows the catalog’s UI contract (see Building user interfaces). none opts out entirely: no accessibility tooling is installed and the generated templates omit accessibility attributes (asked as "None — opt out entirely"). In mode: existing a prior level is never silently flipped. In mode: existing the choice is pre-selected from iru-explore’s `Accessibility: line.

Asked via AskUserQuestion when frontend: hilla and not supplied (Enforce recommended)

args: visibility

No

public, private, or internal. Otherwise detected with gh repo view --json visibility when a GitHub remote exists, else asked (Public recommended when open source). internal behaves like private for every cost decision; open source with a non-public repository triggers a contradiction warning.

Detected via gh, else asked

args: ci

No

yes or no. Whether to generate GitHub Actions workflows. Recommended for public repositories; for private ones the included-minutes budget (2,000/month on Free, 3,000 on Pro and Team, 50,000 on Enterprise Cloud; Linux 2-core $0.006/min) is shown. no makes Step 8 skip iru-setup-java-springboot-github-workflows entirely: no build.yml, deploy.yml, undeploy.yml, security.yml or .github/dependabot.yml.

Asked via AskUserQuestion when not supplied

args: ci-tests

No

unit (Surefire *Test only; Failsafe *IT stays local) or full (Surefire plus Failsafe against the Testcontainers stack). Only meaningful when ci: yes; unit is recommended for private/internal repositories.

Asked when ci: yes

args: pages

No

yes or no. Whether CI publishes the Antora site, Maven site and API docs to GitHub Pages. Only meaningful when ci: yes. Public repositories get yes without asking; private/internal ones are asked (No recommended: Pages needs Pro, Team or Enterprise Cloud and the site is public on the internet unless Enterprise Cloud access control is used).

Asked when ci: yes and not public

args: rolling-deployments (+ deployment-strategy / advance / steps / bake-minutes)

No

rolling-deployments is yes/no and only meaningful with ci: yes; deployment-strategy is rolling/blue-green/canary/linear and advance is auto/manual/hybrid (both only meaningful with rolling-deployments: yes). Optional steps (comma list of percentages) and bake-minutes override the Step 3c defaults (10,50,100 and 10). They pre-resolve Step 3c ("Support blue/green rolling deployments?"), which is opt-in: the default is today’s single-job deploy.yml. With ci: no the step is skipped, because deploy.yml drives the rollout and promote.yml advances it. Recorded as the manifest’s deploy.rolling block. Switch later with Spring Boot Rolling Deployments.

Asked when ci: yes and not supplied (No recommended for a small or dev-only service)

args: on-existing

No

ask, keep, update or replace, for scripted runs. Never asked as a question. Forwarded to sub-skills and to the Step 9 supporting-file skills only when it arrived via args; otherwise each sub-skill asks Update / Keep as is / Replace per artifact it owns. Also pre-answers Step 6’s question about an existing springboot-stack.yml.

ask

groupId, artifactId, version, base Java package, service description, developer name/email/organizationUrl

Yes

Free-text project-identity fields asked in plain conversation in Step 2. The artifactId becomes the prefix of every module’s own artifactId; the base package roots every module’s package (the same for Java and Kotlin).

version defaults to 0.0.1-SNAPSHOT

Spring Boot version

Yes

Confirmed via AskUserQuestion from the live Initializr catalogue, offering the current GA release as the recommendation. Pre-release entries are never offered as the default.

bootVersion.default from the API

Java version

Yes

Confirmed via AskUserQuestion, filtered to versions the Initializr accepts. Anything below 21 is refused.

21

Kotlin version

Derived (Kotlin only)

Not asked: resolved from the kotlin.version the chosen Spring Boot version manages (probed through Initializr or read from spring-boot-dependencies), never from Maven Central’s newest release. A user override is recorded but flagged as untested by Spring Boot, and Step 7 cross-checks it against the reference build.

The Boot-managed Kotlin version

Deployment platform

Yes

AskUserQuestion: Amazon Web Services or Google Cloud. Drives the OpenTofu layout, the dynamic-configuration recommendation, and the deploy workflows.

None — user must choose

Concurrency model

Yes

AskUserQuestion: non-reactive/blocking (Spring MVC), reactive (WebFlux/Netty), or both. Decides which starter every other technology resolves to, so it is settled before any technology choice.

Blocking is presented as the recommendation

Databases

No

Multi-select from MongoDB, Couchbase, relational (PostgreSQL or MariaDB), Elasticsearch, Neo4j, and Qdrant, each presented with the workload shape it suits. Every engine chosen also requires an index/migration tool (Flamingock, Liquibase and its MongoDB/Couchbase/Neo4j extensions, or Flyway).

None

Caches

No

Multi-select: Caffeine (local, per-node) and/or Redis (shared across replicas).

None

Spring Security

No

Yes/no, plus whether the service validates incoming JWTs (oauth2-resource-server), initiates login flows (oauth2-client), or both.

No

Spring Cloud Stream / Kafka

No

Yes/no, plus the directions needed (produce, consume, or both). AVRO is the message format, and an AsyncAPI specification alongside the schemas documents the topics carrying them.

No

REST server, gRPC server, GraphQL server

No

Yes/no each. All three are contract-first: specs live in apis/ and code is generated from them. GraphQL additionally needs a web transport starter alongside spring-boot-starter-graphql, which carries none of its own.

No

REST clients, gRPC clients, GraphQL clients

No

A name per downstream service; each becomes an infrastructure/clients/<name> module and an apis/ spec directory. One module per service, with a generator execution per protocol, when a service is reached over more than one.

None

API mocking tool

Only if a client was named

Which mock stands in for the downstream services in integration tests and local runs — Microcks whenever any gRPC or GraphQL client exists (it mocks all three protocols from the same contracts in one container), WireMock for a REST-only service (lighter, with a wiremock-grpc-extension available if gRPC arrives later). Recorded as stack.apiMock and acted on by Setup Java Spring Boot Testcontainers.

Microcks with gRPC or GraphQL, WireMock for REST-only

Logging, metrics, tracing

No

Asked individually; all three recommended. Metrics adds Prometheus/Grafana containers for local development.

Recommended on

Spring AI

No

Yes/no. If yes: the LLM providers (offered from the live catalogue), an optional vector store, and optional MCP server/client support. The user is warned first that this requires a paid provider subscription.

No

Dynamic configuration

Yes

AskUserQuestion: Kubernetes ConfigMaps/Secrets, AWS Secrets Manager, Spring Cloud Config Server, or none. The recommendation follows from the deployment platform.

Derived from the platform choice

Other Initializr dependencies

No

Anything else from the live catalogue, by id or name, with a warning that entries outside the groups above are typically less relevant and some actively conflict with the contract-first hexagonal shape.

None

Outputs

  • springboot-stack.yml at the repository root — the manifest recording the resolved identity, every technology choice, and also openSource, sonar (mode/organization/projectKey/hostUrl), frontend (none/hilla), visibility, ci (enabled/tests/pages), and the optional deploy.rolling block (enabled, strategy, advance, steps, bakeMinutes; absent means rolling deployments are disabled), with container image tags pinned. If a manifest already existed, the user chooses Update / Keep as is / Replace (or on-existing applies). Meant to be committed; read by every sub-skill and later by iru-update-java-springboot-documentation.

  • The full build (via iru-setup-java-springboot-pom): for Maven (Java, or Kotlin + Maven) a root reactor pom.xml plus one pom per module; for Kotlin + Gradle settings.gradle.kts, gradle/libs.versions.toml, the build-logic/ convention plugins, one build.gradle.kts per module and the Gradle wrapper. Kotlin builds also get a root detekt.yml.

  • The hexagonal source tree — ports, adapters, use cases, the @SpringBootApplication class, per-profile configuration, migration changelogs, and an ArchUnit test enforcing the dependency direction, as Java or Kotlin sources (via iru-setup-java-springboot-modules).

  • The apis/ contract tree, the OpenAPI/protobuf/GraphQL-SDL/AVRO generator wiring, and the AsyncAPI specification and documentation generators for messaging (via iru-setup-java-springboot-apis).

  • When frontend: hilla: the Vaadin/Hilla React frontend in the boot module — the Vaadin BOM/starters, the vaadin-maven-plugin execution, src/main/frontend/, Vitest with lcov coverage, and ESLint/Prettier (via iru-setup-java-springboot-hilla), together with .ui-quality.yml and the Playwright UI tests that capture .ui-screenshots/ across states, left-to-right/right-to-left and light/dark with axe-core checks at the chosen accessibility level.

  • compose.yaml and the Testcontainers integration-test harness (via iru-setup-java-springboot-testcontainers).

  • An infra/ OpenTofu configuration for the chosen cloud (via iru-setup-java-springboot-platform).

  • build.yml, deploy.yml, undeploy.yml, and security.yml GitHub Actions workflows plus .github/dependabot.yml (via iru-setup-java-springboot-github-workflows) — all skipped when ci: no. When rolling deployments are enabled, deploy.yml becomes a staged rollout and a promote.yml workflow is generated to advance, roll back or abort it (a rolling strategy keeps the single-job deploy.yml and generates no promote.yml); the OpenTofu configuration then also carries the rollout infrastructure and rollout_* outputs.

  • An Antora documentation site with Mermaid and Kroki and the full service page set (via iru-update-java-springboot-documentation).

  • Repository-level supporting files: .gitignore, README.md, CHANGELOG.md, checkstyle.xml (Java only; an existing one is kept), and optionally LICENSE. On Kotlin builds detekt.yml is expected from the pom sub-skill and reported as a gap if missing.

  • A final report with the setup mode and, per component, the action taken (created / updated / replaced / kept as is / skipped (ci: no)), consolidating the open-source/visibility/CI/Sonar/frontend choices, whether rolling deployments are enabled (strategy, advance mode, steps and bake minutes, whether promote.yml was generated, the rollout_* outputs and prerequisites, the cost note that blue/green temporarily doubles capacity, and that /iru-springboot-rolling-deployments enable|disable switches it later) (and, when frontend: hilla, the accessibility level, the .ui-quality.yml action, and what iru-setup-java-springboot-hilla reported back), every secret and variable that must be supplied out-of-band (the Sonar token only when sonar.mode is not none, plus GITLEAKS_LICENSE if a Pro key is used), every open gap, and the result of the three verification builds (Maven or Gradle, as run).

The generated files' bytes come from template files under templates/ (and, where a template needs variant-specific notes, reference/) in .claude/skills/iru-setup-java-springboot/; the skill reads only the files for the variant it resolved, not the whole set, which keeps its SKILL.md small.

Execution flow

flowchart TD A["Start /iru-setup-java-springboot"] --> B["Step 0: Parse args, announce setup mode\n(from scratch / update + inventory),\ndetect language and build tool,\nverify prerequisites"] B -- incompatible root build, user chooses stop --> STOP[Stop; report] B -- ok --> C["Step 1: Fetch Initializr metadata;\nconfirm Boot version and Java version (21 minimum)"] C -- API unreachable --> STOP2["Stop — never fall back\nto hardcoded versions"] C --> D["Step 2: Collect project identity;\ninfer repository info from git"] D --> E["Step 3: Language (Java/Kotlin), build tool\n(Kotlin only), Kotlin version, platform\n(AWS/GCP) and concurrency model"] E --> EB["Step 3b: Open source, visibility, CI\n(ci, ci-tests, pages), Sonar mode, frontend, accessibility"] EB -- "ci: yes" --> EC["Step 3c: Rolling deployments?\n(strategy, advance, steps, bake minutes)"] EB -- "ci: no, step skipped" --> F EC --> F["Step 4: Choose technologies\n(databases, caches, security, Kafka, servers,\nclients, observability, AI, dynamic config)"] F --> G["Step 5: Confirm the whole plan"] G -- corrections --> F G -- confirmed --> H["Step 6: Write springboot-stack.yml\n(Update / Keep as is / Replace if it exists)"] H --> I["Step 7: Fetch the reference build from Initializr\n(pom.xml, or starter build.gradle.kts)"] I -- invalid id / incompatible version --> F I --> J["Step 8: Delegate to sub-skills in order\n(8th when frontend: hilla; workflows skipped\nwhen ci: no), each via iru-isolated-skill-executor"] J -.->|"frontend: hilla only,\nafter APIs, before Testcontainers"| JH["iru-setup-java-springboot-hilla"] JH -.-> J J -- no usable root reactor pom after pom sub-skill --> STOP3["Stop — no reactor to attach to"] J --> K["Step 9: Supporting files\n(.gitignore, README, CHANGELOG, checkstyle.xml\nfor Java, detekt.yml check for Kotlin, LICENSE)"] K --> L["Step 10: Verify — Maven verify/test/verify or\nGradle build/test/integrationTest\n(via iru-gate-runner)"] L --> M["Step 11: Report, secrets table,\nand review warnings"]

Dependencies

Invokes

Each of the following is invoked via the iru-isolated-skill-executor agent rather than a direct Skill call, in this order — every sub-skill reads springboot-stack.yml and the filesystem directly, so only a short completion summary needs to come back:

  • Setup Java Spring Boot Poms — Step 8, first: the root reactor pom and every module pom. Generates the Maven reactor, or the Gradle KTS settings/catalog/convention plugins/wrapper for Kotlin + Gradle, reading the language and build tool from the manifest. Also receives the path to the Initializr reference build saved in Step 7. If this reports that the root pom was not written (or an existing non-reactor pom was kept), the whole run stops. Receives mode, and on-existing only when it arrived via args.

  • Setup Java Spring Boot Modules — Step 8: the source tree (Java or Kotlin), ports, adapters, profiles, and the ArchUnit test. Runs after the poms because it writes sources into modules rather than creating them.

  • Setup Java Spring Boot APIs — Step 8: the apis/ contracts, the code generators, and the AsyncAPI documentation generators. Runs after the modules because generated sources need a module to land in.

  • Setup Java Spring Boot Hilla — Step 8, sub-step 3b, only when the manifest’s frontend: hilla: the Vaadin/Hilla React frontend scaffolded into the boot module. Runs after the APIs (the boot module and API-generated code it may call must already exist) and before Testcontainers (the compose stack and CI docs job need to know a frontend toolchain now exists on disk).

  • Setup Java Spring Boot Testcontainers — Step 8: compose.yaml and the integration-test harness. Runs after the APIs (and Hilla, when present) because the compose stack must know whether a schema registry is needed.

  • Setup Java Spring Boot Platform — Step 8: the OpenTofu configuration. When deploy.rolling.enabled is true it also receives rolling: yes, deployment-strategy, advance, steps and bake-minutes (alongside mode/on-existing) and generates the rollout infrastructure; rolling: no or nothing when disabled.

  • Setup Java Spring Boot GitHub Workflows — Step 8: the build, deploy, undeploy and security workflows plus Dependabot, using Maven or ./gradlew commands and Javadoc or Dokka per the manifest. When rolling deployments are enabled it generates a staged deploy.yml and the promote.yml workflow (receiving the same rolling:/deployment-strategy:/advance:/steps:/bake-minutes: lines). Reads visibility, ci.tests and ci.pages from the manifest. Skipped entirely when ci.enabled: false. Runs late because it surveys what is actually on disk.

  • Update Java Spring Boot Documentation — Step 8, last: the Antora site and the service page set, derived from the finished codebase, with commands and samples matching the manifest’s build tool and language.

Rolling deployments can be switched on or off after the bootstrap with Spring Boot Rolling Deployments, which edits the manifest’s deploy.rolling block and re-runs the platform and workflows sub-skills.

In Step 9 it also invokes directly, if available, Setup Java Gitignore, Setup Readme, and Setup Changelog for the repository-level files the Spring Boot sub-skills don’t own (forwarding ci, pages and sonar to the README skill, and on-existing when it arrived via args). It additionally recommends — but does not invoke — Check License for license headers and Check Security for secret scanning, the latter specifically if an LLM API token may ever have been committed.

Invoked by

  • iru-isolated-skill-executor — spawned once per sub-skill in Step 8, so each sub-skill’s (seven, eight when frontend: hilla) template expansion, file reads, and build output don’t accumulate in this orchestrator’s context over a single bootstrap run.

  • iru-gate-runner — spawned for each of Step 10’s three verification runs (Maven or Gradle), so a multi-module build log never lands in this conversation.

Source

SKILL.md on GitHub — the file this page was generated from.