Search code examples
javaspringgrailsgroovyspring-dsl

Spring bean config using static method from another bean with grails DSL


On Grails 2.3.7, a service exposes several decorator methods:

class CacheManager {
  static ReadOnlyCache getReadOnlyCache(name)
  static ReadWriteCache getReadWriteCache(name)
}

I want to configure services with these decorator methods, something like this:

beans = {
  cacheManager(CacheManager){ ... }

  pdfProcessor(PDFProcessor){
    documentCache = ref('cacheManager').getReadOnlyCache('docscache')
  }
  isbnValidator(ISBNValidator){
    cache = ref('cacheManager').getReadWriteCache('simplecache')
  }

Is there a way to achieve this?

UPDATE

Thanks to Ian's suggestion, I got this generic solution working:

@Singleton
class CacheManager {
  static ReadOnlyCache getReadOnlyCache(name)
  static ReadWriteCache getReadWriteCache(name)
}

beans = {
  cacheManager(CacheManager){ bean ->
    bean.factoryMethod = 'getInstance'

  cacheDecorator(MethodInvokingFactoryBean) { bean ->
    bean.dependsOn = ['cacheManager']
    targetClass = CacheManager
    targetMethod = 'getInstance'      
  }

  pdfProcessor(PDFProcessor){
    documentCache = "#{cacheDecorator.getReadOnlyCache('docscache')}"
  }
  isbnValidator(ISBNValidator){
    cache = "#{cacheDecorator.getReadWriteCache('simplecache')}"
  }

Configure cacheDecorator as MethodInvokingFactoryBean, which returns singleton cacheManager, to safely invoke its methods.


Solution

  • If you just want to ensure the cacheManager is properly set up before invoking the getter methods then you could do that purely at the configuration level with something like

    cacheManager(CacheManager) { ... }
    
    pdfDocumentCache(MethodInvokingFactoryBean) { bean ->
      bean.dependsOn = ['cacheManager']
      targetClass = CacheManager
      targetMethod = 'getROCache'
      arguments = ['somecache']
    }
    
    pdfProcessor(PDFProcessor) {
      documentCache = pdfDocumentCache
    }
    

    The dependsOn should ensure the static getROCache method is not called until the cacheManager bean has been initialized.