You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@grails.apache.org by "jamesfredley (via GitHub)" <gi...@apache.org> on 2026/02/19 18:05:11 UTC

[I] AbstractWhereImplementer uses wrong MethodNode for findConnectionId - @Where queries ignore class-level @Transactional(connection) [grails-core]

jamesfredley opened a new issue, #15416:
URL: https://github.com/apache/grails-core/issues/15416

   ## Summary
   
   `AbstractWhereImplementer.doImplement()` calls `findConnectionId(newMethodNode)` instead of `findConnectionId(abstractMethodNode)`, which means `@Where`-annotated methods on Data Services with class-level `@Transactional(connection = '...')` will silently route queries to the default datasource instead of the specified connection.
   
   ## Root Cause
   
   In `AbstractWhereImplementer.groovy` line 99:
   
   ```groovy
   Expression connectionId = findConnectionId(newMethodNode)
   ```
   
   `findConnectionId` resolves the `@Transactional` annotation via `TransactionalTransform.findTransactionalAnnotation(methodNode)`, which falls back to `methodNode.getDeclaringClass()`. The `newMethodNode` (the generated implementation method) declares on the generated impl class, which does not carry the `@Transactional` annotation. The `abstractMethodNode` (the original interface/abstract class method) declares on the class that has the annotation.
   
   This causes `findConnectionId` to return null, so the `withConnection(connectionId)` call on the DetachedCriteria is never added, and the query runs against the default datasource.
   
   ## Affected Code
   
   `grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractWhereImplementer.groovy`
   
   ## Example
   
   ```groovy
   @Service(Metric)
   @Transactional(connection = 'secondary')
   interface MetricDataService {
   
       @Where({ timestamp >= from })
       List<Metric> findAfter(Date from)
   }
   ```
   
   `findAfter()` will query the default datasource instead of `secondary`.
   
   ## Fix
   
   Change line 99 from:
   ```groovy
   Expression connectionId = findConnectionId(newMethodNode)
   ```
   to:
   ```groovy
   Expression connectionId = findConnectionId(abstractMethodNode)
   ```
   
   Both `abstractMethodNode` and `newMethodNode` are available in the `doImplement` method signature.
   
   ## Context
   
   Discovered while fixing the same bug pattern in PR #15395. That PR fixed `SaveImplementer`, `DeleteImplementer`, `FindAndDeleteImplementer`, and `AbstractDetachedCriteriaServiceImplementor`. The `AbstractWhereImplementer` instance was pre-existing on the `7.0.x` branch.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@grails.apache.org.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [I] Data Service query methods ignore class-level @Transactional(connection) - @Where and DetachedCriteria operations route to wrong datasource [grails-core]

Posted by "jdaugherty (via GitHub)" <gi...@apache.org>.
jdaugherty closed issue #15416: Data Service query methods ignore class-level @Transactional(connection) - @Where and DetachedCriteria operations route to wrong datasource
URL: https://github.com/apache/grails-core/issues/15416


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@grails.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org