Skip to content

feat: GORM O(M+N) scaling — GormRegistry, GormEnhancer, and core API refactor#15780

Open
borinquenkid wants to merge 13 commits into
feat/gorm-datastore-infrafrom
feat/gorm-registry-core-impl
Open

feat: GORM O(M+N) scaling — GormRegistry, GormEnhancer, and core API refactor#15780
borinquenkid wants to merge 13 commits into
feat/gorm-datastore-infrafrom
feat/gorm-registry-core-impl

Conversation

@borinquenkid

Copy link
Copy Markdown
Member

Summary

Introduces the GormRegistry singleton that replaces the O(M×N) static map allocation in GormEnhancer. APIs are registered once at entity-registration time and looked up in O(1).

  • GormRegistry — singleton keyed by (entityClass, qualifier); handles MultiTenant qualifier expansion, thread-local preferred datastore, and concurrent-safe removal on close()
  • GormApiFactory / DefaultGormApiFactory — pluggable factory per datastore type; adapters override this to supply typed API instances
  • GormApiResolver — routes static/instance/validation API lookups through the registry with fallback to the default datastore
  • ConnectionSourceNameResolver — extracts and normalises connection-source names from a datastore without leaking ConnectionSourcesSupport internals
  • GormEnhancer — delegates all registration and lookup to GormRegistry; allQualifiers() used only for datastore routing, not eager API allocation
  • GormStaticApi / GormInstanceApi / GormValidationApi — use DatastoreResolver instead of holding a direct Datastore reference; support qualifier-aware execution via executeQualified()
  • AbstractGormApi.execute() — distinguishes datasource connection qualifiers from tenant-ID qualifiers to avoid overwriting the active tenant context
  • CurrentTenantHolder — thread-safe tenant binding for DISCRIMINATOR multi-tenancy
  • ServiceTransformation / TransactionalTransform — resolve transaction manager via GormRegistry instead of static map lookups
  • DefaultTransactionTemplateFactory / TransactionTemplateFactory — pluggable transaction template creation per datastore type

Test plan

  • ./gradlew :grails-datamapping-core:test passes (tests are in the companion PR)
  • No regressions in GormEnhancerAllQualifiersSpec

Stack

🤖 Generated with Claude Code

borinquenkid and others added 7 commits June 27, 2026 13:25
…refactor

Introduce GormRegistry singleton replacing O(M×N) static maps in GormEnhancer.
APIs are registered once at entity-registration time and looked up in O(1).

- GormRegistry: singleton keyed by (entityClass, qualifier); handles MultiTenant
  qualifier expansion, thread-local preferred datastore, and concurrent-safe removal
- GormApiFactory / DefaultGormApiFactory: pluggable factory per datastore type
- GormApiResolver: routes static/instance/validation API lookups through the registry
- GormEnhancer: delegates all registration and lookup to GormRegistry
- GormStaticApi / GormInstanceApi / GormValidationApi: use DatastoreResolver instead
  of holding a direct Datastore reference; support qualifier-aware execution
- AbstractGormApi.execute(): distinguishes datasource connection qualifiers from
  tenant-ID qualifiers to avoid overwriting the active tenant context
- CurrentTenantHolder: thread-safe tenant binding for DISCRIMINATOR multi-tenancy
- ServiceTransformation / TransactionalTransform: resolve transaction manager via
  GormRegistry instead of static map lookups

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…efactor

HibernateGormEnhancer (H5 and H7) both declare @OverRide registerConstraints
as a no-op. The scaling commit's GormEnhancer refactor omitted this protected
hook method, making the @OverRide annotation invalid and causing a Java stub
compilation error: "method does not override or implement a method from a
supertype".

Restores the original implementation (loads ConstraintRegistrar via reflection
if present) and calls it from the constructor, consistent with the pre-scaling
behaviour.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ropped by scaling refactor

GormEnhancer: restore protected registerConstraints(Datastore) hook that H5/H7
HibernateGormEnhancer override as a no-op. Its absence broke Java stub
generation with "@OverRide … method does not override a supertype method".

MongoStaticApi: restore persistentEntity and multiTenancyMode fields that
GormStaticApi no longer carries after the scaling refactor. Initialise
persistentEntity from the mapping context and multiTenancyMode from
MongoDatastore.getMultiTenancyMode() so wrapFilterWithMultiTenancy and
preparePipeline compile under @CompileStatic.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…stractGormApi.execute()

The GORM scaling commit introduced a non-default qualifier path in execute() that
unconditionally called Tenants.withId(datastore, qualifier) for multi-tenant entities.
This was correct for DATABASE mode (qualifier == tenant ID == connection name) but
broke DISCRIMINATOR mode: when a @service with @transactional(connection='secondary')
executed a query, 'secondary' was bound as the current tenant ID instead of the real
tenant from the TenantResolver, causing discriminator filters to match 'secondary' and
return 0 rows.

Fix: probe getDatastoreForConnection(qualifier) to determine whether the qualifier
names a real datasource connection. If it resolves (non-null), it is a connection name
— fall through to executeQualified without touching the tenant context. If it throws or
returns null, the qualifier is a tenant ID (e.g. from withTenant()) — bind it via
Tenants.withId as before.

Update GormRegistrySpec to explicitly stub getDatastoreForConnection(_) >> null on the
DISCRIMINATOR-mode test stub, mirroring real HibernateDatastore behaviour (which throws
ConfigurationException for unknown connection names) and avoiding Spock's covariant-
interface default of returning the stub itself.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…istry

findStaticApi/InstanceApi/ValidationApi: the tenant-lookup at priority-2 only
checked CurrentTenantHolder.  In DATABASE and SCHEMA modes the tenant ID is never
stored there explicitly — it comes from the TenantResolver (e.g. a subdomain or
system-property resolver).  Consult the resolver for those strict modes so that
per-tenant child APIs are selected correctly even when no tenant has been bound
via Tenants.withId().  Guard with TenantNotFoundException propagation so missing
tenants surface as errors rather than silently falling back to the default API.
Also skip the API redirect when tenantId equals 'default' to avoid self-loops.

createStaticApi / createInstanceApi / createValidationApi: replace the caller-
supplied DatastoreResolver with a bound lambda that always returns the specific
Datastore captured at registration time.  The old resolver was evaluated lazily
at call time and could invoke tenant-resolution logic before any tenant context
was active, causing spurious TenantNotFoundException during bootstrapping.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…affected tests

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…k lines in HibernateGormEnhancer

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@borinquenkid borinquenkid force-pushed the feat/gorm-registry-core-impl branch from 24dd795 to b49c19f Compare June 27, 2026 20:46
borinquenkid and others added 6 commits June 27, 2026 16:47
…mpatibility

Adapter subclasses (SimpleMapDatastore, HibernateGormEnhancer, etc.) override
getStaticApi/getInstanceApi/getValidationApi/createDynamicFinders as protected
extension points. Removing them in the core refactor breaks compilation of those
adapters until their own PRs are merged. Restore as @deprecated stubs delegating
to GormRegistry so the adapter modules compile against this PR in isolation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adapter modules (hibernate5, converters, graphql) reference static methods
and constructors removed in the core refactor. Restore them as @deprecated
stubs delegating to GormRegistry so all adapters compile against this PR
in isolation, without requiring the full stack to be merged together:

- GormEnhancer: add 2-arg (Datastore, TxManager) constructor; static
  findStaticApi, findInstanceApi, findValidationApi, findDatastore delegates
- GormStaticApi: add (Datastore, finders) and (Datastore, finders, TxManager)
  deprecated constructors extracting MappingContext from the Datastore
- AbstractGormApi: restore deprecated persistentEntity field populated in
  both constructor paths so @CompileStatic subclasses (AbstractHibernateGorm*)
  can still read it directly

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ter compat

HibernateGormStaticApi (H7) assigns this.datastore = datastore in its
constructor, requiring a setDatastore() setter. AbstractDatastoreApi now
provides a deprecated setter that swaps the resolver to a StaticDatastoreResolver.
Also fix CodeNarc MissingBlankLineBeforeAnnotatedField for persistentEntity.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…spatch

Three targeted fixes that eliminate H5/H7 runtime NPEs introduced by the
GormRegistry refactor:

1. Remove setDatastore(Datastore) from AbstractDatastoreApi — adding a public
   setter for 'datastore' caused Groovy @CompileStatic to route constructor
   field assignments (e.g. this.datastore = hds in AbstractHibernateGorm-
   ValidationApi) through the setter instead of the declared local field,
   leaving that field null and causing ValidationEvent.<init> to throw
   IllegalArgumentException: null source.

2. Fix deprecated GormStaticApi(Class, Datastore, List[, PlatformTransactionManager])
   constructors to wire a real DatastoreResolver closure instead of null,
   so getDatastore() returns the correct Datastore at runtime for H5/H7
   adapters that still call these constructors.

3. Fix GormEnhancer.addStaticMethods mc.static.propertyMissing to convert
   any non-MissingPropertyException (e.g. ConfigurationException from H5's
   HibernateGormStaticApi.propertyMissing treating the name as a datasource
   qualifier) into MissingPropertyException so Groovy can fall through to
   methodMissing for dynamic finder dispatch (e.g. Person.countByTitle).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…cApi

Without setDatastore(Datastore) in AbstractDatastoreApi, getDatastore()
makes 'datastore' a read-only property for classes without a local
datastore field. HibernateGormStaticApi had no local datastore field, so
this.datastore = datastore failed @CompileStatic compilation. The
assignment was already redundant — the deprecated super constructor wires
a DatastoreResolver that returns the correct HibernateDatastore.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…no GormApiFactory registered

Without a specialized GormApiFactory registered for MongoDB (only H5/H7 register
HibernateGormApiFactory via registerConstraints), GormRegistry.registerEntity fell
back to DefaultGormApiFactory, which created base GormStaticApi instead of
MongoStaticApi — causing ClassCastException in MongoEntity.currentMongoStaticApi().

When no specialized factory is registered for the datastore, delegate to the
enhancer's overridden getStaticApi/getInstanceApi/getValidationApi methods, which
polymorphically dispatch to adapter-specific anonymous subclass overrides (e.g.
MongoDatastore's anonymous MongoGormEnhancer override that creates MongoStaticApi).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@testlens-app

testlens-app Bot commented Jun 28, 2026

Copy link
Copy Markdown

🚨 TestLens detected 141 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 / Build Grails-Core (macos-latest, 21) > :grails-data-graphql-core:test

Test Runs
DeleteEntityDataFetcherSpec > test get
DeleteEntityDataFetcherSpec > test get invalid
EntityDataFetcherSpec > test get
EntityDataFetcherSpec > test pagination
SingleEntityDataFetcherSpec > test get
SoftDeleteEntityDataFetcherSpec > test get
UpdateEntityDataFetcherSpec > test get
UpdateEntityDataFetcherSpec > test optimistic locking
UpdateEntityDataFetcherSpec > test optimistic locking with null version

CI / Build Grails-Core (macos-latest, 21) > :grails-datamapping-core:test

Test Runs
CompileStaticServiceInjectionSpec > test @CompileStatic abstract class with injected @service properties compiles
CompileStaticServiceInjectionSpec > test impl has datastore infrastructure when abstract class has @service properties
GormEnhancerAllQualifiersSpec > MultiTenant entity with ALL datasource expands to all qualifiers
GormEnhancerAllQualifiersSpec > MultiTenant entity with default datasource expands to all qualifiers
GormEnhancerAllQualifiersSpec > MultiTenant entity with explicit non-default datasource preserves qualifier
GormEnhancerAllQualifiersSpec > MultiTenant entity with multiple explicit datasources preserves all qualifiers
GormEnhancerAllQualifiersSpec > close keeps a newer enhancer registered for the same datastore
GormEnhancerAllQualifiersSpec > non-MultiTenant entity with ALL datasource expands to all qualifiers
GormEnhancerAllQualifiersSpec > non-MultiTenant entity with default datasource keeps default only
GormEnhancerAllQualifiersSpec > non-MultiTenant entity with explicit datasource preserves qualifier
GormEnhancerAllQualifiersSpec > registerEntity adds static api under default and secondary for MultiTenant entity
GormEnhancerAllQualifiersSpec > registerEntity adds static api under default and secondary for non-default datasource
GormEnhancerAllQualifiersSpec > registerEntity adds static api under default for default datasource
GormEnhancerAllQualifiersSpec > registerEntity creates expanded MultiTenant qualifier APIs lazily
GormEnhancerAllQualifiersSpec > registerEntity creates tenant APIs lazily for database-per-tenant qualifiers
GormEntityTransformSpec > test property/method missing
MethodValidationTransformSpec > test simple validated property
ServiceTransformSpec > test implement abstract class
ServiceTransformSpec > test implement interface
ServiceTransformSpec > test service transform on abstract protected methods

CI / Build Grails-Core (macos-latest, 21) > :grails-fields:test

Test Runs
DefaultInputRenderingPersistentSpec > input for a #description property does have `.id` at the end of the name > input for a many-to-one property does have `.id` at the end of the name
DefaultInputRenderingPersistentSpec > input for a #description property does have `.id` at the end of the name > input for a one-to-one property does have `.id` at the end of the name
DefaultInputRenderingPersistentSpec > input for a #description property doesn't have `.id` at the end of the name > input for a many-to-many property doesn't have `.id` at the end of the name
DefaultInputRenderingPersistentSpec > input for a #description property is a select > input for a many-to-many property is a select
DefaultInputRenderingPersistentSpec > input for a #description property is a select > input for a many-to-one property is a select
DefaultInputRenderingPersistentSpec > input for a #description property is a select > input for a one-to-one property is a select
DefaultInputRenderingPersistentSpec > select for a #description property with a value of #value has the correct option selected > select for a many-to-many property with a value of [Homer Simpson] has the correct option selected
DefaultInputRenderingPersistentSpec > select for a #description property with a value of #value has the correct option selected > select for a many-to-one property with a value of Homer Simpson has the correct option selected
DefaultInputRenderingPersistentSpec > select for a #description property with a value of #value has the correct option selected > select for a one-to-one property with a value of Homer Simpson has the correct option selected
DefaultInputRenderingSpec > input for a #description property does have `.id` at the end of the name > input for a many-to-one property does have `.id` at the end of the name
DefaultInputRenderingSpec > input for a #description property does have `.id` at the end of the name > input for a one-to-one property does have `.id` at the end of the name
DefaultInputRenderingSpec > input for a #description property doesnt have .id at the end of the name > input for a many-to-many property doesnt have .id at the end of the name
DefaultInputRenderingSpec > input for a #description property is a select > input for a many-to-many property is a select
DefaultInputRenderingSpec > input for a #description property is a select > input for a many-to-one property is a select
DefaultInputRenderingSpec > input for a #description property is a select > input for a one-to-one property is a select
DefaultInputRenderingSpec > select for a #description property with a value of #value has the correct option selected > select for a many-to-many property with a value of [Homer Simpson] has the correct option selected
DefaultInputRenderingSpec > select for a #description property with a value of #value has the correct option selected > select for a many-to-one property with a value of Homer Simpson has the correct option selected
DefaultInputRenderingSpec > select for a #description property with a value of #value has the correct option selected > select for a one-to-one property with a value of Homer Simpson has the correct option selected

CI / Build Grails-Core (ubuntu-latest, 21) > :grails-data-graphql-core:test

Test Runs
DeleteEntityDataFetcherSpec > test get
DeleteEntityDataFetcherSpec > test get invalid
EntityDataFetcherSpec > test get
EntityDataFetcherSpec > test pagination
SingleEntityDataFetcherSpec > test get
SoftDeleteEntityDataFetcherSpec > test get
UpdateEntityDataFetcherSpec > test get
UpdateEntityDataFetcherSpec > test optimistic locking
UpdateEntityDataFetcherSpec > test optimistic locking with null version

CI / Build Grails-Core (ubuntu-latest, 21) > :grails-datamapping-core:test

Test Runs
CompileStaticServiceInjectionSpec > test @CompileStatic abstract class with injected @service properties compiles
CompileStaticServiceInjectionSpec > test impl has datastore infrastructure when abstract class has @service properties
GormEnhancerAllQualifiersSpec > MultiTenant entity with ALL datasource expands to all qualifiers
GormEnhancerAllQualifiersSpec > MultiTenant entity with default datasource expands to all qualifiers
GormEnhancerAllQualifiersSpec > MultiTenant entity with explicit non-default datasource preserves qualifier
GormEnhancerAllQualifiersSpec > MultiTenant entity with multiple explicit datasources preserves all qualifiers
GormEnhancerAllQualifiersSpec > close keeps a newer enhancer registered for the same datastore
GormEnhancerAllQualifiersSpec > non-MultiTenant entity with ALL datasource expands to all qualifiers
GormEnhancerAllQualifiersSpec > non-MultiTenant entity with default datasource keeps default only
GormEnhancerAllQualifiersSpec > non-MultiTenant entity with explicit datasource preserves qualifier
GormEnhancerAllQualifiersSpec > registerEntity adds static api under default and secondary for MultiTenant entity
GormEnhancerAllQualifiersSpec > registerEntity adds static api under default and secondary for non-default datasource
GormEnhancerAllQualifiersSpec > registerEntity adds static api under default for default datasource
GormEnhancerAllQualifiersSpec > registerEntity creates expanded MultiTenant qualifier APIs lazily
GormEnhancerAllQualifiersSpec > registerEntity creates tenant APIs lazily for database-per-tenant qualifiers
GormEntityTransformSpec > test property/method missing
MethodValidationTransformSpec > test simple validated property
ServiceTransformSpec > test implement abstract class
ServiceTransformSpec > test implement interface
ServiceTransformSpec > test service transform on abstract protected methods

CI / Build Grails-Core (ubuntu-latest, 21) > :grails-fields:test

Test Runs
DefaultInputRenderingPersistentSpec > input for a #description property does have `.id` at the end of the name > input for a many-to-one property does have `.id` at the end of the name
DefaultInputRenderingPersistentSpec > input for a #description property does have `.id` at the end of the name > input for a one-to-one property does have `.id` at the end of the name
DefaultInputRenderingPersistentSpec > input for a #description property doesn't have `.id` at the end of the name > input for a many-to-many property doesn't have `.id` at the end of the name
DefaultInputRenderingPersistentSpec > input for a #description property is a select > input for a many-to-many property is a select
DefaultInputRenderingPersistentSpec > input for a #description property is a select > input for a many-to-one property is a select
DefaultInputRenderingPersistentSpec > input for a #description property is a select > input for a one-to-one property is a select
DefaultInputRenderingPersistentSpec > select for a #description property with a value of #value has the correct option selected > select for a many-to-many property with a value of [Homer Simpson] has the correct option selected
DefaultInputRenderingPersistentSpec > select for a #description property with a value of #value has the correct option selected > select for a many-to-one property with a value of Homer Simpson has the correct option selected
DefaultInputRenderingPersistentSpec > select for a #description property with a value of #value has the correct option selected > select for a one-to-one property with a value of Homer Simpson has the correct option selected
DefaultInputRenderingSpec > input for a #description property does have `.id` at the end of the name > input for a many-to-one property does have `.id` at the end of the name
DefaultInputRenderingSpec > input for a #description property does have `.id` at the end of the name > input for a one-to-one property does have `.id` at the end of the name
DefaultInputRenderingSpec > input for a #description property doesnt have .id at the end of the name > input for a many-to-many property doesnt have .id at the end of the name
DefaultInputRenderingSpec > input for a #description property is a select > input for a many-to-many property is a select
DefaultInputRenderingSpec > input for a #description property is a select > input for a many-to-one property is a select
DefaultInputRenderingSpec > input for a #description property is a select > input for a one-to-one property is a select
DefaultInputRenderingSpec > select for a #description property with a value of #value has the correct option selected > select for a many-to-many property with a value of [Homer Simpson] has the correct option selected
DefaultInputRenderingSpec > select for a #description property with a value of #value has the correct option selected > select for a many-to-one property with a value of Homer Simpson has the correct option selected
DefaultInputRenderingSpec > select for a #description property with a value of #value has the correct option selected > select for a one-to-one property with a value of Homer Simpson has the correct option selected

CI / Build Grails-Core (ubuntu-latest, 25) > :grails-data-graphql-core:test

Test Runs
DeleteEntityDataFetcherSpec > test get
DeleteEntityDataFetcherSpec > test get invalid
EntityDataFetcherSpec > test get
EntityDataFetcherSpec > test pagination
SingleEntityDataFetcherSpec > test get
SoftDeleteEntityDataFetcherSpec > test get
UpdateEntityDataFetcherSpec > test get
UpdateEntityDataFetcherSpec > test optimistic locking
UpdateEntityDataFetcherSpec > test optimistic locking with null version

CI / Build Grails-Core (ubuntu-latest, 25) > :grails-datamapping-core:test

Test Runs
CompileStaticServiceInjectionSpec > test @CompileStatic abstract class with injected @service properties compiles
CompileStaticServiceInjectionSpec > test impl has datastore infrastructure when abstract class has @service properties
GormEnhancerAllQualifiersSpec > MultiTenant entity with ALL datasource expands to all qualifiers
GormEnhancerAllQualifiersSpec > MultiTenant entity with default datasource expands to all qualifiers
GormEnhancerAllQualifiersSpec > MultiTenant entity with explicit non-default datasource preserves qualifier
GormEnhancerAllQualifiersSpec > MultiTenant entity with multiple explicit datasources preserves all qualifiers
GormEnhancerAllQualifiersSpec > close keeps a newer enhancer registered for the same datastore
GormEnhancerAllQualifiersSpec > non-MultiTenant entity with ALL datasource expands to all qualifiers
GormEnhancerAllQualifiersSpec > non-MultiTenant entity with default datasource keeps default only
GormEnhancerAllQualifiersSpec > non-MultiTenant entity with explicit datasource preserves qualifier
GormEnhancerAllQualifiersSpec > registerEntity adds static api under default and secondary for MultiTenant entity
GormEnhancerAllQualifiersSpec > registerEntity adds static api under default and secondary for non-default datasource
GormEnhancerAllQualifiersSpec > registerEntity adds static api under default for default datasource
GormEnhancerAllQualifiersSpec > registerEntity creates expanded MultiTenant qualifier APIs lazily
GormEnhancerAllQualifiersSpec > registerEntity creates tenant APIs lazily for database-per-tenant qualifiers
GormEntityTransformSpec > test property/method missing
MethodValidationTransformSpec > test simple validated property
ServiceTransformSpec > test implement abstract class
ServiceTransformSpec > test implement interface
ServiceTransformSpec > test service transform on abstract protected methods

CI / Build Grails-Core (windows-latest, 25) > :grails-data-graphql-core:test

Test Runs
DeleteEntityDataFetcherSpec > test get
DeleteEntityDataFetcherSpec > test get invalid
EntityDataFetcherSpec > test get
EntityDataFetcherSpec > test pagination
SingleEntityDataFetcherSpec > test get
SoftDeleteEntityDataFetcherSpec > test get
UpdateEntityDataFetcherSpec > test get
UpdateEntityDataFetcherSpec > test optimistic locking
UpdateEntityDataFetcherSpec > test optimistic locking with null version

CI / Build Grails-Core Rerunning all Tasks (ubuntu-latest, 21) > :grails-data-graphql-core:test

Test Runs
DeleteEntityDataFetcherSpec > test get
DeleteEntityDataFetcherSpec > test get invalid
EntityDataFetcherSpec > test get
EntityDataFetcherSpec > test pagination
SingleEntityDataFetcherSpec > test get
SoftDeleteEntityDataFetcherSpec > test get
UpdateEntityDataFetcherSpec > test get
UpdateEntityDataFetcherSpec > test optimistic locking
UpdateEntityDataFetcherSpec > test optimistic locking with null version

🏷️ Commit: 7dcf26e
▶️ Tests: 9925 executed
⚪️ Checks: 39/39 completed

Test Failures (first 10 of 141)

CompileStaticServiceInjectionSpec > test @CompileStatic abstract class with injected @service properties compiles (:grails-datamapping-core:test in CI / Build Grails-Core (macos-latest, 21))
Condition failed with Exception:

impl.getDeclaredField('datastore') != null
|    |
|    java.lang.NoSuchFieldException: datastore
|    	at java.base/java.lang.Class.getDeclaredField(Class.java:2784)
|    	at grails.gorm.services.CompileStaticServiceInjectionSpec.test @CompileStatic abstract class with injected @Service properties compiles(CompileStaticServiceInjectionSpec.groovy:95)
class $BookServiceImplementation

	at grails.gorm.services.CompileStaticServiceInjectionSpec.test @CompileStatic abstract class with injected @Service properties compiles(CompileStaticServiceInjectionSpec.groovy:95)
Caused by: java.lang.NoSuchFieldException: datastore
	at java.base/java.lang.Class.getDeclaredField(Class.java:2784)
	... 1 more
CompileStaticServiceInjectionSpec > test impl has datastore infrastructure when abstract class has @service properties (:grails-datamapping-core:test in CI / Build Grails-Core (macos-latest, 21))
Condition failed with Exception:

impl.getDeclaredField('datastore') != null
|    |
|    java.lang.NoSuchFieldException: datastore
|    	at java.base/java.lang.Class.getDeclaredField(Class.java:2784)
|    	at grails.gorm.services.CompileStaticServiceInjectionSpec.test impl has datastore infrastructure when abstract class has @Service properties(CompileStaticServiceInjectionSpec.groovy:354)
class $RecordServiceImplementation

	at grails.gorm.services.CompileStaticServiceInjectionSpec.test impl has datastore infrastructure when abstract class has @Service properties(CompileStaticServiceInjectionSpec.groovy:354)
Caused by: java.lang.NoSuchFieldException: datastore
	at java.base/java.lang.Class.getDeclaredField(Class.java:2784)
	... 1 more
DefaultInputRenderingPersistentSpec > input for a #description property does have `.id` at the end of the name > input for a many-to-one property does have `.id` at the end of the name (:grails-fields:test in CI / Build Grails-Core (macos-latest, 21))
Condition not satisfied:

people.every { output =~ /option value="$it.id" >$it.name/ }
|      |
|      false
[Bart Simpson, Homer Simpson, Monty Burns]

	at grails.plugin.formfields.DefaultInputRenderingPersistentSpec.input for a #description property does have `.id` at the end of the name(DefaultInputRenderingPersistentSpec.groovy:485)
DefaultInputRenderingPersistentSpec > input for a #description property does have `.id` at the end of the name > input for a one-to-one property does have `.id` at the end of the name (:grails-fields:test in CI / Build Grails-Core (macos-latest, 21))
Condition not satisfied:

people.every { output =~ /option value="$it.id" >$it.name/ }
|      |
|      false
[Bart Simpson, Homer Simpson, Monty Burns]

	at grails.plugin.formfields.DefaultInputRenderingPersistentSpec.input for a #description property does have `.id` at the end of the name(DefaultInputRenderingPersistentSpec.groovy:485)
DefaultInputRenderingPersistentSpec > input for a #description property doesn't have `.id` at the end of the name > input for a many-to-many property doesn't have `.id` at the end of the name (:grails-fields:test in CI / Build Grails-Core (macos-latest, 21))
Condition not satisfied:

people.every { output =~ /option value="$it.id" >$it.name/ }
|      |
|      false
[Bart Simpson, Homer Simpson, Monty Burns]

	at grails.plugin.formfields.DefaultInputRenderingPersistentSpec.input for a #description property doesn't have `.id` at the end of the name(DefaultInputRenderingPersistentSpec.groovy:466)
DefaultInputRenderingPersistentSpec > input for a #description property is a select > input for a many-to-many property is a select (:grails-fields:test in CI / Build Grails-Core (macos-latest, 21))
Condition not satisfied:

people.every { output =~ /option value="$it.id" >$it.name/ }
|      |
|      false
[Bart Simpson, Homer Simpson, Monty Burns]

	at grails.plugin.formfields.DefaultInputRenderingPersistentSpec.input for a #description property is a select(DefaultInputRenderingPersistentSpec.groovy:445)
DefaultInputRenderingPersistentSpec > input for a #description property is a select > input for a many-to-one property is a select (:grails-fields:test in CI / Build Grails-Core (macos-latest, 21))
Condition not satisfied:

people.every { output =~ /option value="$it.id" >$it.name/ }
|      |
|      false
[Bart Simpson, Homer Simpson, Monty Burns]

	at grails.plugin.formfields.DefaultInputRenderingPersistentSpec.input for a #description property is a select(DefaultInputRenderingPersistentSpec.groovy:445)
DefaultInputRenderingPersistentSpec > input for a #description property is a select > input for a one-to-one property is a select (:grails-fields:test in CI / Build Grails-Core (macos-latest, 21))
Condition not satisfied:

people.every { output =~ /option value="$it.id" >$it.name/ }
|      |
|      false
[Bart Simpson, Homer Simpson, Monty Burns]

	at grails.plugin.formfields.DefaultInputRenderingPersistentSpec.input for a #description property is a select(DefaultInputRenderingPersistentSpec.groovy:445)
DefaultInputRenderingPersistentSpec > select for a #description property with a value of #value has the correct option selected > select for a many-to-many property with a value of [Homer Simpson] has the correct option selected (:grails-fields:test in CI / Build Grails-Core (macos-latest, 21))
Condition not satisfied:

output =~ /option value="${people[1].id}" selected="selected" >${people[1].name}/
|      |                   |     |   |                           |     |   |
|      |                   |     |   2                           |     |   Homer Simpson
|      |                   |     Homer Simpson                   |     Homer Simpson
|      |                   |                                     [Bart Simpson, Homer Simpson, Monty Burns]
|      |                   [Bart Simpson, Homer Simpson, Monty Burns]
|      java.util.regex.Matcher[pattern=option value="2" selected="selected" >Homer Simpson region=0,54 lastmatch=]
<select name="prop" id="prop" multiple="" >
</select>

	at grails.plugin.formfields.DefaultInputRenderingPersistentSpec.select for a #description property with a value of #value has the correct option selected(DefaultInputRenderingPersistentSpec.groovy:525)
DefaultInputRenderingPersistentSpec > select for a #description property with a value of #value has the correct option selected > select for a many-to-one property with a value of Homer Simpson has the correct option selected (:grails-fields:test in CI / Build Grails-Core (macos-latest, 21))
Condition not satisfied:

output =~ /option value="${people[1].id}" selected="selected" >${people[1].name}/
|      |                   |     |   |                           |     |   |
|      |                   |     |   2                           |     |   Homer Simpson
|      |                   |     Homer Simpson                   |     Homer Simpson
|      |                   |                                     [Bart Simpson, Homer Simpson, Monty Burns]
|      |                   [Bart Simpson, Homer Simpson, Monty Burns]
|      java.util.regex.Matcher[pattern=option value="2" selected="selected" >Homer Simpson region=0,77 lastmatch=]
<select name="prop.id" id="prop" >
<option value="null"></option>
</select>

	at grails.plugin.formfields.DefaultInputRenderingPersistentSpec.select for a #description property with a value of #value has the correct option selected(DefaultInputRenderingPersistentSpec.groovy:525)

Muted Tests (first 20 of 141)

Select tests to mute in this pull request:

  • CompileStaticServiceInjectionSpec > test @CompileStatic abstract class with injected @service properties compiles
  • CompileStaticServiceInjectionSpec > test impl has datastore infrastructure when abstract class has @service properties
  • DefaultInputRenderingPersistentSpec > input for a #description property does have `.id` at the end of the name
  • DefaultInputRenderingPersistentSpec > input for a #description property doesn't have `.id` at the end of the name
  • DefaultInputRenderingPersistentSpec > input for a #description property is a select
  • DefaultInputRenderingPersistentSpec > select for a #description property with a value of #value has the correct option selected
  • DefaultInputRenderingSpec > input for a #description property does have `.id` at the end of the name
  • DefaultInputRenderingSpec > input for a #description property doesnt have .id at the end of the name
  • DefaultInputRenderingSpec > input for a #description property is a select
  • DefaultInputRenderingSpec > select for a #description property with a value of #value has the correct option selected
  • DeleteEntityDataFetcherSpec > test get
  • DeleteEntityDataFetcherSpec > test get invalid
  • EntityDataFetcherSpec > test get
  • EntityDataFetcherSpec > test pagination
  • GormEnhancerAllQualifiersSpec > MultiTenant entity with ALL datasource expands to all qualifiers
  • GormEnhancerAllQualifiersSpec > MultiTenant entity with default datasource expands to all qualifiers
  • GormEnhancerAllQualifiersSpec > MultiTenant entity with explicit non-default datasource preserves qualifier
  • GormEnhancerAllQualifiersSpec > MultiTenant entity with multiple explicit datasources preserves all qualifiers
  • GormEnhancerAllQualifiersSpec > close keeps a newer enhancer registered for the same datastore
  • GormEnhancerAllQualifiersSpec > non-MultiTenant entity with ALL datasource expands to all qualifiers

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.

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.

1 participant