Skip to content

Commit 8f4c8d3

Browse files
jeffjensenclaude
andcommitted
feat(arch): Add appName property and expand Spring/testing wiring
Implements the java-service-archetype Needed Changes spec: every generated project now needs a human-readable name driving its class/property/prose naming, richer SQL-logging and Spring Boot Admin observability, and shared REST/GraphQL acceptance-test infrastructure, instead of hand-rolling these per project after generation. * Add required appName property (no default, prompted first) with class-name, property-value, and prose transform rules * Generate package-info.java only under src/main/java (Java rejects two files compiled for the same package); acceptance-tests' lone one now describes the functional tests themselves * Add datasource-proxy-spring-boot-starter (SQL logging) to database integration modules and acceptance-tests; add spring-boot-admin-starter-client and make app's web/actuator stack unconditional regardless of presentationTypes * Generate shared RestAcceptanceTestBase/GraphQlAcceptanceTestBase in common-testing, and per-project AppRestAcceptanceTestBase/ AppGraphQlAcceptanceTestBase, {appName}AcceptanceTestConfiguration, and logback-spring.xml in acceptance-tests * Add appName-derived <name>/<description> and dependency-comment labels (spring/this app/sql logging) across parent, app, service, domain-service, domain-rest/graphql, presentation-graphql, and common-testing poms * common-testing now depends on every domain module; no domain module depends on common-testing, keeping the reactor acyclic * Update all 16 archetype ITs, the interactive test scripts, and the site docs (requirements/modules/usage/index/building.adoc) plus CLAUDE.md to match Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P76PdSVUG6SNJeXcGPrhyn
1 parent 22a7eed commit 8f4c8d3

41 files changed

Lines changed: 1378 additions & 404 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/main/resources/META-INF/archetype-post-generate.groovy

Lines changed: 408 additions & 97 deletions
Large diffs are not rendered by default.

src/main/resources/META-INF/maven/archetype-metadata.xml

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@
1212
1313
PROMPT GUIDE
1414
============
15+
appName
16+
Brief, human-readable application name: capitalized words separated by spaces,
17+
e.g. "Order Service". Drives generated class names (spaces removed, e.g.
18+
OrderService), generated property values (spaces removed and lowercased, e.g.
19+
orderservice), and prose/Javadoc (used unmodified).
20+
1521
integrations
1622
Comma-separated list of type:name pairs.
1723
Supported types: database, rest, graphql, file, email, jms, kafka, ...
@@ -36,6 +42,11 @@
3642
<defaultValue>1.0.0-SNAPSHOT</defaultValue>
3743
</requiredProperty>
3844

45+
<requiredProperty key="appName">
46+
<!-- No default: every project needs its own name.
47+
Brief, capitalized words separated by spaces, e.g. "Order Service". -->
48+
</requiredProperty>
49+
3950
<requiredProperty key="integrations">
4051
<!-- No default: at least one integration is expected.
4152
Format: type:name[,type:name,...]
@@ -62,9 +73,10 @@
6273
spring-boot-starter-parent, every app-composed module gets a @Configuration
6374
class plus the Spring Boot starter suited to its role (common-domain carries
6475
the core spring-boot-starter that the plain modules inherit transitively), and
65-
app gets the Application class plus the role starters and entry-point classes its
66-
composition calls for (web + AppServletInitializer for a rest presentation,
67-
data-jpa + @EnableTransactionManagement for a database integration).
76+
app gets the Application class, is always a monitorable web service regardless
77+
of presentationTypes (core starter, webmvc, actuator, Spring Boot Admin client,
78+
AppServletInitializer), and additionally adds data-jpa + @EnableTransactionManagement
79+
when a database integration is present.
6880
false: omit all Spring artifacts (configs, classes, and pom items). -->
6981
</requiredProperty>
7082

src/site/asciidoc/building.adoc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ Each test is a directory containing three files:
4444

4545
`archetype.properties`::
4646
Property values passed to the archetype at generation time — the Maven coordinates plus the
47-
three archetype-specific properties (`integrations`, `serviceAreas`, `presentationTypes`).
47+
five archetype-specific properties (`appName`, `integrations`, `serviceAreas`, `presentationTypes`,
48+
`includeSpring`).
4849

4950
`goal.txt`::
5051
The Maven goal to run against the generated project after generation.

src/site/asciidoc/index.adoc

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@ mvn archetype:generate \
2222

2323
Replace `VERSION` with the archetype release you want to use.
2424

25-
Maven prompts for standard coordinates (`groupId`, `artifactId`, `version`, `package`)
26-
followed by three archetype-specific properties.
25+
Maven prompts for `appName` and `integrations` first (the two required properties with no
26+
default), then the standard coordinates (`groupId`, `artifactId`, `package`), then confirms.
27+
`serviceAreas`, `presentationTypes`, and `includeSpring` have defaults and are not prompted interactively.
2728
See link:usage.html[Usage] for the full prompts reference.
2829

2930
== Example Output
@@ -50,6 +51,8 @@ my-service/
5051
----
5152

5253
`parent/` is a sibling directory — there is no `pom.xml` at the project root.
53-
Each module contains a full `src/` scaffold and a `package-info.java` in every leaf package.
54+
Each module contains a full `src/` scaffold and a `package-info.java` in every `src/main/java`
55+
leaf package (never under `src/test/java`, since Java rejects two package-info.java files
56+
compiled for the same package).
5457

5558
See link:modules.html[Modules] for a description of each module, its dependencies, and how to build.

src/site/asciidoc/modules.adoc

Lines changed: 90 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,17 @@
55

66
Every module contains a full `src/` scaffold
77
(`src/main/java`, `src/main/resources`, `src/test/java`, `src/test/resources`)
8-
with a `package-info.java` in each module's primary leaf package under both
9-
`src/main/java` and `src/test/java`.
8+
with a `package-info.java` in each module's primary leaf package under
9+
`src/main/java` only — never `src/test/java`, since Java rejects two
10+
`package-info.java` files compiled for the same package. (`acceptance-tests` is the
11+
exception worth calling out: its real test content — the `*AT` classes — lives under
12+
`src/test/java`, but its lone package-info, under `src/main/java`, still describes
13+
"Functional acceptance tests for the application.")
1014

1115
Every module that the `app` composes also carries a Spring `@Configuration` class in a
12-
`.config` sub-package; the `app` module's `Application` class `@Import`s them all so the
13-
whole tree assembles into a single Spring context.
16+
`.config` sub-package; the `app` module's `Application` class `@Import`s them all (each
17+
referenced by simple name via its own import statement) so the whole tree assembles into
18+
a single Spring context.
1419

1520
== Module Naming
1621

@@ -22,6 +27,38 @@ is `my-service-parent`. Every module inherits its `groupId` and `version` from `
2227
This prefix applies to `artifactId`s only — the directory names and Java package names listed
2328
below are unaffected.
2429

30+
Several modules also carry a Maven `<name>`/`<description>` derived from the `appName` prompt
31+
(see <<appname-naming>>).
32+
33+
[[appname-naming]]
34+
== appName-Derived Naming
35+
36+
`appName` (e.g. `Order Service`) drives the `<name>`/`<description>` of these modules. The
37+
area name is folded into named service areas' `service-{name}`/`domain-service-{name}`
38+
naming (trailing for `<name>`, mid-sentence for prose); other modules use `appName` as-is.
39+
40+
[cols="1,2,2"]
41+
|===
42+
|Module |`<name>` |`<description>`
43+
44+
|`parent/` |`${appName} Parent` |`${appName}'s parent POM.`
45+
|`common-testing` |`${appName} Common Testing` |`${appName}'s common testing.`
46+
|`domain-{type}` (REST) |`${appName} Domain REST` |`${appName}'s REST presentation tier domain classes.`
47+
|`domain-{type}` (GraphQL) |`${appName} Domain GraphQL` |`${appName}'s GraphQL presentation tier domain classes.`
48+
|`presentation-graphql` |`${appName} Presentation GraphQL` |`${appName}'s GraphQL presentation tier.`
49+
|`domain-service[-{name}]` |`${appName} Domain Service[ {Area}]` |`${appName}'s[ {area}] service tier domain classes.`
50+
|`service[-{name}]` |`${appName} Service[ {Area}]` |`${appName}'s[ {area}] service tier (business logic).`
51+
|`app` |`${appName} App` |`${appName}'s application configuration including building its deployment assembly.`
52+
|`acceptance-tests` |`${appName} Acceptance Tests` |`${appName}'s acceptance tests.`
53+
|===
54+
55+
`common-domain`, `presentation-rest`, and the per-integration modules (`domain-{type}-{name}`,
56+
`integration-{type}-{name}`) have no dedicated `appName`-derived `<name>`/description yet and
57+
keep their existing generic description text.
58+
59+
`spring.application.name` in `app`'s `application.properties` uses `appName`'s generated-property
60+
form (spaces removed, lowercased), e.g. `orderservice`.
61+
2562
== Fixed Modules
2663

2764
These modules are always generated regardless of input.
@@ -35,28 +72,45 @@ _Package_: `{base.package}.common.domain`
3572
Shared test infrastructure.
3673
+
3774
_Package_: `{base.package}.common.testing` +
38-
_Depends on_: `common-domain`
75+
_Depends on_: `common-domain` and every other domain module (`domain-{type}-{name}`,
76+
`domain-service`/`domain-service-{name}`, `domain-{type}` presentation domain modules).
77+
No domain module depends back on `common-testing` — only `service`/`service-{name}` does — so
78+
this stays acyclic. +
79+
_Spring (includeSpring=true)_: `spring-boot-starter-test` at compile scope; additionally
80+
`spring-boot-starter-graphql-test` at compile scope when a `graphql` presentation is present.
81+
Carries `RestAcceptanceTestBase` (when a `rest` presentation is present) and/or
82+
`GraphQlAcceptanceTestBase` (when a `graphql` presentation is present) — shared
83+
`@SpringBootTest(webEnvironment = RANDOM_PORT)` base classes that `acceptance-tests`'
84+
`AppRestAcceptanceTestBase`/`AppGraphQlAcceptanceTestBase` extend.
3985

4086
`service` _or_ `service-{name}`::
4187
Business logic for a service area (see the `serviceAreas` prompt).
4288
+
4389
_Package_: `{base.package}.service` or `{base.package}.service.{name}` +
4490
_Depends on_: `common-domain`, its own `domain-service` / `domain-service-{name}` module, and the
4591
integration module(s) it consumes — a named area takes the integration sharing its name, while the
46-
single default `service` takes every integration module
92+
single default `service` takes every integration module; if `includeSpring=true`, also
93+
`common-testing` (test scope)
4794

4895
`domain-service` _or_ `domain-service-{name}`::
4996
Domain classes owned by a service area — one per `service` / `service-{name}` module.
5097
+
5198
_Package_: `{base.package}.domain.service` or `{base.package}.domain.service.{name}` +
52-
_Depends on_: `common-domain`
99+
_Depends on_: `common-domain`; if `includeSpring=true`, also `spring-boot-starter-validation`
100+
(no domain module depends on `common-testing`)
53101

54102
`app`::
55-
Application assembly — produces the runnable artifact (e.g. Spring Boot über-jar).
56-
Contains the Spring Boot `Application` (`@SpringBootApplication`) class in
57-
`{base.package}.app.config`, and adds the role starters its composition calls for — a `rest`
58-
presentation adds `spring-boot-starter-web` and an `AppServletInitializer` (WAR deployment)
59-
class; a `database` integration adds `spring-boot-starter-data-jpa` and `@EnableTransactionManagement`.
103+
Application assembly — produces the runnable artifact (e.g. Spring Boot über-jar). If
104+
`includeSpring=true`, `app` is always a monitorable web service regardless of
105+
`presentationTypes` — it adds the core `spring-boot-starter`, `spring-boot-starter-webmvc`,
106+
`spring-boot-starter-actuator`, and `spring-boot-admin-starter-client` (actuator needs a web
107+
server to expose its endpoints), and always generates an `AppServletInitializer` (WAR
108+
deployment) class; a `database` integration additionally adds `spring-boot-starter-data-jpa`
109+
and `@EnableTransactionManagement`. Contains the Spring Boot `Application`
110+
(`@SpringBootApplication`) class in `{base.package}.app.config`. Also creates
111+
`application.properties` (actuator, Spring Boot Admin registration, logging defaults, plus JPA
112+
and SQL logging when a `database` integration is present) and six empty per-environment files
113+
(`application-{ci,dev,local,prod,qa,uat}.properties`) in `src/main/resources`.
60114
+
61115
_Package_: `{base.package}.app`, `{base.package}.app.config` +
62116
_Depends on_: all non-test modules (`common-domain`, all domain and integration modules,
@@ -68,8 +122,20 @@ Functional acceptance tests that exercise the application from the outside.
68122
_Package_: `{base.package}.at` +
69123
_Depends on_: `app`, `common-domain`, all `domain-{type}-{name}` integration domain modules,
70124
all `domain-service` / `domain-service-{name}` service-area domain modules,
71-
all `domain-{type}` presentation domain modules +
72-
_Plugin_: `maven-failsafe-plugin` (`integration-test` + `verify` goals)
125+
all `domain-{type}` presentation domain modules (all labeled "this app" in the pom); also
126+
`common-testing` (test scope) unconditionally, and — if `includeSpring=true` and a `database`
127+
integration is present — `datasource-proxy-spring-boot-starter` (SQL logging), plus
128+
`spring-graphql-test` (test scope) when a `graphql` presentation is present +
129+
_Plugin_: `maven-failsafe-plugin` (`integration-test` + `verify` goals) +
130+
_Spring (includeSpring=true)_: generates `{appNameClass}AcceptanceTestConfiguration`
131+
(package `{base.package}.at.config`) and `src/test/resources/logback-spring.xml`; generates
132+
`AppRestAcceptanceTestBase` (package `{base.package}.at`, extends `common-testing`'s
133+
`RestAcceptanceTestBase`) when a `rest` presentation is present, and/or
134+
`AppGraphQlAcceptanceTestBase` (extends `GraphQlAcceptanceTestBase`) when a `graphql`
135+
presentation is present — both `@ContextConfiguration`'d with the AT configuration class plus
136+
every generated module's `@Configuration` class (reachable transitively via the `app`
137+
dependency), and excluding `DataSourceAutoConfiguration`/`XADataSourceAutoConfiguration` only
138+
when a `database` integration is present.
73139

74140
== Integration Modules
75141

@@ -87,18 +153,21 @@ Integration implementation classes — DAOs, Spring Data JPA repositories, REST
87153
(e.g. `integration-db-users`, `integration-rest-orders`).
88154
+
89155
_Package_: `{base.package}.integration.{type}.{name}` +
90-
_Depends on_: `common-domain`, `domain-{type}-{name}` +
156+
_Depends on_: `common-domain`, `domain-{type}-{name}`; if `includeSpring=true` and the type
157+
is `database`, also `datasource-proxy-spring-boot-starter` (SQL logging) +
91158
_Plugin_: `maven-failsafe-plugin` (`integration-test` + `verify` goals)
92159

93160
== Presentation Modules
94161

95162
Generated per type in the `presentationTypes` prompt.
96163

97164
`domain-{type}`::
98-
Domain classes for a presentation tier (e.g. `domain-rest`, `domain-graphql`).
165+
Domain classes for a presentation tier (e.g. `domain-rest`, `domain-graphql`) — these map
166+
to/from the service-tier domain objects ("the service domain deps").
99167
+
100168
_Package_: `{base.package}.domain.{type}` +
101-
_Depends on_: `common-domain`
169+
_Depends on_: `common-domain`, every `domain-service`/`domain-service-{name}` module; if
170+
`includeSpring=true`, also `spring-boot-starter-validation`
102171

103172
`presentation-{type}`::
104173
Request-handling classes — controllers, resolvers, etc.
@@ -116,10 +185,13 @@ It contains:
116185

117186
* `<parent>` — inherits `spring-boot-starter-parent` (4.1.0) via an empty `<relativePath/>`, supplying Spring dependency management and plugin defaults
118187
* `<packaging>pom</packaging>`
188+
* `<name>`/`<description>` derived from `appName` (see <<appname-naming>>)
119189
* `<modules>` — all sibling modules referenced as `../module` relative paths, sorted alphabetically
120190
* `<dependencyManagement>` — every module pinned to `${project.version}`, split into a TEST section
121191
(`acceptance-tests` and `common-testing`, at `<scope>test</scope>`) and a PROD section (all other
122-
modules, plus managed third-party dependencies such as `spring-core`)
192+
modules, plus managed third-party dependencies such as `spring-core`, `datasource-proxy-spring-boot-starter`,
193+
and `spring-boot-admin-starter-client` — the latter two pinned via their own version properties
194+
since they aren't part of the Spring Boot BOM)
123195
* Common properties: Java 21 via `maven.compiler.release`; UTF-8 source encoding
124196
* `<pluginManagement>` — pinned versions for `maven-compiler-plugin`, `maven-failsafe-plugin`,
125197
`maven-jar-plugin` (with `skipIfEmpty=true`), `maven-surefire-plugin`,

0 commit comments

Comments
 (0)