NullPointerException with dependency injection - grails

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

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.

Related

Grails Dependency Injection from Service

I am trying to injecting my own service elasticsearchService from the following domain class:
class DocumentESO extends ElasticsearchObject{
ElasticsearchService elasticsearchService
def afterInsert() {
elasticsearchService.save(this) // <-- Cannot invoke method save() on null object
}
}
However, it tells me that it Cannot invoke method save() on null object. Here is my service:
#Transactional
class ElasticsearchService {
#Transactional
def save(ElasticsearchObject esObject) {...}
}
Did I misspell something? If I would use ElasticsearchService elasticsearchService = new ElasticsearchService() then it would work, but I don't have the transactional support anymore.
In this answer, robert mentions it needs to initialized, while using meta programming save() for example. Does it mean that I cannot go with dependency injection in this case?
Thus it would be:
def afterInsert() {
ElasticsearchService elasticsearchService = new ElasticsearchService()
elasticsearchService.save(this)
}
??
Service injection in GORM entities is disabled by default since Grails 3.2.8.
You can turn on autowiring in this one particular domain class by adding to DocumentESO:
static mapping = {
autowire true
}
however it's not recommended: https://grails.org/blog/2017-05-09.html

grails 2.1.1 command object service injection for custom validator

Grails 2.1.1
I can't seem to get a command object to be injected with a service so that I can use custom validator. I've tried several things, including
Grails command object data binding and
what the 2.1.1 docs on custom validator suggest, I just can't figure this one out..
Relevant Code:
class RegistrationCommand {
String username
def registrationService
static constraints = {
username validator: { val, obj ->
obj.registrationService.isUsernameUnique(val) }
}
}
class RegistrationService {
def isUsernameUnique(username){
def user = new User(username:username)
user.validate()
if(user.errors.hasFieldErrors("username")){
return false
}else{
return true
}
}
Resolved.. Issue was due to plugin.
I'm using a plugin for client side jquery validation (jquery-validation-ui-1.4.2). The command object being created by the plugin's controller wasn't getting injected with the service. The issue was reported https://github.com/limcheekin/jquery-validation-ui/issues/17 . The fix does work but has not been pushed upstream yet.

How to set parameters on Groovy/Grails InvokeHelper.invokeMethod()

I have a Grails webapp running a Spring Integration inbound-channel-adapter that is configured to receive emails and there is a service activator that processes the message. This service activator pulls out pieces and parts of the email based on business rules and then needs to update Grails domain objects and save those changes to the database.
Spring Integration service activator code snippet:
HashMap<String, Serializable> params = new HashMap<String, Serializable>();
params.put("notification", notification );
params.put("notificationType", notificationType );
params.put("sender", notificationSender );
InvokerHelper.invokeMethod(NotificationCreationService.class, "createNotification", params);
Grails NotificationCreationService action snippet:
def static createNotification() {
if (params.notification != null && params.notificationType != null && params.sender != null) {
String notification = params.get("notification") as String
NotificationType notificationType = params.get("notificationType") as NotificationType
String sender = params.get("sender") as String
def NotificationMessage notificationMessage = null
notificationMessage = new NotificationMessage()
notificationMessage.notification = notification
notificationMessage.save(flush: true)
...
}
}
NotificationMessage is a standard Grails domain class
Error generated:
org.springframework.integration.MessageHandlingException:
groovy.lang.MissingMethodException: No signature of method: mycompany.pyproject.mypackage.NotificationMessage.save() is applicable for argument types: () values: []
Possible solutions: save(), save(boolean), save(java.util.Map), wait(), any(), wait(long)
If I change createNotification() to not be static then I get the following:
org.springframework.integration.MessageHandlingException:
groovy.lang.MissingMethodException: No signature of method: static mycompany.pyproject.mypackage.NotificationCreationService.createNotification() is applicable for argument types: (java.util.HashMap) values: [...]
Possible solutions: createNotification(java.util.HashMap), createNotification(java.lang.String, napa.changedetection.alert.NotificationType, java.lang.String)
I've tried other combinations of InvokeHelper.invokeMethod() and the definitions of the Grails actions with similar results. InvokeHelper has several other methods for invoking methods as well as setting different properties, but I haven't found the magic combination to make this work and any internet searched have turned up very little as far as example code for InvokeHelper.
Ideally, the Grails action would not be static and it would use the standard params mechanism. This would allow me to call the same action directly from the Grails code as well as from the Spring Integration service activator via the InvokeMethod functionality.
Does anyone have any thought on how to tie this together?
You should not use InvokeHelper now, Grails 2 injects signature at compile time for java purposes (except dynamic finders, but you can guess why).
In your Java bean I would inject notificationCreationService using :
resources.groovy/xml + setter
OR
Constructor + applicationContext (implement ApplicationContextAware)
Using the service reference should work, if not there is a bug to analyse there.
Where did you declare your service activator ?

Can't inject grailsApplication into service

I'm having an issue injecting grailsApplication into a service I created in Grails 2.1. I have built a simple test application (hoping I could figure out this issue and then port the fix over to my real application) that consists of a single controller, view, and service.
The controller looks like this:
class IncidentController {
static allowedMethods = [save: "POST", update: "POST", delete: "POST"]
def incidentService
def index() {
incidentService.serviceMethod()
redirect(action: "list", params: params)
}
// Other stuff
}
My service consists simply of this:
class IncidentService {
def grailsApplication
def serviceMethod() {
System.out.println("Grails application: " + grailsApplication)
}
}
And I declare the injection of IncidentService in my resources.groovy as follows:
beans = {
incidentService(org.myorg.test.IncidentService)
}
Now everything I have read online says that this should work fine and I should be able to access my configs through the grailsApplication in the service. However, grailsApplication is null whenever I try to. If I add a ConfigObject to the service and set it by passing grailsApplication.getConfig() from the controller, it works fine.
Can anyone please point me in the right direction for figuring out what the problem is here?
Thank you
You shouldn't have to add your IncidentService to resources.groovy. If that service is under grails-app/services it will be done for you. Remove that and try it again. I think that might be your problem

Fetching some value from message.properties in Grails

Want to fetch a value from message.properties file in grails in a job , how can I do that ??
My Job:
def execute() {
// execute task
List<String> emails = NayaxUser.findAllByEmailSent(false)*.username
emails.each {emailAddress->
mailService.sendMail {
//todo: FETCH FROM MESSAGE.PROPERTIES
to emailAddress
from FETCH FROM MESSAGE.PROPERTIES
subject FETCH FROM MESSAGE.PROPERTIES
html body.toString()
}
}
}
You can use:
g.message(code: 'my.message.code')
//or
g.message(code: 'my.message.code', args: [arg1, arg2])
You can inject the messageSource to retrieve the message:
class MyJob {
def messageSource
def execute() {
...
def message = messageSource.getMessage('message.code', ...)
...
}
}
Here's the documentation for getMessage(); you need to provide a couple more method arguments, namely args (an Object[]) and a Locale.
You can get a reference to the messageSource bean from anywhere using:
import org.codehaus.groovy.grails.commons.ApplicationHolder
import org.springframework.context.MessageSource
MessageSource messageSource = ApplicationHolder.application.mainContext.getBean('messageSource')
You can then get the messages themselves using the methods of the MessageSource interface.
Just as an addition to above answers, there could be following places where you need to implement internationalisation or fetch the message from message bundles.
views
controllers
services
Filters
Utility files(e.g. in util package or generalised exception message handling)
Special files e.g. in Shiro security rest realms
Below are the elaborate usage scenarios:
Views:- we have taglib available with message tag. Use this on views.
controllers :- message method is by default available here and locale conversion is automatically handled. See enter link description here
service: we may call taglibs inside services as below:
def myCustomTaglib = grailsApplication.mainContext.getBean('com.custom.MyCustomTagLib');
Or inject messageSource bean as
def messageSource
4.Filters / utility / Special files:- For these you may create something like below and then use it throughout.
String i18nMessage(def input,String defaultMessage) {
String[] languageCode = RequestContextHolder.currentRequestAttributes().request.getHeader("Accept-Language").split("-")
Locale locale = languageCode.length == 2 ? new Locale(languageCode[0], languageCode[1]) : new Locale(languageCode[0])
String message = defaultMessage
try {
message = messageSource.getMessage(input.code,input?.args?.toArray(),locale)
}catch (NoSuchMessageException nsme ){
log.info("No such error message--> ${nsme.getMessage()}")
}
return message
}
Also, if you get exception below:
java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
Then, you might need to add request listener to your web.xml
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
Note: web.xml is not available by default, you need to generate it from template.
These are the most common places you might need message bundle conversions.
Solution at point 4 would work in almost all cases. If you notice locale has been handled here manually which we could pass after fetching from requestHeader or request params optionally.
Hope it helps.

Resources