Setup Java Spring Boot Modules
| This documentation was generated with the assistance of AI. Please report any inaccuracies. |
Turns a reactor of empty modules into a Spring Boot service skeleton that compiles, starts, and demonstrates the hexagonal pattern well enough that the first real feature has an obvious shape to follow.
Purpose
The language and build tool come from springboot-stack.yml: project.language (java or kotlin, absent means java) and project.buildTool (maven or gradle, absent means maven; gradle only appears with Kotlin). The Java path is unchanged. With Kotlin the same layering, ports, configuration files and migrations are written, but into src/main/kotlin and src/test/kotlin, with Kotlin idioms: data classes and @JvmInline value class for value objects, a regular class for the aggregate root, hand-written extension-function mappers instead of MapStruct (no Lombok, no kapt/KSP), constructor-bound @ConfigurationProperties data classes with @RefreshScope @Validated, use cases wired as @Bean`s in `boot/config so application keeps no Spring dependency, a runApplication entry point, suspend fun/Flow for reactive stacks, KDoc, and JUnit 5 with MockK. When iru-kotlin-springboot-code-one-task is installed, its reference/ files are treated as the authoritative rules for the generated Kotlin.
iru-setup-java-springboot-modules writes one worked example per adapter kind, not a set of empty files: a
single aggregate, its repository port, one adapter implementing that port against the chosen database, one use
case, one endpoint. The reasoning is explicit in the skill — a developer’s first task is to rename or delete the
example, and both are easier than inventing the layering from an empty tree.
The module it treats as load-bearing is domain. Because domain is the one module every other module may depend
on, every capability an outer module provides is declared there as an interface (a port): repository ports, an
event publisher, one client port per downstream service, a metrics publisher, a configuration provider, and a
small domain-exception hierarchy that the API modules map to HTTP or gRPC status codes. domain carries no Spring
annotations at all — the enforcer rule from iru-setup-java-springboot-pom makes that a build failure.
It also writes the runtime configuration: application.yml plus local/dev/prod profiles, with structured JSON
logging for deployed profiles, actuator probes and Prometheus exposure on a separate management port, graceful
shutdown, and virtual threads enabled when the stack is blocking on Java 21+. Every deployed profile uses
placeholders only — no credential, host, or token is written into a committed file, and no default that would
accidentally work against something real.
Finally it writes an ArchUnit test in `boot’s test sources. The enforcer rules catch violations at module granularity; ArchUnit catches them at package granularity, which is where they actually creep in.
The skill announces whether the run is scaffolding from scratch or updating an existing source tree (listing the
modules that already have sources). Hand-written .java code is never overwritten, whatever the options say. For
each generated artifact it owns that already exists (the application*.yml profile files, the ArchUnit test, each
engine’s migration directory, the worked example) it warns and asks Update (Recommended) / Keep as is /
Replace unless on-existing pre-answers. Replace is only offered for wholly generated files (profile YAML, the
ArchUnit test), never for a class containing hand-written logic.
Plugin
Shipped by the iru-springboot plugin of the ai-catalog marketplace (install with /plugin install iru-springboot@ai-catalog; see Plugins).
Inputs
| Argument | Required | Description | Default |
|---|---|---|---|
|
No |
|
|
|
No |
|
None |
|
No |
|
|
An existing build |
Yes |
Maven: a root |
None — a precondition, not a default |
Existing hand-written sources |
No |
Any |
Skip and report |
Outputs
-
The package layout under
src/main/java(orsrc/main/kotlinfor Kotlin),src/main/resources, and the matching test source root for every module. -
domain— the aggregate, value objects, every port interface with Javadoc describing its contract, and the domain-exception hierarchy. -
application— one use case class per use case, with a Mockito unit test that mocks every port. -
infrastructure/database/<engine>— persistence entity, Spring Data repository, MapStruct mapper (Kotlin: extension-function mappers), the port adapter, the migration/changelog directory for that engine’s tooling (Flamingock change class, Liquibase changelog including apgvectorextension changeset where relevant, or a Flyway script), and an integration test. -
infrastructure/configuration— validated@ConfigurationPropertiesbeans annotated@RefreshScope, the configuration port adapter, and the wiring for the dynamic-configuration mechanism the manifest names. -
infrastructure/clients/<name>— a port adapter over the generated client, with MapStruct mapping, transport failures translated to domain exceptions, explicit connect/read timeouts, and its base URL bound fromclients.<name>.base-urlwith no default in any deployed profile. That binding is what lets the integration harness redirect the client to the compose stack’s API mock; an adapter that hardcodes a host cannot be tested against anything and will reach a real downstream service from CI. -
infrastructure/producersandapi/consumers— the Kafka publisher adapter and consumer beans, AVRO mappers, bindings, consumer group, and a dead-letter topic with a bounded retry policy. Everydestinationandgroupchosen here is reported so it can be reconciled with the AsyncAPI specification Setup Java Spring Boot APIs writes inapis/messaging/: a binding whose topic appears as no AsyncAPI channel is a topic nobody outside the repository can discover. -
infrastructure/metrics— the metrics port implemented over Micrometer, with a constants class (Kotlin: anobjectof `const val`s) for every metric name and tag key, and bounded tag cardinality documented in the Javadoc. -
api/graphql-server—@Controllerclasses implementing the generated resolver interfaces, mappers, aDataFetcherExceptionResolver(GraphQL answers200 OKwith anerrorsarray, so exception mapping is entirely the application’s job), and query depth/complexity limits — without which one deeply nested query can exhaust the service. The worked field resolver is written batched (@BatchMapping/DataLoader) rather than N+1, because the scaffolded shape is the one that gets copied. -
api/rest-server/api/grpc-server— controllers or services implementing the generated interfaces, mappers, the exception-to-status advice (RFC 9457ProblemDetailfor REST), and the security filter chain if enabled. -
boot— the@SpringBootApplicationclass (Kotlin: plusUseCaseConfigurationdeclaring the use cases as@Bean`s), `application.ymland the three profile files, composition-root@Configuration, a context smoke test, and the ArchUnit architecture test. -
A report stating the language and build tool used, whether the tree was scaffolded from scratch or updated, the action taken per pre-existing artifact (created / updated / replaced / kept as is) with any gaps left in kept files, plus the configuration-property list, the metrics list, and the exception-to-status mapping formatted for pasting into the documentation tables.
Execution flow
mvn verify (or ./gradlew integrationTest) is deliberately not run here: the *IT tests need the Testcontainers harness that
Setup Java Spring Boot Testcontainers sets up in the next step, so integration tests failing
at this point is expected rather than a defect.
Dependencies
Invokes
None. It reads springboot-stack.yml and the existing poms or Gradle build files, and writes sources and configuration. For Kotlin it reads the reference/ files of iru-kotlin-springboot-code-one-task as style rules when that skill is installed, but does not invoke it.
Invoked by
-
Setup Java Spring Boot — Step 8, module tree and source skeleton, via the
iru-isolated-skill-executoragent.
Also runs standalone (/iru-setup-java-springboot-modules) against an existing reactor.
Related agents
-
iru-gate-runner— spawned for Step 12’smvn clean testor./gradlew clean test, so a multi-module compile-and-test log is summarized rather than dumped into the caller’s context.
Source
SKILL.md on GitHub — the file this page was generated from.