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
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.
Inputs
| Argument | Required | Description | Default |
|---|---|---|---|
|
No |
|
|
An existing reactor |
Yes |
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,src/main/resources, andsrc/test/javafor 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, 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 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,application.ymland the three profile files, composition-root@Configuration, a context smoke test, and the ArchUnit architecture test. -
A report that includes the configuration-property list, the metrics list, and the exception-to-status mapping formatted for pasting into the documentation tables.
Execution flow
mvn verify 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, and writes sources and configuration.
Invoked by
-
Setup Java Spring Boot — Step 8, second of seven sub-skills, via the
iru-isolated-skill-executoragent. Runs after Setup Java Spring Boot Poms because it needs modules to write into, and before Setup Java Spring Boot APIs, whose generated code the adapters written here consume.
Also runs standalone (/iru-setup-java-springboot-modules) against an existing reactor.
Related agents
-
iru-gate-runner— spawned for Step 12’smvn 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.