feat(storage): auto-configure the object store from openelements.storage.* - #48
Merged
Merged
Conversation
…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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Step 2 for
spring-services-storage: theObjectStoreimplementations 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 threeObjectStoreimplementations 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.typenames one. Unset, nothing is registered at all.@ConditionalOnMissingBeanon each store means an application that declares its ownObjectStorekeeps it.Shape
StorageAutoConfigurationcarries the@Beanmethods itself rather than importing a@Configurationthe way scim/search/dbbackup do. That shape exists in those modules because their configs are component-scanned and imported byFullSpringServiceConfig; storage needs neither. It also matters for correctness —@ConditionalOnMissingBeanis only reliable while auto-configurations are being processed, which is whyApplicationInfoAutoConfigurationin core has the same shape.StoragePropertiesreplaces the origin application'sstorage.s3.*@Valueplaceholders. The@Valueform 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.S3ConfigbecomesS3Clients. The Spring wiring moved up into the auto-configuration, which leaves a plain helper holding thechunkedEncodingEnabled(false)knowledge — and leaves the wholeservices.storage.*tree free of Spring.Tests
StorageAutoConfigurationTest, 9 cases overApplicationContextRunner: 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 (nos3block, an incompletes3block,filewithout a root).AggregateStarterIntegrationTestgains one case: under a full classpath in a real Boot context, noObjectStorebean 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.mdis 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