I have created a service NotifierService to send emails using grails mail plugin.
class NotifierService {
MailService mailService
def sendWarningEmail(String name, String email, Date blockingDate) {
try {
mailService.sendMail {
to email
from "noreply-myApp#domain.com"
subject "Status message: Warning"
body (view:"/email/warningEmail", model:[
name:name,
blockingDate:blockingDate
])
}
} catch (Exception e) {
e.printStackTrace()
}
}
}
I have created another service ApplicationUtilService in which I am trying to use the NotifierService.
class ApplicationUtilService{
def notifierService
def notifyUser(){
notifierService.sendWarningEmail("User name", "user#domain.com", new Date())
}
}
I am trying to call notifyUser() in a grails job UpdateJob
class UpdateJob{
def applicationUtilService
static triggers = {
// Scehduling parameters
}
def execute(){
applicationUtilityService.notifyUser()
}
}
I get the following error
Error 2014-12-05 12:04:53,550 [quartzScheduler_Worker-1] ERROR listeners.ExceptionPrinterJobListener - Exception occurred in job: Grails Job
Message: java.lang.NullPointerException: Cannot invoke method notifyUser() on null object
Line | Method
->> 111 | execute in grails.plugins.quartz.GrailsJobFactory$GrailsJob
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 202 | run in org.quartz.core.JobRunShell
^ 573 | run . . in org.quartz.simpl.SimpleThreadPool$WorkerThread ...`
It works when I instantiate as
ApplicationUtilService applicationUtilService = new ApplicationUtilService()
instead of using grails dependency injection. Again, the same problem with the notifierService in ApplicationUtilService and fixed by instantiating same as above.
Now, the real problem is with the mailService. The instantiation as above didn't work. How could I resolve it
The Null Pointer is occurring on UpdateJob.applicationUtilService, so it seems like applicationUtilService isn't being injected into UpdateJob correctly. Is UpdateJob in the right package?
Related
I'm working on grails 2.4.5.
I connect my project to oracle 11g.
In datasource, I add:
dataSource {
pooled = true
dialect = org.hibernate.dialect.Oracle10gDialect
driverClassName = 'oracle.jdbc.OracleDriver'
username = 'grails' // YOUR USERNAME AND PASS
password = 'grails'
url = 'jdbc:oracle:thin:localhost:1521:orcl'
dbCreate = 'update'
}
Then it connects and when I create new domain, new table in db creates.
However when I add new:
new Book(name:'The Strain').save(flush:true)
Then errors appear:
2015-07-29 17:10:30,036 [Thread-10] ERROR plugins.AbstractGrailsPluginManager - Plugin [controllers:2.4.5] could not reload changes to file [C:\Users\Thuc Tran\IdeaProjects\EmailTutorial\grails-app\controllers\emailtutorial\PlaceController.groovy]: Cannot invoke method getPropertyValue() on null object
Message: Cannot invoke method getPropertyValue() on null object
Line | Method
->> 120 | configureScaffoldingController in ScaffoldingGrailsPlugin
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
^ 105 | doCall in ScaffoldingGrailsPlugin$_closure3
Any solutions will be appreciated. Thanks.
I solved this problem. I post the solution for those who need it.
On oracle, create sequence, eg: BOOK_SEQ on my case. Make sure that on oracle, when you add new record, id will be auto increment.
Then on the domain class, static mapping quote, add:
static mapping = {
id generator:'sequence', params:[sequence:'BOOKS_SEQ']
}
So that's all.
If answer not clear, I feel free to answer.
Thanks.
I'm trying to create an async task that will not block the request. The user make the request, the task will start, and the controller will render "Job is running...", this is for avoid the request being blocked waiting the task to complete.
Once the task is finish, it will execute the onComplete and do something with the result of that task (for example call a service that will send a mail to an user)
| Error 2014-09-16 17:38:56,721 [Actor Thread 3] ERROR gpars.LoggingPoolFactory - Async execution error: null
The code is the following:
package testasync
import static grails.async.Promises.*
class TestController {
def index() {
//Create the job
def job1 = task {
println 'Waiting 10 seconds'
Thread.sleep(10000)
return 'Im done'
}
//On error
job1.onError { Throwable err ->
println "An error occured ${err.message}"
}
//On success
job1.onComplete { result ->
println "Promise returned $result"
}
render 'Job is running...'
}
Complete stacktrace:
| Error 2014-09-17 10:35:24,522 [Actor Thread 3] ERROR gpars.LoggingPoolFactory - Async execution error: null
Message: null
Line | Method
->> 72 | doCall in org.grails.async.factory.gpars.GparsPromise$_onError_closure2
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 62 | run in groovyx.gpars.dataflow.DataCallback$1
| 1145 | runWorker in java.util.concurrent.ThreadPoolExecutor
| 615 | run in java.util.concurrent.ThreadPoolExecutor$Worker
^ 745 | run . . . in java.lang.Thread
I ended using the executor framework with the grails-executor plugin. I uploaded a very basic example here: https://github.com/agusl88/grails-async-job-queuqe
That code is using a "custom" version of the grails-executor plugin, i merged some PR's from the plugin repo and packaged as jar just for testing propuses. The repo of the plugin is this: https://github.com/basejump/grails-executor
I was able to get rid of this exception in a controller by removing the onComplete and onError calls. I guess the exception happens because the parent thread ended when you called render.
So your:
Promise p = task {
complexAsyncMethodCall(); // (1) do stuff
}
.onComplete { result -> println result } // (2) on success
.onError { Throwable t -> System.err.println("Error: " + t) } // (3) on error
Becomes:
Promise p = task {
try {
def result = complexAsyncMethodCall(); // (1) do stuff
println result // (2) on success
} catch(Throwable t) {
System.err.println("Error: " + t) // (3) on error
}
}
This adds coupling between your work (1) and the result processing (2 and 3) but you could overcome this by writing your own Closure wrapper that takes extra Closures as arguments. Something like this:
// may not work! written off the top of my head
class ProcessableClosure<V> extends Closure<V> {
Closure<V> work;
Closure<?> onError;
Closure<?> onComplete;
#Override
public V call(Object... args) {
try {
def result = work.call(args); // (1) do stuff
onComplete.call(result); // (2) on complete
} catch(Exception e) {
onError.call(result); // (3) on error
}
}
}
That makes your code more readable:
Closure doWork = { complexAsyncMethodCall(); } // (1) do stuff
Closure printResult = { println it } // (2) on complete
Closure logError = { Throwable t -> log.error t } // (3) on error
Closure runEverythingNicely = new ProcessableClosure(work: doWork, onComplete: printResult, onError: logError)
Promise p = task { runEverythingNicely }
When creating a Promise async task inside a controller you actually have to return the response by calling the get() method on the task, or the onError and onComplete methods will never be called. Adding:
job1.get()
Before your call to render will resolve the issue.
In my case, just returning a promise worked.
MyService.groovy
import static grails.async.Promises.*
def getAsync(){
Promise p = task {
//Long running task
println 'John doe started digging a hole here.'
Thread.sleep(2000)
println 'John doe working......'
return 'Kudos John Doe!'
}
p.onError { Throwable err ->
println "Poor John"+err
}
p.onComplete { result ->
println "Congrats." +result
}
println 'John Doe is doing something here.'
return p
}
I get the error "Caused by NullPointerException: null ->> 64 | getMailConfig in grails.plugin.mail.MailService". I have configured the config.groovy as per the documentation provided by mail plugin.
Please help me to resolve this issue.
Find my config.groovy code below.
grails
{
mail {
host = "smtp.gmail.com"
port = 465
username = "xxxxxx#gmail.com"
password = "xxxxxx"
props = ["mail.smtp.auth":"true",
"mail.smtp.socketFactory.port":"465",
"mail.smtp.socketFactory.class":"javax.net.ssl.SSLSocketFactory",
"mail.smtp.socketFactory.fallback":"false"]
}
}
Find my groovy class code below.
package common
import grails.plugin.mail.*;
public class FlowSchedule implements Job {
def mailService = new MailService()
public void execute(JobExecutionContext context)
throws JobExecutionException {
//some extra logic here
sendEmail(schedulerEntry.name,schedulerEntry.email)
}
def sendEmail(String name,String email)
{
mailService.sendMail {
to "amith.ravuru#citrix.com"
subject "Hello Amith"
body 'this is some text'
}
}
}
Complete Error trace:
Error |
2014-07-14 12:41:00,041 [DefaultQuartzScheduler_Worker-4] ERROR core.ErrorLogger - Job (group.Job_1 threw an exception.
Message: Job threw an unhandled exception.
Line | Method
->> 213 | run in org.quartz.core.JobRunShell
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
**^ 573 | run in org.quartz.simpl.SimpleThreadPool$WorkerThread
Caused by NullPointerException: null**
**->> 64 | getMailConfig in grails.plugin.mail.MailService**
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 59 | sendMail in ''
| 94 | sendEmail in common.FlowSchedule$$EOk1HyVA
| 79 | execute in ''
| 202 | run in org.quartz.core.JobRunShell
^ 573 | run in org.quartz.simpl.SimpleThreadPool$WorkerThread
I solved the issue by moving the sendEmail part to a controller. Then, call the controller method from any class in src/groovy. Because, in controllers, grailsApplication can be injected using def grailsApplication. Please find the controller code below.
class SendMailController
{
def grailsApplication
def sendEmail(String name,String email,String mailsubject)
{
if(email != null)
{
try
{
sendMail {
to email
from "exabgpnotifier#gmail.com"
subject "ExaBGP Notification"
body "Hello "+name+"\n\n"+ mailsubject +" \n\nRegards,\nExaBGP Team"
}
}
catch(Exception e)
{
e.printStackTrace()
println "ERROR!!: Unable to send the notification to email "+ finalemaillist.toString()
}
}
}
}
I guess that this plugin injects mailService into your application. So instead of creating service with constructor like you've done:
def mailService = new MailService()
Just declare the field and let DI mechanism to do the work of injecting the value:
def mailService
The remaining part of your code looks okay. Think about changing the name of sendMail method, now it's a bit confusing when you've got the same names for your method and the one from mailService.
Hope it'll help!
I don't think this will work:
grails
{
mail {
host = "smtp.gmail.com"
port = 465
username = "xxxxxx#gmail.com"
password = "xxxxxx"
props = ["mail.smtp.auth":"true",
"mail.smtp.socketFactory.port":"465",
"mail.smtp.socketFactory.class":"javax.net.ssl.SSLSocketFactory",
"mail.smtp.socketFactory.fallback":"false"]
}
}
That is valid code but doesn't do what you intend. The opening curly brace after grails needs to be on the same line so the closure is treated as an argument to the grails method.
grails {
mail {
host = "smtp.gmail.com"
port = 465
username = "xxxxxx#gmail.com"
password = "xxxxxx"
props = ["mail.smtp.auth":"true",
"mail.smtp.socketFactory.port":"465",
"mail.smtp.socketFactory.class":"javax.net.ssl.SSLSocketFactory",
"mail.smtp.socketFactory.fallback":"false"]
}
}
Open you resources.groovy file and put this entry.
import common.FlowSchedule
beans = {
// make sure you import flow schedule class
flowSchedule(FlowSchedule) {
mailService = ref('mailService')
}
}
Then in your class.
package common
import grails.plugin.mail.*;
public class FlowSchedule implements Job {
def mailService
public void execute(JobExecutionContext context)
throws JobExecutionException {
//some extra logic here
sendEmail(schedulerEntry.name,schedulerEntry.email)
}
def sendEmail(String name,String email)
{
mailService.sendMail {
to "amith.ravuru#citrix.com"
subject "Hello Amith"
body 'this is some text'
}
}
}
When you need flow schedule in any controller or service then just do this
class MyService {
def flowSchedule
def myMethod() {
flowSchedule.sendEmail('test','test#test.com')
}
}
Below is my Pgtyp.groovy (domain class):
package marchmock2
class Pgtyp {
Date date_hour
String mv
String pagetype
Integer visits
Integer visits_ly
Integer visits_lw
String time_period
String platform
String device
String browser
static mapping = {
table "pgtyp"
version false
date_hour column: "date_hour"
mv column: "mv"
pagetype column: "pagetype"
visits column: "visits"
visits_ly column:"visits_ly"
visits_lw column:"visits_lw"
time_period column:"time_period"
platform column:"platform"
device column:"device"
browser column:"browser"
}
static constraints = {
}
}
This is how my controller looks like:
package marchmock2
import grails.converters.*
import groovy.sql.Sql
class PgtypController {
def ajaxGetMv = {
def pgtyp = Pgtyp.get(params.id)
render pgtyp as JSON
}
def index() {
}
}
And finally, this is my index.gsp:
<html>
<head>
<g:javascript src="jquery-1.10.2.min.js"/>
<g:javascript src="prototype.js"/>
</head>
<body>
<form>
<g:select from="['AFFILIATES', 'SEO', 'SEM','DISPLAYADS']" name="mv" onchange="${remoteFunction(
controller:'Pgtyp',
action:'ajaxGetMv',
params:'\'id=\' + escape(this.value)',
onSuccess: 'printpgtyp(data)')}"></g:select>
</form>
<g:javascript>
function printpgtyp(data) {
console.log(data)
}
</g:javascript>
</body>
</html>
When I run my app, I get a dropdown and on selecting any option from it I get an error saying:
POST http://localhost:8080/marchmock2/pgtyp/ajaxGetMv 500 (Internal Server Error)
What do I do with it? Is there any error in the way I'm writing it or have I misunderstood anything? Any help would be appreciated.
UPDATE
|
2014-07-04 16:37:23,149 [http-bio-8080-exec-10] ERROR [/marchmock2].[gsp] - Servlet.service() for servlet [gsp] in context with path [/marchmock2] threw exception
Message: It looks like you are missing some calls to the r:layoutResources tag. After rendering your page the following have not been rendered: [defer]
Line | Method
->> 1145 | runWorker in java.util.concurrent.ThreadPoolExecutor
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 615 | run in java.util.concurrent.ThreadPoolExecutor$Worker
^ 744 | run . . . in java.lang.Thread
UPDATE2
Following an answer on stackoverflow, I changed to and the error mentioned in first UPDATE is gone. However, when I select 'SEO' from the dropdown, I get the following error
TypeMismatchException occurred when processing request: [POST] /marchmock2/pgtyp/ajaxGetMv - parameters:
id: SEO
Provided id of the wrong type for class marchmock2.Pgtyp. Expected: class java.lang.Long, got class java.lang.String. Stacktrace follows:
Message: Provided id of the wrong type for class marchmock2.Pgtyp. Expected: class java.lang.Long, got class java.lang.String
i'm a bit new on the groovy grails technology and i'm having a problem with this one
i looked at this could not initialize proxy - no Session but the application don't get stale too long
I am trying to access the session object on my SecurityFilter placed on the config subfolder. I just wanted to do a check for every request on the controllers to verify if a user has the rights to do such actions.
class SecurityFilters {
def filters = {
userFilterList(controller:"user", action:"list") {
before = {
if (!session.user.accountType.equals("Admin")) {
redirect(uri: "/")
}
}
}
userFilterShow(controller:"user", action:"show") {
before = {
if (!session.user.accountType.equals("Admin")) {
redirect(uri: "/")
}
}
}
userFilterEdit(controller:"user", action:"edit") {
before = {
if (!session.user.accountType.equals("Admin")) {
redirect(uri: "/")
}
}
}
}
}
but I get this error
Message: could not initialize proxy - no Session
Line | Method
->> 6 | doCall in SecurityFilters$_closure1_closure2_closure5
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 186 | doFilter in grails.plugin.cache.web.filter.PageFragmentCachingFilter
| 63 | doFilter in grails.plugin.cache.web.filter.AbstractFilter
| 1110 | runWorker in java.util.concurrent.ThreadPoolExecutor
| 603 | run . . . in java.util.concurrent.ThreadPoolExecutor$Worker
^ 636 | run in java.lang.Thread
before I get to this point I placed the user object on the session object right after doing the login instructions but I am not sure what happened that the session object became not available
some of the properties of the user object were not retrieved, so in the login when I put the user object in the on the session, I also had to manually transfer the property that I needed so I could retrieve again for later use
session.user = user //not enough
session.user.accountType = user.accountType
now I was able to retrieve the user object from the session object and get the property that I wanted to get