views:

361

answers:

2

I want a grails service to be able to access Domain static methods, for queries, etc.

For example, in a controller, I can call

IncomingCall.count()

to get the number of records in table "IncomingCall"

but if I try to do this from inside a service, I get the error:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'incomingStatusService': Invocation of init method failed; nested exception is groovy.lang.MissingMethodException: No signature of method: static ms.wdw.tropocontrol.IncomingCall.count() is applicable for argument types: () values: []

How do these methods get injected? There's no magic def statement in a controller that appears to do this. Or is the problem that Hibernate isn't available from my Service class?

I also tried it this way:

import ms.wdw.tropocontrol.IncomingCall
import org.codehaus.groovy.grails.commons.ApplicationHolder

// ...

void afterPropertiesSet() {

    def count = ApplicationHolder.application.getClassForName("IncomingCall").count()
    print "Count is " + count
}

and it failed. ApplicationHolder.application.getClassForName("IncomingCall") returned null. Is this just too early to call this? Is there a "late init" that can be called? I thought that was the purpose of "afterPropertiesSet()"...

+2  A: 

The metaclass methods are wired up after the Spring application context is configured, so trying to call them in afterPropertiesSet will fail. Instead you can create a regular init() method and call that from BootStrap:

import ms.wdw.tropocontrol.IncomingCall

class FooService {

   void init() {
      int count = IncomingCall.count()
      println "Count is " + count
   }
}

and call that with this:

class BootStrap {

   def fooService

   def init = { servletContext ->
      fooService.init()
   }
}
Burt Beckwith
Thank you very much! And I'm glad I asked, because I never would have thought to add something in a Bootstrap class....
ראובן
And this works. I start a worker thread from the "init" method and I can access my Domain class dynamic methods from that....
ראובן
A: 

The real answer, I discovered, is not to do this.

I should instead inject my service into my domain class and call it from there.

I can use the "trigger" methods, like afterInsert to call my service methods as needed

class Deal {
    def authenticateService

    def afterInsert() {
        def user = authenticateService.userDomain();
        ....
    }
....
}

(for example, from the grails services documentation)

ראובן