Page 1
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 1
© Copyright 2010, Software Alchemy
Getting Groovy with Grails
Bryan BashamSoftware Alchemy
[email protected]
http://www.linkedin.com/in/SoftwareAlchemist
GrailsArchitecture
GettingGroovy w/
Grails
DomainModeling
GettingStarted
Page 2
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 2
© Copyright 2010, Software Alchemy
GrailsArchitecture
DomainModeling
GettingGroovy w/
Grails
InstallGrails
CreateApp
CreateEntity GUI Scaffolding
BasicDomainModeling
GettingStarted
Getting Started
Page 3
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 3
© Copyright 2010, Software Alchemy
Install Grails
● Download Grails at http://www.grails.org/ – I am using version 1.3.4 for this tech talk
● Unpack ZIP file on computer● Set GRAILS_HOME environment variable● Add $GRAILS_HOME/bin to PATH
Page 4
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 4
© Copyright 2010, Software Alchemy
Create a Grails App
● Execute command, eg:grails create-app MyApp
Page 5
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 5
© Copyright 2010, Software Alchemy
MyApp Use Cases
List employees
Update employee
Create employee
Retrieve employee
Delete employee
Classic CRUDOperations
Page 6
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 6
© Copyright 2010, Software Alchemy
Create a Domain Entity
● Create the Employee domain class, eg:grails create-domain-class com.example.Employee
package com.example
class Employee {
String firstName String lastName Integer age
static constraints = { }}
«entity»Employee
{from com.example}
firstName : StringlastName : Stringage : Integer
Page 7
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 7
© Copyright 2010, Software Alchemy
Create a GUI Controller
● Create the Employee controller class, eg:grails create-controller com.example.Employee
package com.example
class EmployeeController { def scaffold = Employee}
● Grails scaffolding provides all basic CRUD operations and GUI Views
Page 8
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 8
© Copyright 2010, Software Alchemy
Default GUI Scaffolding
Page 9
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 9
© Copyright 2010, Software Alchemy
Default GUI Scaffolding (2)
Page 10
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 10
© Copyright 2010, Software Alchemy
Default GUI Scaffolding (3)
Page 11
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 11
© Copyright 2010, Software Alchemy
Behind the Looking Glass
● Create the Employee GUI controller class:grails generate-controller com.example.Employee
class EmployeeController { def index = { redirect(action: "list", params: params) } def list = { params.max = Math.min(params.max ? params.int('max') : 10, 100) [employeeList: Employee.list(params), employeeTotal: Employee.count()] } def save = { def employee = new Employee(params) if (employee.save(flush: true)) { flash.message = "Employee ${employee.id} created." redirect(action: "show", id: employee.id) } else { render(view: "create", model: [employeeInstance: employee]) } }
Page 12
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 12
© Copyright 2010, Software Alchemy
Behind the Looking Glass (2)
● Create the Employee GUI views:grails generate-views com.example.Employee
Page 13
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 13
© Copyright 2010, Software Alchemy
Behind the Looking Glass (3)
● The list.gsp View: <table> <tbody> <g:each in="${employeeList}" status="i" var="employee"> <tr class="${(i % 2) == 0 ? 'odd' : 'even'}"> <td><g:link action="show" id="${employee.id}"> ${fieldValue(bean: employee, field: "id")}</g:link> </td> <td>${fieldValue(bean: employee, field: "age")}</td> <td>${fieldValue(bean: employee, field: "firstName")}</td> <td>${fieldValue(bean: employee, field: "lastName")}</td> </tr> </g:each> </tbody></table>
Page 14
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 14
© Copyright 2010, Software Alchemy
Behind the Looking Glass (4)
● The create.gsp View: <g:form action="save" > <table> <tbody>
<tr class="prop"> <td valign="top" class="name"> <label for="age"><g:message code="employee.age.label" default="Age" /></label> </td> <td valign="top" class="value ${hasErrors(bean: employeeInstance, field: 'age', 'errors')}"> <g:textField name="age" value="${fieldValue(bean: employeeInstance, field: 'age')}" /> </td> </tr>
...
</tbody> </table></g:form>
Page 15
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 15
© Copyright 2010, Software Alchemy
A Simple Relationship
class Employee {
String firstName String lastName Integer age Department department
static constraints = { }}
«entity»Department
{from com.example}
name : String
«entity»Employee
{from com.example}
firstName : StringlastName : Stringage : Integer
department
10..*
class Department {
String name
static constraints = { }}
Page 16
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 16
© Copyright 2010, Software Alchemy
Create GUI components
● Create Department GUIs and recreate Employee GUIs
A drop-down list of department objects, but the names are weird.
Page 17
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 17
© Copyright 2010, Software Alchemy
Fix Department Display
● Add a simple toString method:class Department {
String name
String toString() { name }
static constraints = { }}
The toString method is used to create a useful display name. You could also create custom GSP code for the drop-down list widget.
Page 18
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 18
© Copyright 2010, Software Alchemy
GrailsArchitecture
Conv/Config
Buildtools
Web techPlugins
Groovy
GettingGroovy w/
Grails
DomainModeling
InstallGrails
CreateApp
CreateEntity GUI Scaffolding
BasicDomainModeling
GettingStarted
Grails Architecture
Page 19
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 19
© Copyright 2010, Software Alchemy
Grails Technology Stack
The Java Virtual Machine
Groovy
Java Lang / JRE JDK
Grails
JavaEE Spring Hibernate SiteMesh
Plugins...
Your Grails Application
Page 20
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 20
© Copyright 2010, Software Alchemy
Groovy Quick Look
● Groovy is a scripting langage on top of Java● Syntax for lists and maps:
– [1, 2, 3]
– [foo:1, bar:2, baz:3]
● Closures:– [1, 2, 3].collect { it * it } => [1, 4, 9]
● Fancy Strings:– 'foo' is a Java String– “foo is ${map.foo}” is a GString
Page 21
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 21
© Copyright 2010, Software Alchemy
Groovy Quick Look (2)
● Groovy classes are JavaBeansclass Employee { String name Integer age}
● Setter/Getters are auto created unless specified:
class Employee { String name Date dateOfBirth Integer getAge() { /* calc age from DoB */ }}
Page 22
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 22
© Copyright 2010, Software Alchemy
Convention over Configuration
● Configuration is kept to a bare minimum● Convention abounds:
– Entities– Controllers and URL patterns– Services and dependency injection– Tag libraries– Scaffolding– and much more
Page 23
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 23
© Copyright 2010, Software Alchemy
Logging
● Configure logging in grails-app/conf/ Config.groovy file:
log4j = { root { info 'stdout' additivity = true } info 'com.example' // more configuration snipped}
● Log objects automatically available:if (employeeInstance.save(flush: true)) { log.info "Employee ${employeeInstance.id} created." redirect(action: "show", id: employeeInstance.id)}
Page 24
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 24
© Copyright 2010, Software Alchemy
Data Sources
● Configured in the grails-app/conf/ DataSource.groovy file
● Database driver JAR file configured in the grails-app/conf/BuildConfig.groovy file
● Must create the database before using, but schema creation is handled by Grails
– Use create-drop to create the DB on every run– This option destroys any data stored– Typically used during rapid prototyping
Page 25
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 25
© Copyright 2010, Software Alchemy
Example: MySQL
● DataSource.groovy:environments { development { dataSource { dbCreate = "create-drop" // one of 'create', 'create-drop','update' url = "jdbc:mysql://localhost:8889/my-app-db" driverClassName = "com.mysql.jdbc.Driver" username = "root" password = "root" } }
● BuildConfig.groovy: dependencies { runtime 'mysql:mysql-connector-java:5.1.12' }
Page 26
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 26
© Copyright 2010, Software Alchemy
Pre-populate DB
● Pre-populate the database using the grails-app/conf/BootStrap.groovy file:
import com.example.Department;
class BootStrap {
def init = { servletContext -> if ( Department.count() == 0 ) { new Department(name:"Accounting").save() new Department(name:"Marketing").save() new Department(name:"Development").save() new Department(name:"Sales").save() } } def destroy = { }}
The count() method is like the SQL statement:SELECT count(*) FROM department
The save() method is like an SQL INSERT statement.
Page 27
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 27
© Copyright 2010, Software Alchemy
Eclipse Integration
● Install the Groovy plugin:http://dist.springsource.org/release/GRECLIPSE/e3.6/
● Groovy support in Eclipse is spotty but workable
– Hard to find all necessary libraries– No obvious access to source or javadocs– Debugging Grails apps is very difficult
● Maven helps with some of these issues
Page 28
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 28
© Copyright 2010, Software Alchemy
Maven Integration
● Creating a Grails app with Maven 2:mvn archetype:generate -DarchetypeGroupId=org.grails \
-DarchetypeArtifactId=grails-maven-archetype \-DarchetypeVersion=1.3.4 \-DgroupId=com.example -Dversion=0.1 -DartifactId=MyMavenApp
cd MyMavenApp/
mvn initialize
● Supporting Eclipse:mvn -DdownloadSources=true -DdownloadJavadocs=true \
eclipse:eclipse
Page 29
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 29
© Copyright 2010, Software Alchemy
Ant Integration
● You can use Grails scripts in an Ant script● You can use Ant tasks in your own Grails
scripts, Example:ant.property(file:"${basedir}/application.properties")def appName = "${Ant.project.properties['app.name']}"def appVersion = "${Ant.project.properties['app.version']}"def appPath = "${appName}-${appVersion}"
target(main: "Create an archive of the complete project source.") { ant.zip(destfile: "../${appPath}-dist.zip") { zipfileset(dir:"${basedir}", prefix:"${appPath}") { exclude(name:"target/**") exclude(name:"web-app/WEB-INF/classes/**") } }}
setDefaultTarget(main)
Page 30
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 30
© Copyright 2010, Software Alchemy
External Deployment
● Build a WAR file using this command:grails dev war
● Deploy to your JavaEE compilant web container
– WAR includes all Groovy and Grails JARs– WAR includes all infrastructure JARs– WAR includes DB driver JAR– WAR includes all plugins
Page 31
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 31
© Copyright 2010, Software Alchemy
Web Technologies
● Controllers● Views: GSPs● Tag libraries● Filters
Page 32
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 32
© Copyright 2010, Software Alchemy
Controllers
● Controllers are Groovy classes that reside in the grails-app/controllers source directory
● Method names map to URL patterns, eg: http://localhost:8080/MyApp/employee/list
– Maps to EmployeeController and list method● View selection:
– Use render to render a specific View component– Use redirect to tell the browser to redirect– Return a model Map to render this method's
View, eg. list action renders list.gsp
Page 33
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 33
© Copyright 2010, Software Alchemy
Views: GSPs
● Very much like JSPs but uses Groovy as the scripting language; cavet: don't script!
● Use custom tags for view logic– Large built-in library– Easy to create your own
● GSP attributes:– standard JSP attribute scopes plus flash scope– named values in the action method's model Map
● Grails uses SiteMesh for layout control
Page 34
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 34
© Copyright 2010, Software Alchemy
Tag Libraries
● Tag libraries are Groovy classes that reside in the grails-app/taglib source directory
● Each method provides a custom tag, eg:class MyTags { def isAdmin = { attrs, body -> def user = attrs['user'] if ( user != null && checkUserPrivs(user) ) { out << body() } }}
● No configuration required● Automatically available in all GSPs, eg:<g:isAdmin user=”${theUser}”>ADMIN CONTENT</g:isAdmin>
Page 35
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 35
© Copyright 2010, Software Alchemy
Request Filters
● Filters are Groovy classes that reside in the grails-app/conf source directory that end in Filters
class SecurityFilters { def filters = { loginCheck(controller:'*', action:'*') { before = { if (params.controller == null) { redirect(action:'login') return true } else if(!session.user && !actionName.equals('login')) { redirect(action:'login') return false } } } }}
Page 36
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 36
© Copyright 2010, Software Alchemy
Transactions and Services
● Controller actions can be made transactional– Use Spring SessionFactory injection– Or use the withTransaction method
● Service components are a better solution– All classes that reside in the grails-
app/services source directory– Use the def transactional = true for Spring
transaction AOP wrapping– Inject the service into the controller:
def storeService // auto-injects StoreService
Page 37
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 37
© Copyright 2010, Software Alchemy
Plugins
● Grails is a framework built on plugins● Default plugins:
– Hibernate: the Grails ORM (aka GORM)– Tomcat: the Grails default runtime environment
● Hundreds of additional plugins– Security (40)– Services (117)– JavaScript frameworks (74)– many more...
Page 38
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 38
© Copyright 2010, Software Alchemy
Spring Security Plugin
● Install the plugin:grails install-plugin spring-security-core
● Create the User and Role entities:grails s2-quickstart com.example.security User Role
«javaPackage»com.example.security
«entity»Role
authority : String
«entity»User
username : Stringpassword : Stringenabled : boolean role
1
0..*
«entity»UserRoleuser
1
/+authorities
Page 39
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 39
© Copyright 2010, Software Alchemy
BootStrap Roles and Users
import com.example.security.*;class BootStrap { def springSecurityService def init = { servletContext -> // Define user role's def hrRepRole = Role.findByAuthority('ROLE_HR_REP') ?: new Role(authority: 'ROLE_HR_REP').save(failOnError: true) def hrMgrRole = Role.findByAuthority('ROLE_HR_MANAGER') ?: new Role(authority: 'ROLE_HR_MANAGER').save(failOnError: true) def adminRole = Role.findByAuthority('ROLE_ADMIN') ?: new Role(authority: 'ROLE_ADMIN').save(failOnError: true) // a few users: def adminUser = User.findByUsername('admin') ?: new User( username: 'admin', password: springSecurityService.encodePassword('admin'), enabled: true).save(failOnError: true) if (!adminUser.authorities.contains(adminRole)) { UserRole.create adminUser, adminRole } // and so on }}
Page 40
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 40
© Copyright 2010, Software Alchemy
Define Security Constraints
● Use annotations on controller actions, eg:import grails.plugins.springsecurity.Securedclass DepartmentController { @Secured(['ROLE_HR_MANAGER', 'ROLE_HR_REP']) def list = { ... } @Secured(['ROLE_HR_MANAGER']) def create = { ... } @Secured(['ROLE_ADMIN']) def delete = { ... }}
● Or static URL rules in the Config.groovy file● Or store the rules in the database
Page 41
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 41
© Copyright 2010, Software Alchemy
GrailsArchitecture
Conv/Config
Buildtools
Web techPlugins
Groovy
GettingGroovy w/
Grails
InstallGrails
CreateApp
CreateEntity GUI Scaffolding
BasicDomainModeling
GettingStarted
DomainModeling
Relationships
Validation
Enumeratedtypes
Derivedproperties
Embeddedproperties
Inheritance
Domain Modeling
Page 42
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 42
© Copyright 2010, Software Alchemy
HrApp Use Cases
View HR action historyEmployee
Manager
HR Rep
HR Mgr
View department staff
Promote employee
Issue pay raise for employee
Confirm employee promotion
Confirm employee pay raise
Issue cost-of-living raise to department
Hire employee
Terminate employeeConfirm employee hire
Confirm employee termination
Confirm department COL raise
Create/update job roles
Page 43
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 43
© Copyright 2010, Software Alchemy
Domain Model is King!
Page 44
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 44
© Copyright 2010, Software Alchemy
Property Validations
● Property constraints are defined in the Domain model, eg:
class Employee { // skipping property definitions static constraints = { firstName(nullable:false, blank:false, maxSize:32) lastName(nullable:false, blank:false, maxSize:64) dateOfBirth(nullable:true) homeAddress(nullable:false) homePhone(nullable:false) cellPhone(nullable:true) department(nullable:false) jobRole(nullable:true) salary(nullable:true, min:10000) proposedChange(nullable:true) // workflow properties user(nullable:false) status(nullable:false) }
Page 45
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 45
© Copyright 2010, Software Alchemy
Basic Enumerated Types
● Grails supports Java-style enums, eg:class Employee { // other properties Status status enum Status { CREATED, HIRED, DISCIPLINARY_REVIEW, TERMINATED; static def getActiveStatuses = { return [HIRED, DISCIPLINARY_REVIEW] } } // more code}
● ...but the enum name is stored in the DB field which is a bit wasteful, so...
«enumeratedType»Status
+CREATED+HIRED+DISCIPLARY_REVIEW+TERMINATED
«entity»Employee
firstName : StringlastName : String...status : Status
Page 46
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 46
© Copyright 2010, Software Alchemy
Enumerated Types with Ids
● You can define an id field in the enum, eg:class EmployeeAction { // other properties enum ActionType { HIRE('HI'), RAISE('RA'), COL_RAISE('CR'), PROMOTE('PO'), TERMINATE('TE'); final String id ActionType(String id) { this.id = id } } // more code}
● ...so now the DB field is a two-char value.
«enumeratedType»Status
+HIRE('HI')+RAISE('RA')+COL_RAISE('CR')+PROMOTE('PO')+TERMINATE('TE')
id : String
«entity»EmployeeAction
type : ActionTypeemployee : EmployeenewRole : JobRole...
Page 47
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 47
© Copyright 2010, Software Alchemy
Derived Properties
● Also know as transient properties, eg:class Employee { // Properties Date dateOfBirth
// Derived properties Integer getAge() { // corner case if ( dateOfBirth == null ) return null; // calculate and memoize the employee's age _age = _age ?: DateUtils.dateDiffYears(new Date(), dateOfBirth) return _age } private Integer _age
// GORM constraints static transients = [ 'age', ... ]
}
«entity»Employee
dateOfBirth : Date/age : Integer...
Page 48
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 48
© Copyright 2010, Software Alchemy
Derived Relationships
● You can do the same with computed relationships, eg:
class Employee {
// Derived properties List<EmployeeAction> getHistory() { // calculate and memoize the employee's HR history _history = _history ?: EmployeeAction.findAllByEmployee( this, [sort:'proposedDate', order:'asc'] ) return _history } private List<EmployeeAction> _history
// GORM constraints static transients = [ 'age', 'history', ... ]
}
«entity»EmployeeAction/history
*«entity»Employee
Page 49
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 49
© Copyright 2010, Software Alchemy
Embedded Properties
● Grails encourages rich object models even for non-Entity objects, eg:
class Employee { // Properties Address homeAddress PhoneNumber homePhone PhoneNumber cellPhone
// GORM constraints static embedded = [ 'homeAddress', 'homePhone', 'cellPhone' ]
}
class PhoneNumber { // Properties String areaCode String prefix String number // GORM constraints...}
«entity»Employee
homeAddress : AddresshomePhone : PhoneNumbercellPhone : PhoneNumber
«valueObject»PhoneNumber
areaCode : Stringprefix : Stringnumber : String
Page 50
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 50
© Copyright 2010, Software Alchemy
Embedded Properties (2)
● GORM creates a DB schema with each field of the Value Object embedded in the fields of the Entity.
class Employee { // Properties Address homeAddress PhoneNumber homePhone PhoneNumber cellPhone
}
Page 51
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 51
© Copyright 2010, Software Alchemy
Relationships
● Grails supports: one-to-one, one-to-many and many-to-many
● Grails supports uni- and bi-directional relationships
● Grails support ownership, with cascading deletes
● Grails supports unordered sets, sorted sets, and lists (with ordering index)
Page 52
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 52
© Copyright 2010, Software Alchemy
One-to-One Relationships
class Employee { // Properties Department department JobRole jobRole User user
// GORM constraints static constraints = { department(nullable:false) jobRole(nullable:true) user(nullable:false)}
«entity»JobRole
jobRole
0..1
«entity»User
{from com.example.security}user1
«entity»Employee
user : UserjobRole : JobRoledepartment : Department
«entity»Department department
1
Page 53
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 53
© Copyright 2010, Software Alchemy
One-to-Many
class HRRepresentative extends Employee {// Properties
Set<Department> departments // GORM constraints static hasMany = [ 'departments' : Department ]}
«entity»HRRepresentative
departments : Set<Department>
«entity»Department
departments
*
Page 54
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 54
© Copyright 2010, Software Alchemy
Inheritance
● Inheritance is supported with little to no configuration
● By default, the whole hierarchy is stored in one table
● You can configure Grails to use multiple tables● ...but be aware of the DB performance impact
of multiple selects and table joins
Page 55
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 55
© Copyright 2010, Software Alchemy
Inheritance (2)
class Employee { ... }
class HRRepresentative extends Employee { ... }
class Manager extends Employee { ... }
class Engineer extends Employee { ... }
«entity»Employee
«entity»HRRepresentative
«entity»Manager
«entity»Engineer
Page 56
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 56
© Copyright 2010, Software Alchemy
Inheritance (3)
● The resulting DB table:
Page 57
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 57
© Copyright 2010, Software Alchemy
GrailsArchitecture
Conv/Config
Buildtools
Web techPlugins
Groovy
GettingGroovy w/
Grails
InstallGrails
CreateApp
CreateEntity GUI Scaffolding
BasicDomainModeling
GettingStarted
DomainModeling
Relationships
Validation
Enumeratedtypes
Derivedproperties
Embeddedproperties
Inheritance
Q & A
Page 58
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 58
© Copyright 2010, Software Alchemy
Ten Great Topics Not Covered
1) Supports unit and integration testing
2) Supports RESTful URL patterns
3) Supports Java and Spring integration
4) Supports multiple environments
5) Integration to legacy DBs using Hibernate mappings
6) Supports turning Service components into Web Services
7) Easy to create your own plugins for cross-team sharing
8) Supports other continuous integration tools: Hudson, Ivy, etc
9) Supports data auditing and time stamping w/ GORM event model
10) Supports Ajax and Spring Web Flows
Page 59
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 59
© Copyright 2010, Software Alchemy
Resources
● Groovy (http://groovy.codehaus.org/)– Reference docs (click here)– Reference card (click here)
● Grails (http://www.grails.org/)– Reference docs (click here)
● Eclipse plugin(http://dist.springsource.org/release/GRECLIPSE/e3.6/)
● The Definitive Guide to Grails (by Rocher and Brown, Apress)