getting groovy with grails

Post on 17-May-2015

606 Views

Category:

Documents

6 Downloads

Preview:

Click to see full reader

DESCRIPTION

Grails is an advanced web application development framework focused on rapid prototyping. It uses the Groovy language and runs on a standard JVM. This presentation will provide a hands-on introduction to using Grails and then provides examples of Grails applications. Grails is based upon a plugin architecture and several significant plugins will be described, such as the Spring Security plugin for web authentication and authorization.

TRANSCRIPT

Rochester JUG: 9-Nov-2010

Bryan Basham – Getting Groovy with Grails Slide 1

© Copyright 2010, Software Alchemy

Getting Groovy with Grails

Bryan BashamSoftware Alchemy

basham47@gmail.com

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