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: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to