Skip to content

Multi-module restructuring: feature modules + all + bom (spec 014, steps 2–12)#29

Merged
hendrikebbers merged 11 commits into
mainfrom
feat/014-multi-module-restructuring
Jul 14, 2026
Merged

Multi-module restructuring: feature modules + all + bom (spec 014, steps 2–12)#29
hendrikebbers merged 11 commits into
mainfrom
feat/014-multi-module-restructuring

Conversation

@herbie-bot

Copy link
Copy Markdown
Collaborator

Summary

Completes the Maven reactor restructuring (spec 014) on top of the core split merged in #28. Extracts the five optional feature modules, adds the spring-services-all aggregator and spring-services-bom, wires per-module auto-configuration, enforces dependency isolation, and updates the release tooling and docs. Consumers now depend only on the features they use; spring-services-all preserves the one-step "everything" path.

Spec

  • Spec folder: docs/specs/014-multi-module-restructuring/
  • Design: docs/specs/014-multi-module-restructuring/design.md
  • Plan: docs/specs/014-multi-module-restructuring/steps.md

Changes (steps 2–12)

  • Feature modules extracted from core, each with its own @AutoConfiguration + AutoConfiguration.imports, @ConditionalOnClass guard, and dependency:
    • spring-services-slack (→ slack-api-client)
    • spring-services-search (RestClient, no extra dep)
    • spring-services-dbbackup (RestClient, no extra dep)
    • spring-services-email (→ spring-boot-starter-mail)
    • spring-services-mcp (→ MCP SDK)
  • Core: FullSpringServiceConfig is now core-only; the starter auto-config is renamed SpringServicesCoreAutoConfiguration.
  • spring-services-all: depends on all modules, ships no config; hosts the aggregate/zero-config integration test.
  • spring-services-bom: lockstep version management.
  • Isolation: maven-enforcer bans slack/mcp/mail from core's tree; McpAutoConfigurationTest proves inert-without-SDK.
  • Release/CI: versions:set -DprocessAllModules (lockstep); absolute JReleaser staging dir for multi-module.
  • Docs: docs/releases/upgrade-to-1.4.md (coordinate migration) + README installation/layout.

Test coverage

  • Full reactor -Pfull-build clean verify green: all 9 modules (tests + Javadoc + sources + SBOM). Core 294 + slack 12 + search 27 + dbbackup 13 + email 17 + mcp 38 tests.
  • Aggregate test boots the full classpath and asserts slack/email/mcp beans self-activate.
  • spec-review and quality-review clean (no Critical/blocking findings).

Note

Breaking change: the com.open-elements:spring-services coordinate is now the reactor parent (pom); consumers migrate to spring-services-all or à-la-carte via the BOM. No Java-API or schema change. Target release: 1.4.0. Release-tooling changes are validated at release time (tag-triggered).

Closes #27

🤖 Generated with Claude Code

hendrikebbers and others added 11 commits July 13, 2026 20:38
Step 2 of spec 014. Moves services/slack (main + tests) into a new
spring-services-slack module that depends on spring-services-core and owns the
slack-api-client dependency (removed from core). Adds SlackAutoConfiguration
(@ConditionalOnClass(Slack.class), @import(SlackConfig)) registered via the
module's own AutoConfiguration.imports, so the feature self-activates by
classpath presence. SlackConfig is dropped from FullSpringServiceConfig (now one
fewer core feature).

The auto-config lives in com.openelements.spring.base.slack, outside SlackConfig's
@componentscan of services.slack — co-locating it there caused a duplicate
SlackConfig bean definition.

Reactor green: core 388 + slack 12 = 400 tests.

Spec: docs/specs/014-multi-module-restructuring (#27)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Step 3 of spec 014. Moves services/search (main + tests, incl. WireMock-backed
client tests) into spring-services-search, depending on core. No new third-party
dependency (Meilisearch is reached over Spring's RestClient via core). Adds
SearchAutoConfiguration (@import(SearchConfig)) in com.openelements.spring.base.search
(outside SearchConfig's @componentscan) registered via the module's
AutoConfiguration.imports; runtime opt-in stays governed by SearchConfig's
@ConditionalOnProperty(openelements.meilisearch.enabled). Drops SearchConfig from
FullSpringServiceConfig and de-links a stale DbBackupConfig javadoc reference.

Reactor test-compiles; search module tests green (27).

Spec: docs/specs/014-multi-module-restructuring (#27)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Step 4 of spec 014. Moves services/dbbackup (main + WireMock-backed client test)
into spring-services-dbbackup, depending on core. No new third-party dependency
(RestClient via core). Adds DbBackupAutoConfiguration (@import(DbBackupConfig)) in
com.openelements.spring.base.dbbackup (outside DbBackupConfig's @componentscan) via
the module's AutoConfiguration.imports; runtime opt-in stays governed by
@ConditionalOnProperty(openelements.db-backup.enabled). Drops DbBackupConfig from
FullSpringServiceConfig.

Reactor installs; dbbackup module tests green (13).

Spec: docs/specs/014-multi-module-restructuring (#27)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Step 5 of spec 014. Moves services/email (main + tests) into spring-services-email,
depending on core (uses core's UserEntity) and owning spring-boot-starter-mail
(removed from core). Adds EmailAutoConfiguration
(@ConditionalOnClass(MimeMessage.class), @import(EmailConfig)) in
com.openelements.spring.base.email (outside EmailConfig's @componentscan) via the
module's AutoConfiguration.imports. Graceful degradation without a JavaMailSender is
preserved. Drops EmailConfig from FullSpringServiceConfig and de-links a cross-module
javadoc reference in EmailServiceTest.

Reactor installs; email module tests green (17).

Spec: docs/specs/014-multi-module-restructuring (#27)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Step 6 of spec 014. Moves the com.openelements.spring.base.mcp package (main +
tests) into spring-services-mcp, depending on core (uses core's ApiKeyDataService)
and owning the MCP SDK dependencies mcp-spring-webmvc + mcp-json-jackson2 (removed
from core). Adds McpAutoConfiguration (@ConditionalOnClass(McpServer.class),
@import(McpConfiguration)) via the module's AutoConfiguration.imports, so the MCP
endpoint and its dedicated security chain are only present when the module is on
the classpath (a blast-radius improvement) and stay gated by
@ConditionalOnProperty(openelements.mcp.enabled). McpConfiguration uses @import (not
@componentscan), so the auto-config co-locates safely.

Reactor installs; mcp module tests green (37).

Spec: docs/specs/014-multi-module-restructuring (#27)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…figuration

Step 7 of spec 014. Renames SpringServicesAutoConfiguration ->
SpringServicesCoreAutoConfiguration to reflect that it configures only the
always-present core features, distinct from the per-module feature auto-configs.
FullSpringServiceConfig is now core-only (security, tenant, apikey, settings, tag,
webhook, audit, comment, translation). Updates the core AutoConfiguration.imports,
the activation-guard test, and the test apps/exclusions that referenced the old
name. This is a breaking rename of the class shipped in 1.3.0 (documented in the
upgrade guide).

Full reactor suite green: core 294 + slack 12 + search 27 + dbbackup 13 + email 17
+ mcp 37 = 400 tests.

Spec: docs/specs/014-multi-module-restructuring (#27)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Step 8 of spec 014. spring-services-all depends on core plus every feature module
(slack, search, dbbackup, email, mcp) and ships no configuration of its own — a
pure dependency bundle and drop-in replacement for the pre-split coordinate. Hosts
the relocated aggregate/zero-config starter integration test: a zero-config consumer
app (com.example.aggregate) with the full reactor on the classpath, asserting the
app's own and the core library's persistence resolve and that representative beans
from the slack, email and mcp modules are all present (self-activation by classpath
presence, no @import).

Aggregate test green (2).

Spec: docs/specs/014-multi-module-restructuring (#27)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Step 9 + 10 of spec 014.

spring-services-bom (packaging=pom) manages every module at the lockstep
${project.version}, so a-la-carte consumers import it once and declare modules
without versions.

Isolation guarantees:
- maven-enforcer bannedDependencies in core fails the build if slack-api-client,
  the MCP SDK, or spring-boot-starter-mail ever leak into core's dependency tree
  ("core does not pull optional heavy dependencies").
- McpAutoConfigurationTest proves the feature stays inert (no MCP beans) when the
  MCP SDK type is filtered off the classpath.

Reactor builds all 9 modules; enforcer passes; mcp module tests green (38).

Spec: docs/specs/014-multi-module-restructuring (#27)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Step 11 of spec 014.

- release.sh: versions:set now uses -DprocessAllModules so a global version bump
  stays lockstep across the parent and every module (each pins the parent version
  explicitly).
- release.yml: stage artifacts into an ABSOLUTE github.workspace/target/staging-deploy
  so all module artifacts (core, feature modules, -all, -bom) land in the single
  root staging directory JReleaser reads — a relative path would scatter them
  per-module and JReleaser (run once at root) would miss them.

build.yml (clean verify) and snapshot.yml (reactor deploy) already build/deploy the
whole reactor and need no change. The deploy/JReleaser path only runs on a tag, so it
is validated at release time (per the spec's open question).

Spec: docs/specs/014-multi-module-restructuring (#27)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…actor

Step 12 of spec 014. docs/releases/upgrade-to-1.4.md documents the breaking
coordinate change (spring-services parent pom -> spring-services-all drop-in, or
a-la-carte via the BOM), the self-activation model, and the
SpringServicesAutoConfiguration -> SpringServicesCoreAutoConfiguration rename, with
an ordering note relative to the 1.3.0 schema migration. README Installation and
Project Layout now describe the module coordinates and reactor structure.

Spec: docs/specs/014-multi-module-restructuring (#27)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@hendrikebbers hendrikebbers merged commit ee19a4c into main Jul 14, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Restructure spring-services into a Maven multi-module project (core + optional feature modules)

2 participants