Sap
Sap

Reputation: 5311

NullPointerException with dependency injection

I am trying to use dependency injection for export to excel functionality provided by "Export Plugin" It seems that whenevery I try to use service in my project i get error like following

Stacktrace follows:
java.lang.NullPointerException: Cannot invoke method export() on null object
    at pm.ProjectsController$_closure2.doCall(ProjectsController.groovy:39)
    at pm.ProjectsController$_closure2.doCall(ProjectsController.groovy)
    at java.lang.Thread.run(Thread.java:662)

The code I am using is following, this just means service variable is null

def exportService// i have  tried with and without the initialization
        if(params?.format && params.format != "html"){
            response.contentType = ConfigurationHolder.config.grails.mime.types[params.format]
            response.setHeader("Content-disposition", "attachment; filename=books.${params.extension}")

            exportService.export(params.format, response.outputStream,projectsList, [:], [:])
        }

It seems that no plugin that uses services is working in my project for example AsynchronousMailService in my project didn't work as it was suppose to and thus I have been using it like following

AsynchronousMailService asynchronousMailService = new AsynchronousMailService()
            asynchronousMailService.sendAsynchronousMail  {    
                to projectsInstance.projectLead.emailAddress
                subject "New project is assigned to you"
                html msg
            }

Unless I am missing somethig very basic I do not beleive I should be instantiating this class if the plugin offers the same as service.

Thanks

Upvotes: 1

Views: 2863

Answers (1)

Burt Beckwith
Burt Beckwith

Reputation: 75681

Right, you should never instantiate services or other Spring beans - use dependency injection. It might work, but if the bean has any dependencies of its own they'll be null since you're bypassing Spring.

You're not using dependency injection, you're declaring a local variable and expecting magic.

Dependency injection in Grails uses public fields. Since Groovy creates a public field into a getter and setter under the hood, Spring sees the setter and Grails is configured to inject by name, so as long as the field/setter matches a Spring bean name it works.

So your controller should look something like this:

class MyController {

   def exportService

   def myAction = {
      if (params?.format && params.format != "html") {
         response.contentType = grailsApplication.config.grails.mime.types[params.format]
         response.setHeader("Content-disposition",
                            "attachment; filename=books.${params.extension}")

         exportService.export(params.format,
                 response.outputStream,projectsList, [:], [:])
      }
   }
}

Note that I also removed the use of ConfigurationHolder since it's deprecated. The best way to get access to the config is from the grailsApplication bean. It's already injected in controllers (and taglibs), and in a service or other bean you'd just need a def grailsApplication field declaration.

Upvotes: 3

Related Questions