Skip to content

Add GORM for MongoDB / Spring Data MongoDB interop module#15745

Open
codeconsole wants to merge 3 commits into
apache:8.0.xfrom
codeconsole:feat/mongo-spring-data-interop
Open

Add GORM for MongoDB / Spring Data MongoDB interop module#15745
codeconsole wants to merge 3 commits into
apache:8.0.xfrom
codeconsole:feat/mongo-spring-data-interop

Conversation

@codeconsole

Copy link
Copy Markdown
Contributor

Depends on #15744 (stacked PR)

This is stacked on top of #15744 (opt-in MongoDB transactions). Until #15744 merges, the diff here also includes its commit — please review/merge #15744 first, after which this PR reduces to just the new interop module. The unified transaction here relies on the ClientSession introduced by #15744.

What

A new opt-in module, grails-data-mongodb-spring-data, that lets GORM for MongoDB and Spring Data MongoDB run side by side over the same MongoClient, database and codecs — and, within a single @Transactional method, the same MongoDB transaction.

When the module and spring-data-mongodb are on the classpath of a Spring Boot app that has a GORM MongoDatastore, it auto-configures over GORM's connection:

  • a MongoDatabaseFactory bound to GORM's client + default database (it does not close GORM's client),
  • a MongoTemplate (+ MappingMongoConverter) sharing the driver codec registry,
  • a primary transactionManager (GormSharedSessionMongoTransactionManager) that binds GORM's ClientSession into Spring Data, so a GORM save() and a MongoTemplate/repository write in one @Transactional method commit or roll back together.

Unified transactions require GORM server-side transactions (grails.mongodb.transactional = true, from #15744). Spring Data repositories are enabled the usual way via @EnableMongoRepositories, on a package separate from GORM @Entity classes.

Boundary

Only the connection, codecs and (within a transaction) the ClientSession are shared; the two object-mapping models stay separate (GORM maps @Entity; Spring Data maps its own documents). Sharing the session reaches Spring Data's package-private MongoResourceHolder, so a small helper lives in package org.springframework.data.mongodb — verified against the Spring Data MongoDB 5.x line in Spring Boot 4, class-path only (not JPMS module-path). A single flat transaction (PROPAGATION_REQUIRED) is supported; REQUIRES_NEW/NESTED are not.

Tests

  • UnifiedMongoTransactionSpec — GORM + MongoTemplate commit and roll back together on one session; coexistence read; sequential transactions without session/holder leaks; a Spring Data repository over the shared connection; auto-config wiring; the shared factory does not close GORM's client.
  • GormSpringDataSessionSupportSpec — coupling smoke test that fails loudly if the Spring Data internal shape changes.

Targets 8.0.x.

GORM for MongoDB previously treated a transaction as a client-side flush
boundary: pending writes were batched and flushed on commit, but each write
auto-committed individually and nothing rolled back when a later operation failed.

This adds real server-side transactions backed by a com.mongodb.client.ClientSession.
When grails.mongodb.transactional is enabled (default false), a GORM transaction
starts a ClientSession and MongoDB transaction and every read and write for the
session runs within it, committing or aborting atomically. A new MongoTransaction
drives the commit (retrying on an UnknownTransactionCommitResult) and the abort, and
closes the session afterwards.

The feature is opt-in and degrades gracefully: a standalone topology is detected at
runtime and falls back to the legacy flush-only behavior with a one-time warning.
Identifier generation for native Long ids is intentionally left non-transactional,
mirroring the semantics of database sequences.
@borinquenkid

Copy link
Copy Markdown
Member

Hi @codeconsole,

Please keep an eye on #15678, which modifies the way the MongoRegistry is being handled. It might be worth checking your diff against those updates, as this PR is downstream from 8.0.x-hibernate7.

Introduces an optional module that lets GORM for MongoDB and Spring Data MongoDB
run side by side over the same MongoClient, database and codecs, and - within a
single transaction - the same MongoDB ClientSession.

When the module and spring-data-mongodb are on the classpath of a Spring Boot
application that has a GORM MongoDatastore, SpringDataMongoGormAutoConfiguration
registers, over GORM's existing connection: a MongoDatabaseFactory bound to GORM's
client and default database (which does not close that client), a MongoTemplate and
MappingMongoConverter sharing the driver codec registry, and a primary
transactionManager.

That manager, GormSharedSessionMongoTransactionManager, extends GORM's
DatastoreTransactionManager and binds GORM's ClientSession into Spring Data's
thread-bound resources, so a GORM save() and a MongoTemplate/repository write in one
@transactional method commit or roll back together. Unified transactions require GORM
server-side transactions (grails.mongodb.transactional = true). The two object-mapping
models stay separate; only the connection, codecs and session are shared.
@codeconsole codeconsole force-pushed the feat/mongo-spring-data-interop branch from 36e36a5 to 342579f Compare June 17, 2026 23:16
@testlens-app

testlens-app Bot commented Jun 18, 2026

Copy link
Copy Markdown

✅ All tests passed ✅

🏷️ Commit: fc36b95
▶️ Tests: 9514 executed
⚪️ Checks: 44/44 completed


Learn more about TestLens at testlens.app.

@jdaugherty jdaugherty left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whats the benefit for having Spring Data and GORM?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

3 participants