Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 1
© Copyright 2010, Software Alchemy
Getting Groovy with Grails
Bryan BashamSoftware Alchemy
http://www.linkedin.com/in/SoftwareAlchemist
GrailsArchitecture
GettingGroovy w/
Grails
DomainModeling
GettingStarted
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
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
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
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
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
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
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 8
© Copyright 2010, Software Alchemy
Default GUI Scaffolding
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 9
© Copyright 2010, Software Alchemy
Default GUI Scaffolding (2)
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 10
© Copyright 2010, Software Alchemy
Default GUI Scaffolding (3)
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]) } }
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
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>
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>
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 = { }}
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.
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.
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
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
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
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 */ }}
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
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)}
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
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' }
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.
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
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
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)
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
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
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
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
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>
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 } } } }}
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
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...
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
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 }}
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
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
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
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 43
© Copyright 2010, Software Alchemy
Domain Model is King!
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) }
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
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...
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...
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
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
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
}
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)
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
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
*
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
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
Rochester JUG: 9-Nov-2010
Bryan Basham – Getting Groovy with Grails Slide 56
© Copyright 2010, Software Alchemy
Inheritance (3)
● The resulting DB table:
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
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
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)
Top Related