0
votes

I'm a newbie here, and hopefully I can explain this thoroughly.

Working through Grails in Action book, Second Edition using the Groovy Grails Tool Suite - GGTS (aka Spring Tool Suite - STS).

GGTS release 3.6.4. Grails version 2.4.4

I'm still on Chapter 1. By this time, I've added several 'quotes' to my database. When I do a "println Quote.count()" through the Grails Console I see I have 4 quotes.

I try to run my random GSP and receive the following error:

Line | Method
->>    7 | doCall    in C:/Users/donahujc/Documents/workspace-ggts-3.6.4.RELEASE/qotd/grails-app/views/quote/random.gsp
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

Caused by NullPointerException: Cannot get property 'content' on null object**
->>    7 | doCall    in C__Users_donahujc_Documents_workspace_ggts_3_6_4_RELEASE_qotd_grails_app_views_quote_random_gsp$_run_closure2_closure4
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|     10 | run       in C__Users_donahujc_Documents_workspace_ggts_3_6_4_RELEASE_qotd_grails_app_views_quote_random_gsp
|    198 | doFilter  in PageFragmentCachingFilter.java
|     63 | doFilter  in AbstractFilter.java
|   1142 | runWorker in java.util.concurrent.ThreadPoolExecutor
|    617 | run       in java.util.concurrent.ThreadPoolExecutor$Worker
^    745 | run . . . in java.lang.Thread

What this is telling me is that my call is pointing to nothing. So, I go into the DBConsole back end, and sure enough, my Quote table (which contains Content and Author) isn't there.

How's that possible, when my DataSource.groovy file was changed to the following:

// environment specific settings
environments {
    development {
        dataSource {
            dbCreate = "update" // one of 'create', 'create-drop', 'update', 'validate', ''
            url = "jdbc:h2:devDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE"

I changed "create-drop" to "update" and removed reference to memory (mem:).

I know the data is there, because I can use the Grails Console to query it.

The complicated part is that I can't go through the book all at once. So I've had to close and re-launch GGTS multiple times over several days. I thought that re-running the app would re-initialize the table, but that doesn't seem to be the case.

How can I get this table initialized? I tried adding a new quote. (Somehow my index went from quote #4 to quote #33.) But still no table for my GSP to pull from.

I'm just at a loss at how to get this table (and the data that's in there somewhere) initialized. This is something I'm going to have consistent problems with, because I'll be constantly closing/re-opening GGTS.

Help

EDIT: (Adding more of my code)

Quote Controller:

def random(){
        def allQuotes = Quote.list()
        def randomQuote
        if (allQuotes.size() > 0){
            def randomIdx = new Random().nextInt(allQuotes.size())
        }else {
            randomQuote = new Quote(author:"Anonymous",
                content:"Real Programmers double peace out on quiche")
        }
        [quote:randomQuote]

    }

Random.gsp

<html>
<head>
<title>Random Quote</title> 
</head>
<body>
<div id="quote">
<q>${quote.content}</q>
<p>${quote.author}</p>
</div>
</body>
</html>

Quote.groovy

class Quote {

    String author
    String content
    Date created = new Date()

    static constraints = {
    }
}

Everything has worked fine until now. I know my data is in the DB because I can query it from the Grails Console. But DB console doesn't even show my Quote table :(

1
Have you downloaded the source code from Manning and compared it with your code. I have completed up to chapter 7 of the book using GGTS and not had any issues. Reopening and closing GGTS will have no effect since devDb is stored in a file. - corky_bantam
Hi - yes, I did compare it a few times. Going to look over it some more... I've modified my OP to include code from my class, controller, and view. Maybe I'm missing something simple, but it just doesn't look that way to me. - JuniperSquared
Correction on my part - I didn't download the source code yet. I'm comparing code in the book examples to what I've written. - JuniperSquared
In addition to the answer, I'd like to point out that there are significant differences between Grails 2.3.x and 2.4.x that affect the book. Several problems were reported on the book's forum, so I recommend that you scan through that to identify the issues you're likely to hit. - Peter Ledbrook
Agreed. Another reason why I'm going through this as slowly as I am. Really, I can't thank you enough for your responsiveness. I'll continue going through the forums. - JuniperSquared

1 Answers

1
votes

You're going to kick yourself if that is in fact the code that you're using :). Note that uninitialised variables in Groovy are given a default value of null. So the initial value for the randomQuote variable in the random action is null.

The value of the randomQuote variable is then assigned to the quote variable in the view's model. Looking at the view, I can tell that the NullPointerException is being thrown by the ${quote.content} expression. So if quote is null in the model, that must mean that randomQuote is null in the action.

So what happens when there are quotes in the database? The action takes this branch:

if (allQuotes.size() > 0) {
    def randomIdx = new Random().nextInt(allQuotes.size())
}

As you can see, there is no assignment to the randomQuote variable, so it remains null. The code from listing 1.3 of the book has this:

if (allQuotes.size() > 0) {
    def randomIdx = new Random().nextInt(allQuotes.size())
    randomQuote = allQuotes[randomIdx]
}

Or at least I hope it does. It's showing up in my PDF version.

This was a little long-winded, but I'm hoping that you can follow the reasoning and use that to diagnose other issues that you encounter. I recognise that it's not always easy for newcomers to interpret the various errors they come across.