Skip to content

feat(storage): auto-configure the object store from openelements.storage.* - #48

Merged
herbie-bot merged 1 commit into
mainfrom
feat/storage-autoconfiguration
Sep 25, 2026
Merged

herbie-bot merged 1 commit into
mainfrom
feat/storage-autoconfiguration

Conversation

@herbie-bot

Copy link
Copy Markdown
Collaborator

Step 2 for spring-services-storage: the ObjectStore implementations are wired by Spring instead of waiting for a consumer to instantiate them, and they read the reactor's own property namespace.

Activation is a choice, not a switch

Every other feature module self-activates on classpath presence and guards with @ConditionalOnClass. That does not work here: the module ships three ObjectStore implementations and all three are on the classpath at once, so nothing about the classpath distinguishes them — and classpath order must not be what decides where an application's objects land.

openelements.storage.type names one. Unset, nothing is registered at all.

openelements.storage.type=s3     # + endpoint, region, bucket, access-key, secret-key
openelements.storage.type=file   # + root
openelements.storage.type=memory # heap only; tests and local development

@ConditionalOnMissingBean on each store means an application that declares its own ObjectStore keeps it.

Shape

  • StorageAutoConfiguration carries the @Bean methods itself rather than importing a @Configuration the way scim/search/dbbackup do. That shape exists in those modules because their configs are component-scanned and imported by FullSpringServiceConfig; storage needs neither. It also matters for correctness — @ConditionalOnMissingBean is only reliable while auto-configurations are being processed, which is why ApplicationInfoAutoConfiguration in core has the same shape.
  • StorageProperties replaces the origin application's storage.s3.* @Value placeholders. The @Value form failed start-up on an unresolvable placeholder, and that fail-fast is deliberately kept: a missing setting for the selected type fails start-up naming the property, rather than starting a service that accepts uploads it cannot keep.
  • S3Config becomes S3Clients. The Spring wiring moved up into the auto-configuration, which leaves a plain helper holding the chunkedEncodingEnabled(false) knowledge — and leaves the whole services.storage.* tree free of Spring.

Tests

StorageAutoConfigurationTest, 9 cases over ApplicationContextRunner: inert without a type; each of the three types selects its own implementation and only that one; an application's own bean wins; and three misconfigurations that must fail start-up (no s3 block, an incomplete s3 block, file without a root).

AggregateStarterIntegrationTest gains one case: under a full classpath in a real Boot context, no ObjectStore bean exists without the property. That is the claim that would otherwise regress silently.

Verification

./mvnw -Pfull-build clean verify -Dmaven.javadoc.failOnWarnings=true — green across all twelve modules with all tests. PomChecker guard passes.

Still open

docs/TODO.md is updated: tests for the implementations themselves, InMemoryObjectStore's public mutable fields as published API, the AWS SDK as a hard dependency, and Javadoc that still names the origin application.

🤖 Generated with Claude Code

…age.*

Step 2 for the storage module: the ObjectStore implementations are now
wired by Spring instead of waiting for a consumer to instantiate them,
and they read the reactor's own property namespace.

Activation is a choice, not a switch. The module ships three
implementations and all three are on the classpath at once, so
@ConditionalOnClass — how every other feature module decides — cannot
tell them apart and classpath order must not.
openelements.storage.type names one; unset, nothing is registered.
@ConditionalOnMissingBean lets an application's own ObjectStore win.

- StorageAutoConfiguration carries the @bean methods itself rather than
  importing a @configuration, following ApplicationInfoAutoConfiguration:
  @ConditionalOnMissingBean is only reliable while auto-configurations
  are processed.
- StorageProperties replaces the origin application's storage.s3.* @value
  placeholders with openelements.storage.*, and keeps the fail-fast the
  @value form had: a missing setting for the selected type fails start-up
  naming the property, rather than starting a service that cannot store.
- S3Config becomes S3Clients — the client wiring moved to the
  auto-configuration, leaving a Spring-free helper and, with it, a
  services.storage.* tree that is plain Java.
- The aggregate test now also asserts the module stays inert under a full
  classpath without the property, which is the claim that would otherwise
  regress silently.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@herbie-bot
herbie-bot merged commit deee1b0 into main Sep 25, 2026
1 check passed
@herbie-bot
herbie-bot deleted the feat/storage-autoconfiguration branch September 25, 2026 07:16
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.

2 participants