By Developers, For Developers

Historical errata for Grails

element

PDF PgPaper PgTypeDescriptionFixed onComments
8TYPO

On page 8 4th paragraph line 2, the line “So many Java web frameworks have ben developed” has a typo. It should be “have been” instead of “have ben”.

2009-06-05
50SUGGEST

In the following code snippet:

g1.addToVolunteers(new TekUser(fullName: ‘Bill Smith’,
userName: ‘Mr_Bill’,
password: ‘12345’,
email: ‘mrbill@email.com’,
website: ‘www.mrbillswebsite.com’,
bio: ’Software developer and claymation artis…TRUNC

Why the “TRUNC”? There is nothing else after “artis”. The book should add “))” for clarity.

2009-06-05
50ERROR

The following code should not be included at this point:

def g1 = TekEvent.findByName(‘Gateway Code Camp’)
g1.addToVolunteers(new TekUser(fullName: ‘Sarah Martin’,
userName: ‘sarah’,
password: ‘54321’,
email: ‘sarah@martinworld.com’,
website: ‘www.martinworld.com’,
bio: ‘Web designer and Grails officianado.’))

g1.addToVolunteers(new TekUser(fullName: ‘Bill Smith’,
userName: ‘Mr_Bill’,
password: ‘12345’,
email: ‘mrbill@email.com’,
website: ‘www.mrbillswebsite.com’,
bio: ’Software developer and claymation artis…TRUNC

g1.save()

The mapping has not been defined in TekEvent class and it will cause error when running the application.

On page 55, we are asked to add the above code again. It is kind of confusing.

2009-06-05
60ERROR

static hasMany=[sponsorships:Sponsorship] mapping should not be defined at this stage since Sponsorship domain class has not been defined, yet. Remove this mapping until Sponsorship domain class has been defined.

2009-06-05
67TYPO

Second line, cascading deletes.

2009-06-05
70TYPO

Second line -

Open TekDays/grails-app/controllers/TekEvent.groovy

Should be

Open TekDays/grails-app/controllers/TekEventController.groovy

2009-06-05
81TYPO

Line 7: -

if either of these items in null then

Should be:

if either of these items “is” null then

2009-06-05
89ERROR

Given code - if (TekEvent.get(1))

Shouldn’t it be - if (!TekEvent.get(1)) ?

2009-06-05
104ERROR

When running grails test-app, TekEventTests failed. The reason is we forgot to change ‘John Doe’ to a real tekUser object for organizer.

The following needs to be added to the setup() method:

tekUser = new TekUser(fullName:‘Tammy Tester’,
\t\t\t\t\tuserName:‘tester’,
\t\t\t\t\temail:‘tester@test.com’,
\t\t\t\t\twebsite:‘test.com’,
\t\t\t\t\tbio:‘A test person’)

Please remember to declare tekUser instance variable.

2009-06-05Good call. Thanks! I added a section to chapter 4 on keeping unit tests up to date to address this.
104ERROR

Before running the integration test, please remind the readers to modify their DataSource.groovy file for test environment:

test {
\t\tdataSource {
\t\t\tdbCreate = “update”
\t\t\turl = “jdbc:mysql://localhost:3306/tekdays”
\t\t}
\t}

2009-06-05
104ERROR

Integration test failed with the following error:

groovy.lang.MissingPropertyException: No such property: save for class: TekUser
\tat TaskServiceTests.setUp(TaskServiceTests.groovy:14)
\tat _GrailsTest_groovy$_run_closure4.doCall(_GrailsTest_groovy:203)
\tat _GrailsTest_groovy$_run_closure4.call(_GrailsTest_groovy)
\tat _GrailsTest_groovy$_run_closure2.doCall(_GrailsTest_groovy:147)
\tat _GrailsTest_groovy$_run_closure1_closure19.doCall(_GrailsTest_groovy:113)
\tat _GrailsTest_groovy$_run_closure1.doCall(_GrailsTest_groovy:96)
\tat TestApp$_run_closure1.doCall(TestApp.groovy:66)
\tat gant.Gant$_dispatch_closure4.doCall(Gant.groovy:324)
\tat gant.Gant$_dispatch_closure6.doCall(Gant.groovy:334)
\tat gant.Gant$_dispatch_closure6.doCall(Gant.groovy)
\tat gant.Gant.withBuildListeners(Gant.groovy:344)
\tat gant.Gant.this$2$withBuildListeners(Gant.groovy)
\tat gant.Gant$this$2$withBuildListeners.callCurrent(Unknown Source)
\tat gant.Gant.dispatch(Gant.groovy:334)
\tat gant.Gant.this$2$dispatch(Gant.groovy)
\tat gant.Gant.invokeMethod(Gant.groovy)
\tat gant.Gant.processTargets(Gant.groovy:495)
\tat gant.Gant.processTargets(Gant.groovy:480)

2009-07-28I am not getting that error in my tests. Is it possible that the parentheses were left off of the save() method? Without the parentheses save would be treated as a property and that would cause the MissingPropertyException.
70TYPO

In “We now have controllers for Sponsorship, Task, and message”, “Message” should be capitalized.

2009-06-05
97SUGGEST

In longer code passages like the ones on page 97, it would be nice to have a formatting change (bold face, underlined, etc.) to draw attention to the parts that are different from the code generated by Grails.

2009-06-16I think the best we can do right now is those triangle markers that point out changed lines. I will go back and use those in more places.
101TYPO

There should be a “/” between “controllers” and “TekEvent…”:
Open TekDays/grails-app/controllersTekEventController.groovy
and add this single property declaration at the top of the class:

2009-06-16
100TYPO

When we’re adding the default tasks in TasksService, we’re only supplying a value for the title field. Back on page 66, however, the notes field’s constraint doesn’t allow it to be null (“notes(blank:true, maxSize:5000)”). Any attempts to add a new TekEvent at that point will result in no default tasks being added.

2009-06-16Good catch. I had changed that in later versions of the code but not in the version where it is first introduced. \n \nThanks! \nDave
114ERROR

In the ajaxList.gsp example, second line:

${event?.name - Forum Messages}

it doesn´t work , i think it should be:

${event?.name} - Forum Messages

2009-06-16
129ERROR

The actionName cannot be resolved. It is null in the Security Filter class. Are you sure actionName is accessible in Grails filter?

2009-06-16
117TYPO

There is no content for footnote #2 on page 117.

2009-06-16
117ERROR

I was having a tough time getting the Message details template to load properly with a non-null Message in scope, until I changed the call to “render” from “render(template:”details" , bean:messageInstance)" to “render(template:”details“, model: [messageInstance:messageInstance])”. The source file from the book seemed to indicate it should be the latter.

2009-06-16
131TYPO

This is regarding to the technical error I filed earlier (#39429). I think I know why I was confused. On page 131, the book has the following paragraph:

“This feature is a bit tricky to show in screenshots, but go ahead and
try it out. Run the application and go to the default home page. Choose
any of the controller links and you should come to the list view. Click
on the New button, and you should see the login screen as shown in
Figure 8.1, on page 127. Log in using the credentials of one of the users
we created earlier, and you should be redirected to the create view that
you were aiming at. Good deal!”

When I go to localhost:8080/TekDays, I was brought to the login page directly and not the controller list page. This is because TekDays is our context root and it is not hitting any controller for the first time. That is why I thought the actionName or controllerName (both were null the first time) was not accessible through the filter we defined.

I think we should rephrase this or fix the code but not sure which error category I should file this in. I picked technical error since it is not really a typo or suggestion.

2009-07-28I can't get this to happen. Since the filter intercepts calls to controllers it should not intercept the initial call to the homepage since it isn't rendered by a controller action. If this is still happening for you, perhaps you could bundle up your project and send it to me at daveklein _at_ usa.net \n \nThanks, \nDave
64SUGGEST

you introduce a version of TekEvent with Task and Message before you define at page 65.

The figure 4.9 at page 85 works only if you create a SponsorshipController before.

Thanks in advance for your patience

2009-07-01Good catch Paolo. Thanks for taking the time to post it. I've fixed the code showing up too early and addressed the SponsorshipController not being created.
37SUGGEST

Replace

class TekEventTests extends GroovyTestCase {
void testSomething() {
}
}

which is 1.0.x with 1.1.x

class TekEventTests extends GrailsUnitTestCase {
protected void setUp() {
super.setUp()
}

protected void tearDown() {
super.tearDown()
}

void testSomething() {

}
}

2009-07-09Good catch! Thanks Bill.
61OK

How can finally the Sponsor logo (saved in the DB) be shown in the demo?

2009-07-28That's a great question, Peter. I'll see if I can fit that in somewhere. If not, I'll post an example on my blog. -- Thanks!
11SUGGEST

Second paragraph reads: “As soon as you needed to more
than the tool was designed for, you were stuck.” This needs to be corrected. Typist probably omitted the word “do.”

2009-07-09
16SUGGEST

Dave:

I want to commend you on the job you are doing, explaining Grails/Groovy to a newbee like me. You have helped me to understand where other authors assume my understanding of Java and related concepts.

I do have a general suggestion in regards to format. Place demonstrations of code/syntax on a line of their own instead of embedding them inside of the paragraphs.

A couple of examples: section 1.7 where you explain referencing GString objects, and section 3.1, last paragraph. I had to read it three times to get the jest of your point on how the “1 + 1 = ${1+1…” string would be rendered. There are a few more between there and chapter 4 (where I am now).

Good luck on the final release! Keep up the good work.

John

2009-07-27Thanks for the kind words John. In some places I use inline code because I'm not ready to break the paragraph, but I will look for places where I can break it out to make it more readable. Feel free to post the more egregious examples here. \n \nDave
51TYPO

Figure 4.2 on page 51 is placed in the middle of the code snippet.

I think this type of thing will be cleaned up during the final typesetting, but thanks for taking the time to report it. \n \nDave
57TYPO

Figure 4.4 is not the view I get when viewing the event. I get a bullet list of volunteers, instead of a pick-list, as shown. Also, the sponsorship and other information shown does not yet exist.

2009-07-09
59TYPO

Figure 4.5 is in the middle of code snippet.

This should get fixed in typesetting.
59TYPO

Figure 4.5 is not the correct image for this topic. It shows a “Create TekEvent” view instead of “Show” as the reference in the paragraph states.

2009-07-09
60TYPO

Figure 4.6 precedes the section header (4.5 Adding a Sponsor Class) that it is related to. This may not be desirable.

This too should be fixed in typesetting.
175TYPO

HTML snippet for the password fields is missing the closing

2009-07-13
179TYPO

“We first define a variable called blurbInstance and try to retrieve the Blurb
for this event,…”

All the code samples show creating a variable called blurb, not blurbInstance.

2009-07-13
181TYPO

"

"

css has typo in it: should be border-style:solid

2009-07-13
171TYPO

“You’re help will make a huge difference.”

You’re needs to be Your

2009-07-13
132OK

General suggestion…did you consider using MarkupBuilder rather than building HTML up using Strings in your code examples? I tend to think it’s cleaner, but it’s definitely personal preference.

2009-07-28Hi Matt, \n \nI didn't think about that since there wasn't very much HTML being produced in code. Hopefully it's still readable. \n \nThanks for the tip though, \nDave
89OK

The url for the development branch reads:
“jdbc:mysql://localhost:3306/tekDays”

But should read:
“jdbc:mysql://localhost:3306/devDb”

2009-07-28I wanted to use a different name than the one used for the in-memory database so I just went with "tekdays". The name is arbitrary as long as you create an empty database with the name given it should work fine. \n \nThanks, \nDave
56ERROR

In the code listing for the updated test, it is supposed to be updated to use a TekUser, however it is still a String.

2009-07-26
104SUGGEST

The section, 6.4 ends without having us actually add the new event. Figure 6.6 shows a newly added event, but you never actually have us add it to test our changes. I did, and it definitely works. By the way: in description, saviest should be spelled savviest. Check me on this.

Cheers

2009-07-27
78ERROR

In the code for list.gsp at the bottom of the page, the book has:
Home
while version 1.1.1 of grails produced:
Home

2009-07-26
125ERROR

Nowhere in Chapter 7 does the book instruct to add the hidden input tag for the parent.id to create.gsp. I discovered that my messages were not saving their parent when replying. I checked the downloaded code and the hidden input is there, but its not in the book.

2009-07-28Good catch Marc! I'll get that fixed in the next update. \n \nThanks, \nDave
137TYPO

Starting section 9.1, the book states that index.gsp is not in the grails-app/views directory, however with grails 1.1.1 it is.

2009-07-26Yes, I found a few issues caused by starting this book before 1.1 came out. I think I have them all fixed in the next update. \n \nThanks, \nDave
53TYPO

Section 4.2 states that in Figure 3.1 on page 34, the property “oraganizer” is stll a String. However, the image shows it declared as a “TekUser.” Regards.

2009-07-26What I was trying to say is that the image showed it as a User (actually it shows a TekUser.. fixed that) but the code still had it as a String. I tried to make that clearer. \nThanks, \nDave
39ERROR

The class TekUser that used in the test isn’t created until later in the exercise.

2009-08-28
180TYPO

“Now when the form/dialog is submitted, it will call the TekEventvolunteer action.”

Need a space between “TekEvent” and “volunteer”.

2009-08-28
19OK

assert names.min() 'Amanda' assert names.max() ‘Nate’

Should be:
assert names.min() 'Nate' assert names.max() ‘Matthew’

This way true is returned, and the test is more readable.

2009-09-10Dave Klein says: If we used: \n \nassert names.min() == 'Nate' \nassert names.max() == 'Matthew' \n \nboth assertions would fail. I don't think that would be very clear or helpful. But maybe I'm missing something. Perhaps we could discuss it more on the forum: http://forums.pragprog.com/forums/116 \n \nThanks, \nDave
21TYPO

def employees = [‘Susannah’,‘Noah’,‘Samuel’,‘Gideon’] as Set
In this example we create a Set with three names in it.

In the example we create a Set with 4 names in it, not 3. But the position of the names are from 0 to 3.

2009-09-09Good catch. I originally had 3 in their but then realized I had left one of my kids out of the examples so I added one but didn't adjust the rest of the example. \n \nThanks, \nDave
39ERROR

I must say that i have not tried the exampel, but the logic tells me that it will not work.

void testToString() {
def tekEvent = new TekEvent(
name: ‘Groovy One’,
city: ‘San Francisco, CA’,
organizer: [fullName:‘John Doe’] as TekUser,
venue: ‘Moscone Center’,

At the current place in the book, organizer is a String and not a TekUser object.

2009-08-30
111SUGGEST

protected void setUp() {
super.setUp()
new TekUser(fullName:‘Tammy Tester’,
userName:‘tester’ ,
email:‘tester@test.com’ ,
website:‘test.com’ ,
bio:‘A test person’).save(flush:true)
}

It would be nice to have a explanation for why the save method is used with parameter flush set to true. This parameter has not be used before now.

2009-09-10
128SUGGEST

I’ve heard that that sense of awe and amazement wears off after a while. But I’m still waiting.

The above line is not formated correct, at least that should not be there twice.

2009-09-10Addressed in related item.
128TYPO

I’ve heard that that sense of awe and amazement wears off after a while. But I’m still waiting.

I now understand what should have been in the above line… :o)

I’ve heard that the sense of awesomeness and amazement wears off after a while. But I’m still waiting.

2009-09-10I understand what you're saying. The double "that" can make you pause for a bit, but overall, I think I prefer the original sentence. \n \nI do appreciate this and your other feedback. \n \n \nThanks, \nDave
78TYPO

Superfluous comma

It appears that on last paragraph of page 78, an extraneous comma is present.

Currently, the sentence begins as such:

“The first line of the list, Closure is working with the params property, which, as we saw earlier, is a Map containing all the parameters of the incoming request.”

I would assume it should be:

“The first line of the list closure is working with the params property, which, as we saw earlier, is a Map containing all the parameters of the incoming request.”

2009-09-29
124TYPO

Under the “Creating the Template” paragraph, there is a reference to the following file: TekDays/grails-app/views/messages/show.gsp

The directory should be ../views/message/, not ../views/messages/

2009-09-29Good catch Eric! \n \nThanks, \nDave
48ERROR

The triple-apostrophe String quotes don’t seem to copy correctly from the pdf ebook. For the TekEvent and TekUser BootStrap snippets (pgs 48-49, 56), I always get two apostrophes, a space, then the third apostrophe. I’m copying the code snippets out of the book using Adobe Reader 9.0 on a Windows XP machine. I don’t remeber having this problem with the last version of the book, though I was using Preview with a Mac.

2009-09-30Copying code from PDFs can be troublesome, however, all the code from the book is available for download. \n \nHope that helps, \nDave
48ERROR

The submit errata links in the ebook are not working. You’re missing the ‘titles’ portion of the URL.

2009-09-30Thanks for pointing this out. It's being looked into. \n \nDave
78TYPO

At the bottom of the page: “Since it is a Groovy Map, any element to which we assign a value will be added if it doesn’t exist.” Remove “if it doesn’t exist”. The line of code that follows in the book shows that params.max will be overwritten even if params.max is already set (in fact, you’d miss the “limit list to a maximum number of entries” functionality if it didn’t do this).

196TYPO

In the code listing

if (params.nickname)
flash.message = “TekEvent not found with id ${params.id}”
else
flash.message = “TekEvent not found with nickname ${params.nickname}”

The if clauses and else should be swapped or the if statement should read
if (!params.nickname)

108TYPO

2nd paragraph under 6.4 Grails Service Classes. 2nd sentence states “doesn’t fit well in any a domain class”. Should be “doesn’t fit well in any domain class”, IMHO. No ‘a’.

111TYPO

In Figure 6.6, the task titles are displayed under Tasks. After creating the Task domain class on page 71, the toString() method is never defined. Thus, after I created a new event and the default tasks were added, they were shown as “Task:1”, “Task:2”, rather than the task titles. The same code (code/things/…) does have Task toString() defined.

60TYPO

first paragraph: should be “fullName” rather than “firstName” in

“We’re giving the Map a firstName element for clarity…”

54SUGGEST

The linked BootStrap.groovy doesn’t match the chapter’s material (it’s actually the final one).

42ERROR

Using Grails 1.1.2: This also applies to all other references to the relationships between TekEvent->TekUser. In the Show GSP pages I see the TekUser: 1 instead of the actual ‘firstName’ value as in the screen grabs. By changing TekEvent show.gsp Organizer fields value to ${tekEventInstance?.organizer?.fullName} now displays ok.

52TYPO

In “We’re giving the Map a firstName element for clarity”, should fullName be used instead of firstName?

175ERROR

In the code listing that ends at the top of this page (for search.gsp), there are one too many

tags. There is a DIV for the nav section, which is closed properly. And a DIV for the body, which is closed twice.

1ERROR

Grails 1.2 was just released, and many of the scripts highlighted in this book have changed slightly. They are now suggesting that all new objects be created within a package. If would be great to see the book updated for this new version of Grails.

1SUGGEST

It might be useful to introduce people to the “grails clean” command early in the book. I had a number of confusing error messages that wasted a lot of my time before I realized that nothing was actually wrong. As bit of digging uncovered “grails clean” and the problems went away.

6961ERROR

needed to alter for grails 1.2.0 (also needed for sp2)

\t\tdef sp1 = new Sponsorship(/*event:g1,
\t\t\t\tsponsor:s1,*/
\t\t\t\tcontributionType:‘Other’,
\t\t\t\tdescription:‘Cool T-Shirts’)

103ERROR

The following code causes an error in the display

  • ${s.sponsor?.encodeAsHTML()}

  • The error message says:

    Exception Message: No such property: sponsor for class: Sponsorship

    Even though I have followed each step successfully to that point (including the domain class setup).

    Has this call changed with a new release?

    56ERROR

    The version of Bootstrap.groovy that can be downloaded does not correspond (contains code related to later chapter) to the text.

    54ERROR

    String toString(){ fullName }

    should have been

    String toString(){ “$fullName” }


    65ERROR

    String toString(){
    name
    }

    should have been

    String toString(){
    “$name”
    }
    *

    63TYPO

    Hi!

    In figure 4.9 on page 63 above you have put a graphical display of the “Task” class. One of its properties is “String description”; however, on the rest of the page you only refer to “notes”.

    Could you change it one way or the other? “description” is IMHO the clearest, but YMMV.

    P.S.: thanks for such a nice book! I would love to see more about AJAX integration in Grails in your chapter 7. Developers need to convince non-technical people with lots of eye candy, and things like the DoJo toolkit can certainly give that extra “punch”. Another point would be to start using packages from the very start of the book; Grails 1.2.1’s default behaviour now expects you to create domain classes in packages.

    Best regards


    Danai Sae-Han

    103SUGGEST

    Hi

    On page 103 of the book (I think it’s page 113 for the PDF; see Jeff Schmidt’s comment as well) there is no mention of adding a toString() method for the Task class.

    Either you could add a toString() method in grails-app/domain/Tasks.groovy, or you could change grails-app/views/tekEvent/show.gsp and use “t.title?.encodeAsHTML()” instead of the default “t?.encodeAsHTML”.

    I would also like to suggest to give an example sorting the task list. You could do this in show.gsp (Grails 1.2.1):

    • ${t.title?.encodeAsHTML()}

    • Given that each Task class must have at least an ID and a title, you could either use “it.title” or “it.id”.

      Best regards

    1SUGGEST

    With newer versions of grails, BootStrap does not work unless you add import tekdays.*

    66TYPO

    In the constraints list:

    • inList: Value must be included in the supplied listv

    should probably be:

    • inList: Value must be included in the supplied list.
    60TYPO

    When defining the Sponsorship Domain Class the following code is required to get the view layer to display the Sponsor’s name:

    String toString() {
    \t\t“$sponsor”
    }

    46TYPO

    When creating the TekUser domain class the toString() code needs to read as follows to work properly in the view layer:

    String toString(){
    “$fullName”
    }

    1TYPO

    yes

    113ERROR

    Mismatch between instructions in paper version of the book and the accompanying code:
    Adds the css class ‘messageField’ to the markup but this has no effect because the accompanying code does not introduce ‘messageField’ into the css until at least after chapter 8.

    116TYPO

    The cut and paste of code into the new ajaxList.gsp at the top of page 116 should read: New Message (Note: ‘event.id’ not ‘eventId’)

    To confirm, go to page 112 top where this code parameter was created to insert into list.gsp and where this is correctly printed.

    72SUGGEST

    Next we’ll create the Message class

    suggestion

    Next we’ll create the Message domani class

    131TYPO

    The margin-left property needs to specify a dimension value.

    Change:
    out << "

    "

    To:
    out << "

    "

    81ERROR

    The following set contains a error in the code:

    else {
    flash.message = “TekEvent not found with id ${params.id}”
    redirect(action:edit,id:params.id)
    }

    It is not possible to redirect to a page with the id as the parameter , when no id is provided.

    A solution may be:

    else {
    flash.message = “TekEvent not found with id ${params.id}”
    redirect(action: “list”)
    }

    188ERROR

    Twitter integration may be different, because it is not possible to post to Twitter.

    Categories: