Reputation: 5311
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
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