feat: add spring-boot-morphium as optional module (review only) - #18
feat: add spring-boot-morphium as optional module (review only)#18Bardioc1977 wants to merge 163 commits into
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughAdds an optional Spring Boot integration with auto-configuration, typed properties, repository proxies, transactions, Actuator health reporting, in-memory testing support, three Maven artifacts, release wiring, and documentation. ChangesSpring Boot integration
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant SpringBoot
participant MorphiumAutoConfiguration
participant MorphiumRepositoryRegistrar
participant MorphiumRepositoryFactoryBean
participant MorphiumRepositoryInvocationHandler
participant Morphium
SpringBoot->>MorphiumAutoConfiguration: bind properties and create Morphium
MorphiumAutoConfiguration->>Morphium: configure and connect
SpringBoot->>MorphiumRepositoryRegistrar: scan repository packages
MorphiumRepositoryRegistrar->>MorphiumRepositoryFactoryBean: register repository bean
MorphiumRepositoryFactoryBean->>MorphiumRepositoryInvocationHandler: create JDK proxy
MorphiumRepositoryInvocationHandler->>Morphium: execute repository operation
Morphium-->>MorphiumRepositoryInvocationHandler: return result
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5f7b4b070d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| de.caluga.morphium.spring.autoconfigure.MorphiumAutoConfiguration | ||
| de.caluga.morphium.spring.autoconfigure.MorphiumHealthAutoConfiguration |
There was a problem hiding this comment.
Register the transaction aspect as auto-configuration
For a normal Spring Boot application whose component scan starts in the user's package, this imports file is the only entry point from the starter, and it never imports or declares MorphiumTransactionAspect. Because the aspect is only annotated with @Component in the library package, adding the starter plus spring-boot-starter-aop leaves no aspect bean in the context, so @MorphiumTransactional methods run without startTransaction()/commit/abort. Add an auto-configuration entry (or a configuration class that creates the aspect conditionally) so the advertised transaction support is actually registered.
Useful? React with 👍 / 👎.
| Param paramAnno = params[i].getAnnotation(Param.class); | ||
| String fieldName = paramAnno != null ? paramAnno.value() : params[i].getName(); |
There was a problem hiding this comment.
Honor @by bindings for annotated find/delete methods
For @Find/@Delete methods such as @Find List<Order> byStatus(@By("status") String status), this inspects @Param instead of Jakarta Data's @By. When applications do not compile repositories with -parameters (the parent compiler config here does not), the condition becomes arg0:0; even with parameter names available, an explicit @By value is ignored. FindMethodBridge then queries the wrong/non-existent field, so annotated find/delete methods return no matches or affect the wrong data.
Useful? React with 👍 / 👎.
| return args -> QueryMethodBridge.executeQuery( | ||
| delegate, method.getName(), args != null ? args : new Object[0], | ||
| returnsSingle, returnsOptional, returnsBoolean, returnsStream, orderBySpec); |
There was a problem hiding this comment.
Return CompletionStage for async derived queries
For a derived repository method declared with an async return type, e.g. CompletionStage<List<Order>> findByStatus(String status), this handler still calls the synchronous executeQuery. Since CompletionStage is only excluded from returnsSingle and there is no async branch, the invocation handler returns the raw query result (List, Long, etc.); the generated JDK proxy then casts that value to CompletionStage and throws ClassCastException instead of running asynchronously. Dispatch these return types to QueryMethodBridge.executeQueryAsync.
Useful? React with 👍 / 👎.
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 19
🧹 Nitpick comments (10)
spring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumRepositoryRegistrar.java (1)
89-89: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winResolve candidate classes with the bean class loader.
getClass().getClassLoader()is the loader of the autoconfigure module. Under Spring Boot DevTools the application classes are loaded by a restart class loader, and under a WAR deployment they can also live in a separate loader. In those setupsClassUtils.forNameeither fails or returns a class from the wrong loader, so repositories are skipped or the proxy is built against a stale type.Implement
BeanClassLoaderAwareand use the injected loader.♻️ Proposed change to use the bean class loader
-public class MorphiumRepositoryRegistrar implements ImportBeanDefinitionRegistrar { +public class MorphiumRepositoryRegistrar implements ImportBeanDefinitionRegistrar, BeanClassLoaderAware { private static final Logger log = LoggerFactory.getLogger(MorphiumRepositoryRegistrar.class); + + private ClassLoader beanClassLoader = MorphiumRepositoryRegistrar.class.getClassLoader(); + + `@Override` + public void setBeanClassLoader(ClassLoader classLoader) { + this.beanClassLoader = classLoader; + }- Class<?> iface = ClassUtils.forName(className, getClass().getClassLoader()); + Class<?> iface = ClassUtils.forName(className, beanClassLoader);Add the import:
+import org.springframework.beans.factory.BeanClassLoaderAware;🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@spring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumRepositoryRegistrar.java` at line 89, Update MorphiumRepositoryRegistrar to implement BeanClassLoaderAware, store the injected bean class loader via setBeanClassLoader, and use that loader in the ClassUtils.forName call instead of getClass().getClassLoader().spring-boot-morphium/morphium-spring-boot-autoconfigure/src/test/java/de/caluga/morphium/spring/autoconfigure/TestEntityRepository.java (1)
12-16: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd coverage for the annotated-query and pagination branches.
This repository exercises only derived queries.
MorphiumRepositoryInvocationHandleralso implements@Query(JDQL),@Find,@Delete,PageRequest/Orderpaging andLimit. Those branches are untested, and the@Query/@Findpaths additionally depend on reflective parameter names, so a missing-parametersflag would not be detected by the current suite.Add methods that cover the annotated paths.
💚 Proposed additional repository methods
List<TestEntity> findByStatusAndPriority(String status, int priority); long countByStatus(String status); + + `@Query`("where status = :status") + List<TestEntity> byStatusJdql(`@Param`("status") String status); + + `@Find` + List<TestEntity> lookup(`@Param`("status") String status, PageRequest pageRequest); }Add the imports:
+import jakarta.data.page.PageRequest; +import jakarta.data.repository.Find; +import jakarta.data.repository.Param; +import jakarta.data.repository.Query;🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@spring-boot-morphium/morphium-spring-boot-autoconfigure/src/test/java/de/caluga/morphium/spring/autoconfigure/TestEntityRepository.java` around lines 12 - 16, Extend TestEntityRepository with methods covering MorphiumRepositoryInvocationHandler’s `@Query` (JDQL), `@Find`, and `@Delete` paths, plus PageRequest/Order pagination and Limit behavior. Use annotated method parameters whose reflective names are required, ensuring the test configuration preserves parameter metadata and would fail without the -parameters compiler flag. Add corresponding repository tests that exercise each branch and validate the returned or affected entities.spring-boot-morphium/README.md (1)
22-22: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winClear the README Markdown warnings.
Keep the blank line at Line 22 inside the blockquote. Add a
textlanguage tag to the plain-text fences at Lines 303 and 327. This removes the reported MD028 and MD040 warnings.Also applies to: 303-303, 327-327
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@spring-boot-morphium/README.md` at line 22, Update the README Markdown formatting: keep the blank line at line 22 within the existing blockquote, and label the plain-text fenced blocks at lines 303 and 327 with the text language tag to clear MD028 and MD040 warnings.Source: Linters/SAST tools
spring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumAutoConfiguration.java (3)
113-116: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winRestrict the ClassGraph scan to the application packages.
new ClassGraph().enableAnnotationInfo().scan()scans the whole classpath, including every dependency JAR. This runs synchronously during bean creation and adds startup latency proportional to classpath size. The stated goal is to avoid Morphium's own ClassGraph scan, but an unrestricted scan performs the same work.Restrict the scan with
acceptPackages(...). Spring Boot already records the application base packages throughAutoConfigurationPackages.get(beanFactory). Alternatively, add amorphium.entity-packagesproperty so applications can declare the scan scope.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@spring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumAutoConfiguration.java` around lines 113 - 116, Restrict the ClassGraph scan in MorphiumAutoConfiguration to application packages instead of scanning the entire classpath. Obtain the packages from Spring Boot’s AutoConfigurationPackages using the existing beanFactory context and pass them to ClassGraph.acceptPackages(...) before scan(), preserving annotation scanning and the current scan-result handling.
196-201: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winFail fast when only one credential property is set.
The guard applies authentication only when
usernameandpasswordare both non-null. If an operator setsmorphium.usernameand omitsmorphium.password, or the reverse, Morphium connects without authentication and no diagnostic is produced. Against a MongoDB instance that permits unauthenticated access, the application then runs with the wrong identity. Against an authenticating instance, the failure surfaces later as an opaque driver error.Reject the half-configured state at startup.
♻️ Proposed fix to validate credential pairing
// Credentials - if (properties.getUsername() != null && properties.getPassword() != null) { + boolean hasUsername = properties.getUsername() != null; + boolean hasPassword = properties.getPassword() != null; + if (hasUsername != hasPassword) { + throw new IllegalStateException( + "morphium.username and morphium.password must be configured together"); + } + if (hasUsername) { cfg.authSettings().setMongoLogin(properties.getUsername()); cfg.authSettings().setMongoPassword(properties.getPassword()); cfg.authSettings().setMongoAuthDb(properties.getAuthDatabase()); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@spring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumAutoConfiguration.java` around lines 196 - 201, Update the credential handling in MorphiumAutoConfiguration so startup rejects configurations where exactly one of properties.getUsername() or properties.getPassword() is non-null. Fail with a clear configuration error before connecting; retain the existing authSettings setup when both are provided and unauthenticated behavior when neither is set.
275-284: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winDo not retry
MorphiumDriverExceptionby message text alone.
connectWithRetrytreats only"No primary node found"or"not connected yet"as transient, but many non-transient driver errors are alsoMorphiumDriverExceptionand use different messages.MorphiumDriverNetworkExceptioncovers connection failures better, but it is not the only throw path for connection-time issues. Keep the message check only with a build-level assertion against the exact core message, or use a central transient-failure predicate frommorphium-corethat is not string-based.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@spring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumAutoConfiguration.java` around lines 275 - 284, Update isTransient(Throwable) so MorphiumDriverException retries are determined by a central morphium-core transient-failure predicate or an exact build-level assertion, rather than matching arbitrary message text. Preserve cause-chain traversal and ensure only confirmed transient connection failures return true.spring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumHealthAutoConfiguration.java (1)
81-92: 🧹 Nitpick | 🔵 TrivialConsider whether
isConnected()is a strong enough liveness signal.The indicator reports
UPfromdriver.isConnected()alone. On a pooled driver this is normally a local state read, not a round trip to MongoDB. A pool that holds stale sockets, or a cluster that has lost its primary, can therefore still reportUP. Readiness probes and alerts built on this endpoint would then miss a real outage.If Morphium exposes a cheap server command such as a
pingorhello, run it here behind a short timeout and reportUPonly when it succeeds. KeepisConnected()as the fast pre-check.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@spring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumHealthAutoConfiguration.java` around lines 81 - 92, Update the health indicator supplier around driver.isConnected() to retain it as a fast pre-check, then execute Morphium’s available lightweight MongoDB liveness command (such as ping or hello) with a short timeout before returning Health.up(). Report Health.down() when the pre-check or command fails, while preserving the existing health details and replica-set metadata.spring-boot-morphium/morphium-spring-boot-autoconfigure/src/test/java/de/caluga/morphium/spring/autoconfigure/MorphiumAutoConfigurationTest.java (2)
24-28: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winAssert the concrete driver type instead of a name substring.
getSimpleName().contains("InMem")passes for any class whose simple name contains that substring. The assertion does not prove that Morphium selectedInMemDriver. Assert the type directly.💚 Proposed fix to assert the driver type
`@Test` void driverIsInMemory() { - assertTrue(morphium.getDriver().getClass().getSimpleName().contains("InMem"), - "Expected InMemDriver but got: " + morphium.getDriver().getClass().getName()); + assertInstanceOf(InMemDriver.class, morphium.getDriver(), + "Expected InMemDriver but got: " + morphium.getDriver().getClass().getName()); }Add the import:
import de.caluga.morphium.driver.inmem.InMemDriver;Confirm the package of
InMemDriverbefore you apply this change.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@spring-boot-morphium/morphium-spring-boot-autoconfigure/src/test/java/de/caluga/morphium/spring/autoconfigure/MorphiumAutoConfigurationTest.java` around lines 24 - 28, Update driverIsInMemory to assert that morphium.getDriver() is an instance of the concrete InMemDriver type rather than checking whether its simple class name contains “InMem”; verify and use the correct InMemDriver package import.
11-22: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd auto-configuration tests with
ApplicationContextRunner.The current test starts one full application context and asserts two facts. Several behaviors that this cohort introduces have no coverage:
@ConditionalOnMissingBeanback-off when the application defines its ownMorphiumbean.- The
indexCheckswitch, including an unrecognized value.atlasUrlprecedence overhosts.- The credential guard when only
morphium.usernameis set.MorphiumHealthAutoConfiguration, which has no test at all.
ApplicationContextRunnercovers each case in milliseconds without a full context per scenario, and it asserts on conditions directly. A runner test that supplies a user-definedMorphiumbean would also confirm whether the health indicator still registers, which is the concern I raised onMorphiumHealthAutoConfigurationLines 54-57.💚 Example runner test for the back-off path
private final ApplicationContextRunner runner = new ApplicationContextRunner() .withConfiguration(AutoConfigurations.of( MorphiumAutoConfiguration.class, MorphiumHealthAutoConfiguration.class)) .withPropertyValues("morphium.database=test", "morphium.driver-name=InMemDriver"); `@Test` void backsOffWhenUserDefinesMorphiumBean() { runner.withUserConfiguration(CustomMorphiumConfig.class) .run(context -> { assertThat(context).hasSingleBean(Morphium.class); assertThat(context).getBean(Morphium.class).isSameAs( context.getBean(CustomMorphiumConfig.class).custom); assertThat(context).hasBean("morphiumHealthIndicator"); }); } `@Test` void unknownIndexCheckIsRejected() { runner.withPropertyValues("morphium.index-check=NOT_A_MODE") .run(context -> assertThat(context).hasFailed()); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@spring-boot-morphium/morphium-spring-boot-autoconfigure/src/test/java/de/caluga/morphium/spring/autoconfigure/MorphiumAutoConfigurationTest.java` around lines 11 - 22, Replace the single full-context test in MorphiumAutoConfigurationTest with ApplicationContextRunner coverage for MorphiumAutoConfiguration and MorphiumHealthAutoConfiguration. Add scenarios for user-defined Morphium back-off while retaining the health indicator, indexCheck enabled/disabled and unknown-value failure, atlasUrl taking precedence over hosts, and username-only credential rejection; assert each condition and resulting bean/configuration behavior directly.spring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumProperties.java (1)
108-115: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winThe index-check strategy is an untyped
Stringand is validated nowhere.morphium.index-checkis carried as a free-formStringand consumed by aswitchwith nodefaultbranch. A typo such asCREATE_ON_STARUPtherefore matches no case, produces no warning, and leaves theMorphiumConfigdefault in place. An operator who intendsNO_CHECKsilently gets eager index creation on startup. Anullvalue, reachable through the public setter, also throws aNullPointerExceptionfrom theswitch. Binding the property to an enum fixes both sites at once, because the SpringBinderthen rejects an invalid value at startup with a clear message, and relaxed binding still acceptscreate-on-startup.
spring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumProperties.java#L108-L115: change theindexCheckfield type fromStringtoCollectionCheckSettings.IndexCheck, update the getter, the setter, and the Javadoc accordingly.spring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumAutoConfiguration.java#L164-L177: switch on the enum. Keep theCREATE_ON_WRITE_NEW_COLcase routed throughsetAutoIndexAndCappedCreationOnWrite(true), because that call also sets the capped check, which a directsetIndexCheckcall does not. If you keep theStringtype instead, add adefaultbranch that logs a warning and names the four accepted values.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@spring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumProperties.java` around lines 108 - 115, Bind MorphiumProperties.indexCheck to CollectionCheckSettings.IndexCheck instead of String, and update its getter, setter, and Javadoc; in MorphiumAutoConfiguration’s index-check handling, switch on the enum while preserving CREATE_ON_WRITE_NEW_COL through setAutoIndexAndCappedCreationOnWrite(true). Apply these changes in spring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumProperties.java#L108-L115 and spring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumAutoConfiguration.java#L164-L177.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@CHANGELOG.md`:
- Around line 103-114: Update the “zero breaking-change cost” statement in the
pre-integration conversion changelog entry to qualify it as applying only to
released Maven Central coordinates, while retaining the existing migration
requirements for pre-integration snapshot users.
In `@docs/spring-boot.md`:
- Around line 298-304: Update the “Full Documentation” link in
docs/spring-boot.md:298-304 to target spring-boot-morphium/README.md using a
file URL rather than the current tree URL. Apply the identical correction in
spring-boot-morphium/docs-for-morphium/spring-boot.md:298-304, preserving the
surrounding documentation text.
In `@spring-boot-morphium/CHANGELOG.md`:
- Line 7: Update the Unreleased heading in the changelog to use the lockstep
Morphium reactor version, 6.3.0-SNAPSHOT, or the project’s generated version
value instead of the module-specific 1.0.0-SNAPSHOT.
In
`@spring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumAutoConfiguration.java`:
- Around line 95-98: Update the guard in MorphiumAutoConfiguration around
getReplicaSetName() to reject blank values as buildConfig() does, before calling
m.getDriver().setReplicaSet(true). Preserve the existing isReplicaSet() check
and only force replica-set topology when a nonblank replica-set name is
configured.
- Around line 243-262: Update connectWithRetry to retain each Morphium instance
whose construction or initialization fails, close it before retrying, and also
close it before propagating a non-transient or final-attempt failure. Preserve
the existing retry delay and interruption handling, ensuring cleanup occurs
without masking the original exception.
- Around line 117-136: Update the type ID registration flow around
MorphiumAutoConfiguration and AnnotationAndReflectionHelper.registerTypeIds to
detect collisions before applying the mappings. Reject duplicate explicit typeId
values and conflicts between typeIds and fully qualified class names instead of
allowing later entries to overwrite earlier ones; preserve registration only
when every key maps unambiguously to a single entity class.
In
`@spring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumRepositoryFactoryBean.java`:
- Around line 154-177: Update findIdFieldName so the id and morphiumId fallback
searches each class in the same superclass hierarchy loop used for `@Id` fields,
returning the first matching field name; do not limit fallback lookup to
entityClass.getDeclaredField.
In
`@spring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumRepositoryInvocationHandler.java`:
- Around line 46-59: Update invoke in MorphiumRepositoryInvocationHandler to
detect repository-interface default methods and dispatch them with
InvocationHandler.invokeDefault before calling handlers.computeIfAbsent.
Preserve existing Object-method handling and CRUD, annotation, and derived-query
dispatch for non-default methods.
- Around line 145-166: Update buildDerivedQueryHandler to derive returnsSingle
by calling the existing isSingleReturn(method) helper instead of duplicating
return-type checks. Remove the local classification expression while preserving
the existing returnsOptional, returnsBoolean, and returnsStream handling.
- Around line 223-238: Ensure parameter names are available wherever
buildParamMapSpec and buildConditionsSpec rely on Parameter.getName(): configure
the module’s Spring Boot Maven compiler with parameters=true. Keep the existing
fallback behavior for unannotated, non-special parameters and apply the setting
consistently to the relevant compiler configuration.
In
`@spring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumRepositoryRegistrar.java`:
- Around line 96-103: Update bean-name generation in MorphiumRepositoryRegistrar
around iface and registerBeanDefinition: use the uncapitalized simple name by
default, detect when that name is already registered, and fall back to the
interface’s fully qualified class name for collisions. Preserve the existing
bean definition and registration behavior for non-colliding repositories.
In
`@spring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumTransactional.java`:
- Around line 6-10: Update the Javadoc for MorphiumTransactional and/or
MorphiumTransactionAspect to state that transactions apply only to calls routed
through the Spring AOP proxy; direct self-invocation via this does not trigger
aroundTransactional. Do not imply compile-time or load-time weaving unless that
support is actually provided.
In
`@spring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumTransactionAspect.java`:
- Around line 85-86: Update aroundTransactional so Morphium.startTransaction()
is covered by guarded failure cleanup, ensuring the prior thread-local
write-buffer state is restored if transaction startup throws. Prefer fixing
Morphium.startTransaction() itself to restore that state on driver failure;
otherwise add equivalent abort/cleanup around the call while preserving normal
transaction execution.
- Around line 89-93: Update the catch block in MorphiumTransactionAspect around
the existing transaction flow so abortTransaction() failures are caught and
added as suppressed exceptions to the original Throwable t, then rethrow t.
Preserve the current abort attempt and ensure the primary proceed or commit
failure remains the propagated exception.
- Around line 50-53: Register MorphiumTransactionAspect through Spring Boot
auto-configuration instead of relying on component scanning. Add an
auto-configuration class or configuration declaration ordered after
MorphiumAutoConfiguration, expose a MorphiumTransactionAspect bean accepting
Morphium, and include that configuration in AutoConfiguration.imports so
`@MorphiumTransactional` methods are advised automatically.
- Around line 83-94: Update aroundTransactional in MorphiumTransactionAspect to
make transaction ownership thread-aware: start and own a transaction only when
no transaction is already active, while nested `@MorphiumTransactional`
invocations simply proceed without committing or aborting. Ensure only the
outermost invocation commits on success or aborts on failure, and add an
integration test covering an outer transaction aborting after an inner annotated
call returns.
In
`@spring-boot-morphium/morphium-spring-boot-autoconfigure/src/test/java/de/caluga/morphium/spring/autoconfigure/MorphiumRepositoryProxyTest.java`:
- Around line 37-42: Update MorphiumRepository<T, K> or
AbstractMorphiumRepository<T, K> to explicitly redeclare the Jakarta Data CRUD
methods save and findById with return types T and Optional<T>, preserving the
existing key and parameter types. Ensure TestEntityRepository consumers receive
typed results so the casts in MorphiumRepositoryProxyTest are no longer
required.
In `@spring-boot-morphium/morphium-spring-boot-starter/pom.xml`:
- Around line 17-37: Add spring-boot-starter-aop as a non-optional dependency in
the morphium-spring-boot-starter POM so consumers receive the AspectJ runtime
required by MorphiumTransactionAspect and `@MorphiumTransactional`.
In `@spring-boot-morphium/README.md`:
- Line 3: Update the README Build badge URL and link to reference the active
sboesebeck/morphium repository workflow instead of
Bardioc1977/spring-boot-morphium, or remove the badge if no valid integrated
workflow exists.
---
Nitpick comments:
In
`@spring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumAutoConfiguration.java`:
- Around line 113-116: Restrict the ClassGraph scan in MorphiumAutoConfiguration
to application packages instead of scanning the entire classpath. Obtain the
packages from Spring Boot’s AutoConfigurationPackages using the existing
beanFactory context and pass them to ClassGraph.acceptPackages(...) before
scan(), preserving annotation scanning and the current scan-result handling.
- Around line 196-201: Update the credential handling in
MorphiumAutoConfiguration so startup rejects configurations where exactly one of
properties.getUsername() or properties.getPassword() is non-null. Fail with a
clear configuration error before connecting; retain the existing authSettings
setup when both are provided and unauthenticated behavior when neither is set.
- Around line 275-284: Update isTransient(Throwable) so MorphiumDriverException
retries are determined by a central morphium-core transient-failure predicate or
an exact build-level assertion, rather than matching arbitrary message text.
Preserve cause-chain traversal and ensure only confirmed transient connection
failures return true.
In
`@spring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumHealthAutoConfiguration.java`:
- Around line 81-92: Update the health indicator supplier around
driver.isConnected() to retain it as a fast pre-check, then execute Morphium’s
available lightweight MongoDB liveness command (such as ping or hello) with a
short timeout before returning Health.up(). Report Health.down() when the
pre-check or command fails, while preserving the existing health details and
replica-set metadata.
In
`@spring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumProperties.java`:
- Around line 108-115: Bind MorphiumProperties.indexCheck to
CollectionCheckSettings.IndexCheck instead of String, and update its getter,
setter, and Javadoc; in MorphiumAutoConfiguration’s index-check handling, switch
on the enum while preserving CREATE_ON_WRITE_NEW_COL through
setAutoIndexAndCappedCreationOnWrite(true). Apply these changes in
spring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumProperties.java#L108-L115
and
spring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumAutoConfiguration.java#L164-L177.
In
`@spring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumRepositoryRegistrar.java`:
- Line 89: Update MorphiumRepositoryRegistrar to implement BeanClassLoaderAware,
store the injected bean class loader via setBeanClassLoader, and use that loader
in the ClassUtils.forName call instead of getClass().getClassLoader().
In
`@spring-boot-morphium/morphium-spring-boot-autoconfigure/src/test/java/de/caluga/morphium/spring/autoconfigure/MorphiumAutoConfigurationTest.java`:
- Around line 24-28: Update driverIsInMemory to assert that morphium.getDriver()
is an instance of the concrete InMemDriver type rather than checking whether its
simple class name contains “InMem”; verify and use the correct InMemDriver
package import.
- Around line 11-22: Replace the single full-context test in
MorphiumAutoConfigurationTest with ApplicationContextRunner coverage for
MorphiumAutoConfiguration and MorphiumHealthAutoConfiguration. Add scenarios for
user-defined Morphium back-off while retaining the health indicator, indexCheck
enabled/disabled and unknown-value failure, atlasUrl taking precedence over
hosts, and username-only credential rejection; assert each condition and
resulting bean/configuration behavior directly.
In
`@spring-boot-morphium/morphium-spring-boot-autoconfigure/src/test/java/de/caluga/morphium/spring/autoconfigure/TestEntityRepository.java`:
- Around line 12-16: Extend TestEntityRepository with methods covering
MorphiumRepositoryInvocationHandler’s `@Query` (JDQL), `@Find`, and `@Delete` paths,
plus PageRequest/Order pagination and Limit behavior. Use annotated method
parameters whose reflective names are required, ensuring the test configuration
preserves parameter metadata and would fail without the -parameters compiler
flag. Add corresponding repository tests that exercise each branch and validate
the returned or affected entities.
In `@spring-boot-morphium/README.md`:
- Line 22: Update the README Markdown formatting: keep the blank line at line 22
within the existing blockquote, and label the plain-text fenced blocks at lines
303 and 327 with the text language tag to clear MD028 and MD040 warnings.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: d82977c5-ee0c-40ff-83ce-db1dc98b3b24
📒 Files selected for processing (31)
CHANGELOG.mddocs/index.mddocs/spring-boot.mdmkdocs.ymlpom.xmlrelease.shspring-boot-morphium/CHANGELOG.mdspring-boot-morphium/README.mdspring-boot-morphium/docs-for-morphium/spring-boot.mdspring-boot-morphium/morphium-spring-boot-autoconfigure/pom.xmlspring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/EnableMorphiumRepositories.javaspring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumAutoConfiguration.javaspring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumHealthAutoConfiguration.javaspring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumProperties.javaspring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumRepositoryFactoryBean.javaspring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumRepositoryInvocationHandler.javaspring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumRepositoryRegistrar.javaspring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumTransactionAspect.javaspring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumTransactional.javaspring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.importsspring-boot-morphium/morphium-spring-boot-autoconfigure/src/test/java/de/caluga/morphium/spring/autoconfigure/MorphiumAutoConfigurationTest.javaspring-boot-morphium/morphium-spring-boot-autoconfigure/src/test/java/de/caluga/morphium/spring/autoconfigure/MorphiumRepositoryProxyTest.javaspring-boot-morphium/morphium-spring-boot-autoconfigure/src/test/java/de/caluga/morphium/spring/autoconfigure/TestApplication.javaspring-boot-morphium/morphium-spring-boot-autoconfigure/src/test/java/de/caluga/morphium/spring/autoconfigure/TestEntity.javaspring-boot-morphium/morphium-spring-boot-autoconfigure/src/test/java/de/caluga/morphium/spring/autoconfigure/TestEntityRepository.javaspring-boot-morphium/morphium-spring-boot-autoconfigure/src/test/resources/application-test.propertiesspring-boot-morphium/morphium-spring-boot-starter/pom.xmlspring-boot-morphium/morphium-spring-boot-starter/src/main/java/de/caluga/morphium/spring/starter/package-info.javaspring-boot-morphium/morphium-spring-boot-test/pom.xmlspring-boot-morphium/morphium-spring-boot-test/src/main/java/de/caluga/morphium/spring/test/MorphiumTest.javaspring-boot-morphium/pom.xml
| **Two coordinate/naming corrections made during the pre-integration conversion:** the three | ||
| modules were renamed from `spring-boot-morphium-*` to `morphium-spring-boot-*`, following the | ||
| Spring Boot starter naming convention (the `spring-boot-` prefix is reserved for Spring's own | ||
| starters); and the configuration property prefix was renamed from `spring.morphium.*` to | ||
| `morphium.*`, since the `spring.*` namespace is reserved for Spring Boot's own configuration | ||
| keys. Both renames happened before any Maven Central release of this module existed, so they | ||
| carry zero breaking-change cost. **Existing users of the pre-integration | ||
| `de.caluga:spring-boot-morphium-starter:1.0.0-SNAPSHOT`** must update their dependency's | ||
| artifactId to `morphium-spring-boot-starter`, its version to the Morphium version they adopt | ||
| (currently `6.3.x`), and rename every `spring.morphium.*` key in their | ||
| `application.properties`/`.yml` to `morphium.*` (e.g. `spring.morphium.database` → | ||
| `morphium.database`) — no Java API changes; `MorphiumProperties`, `@EnableMorphiumRepositories`, |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Qualify the “zero breaking-change cost” statement.
Line 109 says the renames have zero breaking-change cost. Lines 110-114 require pre-integration snapshot users to change the artifact ID, version, and configuration keys. Limit the claim to released Maven Central coordinates so it does not contradict the migration instructions.
Proposed wording
-Both renames happened before any Maven Central release of this module existed, so they carry zero breaking-change cost.
+Neither name had a Maven Central release, so released coordinates are unchanged; pre-integration snapshot users must apply the migration below.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| **Two coordinate/naming corrections made during the pre-integration conversion:** the three | |
| modules were renamed from `spring-boot-morphium-*` to `morphium-spring-boot-*`, following the | |
| Spring Boot starter naming convention (the `spring-boot-` prefix is reserved for Spring's own | |
| starters); and the configuration property prefix was renamed from `spring.morphium.*` to | |
| `morphium.*`, since the `spring.*` namespace is reserved for Spring Boot's own configuration | |
| keys. Both renames happened before any Maven Central release of this module existed, so they | |
| carry zero breaking-change cost. **Existing users of the pre-integration | |
| `de.caluga:spring-boot-morphium-starter:1.0.0-SNAPSHOT`** must update their dependency's | |
| artifactId to `morphium-spring-boot-starter`, its version to the Morphium version they adopt | |
| (currently `6.3.x`), and rename every `spring.morphium.*` key in their | |
| `application.properties`/`.yml` to `morphium.*` (e.g. `spring.morphium.database` → | |
| `morphium.database`) — no Java API changes; `MorphiumProperties`, `@EnableMorphiumRepositories`, | |
| **Two coordinate/naming corrections made during the pre-integration conversion:** the three | |
| modules were renamed from `spring-boot-morphium-*` to `morphium-spring-boot-*`, following the | |
| Spring Boot starter naming convention (the `spring-boot-` prefix is reserved for Spring's own | |
| starters); and the configuration property prefix was renamed from `spring.morphium.*` to | |
| `morphium.*`, since the `spring.*` namespace is reserved for Spring Boot's own configuration | |
| keys. Neither name had a Maven Central release, so released coordinates are unchanged; pre-integration snapshot users must apply the migration below. **Existing users of the pre-integration | |
| `de.caluga:spring-boot-morphium-starter:1.0.0-SNAPSHOT`** must update their dependency's | |
| artifactId to `morphium-spring-boot-starter`, its version to the Morphium version they adopt | |
| (currently `6.3.x`), and rename every `spring.morphium.*` key in their | |
| `application.properties`/`.yml` to `morphium.*` (e.g. `spring.morphium.database` → | |
| `morphium.database`) — no Java API changes; `MorphiumProperties`, `@EnableMorphiumRepositories`, |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@CHANGELOG.md` around lines 103 - 114, Update the “zero breaking-change cost”
statement in the pre-integration conversion changelog entry to qualify it as
applying only to released Maven Central coordinates, while retaining the
existing migration requirements for pre-integration snapshot users.
| ## Full Documentation | ||
|
|
||
| This page is an overview. The complete module documentation — installation, the full | ||
| property reference, repository usage, transactions, testing, and the detailed | ||
| architecture comparison with Quarkus — lives in the module's own README: | ||
|
|
||
| [`morphium-spring-boot-starter/README.md`](https://github.com/sboesebeck/morphium/tree/develop/morphium-spring-boot-starter/README.md) |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Use the integrated module README path in both documentation copies.
Both links omit the spring-boot-morphium/ directory and use tree for a file. The checked target currently returns 404. ()
docs/spring-boot.md#L298-L304: link tospring-boot-morphium/README.mdwith a file URL.spring-boot-morphium/docs-for-morphium/spring-boot.md#L298-L304: apply the same path and URL correction.
Proposed link target
-[`morphium-spring-boot-starter/README.md`](https://github.com/sboesebeck/morphium/tree/develop/morphium-spring-boot-starter/README.md)
+[`spring-boot-morphium/README.md`](https://github.com/sboesebeck/morphium/blob/develop/spring-boot-morphium/README.md)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| ## Full Documentation | |
| This page is an overview. The complete module documentation — installation, the full | |
| property reference, repository usage, transactions, testing, and the detailed | |
| architecture comparison with Quarkus — lives in the module's own README: | |
| [`morphium-spring-boot-starter/README.md`](https://github.com/sboesebeck/morphium/tree/develop/morphium-spring-boot-starter/README.md) | |
| ## Full Documentation | |
| This page is an overview. The complete module documentation — installation, the full | |
| property reference, repository usage, transactions, testing, and the detailed | |
| architecture comparison with Quarkus — lives in the module's own README: | |
| [`spring-boot-morphium/README.md`](https://github.com/sboesebeck/morphium/blob/develop/spring-boot-morphium/README.md) |
📍 Affects 2 files
docs/spring-boot.md#L298-L304(this comment)spring-boot-morphium/docs-for-morphium/spring-boot.md#L298-L304
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/spring-boot.md` around lines 298 - 304, Update the “Full Documentation”
link in docs/spring-boot.md:298-304 to target spring-boot-morphium/README.md
using a file URL rather than the current tree URL. Apply the identical
correction in spring-boot-morphium/docs-for-morphium/spring-boot.md:298-304,
preserving the surrounding documentation text.
|
|
||
| The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). | ||
|
|
||
| ## [Unreleased] - 1.0.0-SNAPSHOT |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Align the changelog version with lockstep release versioning.
Line 7 uses 1.0.0-SNAPSHOT, but the module documentation states that the module has no separate version line and currently uses the Morphium reactor version. Use 6.3.0-SNAPSHOT or the project’s generated version value.
Proposed fix
-## [Unreleased] - 1.0.0-SNAPSHOT
+## [Unreleased] - 6.3.0-SNAPSHOT📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| ## [Unreleased] - 1.0.0-SNAPSHOT | |
| ## [Unreleased] - 6.3.0-SNAPSHOT |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@spring-boot-morphium/CHANGELOG.md` at line 7, Update the Unreleased heading
in the changelog to use the lockstep Morphium reactor version, 6.3.0-SNAPSHOT,
or the project’s generated version value instead of the module-specific
1.0.0-SNAPSHOT.
| if (properties.getReplicaSetName() != null && !m.getDriver().isReplicaSet()) { | ||
| log.debug("Forcing replicaSet=true on driver (single-node replica set workaround)"); | ||
| m.getDriver().setReplicaSet(true); | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Inspect driver replica-set detection and setReplicaSet usage in morphium-core.
set -euo pipefail
rg -nP --type=java -C6 '\bsetReplicaSet\s*\(' morphium-core/src/main/java || true
rg -nP --type=java -C6 '\bisReplicaSet\s*\(\s*\)\s*\{' morphium-core/src/main/java || true
rg -nP --type=java -C4 'getReplicaSetName\s*\(' morphium-core/src/main/java || trueRepository: Bardioc1977/morphium
Length of output: 15689
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "## Candidate files"
fd -a 'MorphiumAutoConfiguration|Morphium.*Properties'\.java . | sed 's#^\./##'
echo
echo "## AutoConfiguration outline"
ast-grep outline spring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumAutoConfiguration.java --view expanded || true
echo
echo "## Relevant MorphiumAutoConfiguration sections"
sed -n '80,110p' spring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumAutoConfiguration.java | cat -n -v
echo "---"
sed -n '180,200p' spring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumAutoConfiguration.java | cat -n -v
echo
echo "## Properties"
fd -a 'Morphium.*Properties'\.java spring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java | xargs -r sed -n '1,220p'
echo
echo "## setReplicaSet implementation locations"
rg -n --type=java -C8 'public void setReplicaSet|void setReplicaSet|`@Override`' morphium-core/src/main/java/de/caluga/morphium/driver | sed -n '1,220p'Repository: Bardioc1977/morphium
Length of output: 36111
Align the replicaSetName guard with buildConfig.
properties.getReplicaSetName() only rejects null in this block, while buildConfig() also rejects blank values before calling setRequiredReplicaSetName. A whitespace-only morphium.replica-set-name can still force m.getDriver().setReplicaSet(true) without setting a replica-set name. Use the same blank check before forcing the driver topology flag.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@spring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumAutoConfiguration.java`
around lines 95 - 98, Update the guard in MorphiumAutoConfiguration around
getReplicaSetName() to reject blank values as buildConfig() does, before calling
m.getDriver().setReplicaSet(true). Preserve the existing isReplicaSet() check
and only force replica-set topology when a nonblank replica-set name is
configured.
| Map<String, String> typeIds = new HashMap<>(); | ||
| try (scanResult) { | ||
| for (String annotationName : new String[]{Entity.class.getName(), Embedded.class.getName()}) { | ||
| for (var ci : scanResult.getClassesWithAnnotation(annotationName)) { | ||
| String cn = ci.getName(); | ||
| typeIds.put(cn, cn); | ||
| var ai = ci.getAnnotationInfo(annotationName); | ||
| if (ai != null) { | ||
| var typeIdParam = ai.getParameterValues().getValue("typeId"); | ||
| if (typeIdParam instanceof String tid && !".".equals(tid)) { | ||
| typeIds.put(tid, cn); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| if (!typeIds.isEmpty()) { | ||
| AnnotationAndReflectionHelper.registerTypeIds(typeIds); | ||
| log.info("Pre-registered {} entity type IDs, Morphium will skip ClassGraph scan", typeIds.size()); | ||
| } |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Trace preRegisteredTypeIds usage and expected key semantics in morphium-core.
set -euo pipefail
rg -nP --type=java -C10 'preRegisteredTypeIds' morphium-core/src/main/java || true
rg -nP --type=java -C6 '\bregisterTypeIds\s*\(' --glob '!**/spring-boot-morphium/**' . || true
rg -nP --type=java -C6 'getTypeIdForClass|getClassForTypeId|typeId' morphium-core/src/main/java/de/caluga/morphium/AnnotationAndReflectionHelper.java || trueRepository: Bardioc1977/morphium
Length of output: 25529
🏁 Script executed:
#!/bin/bash
# Inspect the Spring Boot builder and core usage around pre-registered keys without running repo code.
set -euo pipefail
printf '--- MorphiumAutoConfiguration relevant section ---\n'
sed -n '100,145p' spring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumAutoConfiguration.java
printf '\n--- Quarkus builder relevant section ---\n'
sed -n '215,270p' quarkus-morphium/runtime/src/main/java/de/caluga/morphium/quarkus/MorphiumProducer.java
printf '\n--- TypeId cache usages ---\n'
rg -n --type=java -C4 'classNameByType|getClassForTypeId|getTypeIdForClass|AnnotationAndReflectionHelper \(|new AnnotationAndReflectionHelper|registerTypeIds|clearTypeIdCache' morphium-core/src/main/java | sed -n '1,220p'
printf '\n--- Behavioral probe: duplicate keys in putAll semantics and explicit FQCN collision ---\n'
python3 - <<'PY'
from copy import deepcopy
def spring_builder(entities):
# Mirrors current Spring builder: put FQCN first, then explicit typeId if non-dot.
m = {}
for cls_name, explicit_type_id in entities:
m[cls_name] = cls_name
if explicit_type_id and explicit_type_id != ".":
m[explicit_type_id] = cls_name
return m
def quarkus_builder(names):
# Mirrors current Quarkus builder: put explicit typeId first if non-dot, then FQCN.
m = {}
for cls_name, explicit_type_id, is_embedded in names:
if explicit_type_id and explicit_type_id != ".":
m[explicit_type_id] = cls_name
m[cls_name] = cls_name
return m
entities_shared = [
("com.example.A", "."),
("com.example.B", "."),
]
print("spring", spring_builder(entities_shared))
# Duplicate explicit typeId.
entities_dup = [
("com.example.A", "shared"),
("com.example.B", "shared"),
]
spring_dup = spring_builder(entities_dup)
quarkus_dup = quarkus_builder([(n, t, False) for n, t in entities_dup])
print("spring duplicate explicit", spring_dup)
print("quarkus duplicate explicit", quarkus_dup)
# Explicit typeId collides with another class FQCN.
entities_collision = [
("com.example.A", "."),
("com.example.B", "com.example.A"),
]
spring_collision = spring_builder(entities_collision)
quarkus_collision = quarkus_builder([("com.example.B", "com.example.A", False)])
print("spring FQCN collision", spring_collision)
print("quarkus FQCN collision", quarkus_collision)
PYRepository: Bardioc1977/morphium
Length of output: 249
🏁 Script executed:
#!/bin/bash
# Inspect the Spring Boot and Quarkus builders, plus type-id cache usage, without running repo code.
set -euo pipefail
echo '--- MorphiumAutoConfiguration relevant section ---'
sed -n '100,145p' spring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumAutoConfiguration.java
echo
echo '--- Quarkus builder relevant section ---'
if [ -f quarkus-morphium/runtime/src/main/java/de/caluga/morphium/quarkus/MorphiumProducer.java ]; then
sed -n '215,270p' quarkus-morphium/runtime/src/main/java/de/caluga/morphium/quarkus/MorphiumProducer.java
fi
echo
echo '--- TypeId cache usages ---'
rg -n --type=java -C4 'classNameByType|getClassForTypeId|getTypeIdForClass|AnnotationAndReflectionHelper \(|new AnnotationAndReflectionHelper|registerTypeIds|clearTypeIdCache' morphium-core/src/main/java | sed -n '1,220p'
echo
echo '--- Behavioral probe: duplicate keys in putAll semantics and explicit FQCN collision ---'
python3 - <<'PY'
def spring_builder(entities):
m = {}
for cls_name, explicit_type_id in entities:
m[cls_name] = cls_name
if explicit_type_id and explicit_type_id != ".":
m[explicit_type_id] = cls_name
return m
def quarkus_builder(names):
m = {}
for cls_name, explicit_type_id, is_embedded in names:
if explicit_type_id and explicit_type_id != ".":
m[explicit_type_id] = cls_name
m[cls_name] = cls_name
return m
entities_shared = [
("com.example.A", "."),
("com.example.B", "."),
]
print("spring same FQCN fallback", spring_builder(entities_shared))
entities_dup = [
("com.example.A", "shared"),
("com.example.B", "shared"),
]
spring_dup = spring_builder(entities_dup)
quarkus_dup = quarkus_builder([(n, t, False) for n, t in entities_dup])
print("spring duplicate explicit typeId", spring_dup)
print("quarkus duplicate explicit typeId", quarkus_dup)
entities_collision = [
("com.example.A", "."),
("com.example.B", "com.example.A"),
]
spring_collision = spring_builder(entities_collision)
quarkus_collision = quarkus_builder([("com.example.B", "com.example.A", False)])
print("spring explicit typeId equals another class FQCN", spring_collision)
print("quarkus explicit typeId equals another class FQCN", quarkus_collision)
PYRepository: Bardioc1977/morphium
Length of output: 32450
Avoid pre-registering duplicate type IDs
AnnotationAndReflectionHelper.registerTypeIds() accepts both explicit typeId values and fully qualified class names, then applies that map with putAll(). If two entities share an explicit typeId, or if typeId is the FQCN of another entity, the second entry wins silently and Morphium deserializes documents to the wrong class. Reject duplicate keys while building the map, or change registerTypeIds() to validate/prevent collisions before copying the map.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@spring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumAutoConfiguration.java`
around lines 117 - 136, Update the type ID registration flow around
MorphiumAutoConfiguration and AnnotationAndReflectionHelper.registerTypeIds to
detect collisions before applying the mappings. Reject duplicate explicit typeId
values and conflicts between typeIds and fully qualified class names instead of
allowing later entries to overwrite earlier ones; preserve registration only
when every key maps unambiguously to a single entity class.
| public Object aroundTransactional(ProceedingJoinPoint pjp) throws Throwable { | ||
| morphium.startTransaction(); |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Restore the write-buffer state when transaction start fails.
Morphium.startTransaction() disables the thread-local write buffer before it calls the driver. If the driver start fails, Line 86 is outside the try block and no abort restores that state. Make Morphium.startTransaction() restore its prior write-buffer state on failure, or add equivalent guarded cleanup here.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@spring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumTransactionAspect.java`
around lines 85 - 86, Update aroundTransactional so Morphium.startTransaction()
is covered by guarded failure cleanup, ensuring the prior thread-local
write-buffer state is restored if transaction startup throws. Prefer fixing
Morphium.startTransaction() itself to restore that state on driver failure;
otherwise add equivalent abort/cleanup around the call while preserving normal
transaction execution.
| morphium.commitTransaction(); | ||
| return result; | ||
| } catch (Throwable t) { | ||
| morphium.abortTransaction(); | ||
| throw t; |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
Preserve the primary failure when abort also fails.
If pjp.proceed() or commitTransaction() fails and abortTransaction() also throws, the abort failure replaces the primary failure. Catch the abort failure, add it as suppressed to the primary failure, and then rethrow the primary failure.
Proposed fix
- } catch (Throwable t) {
- morphium.abortTransaction();
- throw t;
+ } catch (Throwable failure) {
+ try {
+ morphium.abortTransaction();
+ } catch (Throwable abortFailure) {
+ failure.addSuppressed(abortFailure);
+ }
+ throw failure;
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| morphium.commitTransaction(); | |
| return result; | |
| } catch (Throwable t) { | |
| morphium.abortTransaction(); | |
| throw t; | |
| morphium.commitTransaction(); | |
| return result; | |
| } catch (Throwable failure) { | |
| try { | |
| morphium.abortTransaction(); | |
| } catch (Throwable abortFailure) { | |
| failure.addSuppressed(abortFailure); | |
| } | |
| throw failure; |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@spring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java/de/caluga/morphium/spring/autoconfigure/MorphiumTransactionAspect.java`
around lines 89 - 93, Update the catch block in MorphiumTransactionAspect around
the existing transaction flow so abortTransaction() failures are caught and
added as suppressed exceptions to the original Throwable t, then rethrow t.
Preserve the current abort attempt and ensure the primary proceed or commit
failure remains the propagated exception.
| var saved = (TestEntity) repository.save(entity); | ||
| assertNotNull(saved.getId()); | ||
|
|
||
| var found = repository.findById(saved.getId()); | ||
| assertTrue(found.isPresent()); | ||
| assertEquals("test", ((TestEntity) found.get()).getName()); |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Inspect the MorphiumRepository and CrudRepository-facing signatures used by the proxy.
set -euo pipefail
fd -t f 'MorphiumRepository.java' | while IFS= read -r f; do
echo "=== $f ==="
ast-grep outline "$f" --items all
done
fd -t f 'AbstractMorphiumRepository.java' | while IFS= read -r f; do
echo "=== $f ==="
rg -n -C 3 'class AbstractMorphiumRepository|public .* save\(|public .* findById\(' "$f"
doneRepository: Bardioc1977/morphium
Length of output: 2988
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== MorphiumRepository.java ==="
cat -n morphium-jakarta-data/src/main/java/de/caluga/morphium/data/MorphiumRepository.java
echo
echo "=== AbstractMorphiumRepository.java relevant signatures ==="
rg -n 'extends|implements|Optional<|List<|<K extends|K extends|save\(|findById\(|findByStatus|doFindById|doSave\(' morphium-jakarta-data/src/main/java/de/caluga/morphium/data/AbstractMorphiumRepository.java
sed -n '74,260p' morphium-jakarta-data/src/main/java/de/caluga/morphium/data/AbstractMorphiumRepository.java | cat -n
echo
echo "=== Test repository test file relevant lines ==="
sed -n '1,80p' spring-boot-morphium/morphium-spring-boot-autoconfigure/src/test/java/de/caluga/morphium/spring/autoconfigure/MorphiumRepositoryProxyTest.java | cat -n
echo
echo "=== Search for TestEntityRepository definitions ==="
rg -n -C 4 'interface TestEntityRepository|class TestEntityRepository|extends MorphiumRepository<TestEntity|MorphiumRepository<.*TestEntity' .Repository: Bardioc1977/morphium
Length of output: 20277
🌐 Web query:
Jakarta Data CrudRepository save T findById ID return type JDK 1.0 API
💡 Result:
In the Jakarta Data API, the CrudRepository interface does not use JDK 1.0 APIs; it is a modern specification requiring a minimum of Java SE 17 [1]. Regarding the return types for the specified operations: 1. Save: The CrudRepository interface does not define a generic save method itself; instead, it inherits from BasicRepository [2] or utilizes specific insert and update methods [3][4]. The save(S entity) method provided by the BasicRepository interface returns the entity itself (type S) [2]. 2. FindById: This method is inherited from the BasicRepository interface [5][2]. According to the Jakarta Data specification, it returns an Optional (or the entity type T directly depending on specific implementation patterns, though standard repository design typically favors Optional for lookups by ID) [2]. It is important to note that Jakarta Data is a modern Jakarta EE specification and is not associated with the legacy JDK 1.0 API.
Citations:
- 1: https://jakarta.ee/specifications/data/1.0/
- 2: https://jakarta.ee/specifications/platform/11/apidocs/jakarta/data/repository/basicrepository
- 3: https://jakarta.ee/specifications/data/1.1/apidocs/jakarta.data/jakarta/data/repository/crudrepository
- 4: https://jakarta.ee/specifications/data/1.0/apidocs/jakarta.data/jakarta/data/repository/crudrepository
- 5: https://jakarta.ee/specifications/platform/11/apidocs/jakarta/data/repository/crudrepository
Declare generic repository signatures for Jakarta Data CRUD methods.
MorphiumRepository<T, K> currently inherits Jakarta Data save()/findById() without repository-level type bindings, so the proxy exposes those methods as untyped/Object and requires casts in TestEntityRepository consumers. Add explicit generic methods to MorphiumRepository<T, K> or AbstractMorphiumRepository<T, K> with return types T/Optional<T> so TestEntityRepository does not need (TestEntity) casts.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@spring-boot-morphium/morphium-spring-boot-autoconfigure/src/test/java/de/caluga/morphium/spring/autoconfigure/MorphiumRepositoryProxyTest.java`
around lines 37 - 42, Update MorphiumRepository<T, K> or
AbstractMorphiumRepository<T, K> to explicitly redeclare the Jakarta Data CRUD
methods save and findById with return types T and Optional<T>, preserving the
existing key and parameter types. Ensure TestEntityRepository consumers receive
typed results so the casts in MorphiumRepositoryProxyTest are no longer
required.
| <dependencies> | ||
| <dependency> | ||
| <groupId>de.caluga</groupId> | ||
| <artifactId>morphium-spring-boot-autoconfigure</artifactId> | ||
| <version>${project.version}</version> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>de.caluga</groupId> | ||
| <artifactId>morphium</artifactId> | ||
| <version>${project.version}</version> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>de.caluga</groupId> | ||
| <artifactId>morphium-jakarta-data</artifactId> | ||
| <version>${project.version}</version> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>jakarta.data</groupId> | ||
| <artifactId>jakarta.data-api</artifactId> | ||
| </dependency> | ||
| </dependencies> |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
rg -n -C 4 \
'org\.aspectj|`@Aspect`|`@Around`|ConditionalOnClass|MorphiumTransactional|MorphiumTransactionAspect' \
spring-boot-morphium/morphium-spring-boot-autoconfigure/src/main/java
sed -n '16,40p' spring-boot-morphium/morphium-spring-boot-autoconfigure/pom.xml
sed -n '16,40p' spring-boot-morphium/morphium-spring-boot-starter/pom.xmlRepository: Bardioc1977/morphium
Length of output: 36011
Add AOP transitively to morphium-spring-boot-starter.
MorphiumTransactionAspect needs org.aspectj.lang.annotation.Aspect, but spring-boot-starter-aop is optional in morphium-spring-boot-autoconfigure and is not redeclared by this starter. A consumer that adds only morphium-spring-boot-starter will not get the AspectJ runtime needed for @MorphiumTransactional.
Proposed fix
<dependencies>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-aop</artifactId>
+ </dependency>
<dependency>
<groupId>de.caluga</groupId>
<artifactId>morphium-spring-boot-autoconfigure</artifactId>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <dependencies> | |
| <dependency> | |
| <groupId>de.caluga</groupId> | |
| <artifactId>morphium-spring-boot-autoconfigure</artifactId> | |
| <version>${project.version}</version> | |
| </dependency> | |
| <dependency> | |
| <groupId>de.caluga</groupId> | |
| <artifactId>morphium</artifactId> | |
| <version>${project.version}</version> | |
| </dependency> | |
| <dependency> | |
| <groupId>de.caluga</groupId> | |
| <artifactId>morphium-jakarta-data</artifactId> | |
| <version>${project.version}</version> | |
| </dependency> | |
| <dependency> | |
| <groupId>jakarta.data</groupId> | |
| <artifactId>jakarta.data-api</artifactId> | |
| </dependency> | |
| </dependencies> | |
| <dependencies> | |
| <dependency> | |
| <groupId>org.springframework.boot</groupId> | |
| <artifactId>spring-boot-starter-aop</artifactId> | |
| </dependency> | |
| <dependency> | |
| <groupId>de.caluga</groupId> | |
| <artifactId>morphium-spring-boot-autoconfigure</artifactId> | |
| <version>${project.version}</version> | |
| </dependency> | |
| <dependency> | |
| <groupId>de.caluga</groupId> | |
| <artifactId>morphium</artifactId> | |
| <version>${project.version}</version> | |
| </dependency> | |
| <dependency> | |
| <groupId>de.caluga</groupId> | |
| <artifactId>morphium-jakarta-data</artifactId> | |
| <version>${project.version}</version> | |
| </dependency> | |
| <dependency> | |
| <groupId>jakarta.data</groupId> | |
| <artifactId>jakarta.data-api</artifactId> | |
| </dependency> | |
| </dependencies> |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@spring-boot-morphium/morphium-spring-boot-starter/pom.xml` around lines 17 -
37, Add spring-boot-starter-aop as a non-optional dependency in the
morphium-spring-boot-starter POM so consumers receive the AspectJ runtime
required by MorphiumTransactionAspect and `@MorphiumTransactional`.
| @@ -0,0 +1,408 @@ | |||
| # Morphium Spring Boot Starter | |||
|
|
|||
| [](https://github.com/Bardioc1977/spring-boot-morphium/actions/workflows/build.yml) | |||
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Update the build badge for the integrated repository.
Line 3 still reads the archived Bardioc1977/spring-boot-morphium workflow. This README now documents the module inside sboesebeck/morphium, so the badge can report stale status or stop working. Point it to the main repository workflow or remove it.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@spring-boot-morphium/README.md` at line 3, Update the README Build badge URL
and link to reference the active sboesebeck/morphium repository workflow instead
of Bardioc1977/spring-boot-morphium, or remove the badge if no valid integrated
workflow exists.
…ation, not a plain @component A plain @component in this library's own package is only picked up by Spring Boot's component scan when the scan happens to cover that package -- for any real application depending on morphium-spring-boot-starter as an external jar, component scan starts in the application's own base package and never reaches here, so the aspect bean was never created and @MorphiumTransactional methods ran without startTransaction()/commit/abort at all, silently. Changed to @autoConfiguration and registered in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports alongside MorphiumAutoConfiguration and MorphiumHealthAutoConfiguration, so Spring Boot's auto-configuration import mechanism instantiates it regardless of the application's package structure. Adds MorphiumTransactionAspectTest verifying the aspect bean actually exists in the context and that @MorphiumTransactional methods commit on normal return / abort on exception. Found in code review on PR #18 (Bardioc1977/morphium).
…ived queries asynchronously Two related bugs in MorphiumRepositoryInvocationHandler: 1. buildConditionsSpec() (used by @Find/@delete methods) read @PARAM instead of Jakarta Data's @by for field binding. Without -parameters (the parent compiler config does not set it), the fallback to the reflected parameter name produced conditions like "arg0:0" instead of the intended field name; even with parameter names available, an explicit @by value was ignored entirely. FindMethodBridge then queried the wrong/non-existent field, so annotated @Find/@delete methods returned no matches or affected the wrong data. Now reads @by, matching quarkus-morphium's MorphiumDataProcessor. 2. Derived query methods declared with a CompletionStage return type (e.g. findByStatusAsync) were excluded from returnsSingle but never dispatched to QueryMethodBridge.executeQueryAsync -- they always ran the synchronous executeQuery, so the generated proxy tried to cast the raw result (List, Long, etc.) to CompletionStage and threw ClassCastException instead of running asynchronously. Also strips the "Async" method-name suffix before parsing (e.g. "findByStatusAsync" -> "findByStatus"), matching quarkus-morphium's MorphiumDataProcessor convention -- without stripping it, MethodNameParser misreads the suffix as part of the field name and the query matches nothing. Adds regression tests for both: an @find+@by method against real InMemDriver data, and a CompletionStage-returning derived query resolved from a real CompletableFuture. Found in code review on PR #18 (Bardioc1977/morphium).
3a7a29e to
770dde7
Compare
…tFailure on successful connect The PRIMARY_PREFERRED and secondary-retry fallback sites re-read the volatile primaryNode field between null-check, hosts lookup and borrow - the heartbeat nulls it on stepdown/connection error, i.e. exactly during the failover window this code exists for, and hosts.get(null) threw an NPE that bypassed every MorphiumDriverException retry-catch on the read path. Both sites now use a local snapshot; the primary-fallback warning also carries the exception as cause now. getLastConnectFailure() is cleared on a successful connect so callers polling after recovery don't see the stale pre-recovery error.
…s update, BadValue on malformed types - pwd change without 'mechanisms' now preserves the user's existing mechanism set instead of resetting to the both-mechanisms default (which silently re-armed SCRAM-SHA-1 credentials for a SHA-256-only user) - mongod semantics - 'mechanisms' without 'pwd' is now a mongod-compatible subset-only update: stored credentials of the named mechanisms are kept verbatim, others are dropped, non-subset requests fail with BadValue - all optional fields are shape-checked before casting: roles/pwd/mechanisms of the wrong type produce a BadValue command error instead of an uncaught ClassCastException out of the command handler - userWriteEmitLock javadoc gains an explicit SCOPE paragraph: the ordering guarantee covers createUser/updateUser against each other only - raw deletes on admin.system.users and cross-namespace token inversion are documented follow-ups, not properties the lock provides Four new regression tests in UserWriteEventsTest.
…s, shutdown replication guard Three leadership/lifecycle hardenings from the 2026-08-06 review: 1. onLeadershipChange incremented leadershipEpoch and then wrote the primary flag unsynchronized - a preempted stale dispatch could re-assert its outdated flag AFTER a newer transition wrote the current one, leaving a demoted leader with primary==true forever, which no-ops startReplicationToLeader, the liveness probe and the retry chain: the node silently never replicates again. Epoch bump + flag flip are now one atomic unit (applyLeadershipFlip, under leadershipFlagLock); the startup poll in waitForElectionResult mirrors state under the same lock. New concurrent stress test asserts flag-follows-max-epoch. 2. The replication liveness probe sampled the instantaneous isWatchLive(), which routinely drops between two watch sessions - a probe firing in such a gap tore down a ReplicationManager whose connection DID come up. It now checks hasWatchEverRegistered() (watchGeneration > 0), matching its documented 'never actually connected' intent. The existing teardown test pinned the false-positive behavior and now simulates the real never-registered state; a new test pins the transient-gap no-op. 3. A late election/discovery callback could install and start a fresh ReplicationManager after shutdown() already ran stopReplication() - leaking daemon threads that hammer the force-shutdown driver. startReplicationToLeader now has a running guard and stopReplication() is synchronized so the two serialize on the PoppyDB monitor.
… DOWN after a grace period becomeLeader() clears peerLastContact, and isPeerReachable treated a missing entry as reachable forever - so the classic crashed ex-primary, which never acks a single heartbeat of the new leader, stayed SECONDARY for the rest of that leadership (the exact symptom 6b337d0 set out to fix survived in the failover scenario). A missing entry now only counts as reachable within the heartbeat freshness window measured from leaderSince; beyond that the peer reports state 8 / DOWN. New regression test: 3-node RS whose third member is never started - it must go DOWN after the grace period while the live follower stays SECONDARY.
…bbering the running node's pid file The busy-port check printed 'skipping node N' but fell through and started the node anyway: the new JVM couldn't bind, but its pid had already overwritten node-N.pid, and the failure branch then deleted that file - orphaning the still-running original process for stop/status. The skip is an else-branch (NOT continue: the port increment at the loop bottom must keep running, or every later node shifts onto the wrong port - the pre-4ead5fae code had exactly that bug).
…te/updateUser dropUser removes the user document and emits a documentKey-keyed delete event on admin.system.users under userWriteEmitLock - the same store-order-equals- token-order guarantee create/update already have, closing most of the delete gap the 2026-08-06 review documented (raw deletes on the collection remain outside the lock and are now explicitly discouraged in the SCOPE note). UserNotFound (11) for unknown users, BadValue for a missing name. customData follows mongod: createUser stores it, updateUser replaces it wholesale when given (including customData-only updates, which used to be rejected with BadValue) and preserves it when omitted - a pwd change no longer silently discards it (buildUserDocument creates a fresh document, so the carry-over is explicit). Non-document customData is BadValue on both commands. authenticationRestrictions remains unmodeled. Seven new regression tests in UserWriteEventsTest (TDD: all watched RED before implementation).
… as a delete dropuser joins WRITE_COMMANDS, so a secondary rejects it with 10107 NotWritablePrimary like every other write (UserWritePrimaryOnlyTest extended). No replication-side changes needed: the drop rides the existing documentKey- keyed delete apply in ReplicationManager - pinned end-to-end by the new UserReplicationTest.dropUserReplicates (user dropped on the primary stops being loginable on the secondary).
…ms-omission semantics; changelog The users-file section now spells out what the mechanism-preservation fix means for declarative files: an entry that OMITS mechanisms keeps an existing user's current mechanism set (mongod updateUser semantics) instead of resetting to the default pair - listing both mechanisms explicitly is the way back to the default. The out-of-scope note no longer implies dropUser doesn't exist: the file has no reconciliation-delete, but the command now does.
…ng, reply manipulation WireProxy earned its own docs page: it is a general-purpose wire-level test utility, not just the failover harness's engine. The page covers the three use cases (fault injection with freeze/reset/close semantics, frame observation/logging via FrameObserver, response rewriting up to injecting deliberately invalid replies), the address-rewriting trick that keeps a discovering driver inside the proxy topology, and an honest limitations list (no latency injection, client->backend deliberately raw, freeze one-way per connection). Linked from the developer testing guide's wire-failover section and the mkdocs nav under Testing & Development.
wire-proxy.md gains a complete end-to-end example (three proxies in front of a 3-node RS, shared AddressRewriter, logging observer on every proxy, write+ read flowing through, clean teardown) including the expected output - the hello lines showing PROXY addresses is the visible proof the rewriting works, and a mismatch diagnostic hint. Config matches DriverFailoverProxyTest's real setup (SSL/compression off - the proxy cannot frame-parse either). mkdocs build is now warning-free: - anchor fixes: '#authentication---auth' -> '#authentication-auth', '#bootstrapping-users---users-file' -> '#bootstrapping-users-users-file', '#stepdown--failover...' -> '#stepdown-failover...' (slugs verified against the actually generated HTML), why-morphium's '../poppydb.md' -> 'poppydb.md', quickstart's dead developer-guide#annotations -> api-reference#annotation-reference - nav: developer-testing-guide.md (Testing & Development), optimistic-locking and references-and-relationships howtos - releases/* stays out of nav deliberately (not_in_nav), superpowers/ internal design docs are excluded from the site entirely (exclude_docs)
…s, honest virtual-threads note The title said 'Morphium 6.2.4' while the latest tag is v6.2.10 - the version now lives only in the Maven Central badge and the dependency snippets (all bumped to 6.2.10), so the title can't rot again. The 'Java 21 with virtual threads' headline claim is gone: virtual threads were rolled back in 6.2.x (synchronized-pinning deadlocks under JDK 21); the v6.0 history section now says so explicitly instead of advertising three VT bullets that no longer hold, with re-evaluation noted for a JEP 491 (JDK 24+) baseline. The patch- release summary covers 6.2.5-6.2.10 (wire-stream desync fix, responseTo verification, change-stream resume tokens, exclusive-message double- processing). Quick-access gains the v6.2->v6.3 upgrade guide link. Both languages kept in sync.
…o rot Confirmed: the script only ever touched POM versions (versions:set / release:prepare), which is exactly why the README still advertised 6.2.4 while v6.2.10 was long released. bump_readme_versions() now runs right before release:prepare (which needs a clean tree - the helper commits on its own) and rewrites ONLY the machine-readable spots in README.md and README.de.md: <version>X.Y.Z</version> dependency snippets, poppydb-X.Y.Z-cli.jar mentions and de.caluga:poppydb:X.Y.Z coordinates. Deliberately NOT a blanket old->new replace: prose like the patch-release summaries describes content and stays human-maintained. No-op when the READMEs are already current; skipped on --dry-run; BSD-sed/bash-3.2 compatible like the rest of the script. Verified against copies of the real READMEs (18 snippet spots bumped, prose ranges untouched).
PoppyDB was buried inside the historical 'What's New in v6.2' section - as if it were a changelog item rather than a product. Both READMEs now carry a dedicated top-level PoppyDB section right after 'Why Morphium?', with five copy-paste how-tos: embedded test backend, standalone server with snapshot persistence + config file (--cfg/--check-config/--print-config), 3-node replica set (--rs-name/--rs-seed/--rs-priorities, user replication across failover), auth+TLS incl. --users-file provisioning (marked 6.3.0), and the message-queue-without-MongoDB pattern. A PoppyDB feature bullet joins the top list, quick-access links to the PoppyDB guide and deployment playbook, and the old v6.2 subsection shrinks to a pointer at the new section. All flags and API calls verified against docs/poppydb.md and the actual code (PoppyDB ctor, shutdown(), createMessaging()).
The zero-infrastructure option was missing from the very table whose point is infrastructure comparison. The new column stays honest: persistence is 'Snapshots (optional)' rather than 'Built in', and throughput claims 'similar, lower latency' backed by the documented mutual optimization - with the snapshot caveat spelled out in the footnote, which now links to the PoppyDB section. Both languages.
docs/v5-vs-v6-performance.md has the measurement: the same messaging workload ran at 223 msg/s / 4.5 ms latency against PoppyDB vs. 89 msg/s / 11.3 ms against a 3-node MongoDB replica set. The table cell states the relative result (2.5x the MongoDB backend - the absolute numbers come from a different test setup than the ~8K msg/s in the Morphium column, so mixing them in one row would mislead), the footnote carries the concrete numbers and links the benchmark. Both languages.
… numbers measured different things The ~8K msg/s figure is a one-way send->delivery measurement (no processing, no reply - the same kind of number the RabbitMQ/Kafka columns quote) from a different test than the benchmarked 89/223 msg/s, which are complete ping-pongs (request out, response received). One table row mixing both scales was indefensible. Now: a one-way row (Morphium ~8K, PoppyDB not separately measured, RabbitMQ/Kafka industry figures) and a round-trip row (89 msg/s MongoDB RS vs 223 msg/s PoppyDB, 2.5x at less than half the latency), with the footnote spelling out exactly what each row counts. Both languages.
Measures N messages from sender to a single listening receiver, first send to last receipt, no replies - the counterpart to the round-trip ping-pong numbers in docs/v5-vs-v6-performance.md, so the README comparison table can carry a SOURCED one-way figure per backend instead of the historic, no-longer-reproducible ~8K msg/s claim. Two variants: in-process PoppyDB and external MongoDB via -Dmorphium.uri. Tagged manual (a benchmark, not a regression test - asserts only completeness, never a rate); prints a greppable ONEWAY-RESULT line.
… claim MessagingOneWayThroughputBenchmark, run 2026-08-06 on the test-runner LXC (4 CPUs, same infra as the round-trip benchmark): 5000 messages, 4 sender threads, one listening receiver, clock from first send to last receipt. MongoDB (3-node homelab RS, external hosts): 868 msg/s PoppyDB (in-process, 4-CPU test runner): 769 msg/s PoppyDB (in-process, Apple-Silicon laptop): 2101 msg/s Honest reading, now spelled out in the benchmark doc and both README footnotes: one-way throughput is write-bound and an in-process PoppyDB shares the host's CPU with sender and receiver - on a small host it lands slightly BELOW the external replica set, on a laptop-class CPU well above. PoppyDB's real edge is round-trip latency (223 vs 89 msg/s at less than half the latency), and the table now says exactly that instead of implying a universal speedup. The unsourced ~8K figure is retired; the benchmark doc notes its provenance is no longer reproducible.
…tes, not messaging
…uite The CLI jar is the route for NON-Java stacks (the embedded how-to is Java-only): one self-contained jar from Maven Central (classifier cli), Python/Node/Go/Rust integration tests get a MongoDB-compatible server in milliseconds without Docker or Testcontainers. The example downloads it via curl from repo1 (link verified live), starts with --no-config so a stray ~/.config/poppydb/config on a developer machine can't skew a test run, and notes that killing the process discards all state. Both languages. release.sh's bump_readme_versions learns the repo1 PATH-segment pattern (de/caluga/poppydb/X.Y.Z/) - the new curl URL carries the version in the directory as well as the filename, and without this a release would have left a half-bumped, dead download link. Re-verified against a README copy.
…he jacoco version
…test-diffs, fail closed on diff errors
…e, guarded gh calls, changelog precision
… without blocking
…h, badges from the store branch
…mask usage errors publish_test_results() computed --commit/--branch via a plain 'git rev-parse HEAD' in the current working directory. In a CI orchestrator phase workdir (/tmp/morphium-phase-workdir-*, a symlink farm mirroring the repo WITHOUT a .git dir), that resolves to empty strings, which test_results_record.py then rejected as a usage error. Fix the resolution chain: try git rev-parse HEAD directly first (works in a normal checkout); if empty, resolve runtests.sh's own symlink target via python3's os.path.realpath (bash 3.2 has no readlink -f, but python3 is already a hard dependency of this function) and ask git in that real checkout instead. Empty branch falls back to "unknown"; if commit still can't be resolved at all, skip publishing with a notice instead of calling the python helper with blank required args. Also fix test_results_record.py: argparse's default ap.error() exits 2 on usage errors, colliding with the script's own documented "exit 2 = no parsable test logs, nothing to publish" contract. That collision is exactly what turned bug #1's blank --commit into a silently swallowed "skip" instead of the loud usage error it should have been. Override error() to exit 1, printing usage + message to stderr as argparse does by default - only the exit code changes. The intentional sys.exit(2) sites in parse_logdir()/build() are untouched.
Both scripts assumed their git calls ran with CWD inside the real repo checkout. That breaks in CI phase workdirs (/tmp/morphium-phase-workdir-*), a symlink farm mirroring the repo WITHOUT a .git dir - the same bug class already fixed in runtests.sh's commit/branch resolution. publishTestResults.sh: REMOTE_URL=$(git remote get-url "$REMOTE") ran in the CWD and died with 'fatal: not a git repository'. The rest of the script's git calls already operate inside its own temp clone ($WORKDIR/store) and were unaffected - this was the only CWD-bound call. updateReleaseReport.sh: REPO_ROOT was computed via 'cd "$(dirname "$0")" && pwd', which never dereferences the runtests.sh-style symlink a caller invokes it through - it stays inside the symlink farm, so every git call after it (tag lookup, rev-list, remote get-url) and the test_report.py subprocess (whose git calls inherit the CWD) all ran against a non-git directory. Fix, same technique in both: resolve the real repo root from the script's own argv0 via python3 os.path.realpath (bash 3.2 has no readlink -f, and python3 is already a hard dependency of this tooling), validate it with git -C $REPO_DIR rev-parse --git-dir, and either pass -C explicitly (publishTestResults.sh's single call) or cd into it once up front (updateReleaseReport.sh, so its own calls and test_report.py's inherited-CWD subprocess calls both land on the real repo).
Adopt the spring-boot-morphium repository (branch move-to-morphium) as an optional extension module, following the same pattern as morphium-jakarta-data (M2) and quarkus-morphium (M4). Copied per the M5-T4 dry-run copy-list (Abschnitt 1): root pom.xml, the three publishable modules (morphium-spring-boot-autoconfigure/-starter/-test, each pom.xml + src/), README.md, CHANGELOG.md and docs-for-morphium/spring-boot.md. Repo-wide policy/CI files (.git, target/, MIGRATION-NOTES.md, LICENSE, CODE_OF_CONDUCT.md, CONTRIBUTING.md, SECURITY.md, .github/, .gitignore, .DS_Store) are intentionally not carried over. The module-local spring-boot.version property is removed from spring-boot-morphium/pom.xml since it now inherits from morphium-parent (see next commit); the spring-boot-dependencies BOM import stays in the module POM per invariant I4.
Register the spring-boot-morphium module in the extensions profile, after morphium-jakarta-data and quarkus-morphium (in that order), plus a spring-boot.version property (3.4.13), analogous to the existing quarkus.version pattern. The spring-boot-dependencies BOM import stays in spring-boot-morphium/pom.xml (invariant I4) -- only the version property moves here so a Spring Boot upgrade is a single-line change in morphium-parent.
- docs/spring-boot.md: copied from spring-boot-morphium/docs-for-morphium/spring-boot.md - mkdocs.yml: register the Spring Boot page in the Extensions nav section (Jakarta Data, Quarkus Extension, Spring Boot), replacing the M5 placeholder comment left by the quarkus-morphium wave - docs/index.md: add a Spring Boot entry to the Extensions (Optional Modules) section, in the style of the existing Jakarta Data / Quarkus Extension entries - CHANGELOG.md: entry for spring-boot-morphium under Unreleased/Added, after the quarkus-morphium entry, covering the three published artifacts, feature set, the two pre-integration naming corrections (module rename and property prefix rename), lockstep versioning with migration guidance, core independence via -DskipExtensions, no Docker requirement, and provenance from Bardioc1977/spring-boot-morphium README.md/README.de.md intentionally left unchanged: neither carries a module overview listing morphium-jakarta-data or quarkus-morphium either (verified against the M2/M4 commits), so there is no existing structure to extend.
Registers morphium-spring-boot-autoconfigure, morphium-spring-boot-starter, and morphium-spring-boot-test through the module registry (MODULE_DIRS/ MODULE_ARTIFACT_IDS/MODULE_EXTRA_CLASSIFIERS), and adds morphium-spring-boot-parent as its own POM-only special case at both the dry-run and real-release bundle-building sites, mirroring morphium-parent/quarkus-morphium-parent. Unlike quarkus-morphium/integration-tests, morphium-spring-boot-test IS meant for publication: it is a user-facing test-support helper (the @MorphiumTest composite annotation), analogous to poppydb as its own published artifact, not an internal test suite -- this is a deliberate decision, not an assumption carried over from the quarkus-morphium precedent. Also extends ALL_POM_FILES with spring-boot-morphium/pom.xml, same reasoning as the quarkus-morphium/pom.xml entry added in M4: mvn versions:set bumps every pom.xml in the reactor regardless of registry membership. Fixes a real packaging gap found while verifying: morphium-spring-boot-starter has no source files at all (by design -- an empty jar that only pulls in morphium-spring-boot-autoconfigure via a single Maven coordinate, following Spring Boot's own starter convention). With a completely empty src/main/java, maven-source-plugin and maven-javadoc-plugin silently produced no -sources.jar/-javadoc.jar at all -- confirmed real Spring Boot starters (e.g. spring-boot-starter-web) on Maven Central DO publish both, so this needed a fix, not acceptance. Added a minimal package-info.java so both plugins have a compilation unit to process; verified all three modules now produce jar+sources+javadoc after the fix, and the full reactor build/tests remain green.
…ation, not a plain @component A plain @component in this library's own package is only picked up by Spring Boot's component scan when the scan happens to cover that package -- for any real application depending on morphium-spring-boot-starter as an external jar, component scan starts in the application's own base package and never reaches here, so the aspect bean was never created and @MorphiumTransactional methods ran without startTransaction()/commit/abort at all, silently. Changed to @autoConfiguration and registered in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports alongside MorphiumAutoConfiguration and MorphiumHealthAutoConfiguration, so Spring Boot's auto-configuration import mechanism instantiates it regardless of the application's package structure. Adds MorphiumTransactionAspectTest verifying the aspect bean actually exists in the context and that @MorphiumTransactional methods commit on normal return / abort on exception. Found in code review on PR #18 (Bardioc1977/morphium).
…ived queries asynchronously Two related bugs in MorphiumRepositoryInvocationHandler: 1. buildConditionsSpec() (used by @Find/@delete methods) read @PARAM instead of Jakarta Data's @by for field binding. Without -parameters (the parent compiler config does not set it), the fallback to the reflected parameter name produced conditions like "arg0:0" instead of the intended field name; even with parameter names available, an explicit @by value was ignored entirely. FindMethodBridge then queried the wrong/non-existent field, so annotated @Find/@delete methods returned no matches or affected the wrong data. Now reads @by, matching quarkus-morphium's MorphiumDataProcessor. 2. Derived query methods declared with a CompletionStage return type (e.g. findByStatusAsync) were excluded from returnsSingle but never dispatched to QueryMethodBridge.executeQueryAsync -- they always ran the synchronous executeQuery, so the generated proxy tried to cast the raw result (List, Long, etc.) to CompletionStage and threw ClassCastException instead of running asynchronously. Also strips the "Async" method-name suffix before parsing (e.g. "findByStatusAsync" -> "findByStatus"), matching quarkus-morphium's MorphiumDataProcessor convention -- without stripping it, MethodNameParser misreads the suffix as part of the field name and the query matches nothing. Adds regression tests for both: an @find+@by method against real InMemDriver data, and a CompletionStage-returning derived query resolved from a real CompletableFuture. Found in code review on PR #18 (Bardioc1977/morphium).
The M5 branch predates two version bumps on develop (6.3.0 -> 6.3.2).
morphium-parent's version moved on without these four POMs, which
still pointed at 6.3.0-SNAPSHOT -- Maven resolved the stale parent
model, so ${spring-boot.version} (defined only in the current
morphium-parent) was never interpolated and the BOM import failed
with a literal ${spring-boot.version} in the coordinate.
Also drops the explicit relativePath on the top-level module POM,
matching quarkus-morphium and morphium-jakarta-data, which rely on
plain reactor resolution instead.
38705fb to
06f59da
Compare
- MorphiumTransactionAspect: order after MorphiumAutoConfiguration, matching MorphiumHealthAutoConfiguration. @ConditionalOnBean is evaluated against beans registered so far, so without this it only worked by alphabetical-sort coincidence -- any rename could disable the aspect silently. - Sync stale 6.3.0-SNAPSHOT to the actual reactor version (6.3.2) in README.md, docs/spring-boot.md, docs-for-morphium/spring-boot.md. - Fix broken README cross-link (wrong module path, tree instead of blob) in the two doc copies. - Translate a German section heading in the two published (English) doc pages, third occurrence not flagged by review but same drift.
…ries Three defects in the repository proxy's method dispatch, all of them features the module's README already advertises. Derived queries never looked up dynamic Sort/Order/PageRequest/Limit parameters and always dispatched to the simple bridge overload. A Page<T> method therefore got a plain List back (ClassCastException at the proxy boundary) and a Sort<T> argument was silently dropped, giving insertion order with no error at all. Both branches now resolve the four parameter indices the same way buildJdqlHandler already did and call the overload that takes them; it short-circuits back to the simple overload itself when no dynamic parameter is present. @delete always called the void bridge and returned null, so the int/long return types Jakarta Data permits failed unboxing null at the proxy. Numeric return types now use executeAnnotatedDeleteCounted and report the number of deleted entities. @query and @find had no CompletionStage branch, and isSingleReturn did not exclude CompletionStage either, so an async method was analysed as a single-entity query, ran on the caller's thread, and handed the entity itself back where a stage was expected. Both now dispatch to the async bridges, and isSingleReturn excludes CompletionStage so the stage completes with the list the signature promises rather than one element. Also dispatch default methods through InvocationHandler.invokeDefault. A default method carries its own implementation and matched none of the analysis branches, so it ended in "Unsupported repository method". Handled in invoke() rather than analyzeMethod() because invokeDefault needs the proxy instance, which the MethodHandler interface cannot carry, and checked before the derived-query branch since a default method is free to be named findBy*.
…cond REQUIRED propagation, same semantics as quarkus-morphium's MorphiumTransactionalInterceptor: when a transaction is already active on this thread, the advice participates in it rather than opening its own, and leaves commit/abort to the outermost advised call. Without this, one @MorphiumTransactional method calling another lost everything the outer method had done: all drivers reject a second startTransaction() with IllegalArgumentException, that exception propagated into the outer advice's catch, and the outer transaction was aborted. Spring developers arrive with @transactional's REQUIRED default in mind, so this shape is reached easily. No nesting counter is needed - Morphium already tracks the active transaction per thread, which is why the Quarkus interceptor tests getTransaction() rather than counting depth. Retry, write-buffer and CosmosDB handling from that interceptor are deliberately not copied here; they are separate concerns. Documented on the advice: the REQUIRED semantics, and that this aspect has no rollback-rules concept and therefore aborts on any Throwable, unlike Spring's @transactional which by default rolls back on unchecked exceptions only.
preRegisterEntities() ran its own uncached ClassGraph scan and called AnnotationAndReflectionHelper.registerTypeIds, logging that Morphium would skip its own scan. That claim was wrong: registerTypeIds only short-circuits type-ID initialisation, while every other lookup still goes through ClassGraphCache, which builds a full ScanResult on first use. The @driver lookup in particular is unconditional for this module, because driverName always has a value and buildConfig always sets it. Net effect in a real application was two classpath scans instead of one, plus a misleading log line. Removing the method lets the cached scan serve everyone, which it already did for type IDs too. Verified the method had a single call site and no test asserted on it.
One regression test per finding, each verified to fail without its fix. They assert the resulting value, not merely the absence of an exception, because three of these defects had a silent-wrong-result variant: - dynamic Sort: asserts the actual ordering of three differently prioritised entities, since dropping the argument produced insertion order without any error - Page return type: asserts a Page comes back at all - counted @delete: asserts the returned count AND that the rows are gone - CompletionStage on @query and @find: asserts the stage completes with a List rather than a single entity - the shape that a half-fix (async branch without excluding CompletionStage from isSingleReturn) would still have got wrong - default method: deliberately named countBy* so it also proves the isDefault() check wins over derived-query parsing - nested transactions: the inner call goes through a second proxied bean rather than a self-invocation, so the aspect really runs twice; asserts both documents survive, and that an inner failure rolls back both 23 tests total, up from 15.
Copilot's second review pass caught what removing preRegisterEntities() in 767041f missed: an unused classgraph dependency declaration still justified by that method, and three prose copies (docs/spring-boot.md, its docs-for-morphium duplicate, CHANGELOG.md) still describing the pre-scan as a shipped feature. classgraph itself is not needed here - it already arrives transitively through morphium (morphium-core declares it, morphium-parent centralises the version), same as before the explicit declaration was added for the now-removed method.
Review-PR analog zu #16 (morphium-jakarta-data) und #17 (quarkus-morphium):
aktiviert CodeRabbit/Copilot/Codex gegen die neue spring-boot-morphium-Extension,
bevor der Upstream-PR gegen sboesebeck/morphium:develop gestellt wird.
Kontext
Drittes und letztes Erweiterungsmodul dieser Serie: nach
morphium-jakarta-data(#16 → sboesebeck#266, dort noch offen) und
quarkus-morphium(#17)folgt hier
spring-boot-morphium, die Spring Boot Auto-Configuration fürMorphium. Base-Branch ist
pr/quarkus-extension-module(nichtmaster), weilsboesebeck#266 noch nicht gemergt ist — der Diff hier zeigt daher ausschließlich die
spring-boot-morphium-Änderungen.
Was dieser PR macht
spring-boot-morphium/als neues optionales Modul: drei Submodule(
morphium-spring-boot-autoconfigure,-starter,-test), alle dreipubliziert (25 Dateien)
spring-boot-morphium-*→morphium-spring-boot-*(Spring-Boot-Namenskonvention: das
spring-boot--Präfix ist für Springselbst reserviert)
spring.morphium.*→morphium.*(derspring.*-Namensraum ist ebenfalls für Spring reserviert)extensions,spring-boot.versionzentralim Parent (3.4.13), Spring-Boot-BOM-Import bleibt im Modul-POM (Invariante I4)
docs/spring-boot.md, mkdocs.yml, CHANGELOG),release.shum vierArtefakte erweitert (inkl. eines POM-only-Sonderfalls für
morphium-spring-boot-parent)Verifikation
-DskipExtensionsbaut nur 3 Module, kein Spring imKern-Dependency-Tree
vorbestehende Flakies (Messaging-Timing, Byte-Buddy/JDK-25, kein lokaler
Mongo) — keine Regression
Verifikation gefundener Packaging-Bug im
starter-Modul — leeressrc/-Verzeichnis führte zu fehlenden sources/javadoc-Jars — wurde behoben)Vollständiger Bericht:
docs/plans/morphium-module-integration/reports/M5-T6-verification.mdim morphium-jakarta-data-Repo.
Ziel dieses PRs
Ausschließlich Community-Review (CodeRabbit/Copilot/Codex) auslösen. Kein Merge
geplant — nach Review-Fixes wird der Branch vor dem eigentlichen Upstream-PR
auf den dann aktuellen
origin/developrebast (sobald sboesebeck#266 gemergt ist).Summary by CodeRabbit
New Features
morphium.*settings.Documentation