A confused Grails newbie here. I am currently going through the tutorials in
a book (Smith, Ledbrook, "Grails in Action", Manning Publications, 1st Ed)
and am stumped in the first chapter! When browsing to localhost, I get the
error messages further below. The tutorial leads me through creating a
Random Quote of the Day application. As you might suspect, browsing to the
webpage gives a random quote (which were saved in the "Quote" domain class)
with each refresh.
I have made the controller, view, layout, domain class, all of which are
pretty simple. I would imagine that I'd get these errors if there were no
test data, but using the grails console shows me that there are. Despite
this, refreshes of the browser echo the errors in an open terminal.
The code for the Quote domain class and the controller are below as well. I
wanted to change the config file for the development environment to make it
persistent, so that entry is also down there. Let me know if you need to see
anything else...
Any ideas? (Using Grails version 2.4.0 installed on Ubuntu 14.04. Book uses
code for Grails 1.1)
Error:
URI: /qotd/quote/random
Class:java.lang.IllegalStateException
Message: Method on class [qotd.Quote] was used outside of a Grails
application. If running in the context of a test using the mocking API or
bootstrap Grails correctly.
Around line 8 of grails-app/controllers/qotd/QuoteController.groovy
6:
7: def random = {
8: def allQuotes = Quote.list()
9: /*def randomQuote
10: if (allQuotes.size() > 0 )
11: {
Trace
Line | Method
->> 9 | doCall in QuoteController.groovy
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 198 | doFilter in PageFragmentCachingFilter.java
| 63 | doFilter in AbstractFilter.java
| 1145 | runWorker in java.util.concurrent.ThreadPoolExecutor
| 615 | run . . . in java.util.concurrent.ThreadPoolExecutor$Worker
^ 744 | run in java.lang.Thread
Controller
package qotd
class QuoteController {
def index = { }
def random = {
def allQuotes = Quote.list()
/*
def randomQuote
if (allQuotes.size() > 0 )
{
def randomIdx = new Random().nextInt(allQuotes.size())
randomQuote = allQuotes[randomIdx]
} else {
randomQuote = new Quote(author: "Anonymous",
content: "Real Programmers Don't eat Quiche")
}
[quote : randomQuote ]
*/
}
}
Quote domain class
package qotd
class Quote {
String content
String author
Date created = new Date()
static constraints = {
}
}
Development Environment from DataSource.groovy
development {
dataSource {
dbCreate = "update" // one of 'create', 'create-drop', 'update',
'validate', ''
url =
"jdbc:h2:file:~/h2db/quotedevdb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE"
}
}
Yep, as grantmcconnaughey comments, you don't want to declare your controller actions as closures with an '=' sign. It is now recommended to use methods. So you can do:
def random() {
def allQuotes = Quote.list()
}
or:
public random() {
def allQuotes = Quote.list()
}
See the online docs.
Related
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?
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
using the spring security core plugin I am trying to catch event so I am using
grails.plugin.springsecurity.useSecurityEventListener = true
grails.plugin.springsecurity.onInteractiveAuthenticationSuccessEvent = { e, appCtx ->
def request = org.codehaus.groovy.grails.plugins.springsecurity.SecurityRequestHolder.getRequest()
def session = request.getSession(false)
session.myvar=2
}
but it give me :
2014-06-08 21:49:05,333 [http-bio-8080-exec-6] ERROR [/ammc].[default] - Servlet.service() for servlet [default] in context with path [/ammc] threw exception
Message: No signature of method: groovy.util.ConfigObject.getRequest() is applicable for argument types: () values: []
Line | Method
->> 158 | doCall in Config$_run_closure5
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 95 | call in grails.plugin.springsecurity.SecurityEventListener
| 72 | onApplicationEvent in ''
| 49 | doFilter in grails.plugin.springsecurity.web.authentication.RequestHolderAuthenticationFilter
| 82 | doFilter . . . . . in grails.plugin.springsecurity.web.authentication.logout.MutableLogoutFilter
| 1145 | runWorker in java.util.concurrent.ThreadPoolExecutor
| 615 | run . . . . . . . in java.util.concurrent.ThreadPoolExecutor$Worker
^ 745 | run in java.lang.Thread
notice that the line 158 in the config file is exactly the line
def request = org.codehaus.groovy.grails.plugins.springsecurity.SecurityRequestHolder.getRequest()
which is crazy because I am not invoking groovy.util.ConfigObject.getRequest() in this line
I already tried to clean and compile but nothing change.
and at the same time if I want to catch the failure login event, what event I must catch?
update
I am using grails 2.3.8 and spring-security-core:2.0-RC2
To answer the question
This may be late but...
I believe you mean
def request = grails.plugin.springsecurity.web.SecurityRequestHolder.getRequest()
(note the different package name)
This may not be of much help to #Bilel but it may be to anyone else who happens upon the question.
One a side note:
which is crazy because I am not invoking groovy.util.ConfigObject.getRequest() in this line
When you see weird things like groovy.util.ConfigObject I have come to notice that it usually means a variable in Config does not exist.
Also, on another note:
I don't know if doing it in Config.groovy is an absolute requirement but I believe this gets cleaner if you register a listener.
Here's what I would do:
import org.springframework.context.ApplicationListener
import org.springframework.security.authentication.event. InteractiveAuthenticationSuccessEvent
class MyLoginListener implements ApplicationListener<InteractiveAuthenticationSuccessEvent> {
void onApplicationEvent(InteractiveAuthenticationSuccessEvent event) {
def request = grails.plugin.springsecurity.web.SecurityRequestHolder.getRequest()
def session = request.getSession(false)
session.myvar=2
}
}
and then register it in resources.groovy
beans = {
myLoginListener(MyLoginListener)
}
You need the following line in Config.groovy, but you may already have it there anyway.
grails.plugin.springsecurity.useSecurityEventListener = true
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