问题
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
回答1:
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.
回答2:
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.
来源:https://stackoverflow.com/questions/21973247/grails-cannot-get-property-id-on-null-object