Chapter 1. Grails in a hurry...
Listing 1.1. Our first quote controller
Listing 1.2. Adding some output
Listing 1.3. Handling redirects
Listing 1.4. A random quote action
Listing 1.5. Implementing our first view
Listing 1.6. Updating the view
Listing 1.8. Our first domain class with teeth
Listing 1.9. Data source definition—in memory
Listing 1.10. Data source definition—persistent
Listing 1.11. Random refactored
Listing 1.12. A database-driven random
Listing 1.13. Enabling scaffolding
Listing 1.14. Adding basic validation
Listing 1.15. Beefing up our service
Listing 1.16. Invoking our service
Listing 1.17. Our first test case
Listing 1.18. Adding real tests
Listing 1.20. Adding a JavaScript library for Ajax
Listing 1.21. Invoking Ajax functionality
Listing 1.22. The server side of Ajax
Listing 1.23. Crunching numbers: the grails stats command in action
Chapter 2. The Groovy essentials
Listing 2.1. Initializing lists and maps in Groovy
Listing 2.2. Accessing list and map elements
Listing 2.4. Valid and invalid line breaks
Listing 2.5. Regular expression capture groups
Chapter 3. Modeling the domain
Listing 3.1. Our first basic User object
Listing 3.2. Saving and retrieving a domain object from the database
Listing 3.3. Updating users by changing field values and calling save()
Listing 3.4. Deleting objects from the database is a one-liner
Listing 3.5. Grails makes adding constraints straightforward
Listing 3.6. Interrogating the results of a failed validation
Listing 3.7. Recovering from a failed validation
Listing 3.8. Refactored Profile object with a 1:1 relationship with the User object
Listing 3.9. Adding a 1:1 relationship from User to Profile
Listing 3.10. The Post object models all the posts for a given User
Listing 3.11. The User.addToPosts() method makes 1:m relationships easy
Listing 3.12. Accessing a User's posts by walking the object graph
Listing 3.13. Sorting Posts by creation date
Listing 3.14. Modeling a Post that can have many Tags
Listing 3.15. The Tag object models relationships to both Post and User
Listing 3.16. User now hasMany Posts and Tags
Listing 3.17. A complex many-to-many scenario for posts and tags
Chapter 4. Putting the model to work
Listing 4.1. The Profile class models the personal attributes of a user.
Listing 4.2. Changing the standard layout decorator for Hubbub
Listing 4.3. A basic search form for Hubbub
Listing 4.4. Adding the search logic to the UserController.groovy file
Listing 4.5. A basic results screen for the search
Listing 4.6. A variety of dynamic finders in action
Listing 4.7. QBE works by populating a sample object and searching for similar objects
Listing 4.8. Criteria queries give you astonishing power.
Listing 4.9. A dynamic search form
Listing 4.10. Using projections to group and count search results
Listing 4.11. Bootstrapping reference data based on the environment
Chapter 5. Controlling application flow
Listing 5.1. Adding the timeline action to our PostController
Listing 5.2. Displaying a user’s timeline
Listing 5.3. Adding a form for new posts
Listing 5.4. The updated PostController handles new Post objects
Listing 5.5. Catching the index() action and redirecting the user
Listing 5.6. PostService.groovy defines PostService and a related exception class
Listing 5.7. An updated PostController that uses our new PostService
Listing 5.8. Data binding with properties can be perilous
Listing 5.9. A form that will update multiple domain objects in a single submit
Listing 5.10. Implementing a register() action for the UserController
Listing 5.11. Implementing field-level errors is hard work at the moment.
Listing 5.12. A UserRegistrationCommand class
Listing 5.13. A register action that uses command objects
Listing 5.14. Handling image uploading via a command object
Listing 5.15. An image-upload form
Listing 5.16. Sending image data to the browser
Listing 5.17. A basic security filter implementation
Listing 5.18. UrlMappings.groovy holds all the URL routing information for your app.
Chapter 6. Developing tasty views, forms, and layouts
Listing 6.2. Our new registration form demonstrates many of the core form tags.
Listing 6.3. Creating a custom dateFromNow tag
Listing 6.4. Implementing a much nicer date format for Hubbub
Listing 6.5. A lameBrowser tag demonstrating logical tags in action
Listing 6.6. A basic custom template for Hubbub
Listing 6.7. The YUI-generated code
Listing 6.8. A sidebar fragment to include
Listing 6.9. Applying a skin via CSS
Listing 6.10. Defining menu options in your controller
Listing 6.11. Adding a new Post via Ajax
Listing 6.12. Keeping the user updated with JavaScript
Listing 6.13. Implementing the addPostAjax() backend
Listing 6.14. A TinyURL action to shrink URLs via JSON
Listing 6.15. Implementing a callback to handle the JSON return values
Chapter 7. Building reliable applications
Listing 7.1. Our first domain class unit test
Listing 7.2. Testing a Grails service
Listing 7.3. Testing a controller action that returns a model
Listing 7.4. A sample unit test for a tag library
Listing 7.5. Your first integration test—including domain objects and a service
Chapter 8. Using plugins: adding Web 2.0 in 60 minutes
Listing 8.1. Adding a stats action to the UserController
Listing 8.2. Generating a 3-D pie chart
Listing 8.3. Our Google-generated bar chart
Listing 8.4. Generating a multiseries line chart
Listing 8.5. Sending a welcome email
Listing 8.6. A template view for our email, with CSS styling
Listing 8.7. An updated welcome action that defers to the view for rendering
Listing 8.8. custom search controller
Listing 8.9. A first custom search form
Listing 8.10. An updated search controller with hit-term highlighting
Listing 8.11. Updated view code for handling hit terms
Listing 8.12. Displaying marked up hit terms
Listing 8.13. An updated Post object with more custom search tuning
Listing 8.14. Implementing a rich-text bio field editor
Listing 8.15. The backend implementation for autocompleting tags
Chapter 9. Wizards and workflow with webflows
Listing 9.1. Our empty flow definition waiting for some workflow steps
Listing 9.2. A skeleton flow definition
Listing 9.3. Triggering flow steps from a view
Listing 9.4. The on() clause maps the Cancel button name to the next logical action.
Listing 9.5. Command objects in flow steps must implement Serializable.
Listing 9.6. Mapping a command object to a flow step
Listing 9.7. An updated displayProducts view with error handling
Listing 9.8. Implementing a credit card validation action step
Listing 9.9. Invoking a stateful service to validate the card
Listing 9.10. Abstracting credit-card validation to a stateful service
Listing 9.11. A ShippingCommand object holds the user’s shipping preferences
Listing 9.12. Storing details in conversation scope means the data can pass to subflows.
Listing 9.13. Using an action step to determine whether we need custom shipping
Listing 9.14. Triggering a subflow from the parent flow
Listing 9.15. Implementing a custom shipping subflow
Listing 9.16. A simple integration test for our flow
Listing 9.17. Submitting values and handling error conditions
Listing 9.18. Tripping a subflow
Listing 9.19. Our custom shipping flow terminates in lots of interesting ways.
Chapter 10. Don’t let strangers in—security
Listing 10.1. Spring Security configuration for Hubbub’s simple access-control model
Listing 10.2. A functional test to verify the access-control behavior
Chapter 11. Remote access
Listing 11.1. Handling a POST request containing XML
Listing 11.2. Unit-testing a REST controller
Listing 11.3. Using withFormat to generate format-specific responses
Listing 11.4. Manually parsing XML requests in a REST controller
Chapter 12. Understanding messaging and scheduling
Listing 12.1. Updating resources.groovy to connect to ActiveMQ
Listing 12.2. Implementing a Jabber service
Listing 12.3. Exercising our Jabber service with an integration test
Listing 12.4. Handling an incoming message in the service
Listing 12.5. A gateway service that reads and writes Hubbub messages to Jabber
Listing 12.6. A basic daily digest job (using timeout style)
Listing 12.7. A basic daily digest job
Listing 12.8. A basic daily digest job with custom cron settings
Listing 12.9. Using the concurrent property to stop re-entrance
Listing 12.10. A stateful job gets a persistent context to work with
Listing 12.11. The group property makes it easy to control jobs programmatically
Listing 12.12. A controller for pausing and resuming jobs programmatically
Chapter 13. Advanced GORM kung fu
Listing 13.1. A StarPost class inheriting from Post
Listing 13.2. An integration test for our StarPost
Listing 13.3. Embedded relationships stored in a single table
Listing 13.4. Using maps for quick and dirty property storage
Listing 13.5. A sample ehcache.xml configuration file
Listing 13.6. Configuring JNDI data sources for use in Glassfish
Listing 13.7. Configuring multiple data sources in /grails-app/conf/Datasources.groovy
Listing 13.8. Reusing existing Hibernate XML mapping files
Listing 13.9. An extract from a legacy Hibernate mapping file
Listing 13.10. Implementing a list.gsp with Ajax
Listing 13.11. Implementing the Ajax backend to show branch details
Listing 13.12. A more complete showDetails that navigates all relationships
Listing 13.13. Testing validation of legacy classes
Listing 13.14. A domain class with a legacy mapping block
Listing 13.15. Mapping a complex relationship using the mapping DSL
Listing 13.16. Mapping relationships that use join tables
Listing 13.17. Handling existing link tables in many-to-many relationships
Listing 13.18. Handling natural keys with some GORM workarounds
Chapter 14. Spring and transactions
Listing 14.1. Example bean definitions in resources.groovy
Listing 14.2. The reply-aware post service
Listing 14.3. Using withTransaction() for fine-grained transactions
Chapter 15. Beyond compile, test, and run
Chapter 16. Plugin development
Listing 16.1. Initial plugin descriptor
Listing 16.2. Injecting a method into controllers
Listing 16.3. Responding to controller modifications
Listing 16.4. Simple example of the Spring DSL
Listing 16.5. Configuring a servlet filter at runtime
Listing 16.6. A script that creates a user-management UI for the security plugin