Skip to content

i18n: let a plugin that cannot rename downgrade the namespace check to a warning - #16200

Closed
codeconsole wants to merge 1 commit into
apache:8.0.xfrom
codeconsole:feature/i18n-plugin-namespace-lenience-8.0.x
Closed

i18n: let a plugin that cannot rename downgrade the namespace check to a warning#16200
codeconsole wants to merge 1 commit into
apache:8.0.xfrom
codeconsole:feature/i18n-plugin-namespace-lenience-8.0.x

Conversation

@codeconsole

Copy link
Copy Markdown
Contributor

Follow-up to #16102.

The gap

generateI18nDescriptor fails a plugin build when a base name sits outside the plugin's namespace. That default is right, and this PR does not change it — Spring resolves a base name to the first match on the classpath rather than merging, so two artifacts shipping the same base name shadow one another with nothing at runtime to say which won. Failing the plugin's own build puts the error in front of the only person who can rename the bundle.

What it lacks is an escape hatch, and grails { i18n { basenames } } is not one: declared base names are folded into the index before validatePluginNamespace runs, so a plugin cannot declare its way past the check.

That leaves a plugin that genuinely cannot rename — a base name that is part of a published contract, or a bundle vendored from somewhere else — with two options:

  • -x generateI18nDescriptor, which ships no descriptor at all and therefore drops the plugin's messages entirely, or
  • a fork.

The change

grails {
    i18n {
        enforceNamespace = false
    }
}

Downgrades the same diagnosis to a build warning and writes the descriptor as it stands. Default unchanged (true).

The wording is identical whether it throws or warns — what is wrong and how to fix it do not depend on the severity — so validatePluginNamespace becomes describeNamespaceViolation, returning the message or null, and the caller decides. Both the message and the upgrade guide say plainly that the opt-out silences the build, not the collision.

Tests

  • GenerateI18nDescriptorTaskSpec — the check is on by convention; enforceNamespace = false records the bundle and does not throw; the message names the opt-out and its caveat.
  • I18nDescriptorFunctionalSpec + a new i18n-descriptor-plugin-namespace-off test project — the same colliding bundle as i18n-descriptor-plugin-collision, plus the i18n block, exercised end to end through processResources: the build succeeds, still reports the collision, and the descriptor records basenames=messages.

:grails-gradle-plugins:check passes (including validatePlugins), and rat passes.

Context

Found while upgrading an app to 8.0.0-M6. Its Spring Security fork shipped the base name it inherited from the upstream plugin — a real collision, and the check caught it, so this is not a complaint about the rule. Renaming was the right fix there. The opt-out is for the cases where it isn't available.

…to a warning

The namespace check exists because Spring resolves a base name to the first
match on the classpath instead of merging, so two artifacts shipping the same
base name shadow one another with nothing at runtime to say which won. Failing
the plugin's own build is the right default: it puts the error in front of the
only person who can rename the bundle.

It has no escape hatch, though, and grails { i18n { basenames } } is not one --
declared base names are folded into the index before the check runs, so a
plugin cannot declare its way past it. That leaves a plugin that genuinely
cannot rename -- a base name that is part of a published contract, or a bundle
vendored from somewhere else -- with `-x generateI18nDescriptor`, which ships no
descriptor at all and so drops the plugin's messages entirely, or a fork.

Add grails { i18n { enforceNamespace = false } }. It downgrades the same
diagnosis to a build warning and writes the descriptor as it stands; the
default is unchanged. The wording is identical either way, because what is
wrong and how to fix it do not change with the severity, and both the message
and the upgrade guide are explicit that this silences the build rather than the
collision.
@testlens-app

testlens-app Bot commented Aug 23, 2026

Copy link
Copy Markdown

🚨 TestLens detected 9 failed tests 🚨

Here is what you can do:

  1. Inspect the test failures carefully.
  2. If you are convinced that some of the tests are flaky, you can mute them below.
  3. Finally, trigger a rerun by checking the rerun checkbox.

Test Summary

CI - Groovy Joint Validation Build / Build Grails with Groovy snapshot (shard 1) > :grails-data-mongodb-core:test

Test Runs Flakiness
MongoTransactionSpec > test a REQUIRES_NEW inner transaction commits independently of a rolled back outer transaction 5% 🟠
MongoTransactionSpec > test a committed transaction persists all writes atomically 5% 🟠
MongoTransactionSpec > test a findOneAndDelete via the MongoEntity API participates in the transaction 5% 🟠
MongoTransactionSpec > test a per-transaction timeout is rejected rather than silently ignored 5% 🟠
MongoTransactionSpec > test a rolled back transaction discards a native Long id entity (id generation is non-transactional) 5% 🟠
MongoTransactionSpec > test a rolled back transaction discards all writes on the server 5% 🟠
MongoTransactionSpec > test native Long identifier generation works for entities committed in a transaction 5% 🟠
MongoTransactionSpec > test read-your-writes within an active transaction 5% 🟠
MongoTransactionSpec > test writes across multiple collections roll back together 5% 🟠

🏷️ Commit: baffa9d
▶️ Tests: 43395 executed
🟡 Checks: 43/78 completed

Test Failures

MongoTransactionSpec > test a REQUIRES_NEW inner transaction commits independently of a rolled back outer transaction (:grails-data-mongodb-core:test in CI - Groovy Joint Validation Build / Build Grails with Groovy snapshot (shard 1))
com.mongodb.MongoTimeoutException: Timed out while waiting for a server that matches WritableServerSelector. Client view of cluster state is {type=UNKNOWN, servers=[{address=localhost:32845, type=UNKNOWN, state=CONNECTING, exception={com.mongodb.MongoSocketOpenException: Exception opening socket}, caused by {java.net.ConnectException: Connection refused}}]
	at com.mongodb.internal.connection.BaseCluster.logAndThrowTimeoutException(BaseCluster.java:431)
	at com.mongodb.internal.connection.BaseCluster.lambda$selectServer$0(BaseCluster.java:166)
	at com.mongodb.internal.time.Timeout.lambda$onExistsAndExpired$16(Timeout.java:238)
	at com.mongodb.internal.time.Timeout.lambda$run$10(Timeout.java:203)
	at com.mongodb.internal.time.TimePoint.checkedCall(TimePoint.java:100)
	at com.mongodb.internal.time.Timeout.call(Timeout.java:176)
	at com.mongodb.internal.time.Timeout.run(Timeout.java:196)
	at com.mongodb.internal.time.Timeout.onExistsAndExpired(Timeout.java:235)
	at com.mongodb.internal.time.Timeout.onExpired(Timeout.java:228)
	at com.mongodb.internal.connection.BaseCluster.selectServer(BaseCluster.java:165)
	at com.mongodb.internal.connection.SingleServerCluster.selectServer(SingleServerCluster.java:47)
	at com.mongodb.internal.binding.ClusterBinding.getWriteConnectionSource(ClusterBinding.java:91)
	at com.mongodb.client.internal.ClientSessionBinding.getConnectionSource(ClientSessionBinding.java:109)
	at com.mongodb.client.internal.ClientSessionBinding.getWriteConnectionSource(ClientSessionBinding.java:102)
	at com.mongodb.internal.operation.SyncOperationHelper.withSuppliedResource(SyncOperationHelper.java:169)
	at com.mongodb.internal.operation.SyncOperationHelper.withSourceAndConnection(SyncOperationHelper.java:138)
	at com.mongodb.internal.operation.SyncOperationHelper.withConnection(SyncOperationHelper.java:117)
	at com.mongodb.internal.operation.DropDatabaseOperation.execute(DropDatabaseOperation.java:73)
	at com.mongodb.internal.operation.DropDatabaseOperation.execute(DropDatabaseOperation.java:48)
	at com.mongodb.client.internal.MongoClusterImpl$OperationExecutorImpl.execute(MongoClusterImpl.java:474)
	at com.mongodb.client.internal.MongoDatabaseImpl.executeDrop(MongoDatabaseImpl.java:230)
	at com.mongodb.client.internal.MongoDatabaseImpl.drop(MongoDatabaseImpl.java:220)
	at org.grails.datastore.gorm.mongo.transactions.MongoTransactionSpec.setup_closure1(MongoTransactionSpec.groovy:58)
	at org.grails.datastore.gorm.GormStaticApi.withNewSession_closure23(GormStaticApi.groovy:767)
	at org.grails.datastore.mapping.core.DatastoreUtils.executeWithNewSession(DatastoreUtils.java:371)
	at org.grails.datastore.gorm.GormStaticApi.withNewSession(GormStaticApi.groovy:766)
	at org.grails.datastore.gorm.GormEntity$Trait$Helper.withNewSession(GormEntity.groovy:1157)
	at org.grails.datastore.gorm.mongo.transactions.MongoTransactionSpec.setup(MongoTransactionSpec.groovy:57)
MongoTransactionSpec > test a committed transaction persists all writes atomically (:grails-data-mongodb-core:test in CI - Groovy Joint Validation Build / Build Grails with Groovy snapshot (shard 1))
com.mongodb.MongoSocketReadException: Prematurely reached end of stream
	at com.mongodb.internal.connection.SocketStream.read(SocketStream.java:184)
	at com.mongodb.internal.connection.InternalStreamConnection.receiveResponseBuffers(InternalStreamConnection.java:1081)
	at com.mongodb.internal.connection.InternalStreamConnection.receiveCommandResponseBuffers(InternalStreamConnection.java:589)
	at com.mongodb.internal.connection.InternalStreamConnection.receiveCommandMessageResponse(InternalStreamConnection.java:569)
	at com.mongodb.internal.connection.InternalStreamConnection.sendAndReceiveInternal(InternalStreamConnection.java:496)
	at com.mongodb.internal.connection.InternalStreamConnection.lambda$sendAndReceive$1(InternalStreamConnection.java:385)
	at com.mongodb.internal.connection.InternalStreamConnection.sendAndReceive(InternalStreamConnection.java:388)
	at com.mongodb.internal.connection.UsageTrackingInternalConnection.sendAndReceive(UsageTrackingInternalConnection.java:111)
	at com.mongodb.internal.connection.DefaultConnectionPool$PooledConnection.sendAndReceive(DefaultConnectionPool.java:757)
	at com.mongodb.internal.connection.CommandProtocolImpl.execute(CommandProtocolImpl.java:60)
	at com.mongodb.internal.connection.DefaultServer$DefaultServerProtocolExecutor.execute(DefaultServer.java:207)
	at com.mongodb.internal.connection.DefaultServerConnection.executeProtocol(DefaultServerConnection.java:112)
	at com.mongodb.internal.connection.DefaultServerConnection.command(DefaultServerConnection.java:82)
	at com.mongodb.internal.connection.DefaultServerConnection.command(DefaultServerConnection.java:74)
	at com.mongodb.internal.connection.DefaultServer$OperationCountTrackingConnection.command(DefaultServer.java:297)
	at com.mongodb.internal.operation.SyncOperationHelper.lambda$executeRetryableWrite$11(SyncOperationHelper.java:285)
	at com.mongodb.internal.operation.SyncOperationHelper.lambda$withSourceAndConnection$1(SyncOperationHelper.java:146)
	at com.mongodb.internal.operation.SyncOperationHelper.withSuppliedResource(SyncOperationHelper.java:177)
	at com.mongodb.internal.operation.SyncOperationHelper.lambda$withSourceAndConnection$2(SyncOperationHelper.java:142)
	at com.mongodb.internal.operation.SyncOperationHelper.withSuppliedResource(SyncOperationHelper.java:177)
	at com.mongodb.internal.operation.SyncOperationHelper.withSourceAndConnection(SyncOperationHelper.java:138)
	at com.mongodb.internal.operation.SyncOperationHelper.lambda$executeRetryableWrite$12(SyncOperationHelper.java:270)
	at com.mongodb.internal.operation.SyncOperationHelper.lambda$decorateWriteWithRetries$13(SyncOperationHelper.java:329)
	at com.mongodb.internal.async.function.RetryingSyncSupplier.get(RetryingSyncSupplier.java:67)
	at com.mongodb.internal.operation.SyncOperationHelper.executeRetryableWrite(SyncOperationHelper.java:297)
	at com.mongodb.internal.operation.BaseFindAndModifyOperation.execute(BaseFindAndModifyOperation.java:81)
	at com.mongodb.client.internal.MongoClusterImpl$OperationExecutorImpl.execute(MongoClusterImpl.java:474)
	at com.mongodb.client.internal.MongoCollectionImpl.executeFindOneAndUpdate(MongoCollectionImpl.java:787)
	at com.mongodb.client.internal.MongoCollectionImpl.findOneAndUpdate(MongoCollectionImpl.java:766)
	at org.grails.datastore.mapping.mongo.engine.MongoCodecEntityPersister.generateIdentifier(MongoCodecEntityPersister.groovy:443)
	at org.grails.datastore.mapping.mongo.engine.MongoCodecEntityPersister.persistEntity(MongoCodecEntityPersister.groovy:226)
	at org.grails.datastore.mapping.mongo.engine.MongoCodecEntityPersister.persistEntity(MongoCodecEntityPersister.groovy:567)
	at org.grails.datastore.mapping.engine.EntityPersister.persist(EntityPersister.java:188)
	at org.grails.datastore.mapping.core.AbstractSession.persist(AbstractSession.java:609)
	at org.grails.datastore.gorm.GormInstanceApi.save_closure5(GormInstanceApi.groovy:213)
	at org.grails.datastore.mapping.core.DatastoreUtils.execute(DatastoreUtils.java:334)
	at org.grails.datastore.gorm.AbstractGormApi.execute(AbstractGormApi.groovy:164)
	at org.grails.datastore.gorm.GormInstanceApi.save(GormInstanceApi.groovy:206)
	at org.grails.datastore.gorm.GormInstanceApi.save(GormInstanceApi.groovy:173)
	at org.grails.datastore.gorm.GormEntity$Trait$Helper.save(GormEntity.groovy:110)
	at org.grails.datastore.gorm.mongo.transactions.MongoTransactionSpec.test a committed transaction persists all writes atomically_closure2(MongoTransactionSpec.groovy:73)
	at grails.gorm.transactions.GrailsTransactionTemplate$2.doInTransaction(GrailsTransactionTemplate.groovy:103)
	at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:137)
	at grails.gorm.transactions.GrailsTransactionTemplate.execute(GrailsTransactionTemplate.groovy:100)
	at org.grails.datastore.gorm.GormStaticApi.withTransaction(GormStaticApi.groovy:703)
	at org.grails.datastore.gorm.GormEntity$Trait$Helper.withTransaction(GormEntity.groovy:1066)
	at org.grails.datastore.gorm.mongo.transactions.MongoTransactionSpec.test a committed transaction persists all writes atomically(MongoTransactionSpec.groovy:71)
MongoTransactionSpec > test a findOneAndDelete via the MongoEntity API participates in the transaction (:grails-data-mongodb-core:test in CI - Groovy Joint Validation Build / Build Grails with Groovy snapshot (shard 1))
com.mongodb.MongoTimeoutException: Timed out while waiting for a server that matches WritableServerSelector. Client view of cluster state is {type=UNKNOWN, servers=[{address=localhost:32845, type=UNKNOWN, state=CONNECTING, exception={com.mongodb.MongoSocketOpenException: Exception opening socket}, caused by {java.net.ConnectException: Connection refused}}]
	at com.mongodb.internal.connection.BaseCluster.logAndThrowTimeoutException(BaseCluster.java:431)
	at com.mongodb.internal.connection.BaseCluster.lambda$selectServer$0(BaseCluster.java:166)
	at com.mongodb.internal.time.Timeout.lambda$onExistsAndExpired$16(Timeout.java:238)
	at com.mongodb.internal.time.Timeout.lambda$run$10(Timeout.java:203)
	at com.mongodb.internal.time.TimePoint.checkedCall(TimePoint.java:100)
	at com.mongodb.internal.time.Timeout.call(Timeout.java:176)
	at com.mongodb.internal.time.Timeout.run(Timeout.java:196)
	at com.mongodb.internal.time.Timeout.onExistsAndExpired(Timeout.java:235)
	at com.mongodb.internal.time.Timeout.onExpired(Timeout.java:228)
	at com.mongodb.internal.connection.BaseCluster.selectServer(BaseCluster.java:165)
	at com.mongodb.internal.connection.SingleServerCluster.selectServer(SingleServerCluster.java:47)
	at com.mongodb.internal.binding.ClusterBinding.getWriteConnectionSource(ClusterBinding.java:91)
	at com.mongodb.client.internal.ClientSessionBinding.getConnectionSource(ClientSessionBinding.java:109)
	at com.mongodb.client.internal.ClientSessionBinding.getWriteConnectionSource(ClientSessionBinding.java:102)
	at com.mongodb.internal.operation.SyncOperationHelper.withSuppliedResource(SyncOperationHelper.java:169)
	at com.mongodb.internal.operation.SyncOperationHelper.withSourceAndConnection(SyncOperationHelper.java:138)
	at com.mongodb.internal.operation.SyncOperationHelper.withConnection(SyncOperationHelper.java:117)
	at com.mongodb.internal.operation.DropDatabaseOperation.execute(DropDatabaseOperation.java:73)
	at com.mongodb.internal.operation.DropDatabaseOperation.execute(DropDatabaseOperation.java:48)
	at com.mongodb.client.internal.MongoClusterImpl$OperationExecutorImpl.execute(MongoClusterImpl.java:474)
	at com.mongodb.client.internal.MongoDatabaseImpl.executeDrop(MongoDatabaseImpl.java:230)
	at com.mongodb.client.internal.MongoDatabaseImpl.drop(MongoDatabaseImpl.java:220)
	at org.grails.datastore.gorm.mongo.transactions.MongoTransactionSpec.setup_closure1(MongoTransactionSpec.groovy:58)
	at org.grails.datastore.gorm.GormStaticApi.withNewSession_closure23(GormStaticApi.groovy:767)
	at org.grails.datastore.mapping.core.DatastoreUtils.executeWithNewSession(DatastoreUtils.java:371)
	at org.grails.datastore.gorm.GormStaticApi.withNewSession(GormStaticApi.groovy:766)
	at org.grails.datastore.gorm.GormEntity$Trait$Helper.withNewSession(GormEntity.groovy:1157)
	at org.grails.datastore.gorm.mongo.transactions.MongoTransactionSpec.setup(MongoTransactionSpec.groovy:57)
MongoTransactionSpec > test a per-transaction timeout is rejected rather than silently ignored (:grails-data-mongodb-core:test in CI - Groovy Joint Validation Build / Build Grails with Groovy snapshot (shard 1))
com.mongodb.MongoTimeoutException: Timed out while waiting for a server that matches WritableServerSelector. Client view of cluster state is {type=UNKNOWN, servers=[{address=localhost:32845, type=UNKNOWN, state=CONNECTING, exception={com.mongodb.MongoSocketOpenException: Exception opening socket}, caused by {java.net.ConnectException: Connection refused}}]
	at com.mongodb.internal.connection.BaseCluster.logAndThrowTimeoutException(BaseCluster.java:431)
	at com.mongodb.internal.connection.BaseCluster.lambda$selectServer$0(BaseCluster.java:166)
	at com.mongodb.internal.time.Timeout.lambda$onExistsAndExpired$16(Timeout.java:238)
	at com.mongodb.internal.time.Timeout.lambda$run$10(Timeout.java:203)
	at com.mongodb.internal.time.TimePoint.checkedCall(TimePoint.java:100)
	at com.mongodb.internal.time.Timeout.call(Timeout.java:176)
	at com.mongodb.internal.time.Timeout.run(Timeout.java:196)
	at com.mongodb.internal.time.Timeout.onExistsAndExpired(Timeout.java:235)
	at com.mongodb.internal.time.Timeout.onExpired(Timeout.java:228)
	at com.mongodb.internal.connection.BaseCluster.selectServer(BaseCluster.java:165)
	at com.mongodb.internal.connection.SingleServerCluster.selectServer(SingleServerCluster.java:47)
	at com.mongodb.internal.binding.ClusterBinding.getWriteConnectionSource(ClusterBinding.java:91)
	at com.mongodb.client.internal.ClientSessionBinding.getConnectionSource(ClientSessionBinding.java:109)
	at com.mongodb.client.internal.ClientSessionBinding.getWriteConnectionSource(ClientSessionBinding.java:102)
	at com.mongodb.internal.operation.SyncOperationHelper.withSuppliedResource(SyncOperationHelper.java:169)
	at com.mongodb.internal.operation.SyncOperationHelper.withSourceAndConnection(SyncOperationHelper.java:138)
	at com.mongodb.internal.operation.SyncOperationHelper.withConnection(SyncOperationHelper.java:117)
	at com.mongodb.internal.operation.DropDatabaseOperation.execute(DropDatabaseOperation.java:73)
	at com.mongodb.internal.operation.DropDatabaseOperation.execute(DropDatabaseOperation.java:48)
	at com.mongodb.client.internal.MongoClusterImpl$OperationExecutorImpl.execute(MongoClusterImpl.java:474)
	at com.mongodb.client.internal.MongoDatabaseImpl.executeDrop(MongoDatabaseImpl.java:230)
	at com.mongodb.client.internal.MongoDatabaseImpl.drop(MongoDatabaseImpl.java:220)
	at org.grails.datastore.gorm.mongo.transactions.MongoTransactionSpec.setup_closure1(MongoTransactionSpec.groovy:58)
	at org.grails.datastore.gorm.GormStaticApi.withNewSession_closure23(GormStaticApi.groovy:767)
	at org.grails.datastore.mapping.core.DatastoreUtils.executeWithNewSession(DatastoreUtils.java:371)
	at org.grails.datastore.gorm.GormStaticApi.withNewSession(GormStaticApi.groovy:766)
	at org.grails.datastore.gorm.GormEntity$Trait$Helper.withNewSession(GormEntity.groovy:1157)
	at org.grails.datastore.gorm.mongo.transactions.MongoTransactionSpec.setup(MongoTransactionSpec.groovy:57)
MongoTransactionSpec > test a rolled back transaction discards a native Long id entity (id generation is non-transactional) (:grails-data-mongodb-core:test in CI - Groovy Joint Validation Build / Build Grails with Groovy snapshot (shard 1))
com.mongodb.MongoTimeoutException: Timed out while waiting for a server that matches WritableServerSelector. Client view of cluster state is {type=UNKNOWN, servers=[{address=localhost:32845, type=UNKNOWN, state=CONNECTING, exception={com.mongodb.MongoSocketOpenException: Exception opening socket}, caused by {java.net.ConnectException: Connection refused}}]
	at com.mongodb.internal.connection.BaseCluster.logAndThrowTimeoutException(BaseCluster.java:431)
	at com.mongodb.internal.connection.BaseCluster.lambda$selectServer$0(BaseCluster.java:166)
	at com.mongodb.internal.time.Timeout.lambda$onExistsAndExpired$16(Timeout.java:238)
	at com.mongodb.internal.time.Timeout.lambda$run$10(Timeout.java:203)
	at com.mongodb.internal.time.TimePoint.checkedCall(TimePoint.java:100)
	at com.mongodb.internal.time.Timeout.call(Timeout.java:176)
	at com.mongodb.internal.time.Timeout.run(Timeout.java:196)
	at com.mongodb.internal.time.Timeout.onExistsAndExpired(Timeout.java:235)
	at com.mongodb.internal.time.Timeout.onExpired(Timeout.java:228)
	at com.mongodb.internal.connection.BaseCluster.selectServer(BaseCluster.java:165)
	at com.mongodb.internal.connection.SingleServerCluster.selectServer(SingleServerCluster.java:47)
	at com.mongodb.internal.binding.ClusterBinding.getWriteConnectionSource(ClusterBinding.java:91)
	at com.mongodb.client.internal.ClientSessionBinding.getConnectionSource(ClientSessionBinding.java:109)
	at com.mongodb.client.internal.ClientSessionBinding.getWriteConnectionSource(ClientSessionBinding.java:102)
	at com.mongodb.internal.operation.SyncOperationHelper.withSuppliedResource(SyncOperationHelper.java:169)
	at com.mongodb.internal.operation.SyncOperationHelper.withSourceAndConnection(SyncOperationHelper.java:138)
	at com.mongodb.internal.operation.SyncOperationHelper.withConnection(SyncOperationHelper.java:117)
	at com.mongodb.internal.operation.DropDatabaseOperation.execute(DropDatabaseOperation.java:73)
	at com.mongodb.internal.operation.DropDatabaseOperation.execute(DropDatabaseOperation.java:48)
	at com.mongodb.client.internal.MongoClusterImpl$OperationExecutorImpl.execute(MongoClusterImpl.java:474)
	at com.mongodb.client.internal.MongoDatabaseImpl.executeDrop(MongoDatabaseImpl.java:230)
	at com.mongodb.client.internal.MongoDatabaseImpl.drop(MongoDatabaseImpl.java:220)
	at org.grails.datastore.gorm.mongo.transactions.MongoTransactionSpec.setup_closure1(MongoTransactionSpec.groovy:58)
	at org.grails.datastore.gorm.GormStaticApi.withNewSession_closure23(GormStaticApi.groovy:767)
	at org.grails.datastore.mapping.core.DatastoreUtils.executeWithNewSession(DatastoreUtils.java:371)
	at org.grails.datastore.gorm.GormStaticApi.withNewSession(GormStaticApi.groovy:766)
	at org.grails.datastore.gorm.GormEntity$Trait$Helper.withNewSession(GormEntity.groovy:1157)
	at org.grails.datastore.gorm.mongo.transactions.MongoTransactionSpec.setup(MongoTransactionSpec.groovy:57)
MongoTransactionSpec > test a rolled back transaction discards all writes on the server (:grails-data-mongodb-core:test in CI - Groovy Joint Validation Build / Build Grails with Groovy snapshot (shard 1))
com.mongodb.MongoTimeoutException: Timed out while waiting for a server that matches WritableServerSelector. Client view of cluster state is {type=UNKNOWN, servers=[{address=localhost:32845, type=UNKNOWN, state=CONNECTING, exception={com.mongodb.MongoSocketOpenException: Exception opening socket}, caused by {java.net.ConnectException: Connection refused}}]
	at com.mongodb.internal.connection.BaseCluster.logAndThrowTimeoutException(BaseCluster.java:431)
	at com.mongodb.internal.connection.BaseCluster.lambda$selectServer$0(BaseCluster.java:166)
	at com.mongodb.internal.time.Timeout.lambda$onExistsAndExpired$16(Timeout.java:238)
	at com.mongodb.internal.time.Timeout.lambda$run$10(Timeout.java:203)
	at com.mongodb.internal.time.TimePoint.checkedCall(TimePoint.java:100)
	at com.mongodb.internal.time.Timeout.call(Timeout.java:176)
	at com.mongodb.internal.time.Timeout.run(Timeout.java:196)
	at com.mongodb.internal.time.Timeout.onExistsAndExpired(Timeout.java:235)
	at com.mongodb.internal.time.Timeout.onExpired(Timeout.java:228)
	at com.mongodb.internal.connection.BaseCluster.selectServer(BaseCluster.java:165)
	at com.mongodb.internal.connection.SingleServerCluster.selectServer(SingleServerCluster.java:47)
	at com.mongodb.internal.binding.ClusterBinding.getWriteConnectionSource(ClusterBinding.java:91)
	at com.mongodb.client.internal.ClientSessionBinding.getConnectionSource(ClientSessionBinding.java:109)
	at com.mongodb.client.internal.ClientSessionBinding.getWriteConnectionSource(ClientSessionBinding.java:102)
	at com.mongodb.internal.operation.SyncOperationHelper.withSuppliedResource(SyncOperationHelper.java:169)
	at com.mongodb.internal.operation.SyncOperationHelper.withSourceAndConnection(SyncOperationHelper.java:138)
	at com.mongodb.internal.operation.SyncOperationHelper.withConnection(SyncOperationHelper.java:117)
	at com.mongodb.internal.operation.DropDatabaseOperation.execute(DropDatabaseOperation.java:73)
	at com.mongodb.internal.operation.DropDatabaseOperation.execute(DropDatabaseOperation.java:48)
	at com.mongodb.client.internal.MongoClusterImpl$OperationExecutorImpl.execute(MongoClusterImpl.java:474)
	at com.mongodb.client.internal.MongoDatabaseImpl.executeDrop(MongoDatabaseImpl.java:230)
	at com.mongodb.client.internal.MongoDatabaseImpl.drop(MongoDatabaseImpl.java:220)
	at org.grails.datastore.gorm.mongo.transactions.MongoTransactionSpec.setup_closure1(MongoTransactionSpec.groovy:58)
	at org.grails.datastore.gorm.GormStaticApi.withNewSession_closure23(GormStaticApi.groovy:767)
	at org.grails.datastore.mapping.core.DatastoreUtils.executeWithNewSession(DatastoreUtils.java:371)
	at org.grails.datastore.gorm.GormStaticApi.withNewSession(GormStaticApi.groovy:766)
	at org.grails.datastore.gorm.GormEntity$Trait$Helper.withNewSession(GormEntity.groovy:1157)
	at org.grails.datastore.gorm.mongo.transactions.MongoTransactionSpec.setup(MongoTransactionSpec.groovy:57)
MongoTransactionSpec > test native Long identifier generation works for entities committed in a transaction (:grails-data-mongodb-core:test in CI - Groovy Joint Validation Build / Build Grails with Groovy snapshot (shard 1))
com.mongodb.MongoTimeoutException: Timed out while waiting for a server that matches WritableServerSelector. Client view of cluster state is {type=UNKNOWN, servers=[{address=localhost:32845, type=UNKNOWN, state=CONNECTING, exception={com.mongodb.MongoSocketOpenException: Exception opening socket}, caused by {java.net.ConnectException: Connection refused}}]
	at com.mongodb.internal.connection.BaseCluster.logAndThrowTimeoutException(BaseCluster.java:431)
	at com.mongodb.internal.connection.BaseCluster.lambda$selectServer$0(BaseCluster.java:166)
	at com.mongodb.internal.time.Timeout.lambda$onExistsAndExpired$16(Timeout.java:238)
	at com.mongodb.internal.time.Timeout.lambda$run$10(Timeout.java:203)
	at com.mongodb.internal.time.TimePoint.checkedCall(TimePoint.java:100)
	at com.mongodb.internal.time.Timeout.call(Timeout.java:176)
	at com.mongodb.internal.time.Timeout.run(Timeout.java:196)
	at com.mongodb.internal.time.Timeout.onExistsAndExpired(Timeout.java:235)
	at com.mongodb.internal.time.Timeout.onExpired(Timeout.java:228)
	at com.mongodb.internal.connection.BaseCluster.selectServer(BaseCluster.java:165)
	at com.mongodb.internal.connection.SingleServerCluster.selectServer(SingleServerCluster.java:47)
	at com.mongodb.internal.binding.ClusterBinding.getWriteConnectionSource(ClusterBinding.java:91)
	at com.mongodb.client.internal.ClientSessionBinding.getConnectionSource(ClientSessionBinding.java:109)
	at com.mongodb.client.internal.ClientSessionBinding.getWriteConnectionSource(ClientSessionBinding.java:102)
	at com.mongodb.internal.operation.SyncOperationHelper.withSuppliedResource(SyncOperationHelper.java:169)
	at com.mongodb.internal.operation.SyncOperationHelper.withSourceAndConnection(SyncOperationHelper.java:138)
	at com.mongodb.internal.operation.SyncOperationHelper.withConnection(SyncOperationHelper.java:117)
	at com.mongodb.internal.operation.DropDatabaseOperation.execute(DropDatabaseOperation.java:73)
	at com.mongodb.internal.operation.DropDatabaseOperation.execute(DropDatabaseOperation.java:48)
	at com.mongodb.client.internal.MongoClusterImpl$OperationExecutorImpl.execute(MongoClusterImpl.java:474)
	at com.mongodb.client.internal.MongoDatabaseImpl.executeDrop(MongoDatabaseImpl.java:230)
	at com.mongodb.client.internal.MongoDatabaseImpl.drop(MongoDatabaseImpl.java:220)
	at org.grails.datastore.gorm.mongo.transactions.MongoTransactionSpec.setup_closure1(MongoTransactionSpec.groovy:58)
	at org.grails.datastore.gorm.GormStaticApi.withNewSession_closure23(GormStaticApi.groovy:767)
	at org.grails.datastore.mapping.core.DatastoreUtils.executeWithNewSession(DatastoreUtils.java:371)
	at org.grails.datastore.gorm.GormStaticApi.withNewSession(GormStaticApi.groovy:766)
	at org.grails.datastore.gorm.GormEntity$Trait$Helper.withNewSession(GormEntity.groovy:1157)
	at org.grails.datastore.gorm.mongo.transactions.MongoTransactionSpec.setup(MongoTransactionSpec.groovy:57)
MongoTransactionSpec > test read-your-writes within an active transaction (:grails-data-mongodb-core:test in CI - Groovy Joint Validation Build / Build Grails with Groovy snapshot (shard 1))
com.mongodb.MongoTimeoutException: Timed out while waiting for a server that matches WritableServerSelector. Client view of cluster state is {type=UNKNOWN, servers=[{address=localhost:32845, type=UNKNOWN, state=CONNECTING, exception={com.mongodb.MongoSocketOpenException: Exception opening socket}, caused by {java.net.ConnectException: Connection refused}}]
	at com.mongodb.internal.connection.BaseCluster.logAndThrowTimeoutException(BaseCluster.java:431)
	at com.mongodb.internal.connection.BaseCluster.lambda$selectServer$0(BaseCluster.java:166)
	at com.mongodb.internal.time.Timeout.lambda$onExistsAndExpired$16(Timeout.java:238)
	at com.mongodb.internal.time.Timeout.lambda$run$10(Timeout.java:203)
	at com.mongodb.internal.time.TimePoint.checkedCall(TimePoint.java:100)
	at com.mongodb.internal.time.Timeout.call(Timeout.java:176)
	at com.mongodb.internal.time.Timeout.run(Timeout.java:196)
	at com.mongodb.internal.time.Timeout.onExistsAndExpired(Timeout.java:235)
	at com.mongodb.internal.time.Timeout.onExpired(Timeout.java:228)
	at com.mongodb.internal.connection.BaseCluster.selectServer(BaseCluster.java:165)
	at com.mongodb.internal.connection.SingleServerCluster.selectServer(SingleServerCluster.java:47)
	at com.mongodb.internal.binding.ClusterBinding.getWriteConnectionSource(ClusterBinding.java:91)
	at com.mongodb.client.internal.ClientSessionBinding.getConnectionSource(ClientSessionBinding.java:109)
	at com.mongodb.client.internal.ClientSessionBinding.getWriteConnectionSource(ClientSessionBinding.java:102)
	at com.mongodb.internal.operation.SyncOperationHelper.withSuppliedResource(SyncOperationHelper.java:169)
	at com.mongodb.internal.operation.SyncOperationHelper.withSourceAndConnection(SyncOperationHelper.java:138)
	at com.mongodb.internal.operation.SyncOperationHelper.withConnection(SyncOperationHelper.java:117)
	at com.mongodb.internal.operation.DropDatabaseOperation.execute(DropDatabaseOperation.java:73)
	at com.mongodb.internal.operation.DropDatabaseOperation.execute(DropDatabaseOperation.java:48)
	at com.mongodb.client.internal.MongoClusterImpl$OperationExecutorImpl.execute(MongoClusterImpl.java:474)
	at com.mongodb.client.internal.MongoDatabaseImpl.executeDrop(MongoDatabaseImpl.java:230)
	at com.mongodb.client.internal.MongoDatabaseImpl.drop(MongoDatabaseImpl.java:220)
	at org.grails.datastore.gorm.mongo.transactions.MongoTransactionSpec.setup_closure1(MongoTransactionSpec.groovy:58)
	at org.grails.datastore.gorm.GormStaticApi.withNewSession_closure23(GormStaticApi.groovy:767)
	at org.grails.datastore.mapping.core.DatastoreUtils.executeWithNewSession(DatastoreUtils.java:371)
	at org.grails.datastore.gorm.GormStaticApi.withNewSession(GormStaticApi.groovy:766)
	at org.grails.datastore.gorm.GormEntity$Trait$Helper.withNewSession(GormEntity.groovy:1157)
	at org.grails.datastore.gorm.mongo.transactions.MongoTransactionSpec.setup(MongoTransactionSpec.groovy:57)
MongoTransactionSpec > test writes across multiple collections roll back together (:grails-data-mongodb-core:test in CI - Groovy Joint Validation Build / Build Grails with Groovy snapshot (shard 1))
com.mongodb.MongoTimeoutException: Timed out while waiting for a server that matches WritableServerSelector. Client view of cluster state is {type=UNKNOWN, servers=[{address=localhost:32845, type=UNKNOWN, state=CONNECTING, exception={com.mongodb.MongoSocketOpenException: Exception opening socket}, caused by {java.net.ConnectException: Connection refused}}]
	at com.mongodb.internal.connection.BaseCluster.logAndThrowTimeoutException(BaseCluster.java:431)
	at com.mongodb.internal.connection.BaseCluster.lambda$selectServer$0(BaseCluster.java:166)
	at com.mongodb.internal.time.Timeout.lambda$onExistsAndExpired$16(Timeout.java:238)
	at com.mongodb.internal.time.Timeout.lambda$run$10(Timeout.java:203)
	at com.mongodb.internal.time.TimePoint.checkedCall(TimePoint.java:100)
	at com.mongodb.internal.time.Timeout.call(Timeout.java:176)
	at com.mongodb.internal.time.Timeout.run(Timeout.java:196)
	at com.mongodb.internal.time.Timeout.onExistsAndExpired(Timeout.java:235)
	at com.mongodb.internal.time.Timeout.onExpired(Timeout.java:228)
	at com.mongodb.internal.connection.BaseCluster.selectServer(BaseCluster.java:165)
	at com.mongodb.internal.connection.SingleServerCluster.selectServer(SingleServerCluster.java:47)
	at com.mongodb.internal.binding.ClusterBinding.getWriteConnectionSource(ClusterBinding.java:91)
	at com.mongodb.client.internal.ClientSessionBinding.getConnectionSource(ClientSessionBinding.java:109)
	at com.mongodb.client.internal.ClientSessionBinding.getWriteConnectionSource(ClientSessionBinding.java:102)
	at com.mongodb.internal.operation.SyncOperationHelper.withSuppliedResource(SyncOperationHelper.java:169)
	at com.mongodb.internal.operation.SyncOperationHelper.withSourceAndConnection(SyncOperationHelper.java:138)
	at com.mongodb.internal.operation.SyncOperationHelper.withConnection(SyncOperationHelper.java:117)
	at com.mongodb.internal.operation.DropDatabaseOperation.execute(DropDatabaseOperation.java:73)
	at com.mongodb.internal.operation.DropDatabaseOperation.execute(DropDatabaseOperation.java:48)
	at com.mongodb.client.internal.MongoClusterImpl$OperationExecutorImpl.execute(MongoClusterImpl.java:474)
	at com.mongodb.client.internal.MongoDatabaseImpl.executeDrop(MongoDatabaseImpl.java:230)
	at com.mongodb.client.internal.MongoDatabaseImpl.drop(MongoDatabaseImpl.java:220)
	at org.grails.datastore.gorm.mongo.transactions.MongoTransactionSpec.setup_closure1(MongoTransactionSpec.groovy:58)
	at org.grails.datastore.gorm.GormStaticApi.withNewSession_closure23(GormStaticApi.groovy:767)
	at org.grails.datastore.mapping.core.DatastoreUtils.executeWithNewSession(DatastoreUtils.java:371)
	at org.grails.datastore.gorm.GormStaticApi.withNewSession(GormStaticApi.groovy:766)
	at org.grails.datastore.gorm.GormEntity$Trait$Helper.withNewSession(GormEntity.groovy:1157)
	at org.grails.datastore.gorm.mongo.transactions.MongoTransactionSpec.setup(MongoTransactionSpec.groovy:57)

Rerun Controls

Note

Checks are currently running using the configuration below.

Select tests to mute in this pull request:

🔲 MongoTransactionSpec > test a REQUIRES_NEW inner transaction commits independently of a rolled back outer transaction
🔲 MongoTransactionSpec > test a committed transaction persists all writes atomically
🔲 MongoTransactionSpec > test a findOneAndDelete via the MongoEntity API participates in the transaction
🔲 MongoTransactionSpec > test a per-transaction timeout is rejected rather than silently ignored
🔲 MongoTransactionSpec > test a rolled back transaction discards a native Long id entity (id generation is non-transactional)
🔲 MongoTransactionSpec > test a rolled back transaction discards all writes on the server
🔲 MongoTransactionSpec > test native Long identifier generation works for entities committed in a transaction
🔲 MongoTransactionSpec > test read-your-writes within an active transaction
🔲 MongoTransactionSpec > test writes across multiple collections roll back together

Reuse successful test results:

🔲 ♻️ Only rerun the tests that failed or were muted before

Click the checkbox to trigger a rerun:

🔲 Rerun jobs


Learn more about TestLens at testlens.app/docs.

@codecov

codecov Bot commented Aug 23, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 80.00000% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 54.0173%. Comparing base (2ff37a8) to head (baffa9d).

Files with missing lines Patch % Lines
...adle/plugin/i18n/GenerateI18nDescriptorTask.groovy 83.3333% 0 Missing and 2 partials ⚠️
...rails/gradle/plugin/core/GrailsGradlePlugin.groovy 0.0000% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@                Coverage Diff                 @@
##                8.0.x     #16200        +/-   ##
==================================================
+ Coverage     54.0157%   54.0173%   +0.0016%     
- Complexity      20170      20174         +4     
==================================================
  Files            2103       2103                
  Lines          100643     100653        +10     
  Branches        17822      17824         +2     
==================================================
+ Hits            54363      54370         +7     
- Misses          38522      38524         +2     
- Partials         7758       7759         +1     
Files with missing lines Coverage Δ
...grails/gradle/plugin/core/GrailsI18nOptions.groovy 100.0000% <100.0000%> (ø)
...rails/gradle/plugin/core/GrailsGradlePlugin.groovy 0.0000% <0.0000%> (ø)
...adle/plugin/i18n/GenerateI18nDescriptorTask.groovy 86.6667% <83.3333%> (-0.1754%) ⬇️

... and 2 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@codeconsole

Copy link
Copy Markdown
Contributor Author

Withdrawing this — the premise doesn't hold up.

I justified the opt-out with plugins that "cannot rename": a base name that is part of a published contract, or a vendored third-party bundle. Neither survives scrutiny. Message codes are the contract and a rename doesn't touch them; nothing consumes a plugin's base name (Grails 7 discovered bundles by scanning and never read the name, and applications override messages by code in their own bundle). A vendored bundle is vendored by contents, not by file name, so renaming it costs nothing.

The case that prompted this was a Spring Security fork still shipping the upstream plugin's base name. The check was right to catch it — a genuine collision — and the fix was one git mv loop with codes untouched, backward compatible with M5. When the remedy is that cheap, an opt-out mostly serves postponement, and postponement means shipping the collision.

It also cuts against the reason the check fails hard in the first place: a warning in a plugin's own build is read by nobody, and the damage lands in someone else's application later.

Not worth adding speculative configuration surface to a feature this new. Happy to revisit if someone turns up with a bundle they genuinely cannot rename.

@codeconsole
codeconsole deleted the feature/i18n-plugin-namespace-lenience-8.0.x branch August 23, 2026 09:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant