4. Spring: Proxy
La anotación Transactional de Spring crea un proxy en tiempo de ejecución de la clase, el cual tiene a
su vez una instancia de la clase original.
Todas las llamadas a métodos transaccionales son interceptadas por el proxy, que es el encargado
de iniciar una transacción, unirse a la existente… y llamar al método del servicio.
Pero si se hace una llamada a métodos del mismo servicio, el proxy no podrá interceptarla al
encontrarnos por debajo de él, en su instancia del servicio y no se ejecutará la condiciones de
transacción que hayamos puesto.
5. Posibles soluciones
● Grails < 2.3.1
○ Usar .withTransaction()
● Grails > 2.3.1
○ Usar @grails.transaction.Transactional: Durante la compilación
mediante una transformación AST, se crea un nuevo método por cada
método anotado dentro de una GrailsTransactionTemplate que ejecuta
el código del original con los ajustes de transacción.Ya no existe proxy y
como se ha hecho la misma operación con todos los métodos no hay
problemas con las llamadas directas. (Puede fallar con la anotación
@CompileStatic)
9. Obtener proxy: En el servicio
package es.osoco.lightTalk
import org.springframework.cache.annotation.Cacheable
class CacheableService {
def firstMethod() {
proxy.anotherMethod(param1, param2)
// code
}
@Cacheable
private anotherMethod(param1, param2) {
// code
}
private getProxy() {
def proxy = grailsApplication.mainContext.cacheableService
}
}
De este modo obtenemos el proxy
para llamar al método a través de él.
10. Obtener proxy: Genérico
class BootStrap {
def grailsApplication
def init = { servletContext ->
for( sc in grailsApplication.serviceClasses) {
sc.clazz.metaClass.getMyProxy = { ->
grailsApplication.mainContext.getBean(sc.propertyName)
}
}
}
De este modo estará disponible la variable myProxy con el proxy correspondiente en cada
servicio.