Groovy Collections, Closures, and OOP
Harry
· 13 Sep 2026
· 2 views
Why This Matters
Collections and closures are core building blocks in Grails. GORM queries, validation rules, data binding, and configuration all lean on them. Getting comfortable here makes your controllers and services both shorter and more readable.
Lists
def users = ["admin", "manager", "employee"]
users << "guest"
println users[0] // adminLists are ordered and mutable by default.
Sets
Sets hold unique values, which makes them perfect for roles and permissions:
def roles = ["ADMIN", "USER", "ADMIN"] as Set
println roles // [ADMIN, USER]Maps
def config = [host: "localhost", port: 8080]
println config.hostMaps drive Grails configuration, JSON responses, and constraint definitions.
Iteration
users.each { user -> println user }
users.each { println it } // implicit "it"Filtering and Transformation
def adults = users.findAll { it.age >= 18 }
def usernames = users.collect { it.username }Sorting and Grouping
println numbers.sort()
def byRole = users.groupBy { it.role }Closures
A closure is a reusable block of code that can capture variables from its surroundings:
def greet = { name -> println "Hello $name" }
greet("Developer")Closures are passed to GORM queries, validation rules, and event handling throughout Grails.
Classes and Objects
class User {
String username
String email
}
def user = new User(username: "admin", email: "admin@grails.com")Inheritance
class Person { String name }
class Employee extends Person { String employeeId }Interfaces and Traits
Traits are powerful in Grails because owners allow horizontal reuse of behavior:
trait Timestamped {
Date dateCreated
Date lastUpdated
}
class Product implements Timestamped {
String name
}OOP Best Practices in Grails
- Keep domain classes focused on data and rules.
- Move business logic to services.
- Use traits for shared behavior like auditing.
- Avoid deep inheritance hierarchies; prefer composition.
Common Mistakes
- Putting too much logic in domain classes.
- Overusing inheritance.
- Ignoring how Grails binds data from request params.
- Not leveraging traits where they fit.
Key Points
- Lists, sets, and maps have native literals.
- findAll, collect, sort, and groupBy cover most data work.
- Closures appear everywhere in Grails APIs.
- Traits are the preferred way to share behavior.
- Favor composition over deep inheritance.