Reputation: 33
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"
}
}
Upvotes: 3
Views: 836
Reputation: 291
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.
Upvotes: 3