Grails: Cannot invoke method sendEmail() on null object when using in service

Syam picture Syam · Oct 8, 2014 · Viewed 8.1k times · Source

I have created a service NotifierService

class NotifierService {

    MailService mailService

    def sendEmail(String email) {
        mailService.sendMail {
            to email
            from "[email protected]"
            subject "Subject"
            body "Some text"
        }
    }
}

Then, I'm trying to call sendEmail method in another method updateUser in DbService service

class DbService {
    NotifierService notifierService

    def updateUser(){
        //Some Logic
        //Get userObject

        def email = userObject.email

        //Send email
        try {
            notifierService.sendEmail(email)
        } catch (Exception e) {
            e.printStackTrace()
        }
    }

    //Other methods
    .
    .
    .
}

It works fine when I call sendEmail method in BootStrap, but I get the following error when I use it in DbService

| Error java.lang.NullPointerException: Cannot invoke method sendMail() on null object
| Error     at org.codehaus.groovy.runtime.NullObject.invokeMethod(NullObject.java:77)
| Error     at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:45)
| Error     at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
| Error     at org.codehaus.groovy.runtime.callsite.NullCallSite.call(NullCallSite.java:32)
| Error     at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)

I understood that the mailService in NotifierService is not initialized when using it in DbService. How can I resolve it?

The DbService is instantiated in a grails-job

class MyJob {
    DbService dbService = new DbService()


    static triggers = {
        // start delay: 30000 (30sec), repeat: 120000 (2*60*1000 = 2min)
        simple name:'myJobTrigger', startDelay:30000, repeatInterval: 120000, repeatCount: -1
    }

    def execute() {
        println "*******************************************************"
        println "MyJob: "+new Date()
        println "*******************************************************"

        dbService.updateUser()
    }
}

Answer

injecteer picture injecteer · Oct 8, 2014

ok, this is clear then :)

if you do

DbService dbService = new DbService()

then the dependencies will NEVER be populated with spring.

you have to leave it un-initialized so that the service is injected from the application context:

class MyJob {
  DbService dbService // or def dbService
}