Question

I am new to grails and I am getting this error: Cannot get property 'id' on null object I am trying to create a web application that displays fixtures in addition to adding new fixtures. However, when running the application I am unable to add fixtures or display the page that deals with adding the fixtures i.e add.gsp. Here are the classes that are currently available in my application.

Here is my simple Fixture domain class:

package cricketfixturesgrailsapp

class Fixture {
   Date date
   String venue




 // hasMany  = [scores:Scores]

 static hasMany = [team:Team]

static constraints = {
}
}

here is my fixture controller class:

package cricketfixturesgrailsapp

class FixtureController {

 //def index() { }
    def FixtureService


    def add() {
        if (request.method == 'GET') {
            [fixtureBean: new Fixture()]
        }
        else {
            def fixture = FixtureService.createFixture(params.fixture?.date, params.fixture?.venue)
            if (!fixture.hasErrors()) {
                redirect action: 'show', id: fixture.id
                return
            }

            [fixtureBean: fixture]
        }
    }

  def show() {
        def fixture = Fixture.get(params.id)
        if (fixture) {
            [fixtureBean: fixture]
        }

    }
            def find() {
        if (request.method == 'POST') {
            def fixtures = Fixture.findAllByDate(params.date)
            if (fixtures) {
                if (fixtures.size() > 1) {
                    render view: 'selection', model: [fixtures: fixtures]
                }
                else {
                    redirect action: 'show', id: fixtures[0].id
                }
            }
            else {
                [message: 'fixtures.not.found']
            }
        }
    }
}

I've created a fixtureService to deal with creation and update of fixtures

package cricketfixturesgrailsapp

import grails.transaction.Transactional

//@Transactional
class FixtureService {
//def serviceMethod() {

  Fixture createFixture(Date date, String venue)
    {
        def fixture = new Fixture(date: date, venue:venue)
        fixture.save()
        fixture
    }

void updateFixture(Fixture fixture,Date date, String venue)
{
    fixture.date = date
    fixture.venue = venue
    fixture.save()
}

Team createTeam(String teamName1, String teamName2, long fixtureId){

    def team = new Team(teamName1: teamName1, teamName2: teamName2, fixture: Fixture.load(fixtureId))
    team.save()
    team

}
void updateTeam(String teamName1, String teamName2, long fixtureId) {
    team.teamName1 = teamName1
    team.teamName2 = teamName2
    team.fixture = Fixture.load(fixtureId)
    team.save()
}

}

A formfield.gsp for the form

${label}: <span class="errors"><g:fieldError bean="${bean}" field="${field}" /></span>
<br/>
<g:textField name="${name + '.' +field}" value="${fieldValue(bean:bean, field:field)}" />

In addition I've created 3 gsp files, add to add a fixture, find, finds a fixture by venue and show which shows fixtures, here are the 3 gsp files:

Add gsp

<!--
  To change this license header, choose License Headers in Project Properties.

<%@ page contentType="text/html;charset=UTF-8" %>

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Add fixture</title>
    </head>

    <body>
      <h2><g:if test="${!fixtureBean.id}">New </g:if>Fixture:</h2>

      <g:form action="${ fixture.id ? 'edit' : 'add'}" id="${fixtureBean?.id}">
            <table>
                <tr>
                    <th>
                        <g:render template="/common/formField"
                                  model="[name:'fixture', bean:fixtureBean, field:'date', label:'Date']" />
                    </th>
                </tr>
                <tr>
                    <th>
                        <g:render template="/common/formField"
                                  model="[name:'fixture', bean:fixtureBean, field:'venue', label:'Venue']" />
                    </th>
                </tr>

                <tr>
                    <td>
                        <p><input type="submit" value="${ fixtureBean.id ? 'Update' : 'Add'} Fixture"/></p>
                    </td>
                </tr>
            </table>
        </g:form>
    </body>
</html>

    </body>
</html>

find.gsp

<html>
    <head>
        <meta name="layout" content="main">
        <title>Find fixtures</title>
    </head>

    <body id="find">
        <h2>Find fixtures:</h2>

        <g:form action="find">
            <table>
                <tr>
                    <th>
                        venue
                        <br/>
                        <g:textField name="venue"/>
                    <span class="errors"><g:message code="${message}"></g:message></span>
                    </th>
                </tr>
                <tr>
                    <td><p class="submit"><input type="submit" value="Find fixtures"/></p></td>
                </tr>
            </table>
        </g:form>

        <br/>
        <g:link controller="Fixture" action="add">Add fixture</g:link></a>
    </body>
</html>

show.gsp

<html>
    <head>
        <meta name="layout" content="main">
        <title>fixture Information</title>
    </head>

    <body id="show">
        <h2>fixture Information</h2>

            <table>
                <tr>
                    <th>Date</th>
                    <td><b>${fixtureBean.date} ${fixtureBean.venue}</b></td>
                </tr>

            </table>

    </body>
</html>

Also my default home page is index.gsp, where users are expected to click a link to find fixtures which in turn allows a fixture to be added

<!DOCTYPE html>

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Sample title</title>
    </head>
    <body>
      <h2><g:message code="welcome"/></h2>

        <ul>

                        <li><g:link controller="Fixture" action="add">Find fixture</g:link></li>

        </ul>
    </body>
</html>

stacktrace

....Error 
|
2014-02-23 20:35:23,016 [http-bio-8080-exec-8] ERROR errors.GrailsExceptionResolver  - NullPointerException occurred when processing request: [GET] /CricketFixturesGrailsApp/fixture/add
Cannot get property 'id' on null object. Stacktrace follows:
Message: Error evaluating expression [fixture.id ? 'edit' : 'add'] on line [20]: Cannot get property 'id' on null object
    Line | Method
->>   20 | doCall    in C:/apache-tomcat-7.0.50/webapps/CricketFixturesGrailsApp/grails-app/views/fixture/add.gsp
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
Caused by NullPointerException: Cannot get property 'id' on null object
->>   44 | doCall    in C__apache_tomcat_7_0_50_webapps_CricketFixturesGrailsApp_grails_app_views_fixture_add_gsp$_run_closure2_closure8
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|     47 | run       in C__apache_tomcat_7_0_50_webapps_CricketFixturesGrailsApp_grails_app_views_fixture_add_gsp
|    200 | 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
^    722 | run . . . in java.lang.Thread
Was it helpful?

Solution

I believe you are getting the error from the below section of code.

def fixture = FixtureService.createFixture(params.fixture?.date, 
                                           params.fixture?.venue)
if (!fixture.hasErrors()) {
    redirect action: 'show', id: fixture.id //issue here
    return
}

beans(FixtureService in this case) should be injected as:

def fixtureService //lower case 

Hence, fixtureService is not injected the way it is used now. This is my anticipation until a full stacktrace of the error is added to the question. This (service class injection) has to be fixed anyways.

OTHER TIPS

Here is what I would do: Once you have domain, I would generate controllers and gsp pages as well. What would that provide?

First you will have a controller with actual code instead of "scaffold=true". How to generate

Second you will be able to modify/add functionality to controllers and gsp pages that are working, gradually changing behavior & verifying each step.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top