Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Chris Judd & Jim Shingler
CodeMash 2009
Percompile
&
Christopher Judd
President/Consultant of
leader
Creator of open source projects FallME and Fiddle
Jim Shingler
Chief Technical Architect
President of Genuine Solutions
Co-Creator Open Source Project of FallME
Co-Author o...
Goal:
Gain enough Groovy and Grails knowledge to
be able to build a modest Grails applications.
Install Groovy and Grails
...
Example Code
http://github.com/jshingler/codemash2009precompile/tree/master
Software Used
• JDK 1.5 >
• Eclipse 3.4
• Groovy plug-in
• Groovy 1.5.7
• Grails 1.0.4
• Plug-ins
• feeds 1.4
• searchable...
Java Platform
What is Java?
What is Java?
What is Java?
Virtual Machine
What is Java?
Virtual Machine
API/Library
What is Java?
Virtual Machine
API/Library
Java Language
What is Java?
Virtual Machine
API/Library
Java LanguageJavaScript
What is Java?
Virtual Machine
API/Library
Java LanguageJavaScript Groovy
What is Java?
Virtual Machine
API/Library
Java LanguageJavaScript Groovy Ruby
What is Java?
Virtual Machine
API/Library
Java LanguageJavaScript Groovy Ruby Python
Language Stack
Java Language
Language Stack
System (static)
Java Language
Language Stack
Groovy
System (static)
Application (Dynamic)
Java Language
Language Stack
Groovy
Domain Specific Languages
System (static)
Application (Dynamic)
Domain
Groovy By Example
import java.util.ArrayList;
import java.util.List;
public class Student {
private String firstName;
private String lastNam...
import java.util.ArrayList;
import java.util.List;
public class Student {
private String firstName;
private String lastNam...
Congratulations
you are a
programmer
Christopher M. Judd
President, Consultant, Author
685 Farrington Drive
Worthington, Ohio 43085
Phone: (614) 378-4119
Email...
Copy/Paste Compatibility
idiomatic
Convert POJO to POGOimport java.util.ArrayList;
import java.util.List;
public class Student {
private String firstName;
pr...
Convert POJO to POGO
package com.juddsolutions.groovy.basics;
import java.util.ArrayList;
import java.util.List;
public cl...
Simplify Code
package com.juddsolutions.groovy.basics;
import java.util.ArrayList;
import java.util.List;
public class Stu...
Simplify Code
package com.juddsolutions.groovy.basics;
public class Student {
String firstName
String lastName
public stat...
Collections and Closures
package com.juddsolutions.groovy.basics;
public class Student {
String firstName
String lastName
...
Collections and Closures
package com.juddsolutions.groovy.basics;
public class Student {
String firstName
String lastName
...
Scripts
package com.juddsolutions.groovy.basics;
public class Student {
String firstName
String lastName
public static voi...
Scripts
package com.juddsolutions.groovy.basics;
public class Student {
String firstName
String lastName
}
def students = ...
VS
package com.juddsolutions.groovy.basics;
public class Student {
String firstName
String lastName
}
def students = [
new...
VS
package com.juddsolutions.groovy.basics;
public class Student {
String firstName
String lastName
}
def students = [
new...
Groovy Basics
What is Groovy?
Groovy is an expressive, dynamic, object oriented language
built for the JavaVirtual Machine (JVM) with lo...
What is Groovy?
Groovy is an expressive, dynamic, object oriented language
built for the JavaVirtual Machine (JVM) with lo...
What is Groovy?
Groovy is an expressive, dynamic, object oriented language
built for the JavaVirtual Machine (JVM) with lo...
What is Groovy?
Groovy is an expressive, dynamic, object oriented language
built for the JavaVirtual Machine (JVM) with lo...
What is Groovy?
Groovy is an expressive, dynamic, object oriented language
built for the JavaVirtual Machine (JVM) with lo...
def groovy = []
groovy << java
groovy << ruby
groovy << python
groovy << smalltalk
groovy << dynamic
groovy << scripting
g...
Groovy is Java
Groovy is Java
package com.juddsolutions.groovy.basics;
public class Student {
String firstName
String lastName
}
def stud...
Groovy is Java
package com.juddsolutions.groovy.basics;
public class Student {
String firstName
String lastName
}
def stud...
Groovy is Java
package com.juddsolutions.groovy.basics;
public class Student {
String firstName
String lastName
}
def stud...
Groovy is Java
package com.juddsolutions.groovy.basics;
public class Student {
String firstName
String lastName
}
def stud...
Dynamic
Static
StrongWeak
C++
JavaScript
Scala
Dynamic
Static
StrongWeak
C++
JavaScript
Scala
Groovy is:
• Strongly typed
• Dynamically typed
• Optionally typed
• Duck t...
Also known as the Groovy JDK
extends the classes built into the JDK class
library
GDK
Even final classes like String
def p ...
Also known as the Groovy JDK
extends the classes built into the JDK class
library
GDK
Even final classes like String
def p ...
Installing Groovy
1. Download from http://groovy.codehaus.org/Download
• 1.5.7 - Stable Release
• 1.6 beta 2 - Development...
Installing Groovy
1. Download from http://groovy.codehaus.org/Download
• 1.5.7 - Stable Release
• 1.6 beta 2 - Development...
Running Groovy
scripts
shell
console groovyConsole
groovysh
groovy
just include groovy-all-<version>.jar in classpath
Deploying
Note: Quality of Groovy support is represented by size
Ant.property(environment:"env")
grailsHome = Ant.antProject.properties."env.GRAILS_HOME"
includeTargets << new File ( "${g...
Groovy Site - http://groovy.codehaus.org/
Documentation - http://groovy.codehaus.org/Documentation
GDK - http://groovy.cod...
Web Application Framework
Persistable Domains Objects
Controllers
Views (Groovy Server Pages)
Development Environment
Spri...
Griffon
Swing Application Framework
Griffon
Swing Application Framework
How do you introduce
Groovy to the
Enterprise?
Unit Testing
Automation
Builds
Prototyping
Lab 1
1.Create a HelloWorld Groovy script passing your name
as a parameter.
2.Execute the HelloWorld script.
3.javap the H...
Lab 1
1.Create a HelloWorld Groovy script passing your name
as a parameter.
2.Execute the HelloWorld script.
3.javap the H...
Language Basics
Strings
Quote
def quote = "Double Quote"
println "${quote} is a ${quote.class.name}"
Single
def single = 'Single Quote'
pr...
Strings
Quote
def quote = "Double Quote"
println "${quote} is a ${quote.class.name}"
Single
def single = 'Single Quote'
pr...
GString
def datetime = "Datetime: ${new Date()}"
println "${datetime}"
org.codehaus.groovy.runtime.GStringImpl
String inte...
Asserts
assert a != null
assert a != null, 'a must not be null'
An assertion is used to validate an expected condition is ...
Groovy Truth
true
• Non-empty maps
• Non-empty Strings
• Non-zero numbers
• Non-null object references
• Matching regex pa...
Groovy Methods
Implicitly returns last expression
Access modifier is public by default
def passwordtize(text) {
def passwor...
Closures
A block of reusable code.
A closure is an object.
def sayHello = { println "hello!" }
sayHello() //prints "hello!...
Lists
def authors = []
authors.add 'Chris'
authors += 'Jim'
authors << 'Joseph'
println "Authors:"
authors.each{ println i...
Ranges
A list of sequential values.
def numbers = 1..10
assert numbers.size() == 10
numbers.each{ print it }
assert number...
Ranges
A list of sequential values.
def numbers = 1..10
assert numbers.size() == 10
numbers.each{ print it }
assert number...
Maps
An unordered collection of key/value pair where the key is unique.
def map = ['a':'A', 'b':'B', 'c':'C' ]
println map...
Maps
An unordered collection of key/value pair where the key is unique.
def map = ['a':'A', 'b':'B', 'c':'C' ]
println map...
Maps
//Print each key/value pair on aseparate line
map.each { println "Key: ${it.key}, Value: ${it.value}" }
// Print each...
Regular Expressions
Operators
• match (==~)
• find (=~)
• pattern (~string)
// Matching Operators
assert "abc" ==~ 'abc'
as...
Regular Expressions
Operators
• match (==~)
• find (=~)
• pattern (~string)
// Matching Operators
assert "abc" ==~ 'abc'
as...
Operator Overloading
Operator Method
a + b a.plus(b)
a - b a.minus(b)
a * b a.multiply(b)
a ** b a.power(b)
a / b a.div(b)...
a << b a.leftShift(b)
a >> b a.rightShift(b)
switch(a) { case(b) : } b.isCase(a)
~a a.bitwiseNegate()
-a a.negative()
+a a...
a << b a.leftShift(b)
a >> b a.rightShift(b)
switch(a) { case(b) : } b.isCase(a)
~a a.bitwiseNegate()
-a a.negative()
+a a...
Operators
// Spread Operator
def strings = ['chris', 'jim', 'joseph']
println strings*.getAt(0)
// Elvis Operator
def valu...
Operators
// Spread Operator
def strings = ['chris', 'jim', 'joseph']
println strings*.getAt(0)
// Elvis Operator
def valu...
Exception in thread "main" groovy.lang.MissingPropertyException: No such property: b for class: Asserts
at org.codehaus.gr...
Lab 2
1.Create a list from 1-10.Then find all the odd numbers
and print them out.
2.Print out the list of numbers separated...
Groovy Libraries
Basic unit testing
Groovy Unit Tests
Extend GroovyTestCase which extends JUnit TestCase
class RangeTest extends GroovyTestCase {
def lowerCas...
Groovy Unit Tests
Extend GroovyTestCase which extends JUnit TestCase
class RangeTest extends GroovyTestCase {
def lowerCas...
Running Unit Tests
Runs in standard JUnit tools like Eclipse and Ant
Running Unit Tests
Groovy command-line is unit test aware
Database
import groovy.sql.Sql
// Create connection
def sql = Sql.newInstance(
/jdbc:derby:C:Program FilesSunJavaDBdemodatabasestou...
import groovy.sql.Sql
// Create connection
def sql = Sql.newInstance(/jdbc:derby:C:tempblogs;create=true/, "APP",
"APP", "...
I/O
// write file
new File(/C:tempstates.txt/).text = "Ohio"
// append file
def file = new File(/C:tempstates.txt/)
file.appen...
Read File
// read file
new File(/C:tempstates.txt/).eachLine {line ->
println line
}
// read file into String
def contents...
Read URL
def feed = new URL(
"http://juddsolutions.blogspot.com/feeds/posts/default").text
Builders
Groovy Builders
A combination of Groovy language features such as meta-
programming, closures and simplified map syntax for...
def writer = new StringWriter()
def builder = new groovy.xml.MarkupBuilder(writer)
builder.setDoubleQuotes(true)
builder.a...
def writer = new StringWriter()
def builder = new groovy.xml.MarkupBuilder(writer)
builder.setDoubleQuotes(true)
builder.a...
XML Parsing
XML Slurping
def xml = """
<authors>
<author id="1">
<firstName>Chris</firstName>
<lastName>Judd</lastName>
</author>
<aut...
XML Slurping
def xml = """
<authors>
<author id="1">
<firstName>Chris</firstName>
<lastName>Judd</lastName>
</author>
<aut...
Lab 3
1.Write a script that downloads and RSS feed and writes
the id and title to JavaDB.
2.Write a script to read the Jav...
Modern Java Web
Development
Java Web Projects
What do you need to start a Java?
Java Web Projects
• JDK
What do you need to start a Java?
Java Web Projects
• JDK
• Web Container/App Server
What do you need to start a Java?
Java Web Projects
• JDK
• Web Container/App Server
What do you need to start a Java?
Java Web Projects
• JDK
• Web Container/App Server
• Build System
What do you need to start a Java?
Java Web Projects
• JDK
• Web Container/App Server
• Build System
What do you need to start a Java?
Java Web Projects
• JDK
• Web Container/App Server
• Build System
• Application Stack
What do you need to start a Java?
Java Web Projects
• JDK
• Web Container/App Server
• Build System
• Application Stack
What do you need to start a Java?
Java Web Projects
• JDK
• Web Container/App Server
• Build System
• Application Stack
• Persistence Framework
What do you ...
Java Web Projects
• JDK
• Web Container/App Server
• Build System
• Application Stack
• Persistence Framework
What do you ...
Java Web Projects
• JDK
• Web Container/App Server
• Build System
• Application Stack
• Persistence Framework
• Web Framew...
Java Web Projects
• JDK
• Web Container/App Server
• Build System
• Application Stack
• Persistence Framework
• Web Framew...
Java Web Projects
• JDK
• Web Container/App Server
• Build System
• Application Stack
• Persistence Framework
• Web Framew...
Java Web Projects
• JDK
• Web Container/App Server
• Build System
• Application Stack
• Persistence Framework
• Web Framew...
Java Web Projects
• JDK
• Web Container/App Server
• Build System
• Application Stack
• Persistence Framework
• Web Framew...
Java Web Projects
• JDK
• Web Container/App Server
• Build System
• Application Stack
• Persistence Framework
• Web Framew...
Java Web Projects
• JDK
• Web Container/App Server
• Build System
• Application Stack
• Persistence Framework
• Web Framew...
Java Web Projects
• JDK
• Web Container/App Server
• Build System
• Application Stack
• Persistence Framework
• Web Framew...
Java Web Projects
• JDK
• Web Container/App Server
• Build System
• Application Stack
• Persistence Framework
• Web Framew...
Java Web Projects
• JDK
• Web Container/App Server
• Build System
• Application Stack
• Persistence Framework
• Web Framew...
Java Web Projects
• JDK
• Web Container/App Server
• Build System
• Application Stack
• Persistence Framework
• Web Framew...
Java Web Projects
• JDK
• Web Container/App Server
• Build System
• Application Stack
• Persistence Framework
• Web Framew...
Java Web Projects
• JDK
• Web Container/App Server
• Build System
• Application Stack
• Persistence Framework
• Web Framew...
Java Development
Cycle
Code
Java Development
Cycle
Takes too much time and is too complicated
Compile
Package
Deploy
Debug
Test
Conclusion
Java Web and J2EE development is too
complicated and not very agile.
A Solution
A Solution
&
What is Grails
Grails is
• Web Application Framework
• Development Environment
• Open Source under Apache 2.0 License
• Current version 1...
Grails Framework
• JDK
• Web Container/App Server
• Build System
• Application Stack
• Persistence Framework
• Web Framewo...
Grails Architecture
Java Virtual Machine
Java Language Groovy Language
Grails
Application
Libraries
Gant
Spring GORMSiteMe...
MVC Application Design
Controller
GSP
Domain
DB
Service Applications
Controller
GSP
Domain
•Service DB
Domain
•Service
Default Development
Environment
JVM
Jetty (Web Container)
Controller
GSP
Domain
HSQL
DB
Production Environment
JVM
Web Container/App Server
Controller
GSP
Domain
DB
WAR
Conclusion
Java’s capability, flexibility, backwards compatibility and
community have lead to it’s unprecedented success.
H...
Starting with the end in mind
Starting with the end in mind
• Stage 1 - Conventions, MVC
• Stage 2 -View, Styling, Feeds, Search
• Stage 3 - Security an...
Prerequisites
• Install Grails (Grails 1.0.4)
http://grails.org/Download pick the appropriate
distribution for your platfo...
Verify Install
• at a command / shell prompt type grails
Stage 1 - Conventions, MVC
• Grails Application in 60 Seconds or Less,
creating your first application
• Exploring the Grai...
Grails App < 60 secs
• Create a working directory
• From command / shell prompt in that directory type:
grails create-app ...
Grails App < 60 secs
Congratulations
you are a
programmer
Christopher M. Judd
President, Consultant, Author
685 Farrington Drive
Worthington, Ohio 43085
Phone: (614) 378-4119
Email...
So What Happened
• grails create-app blog
created application structure &
copied some files
• grails run-app
started up the...
App Structure & Conventions
A pretty standard application
structure, . . . you can pretty well
guess the purpose of the fil...
Grails commands
Domain Class
• Blog and BlogEntry domain class:
grails create-domain-class Blog
grails create-domain-class BlogEntry
• Wha...
Blog
Properties:
• blogid, title, byline, dateCreated, lastUpdated
Method:
• toString()
class blog {
	 String blogid
	 Str...
BlogEntry
Properties:
• title, body, dateCreated, and lastUpdated
Methods:
• toString()
class BlogEntry {
	 String title
	...
Controller andView
• Create the controller.
grails create-controller Blog
grails create-controller BlogEntry
• What Happen...
Controller andView
• Scaffolding auto generates views and controllers that
support basic CRUD (Create, Read, Update, and
D...
Controller andView
Controller andView
What’s Missing
What’s Missing
• Data validity
What’s Missing
• Data validity
• Relationships
What’s Missing
• Data validity
• Relationships
• Not Pretty (Stage 2)
What’s Missing
• Data validity
• Relationships
• Not Pretty (Stage 2)
• User & Security (Stage 3)
class Blog {
	 String blogid
	 String title
	 String byline
	 Date dateCreated
	 Date lastUpdated
	
	 static constraints =...
Relationships (GORM)
http://www.grails.org/GORM
http://www.grails.org/GORM+-+Defining+relationships
class Blog {
	 String blogid
	 String title
	 String byline
	 Date dateCreated
	 Date lastUpdated
	
	 static hasMany = [ b...
class BlogEntry {
	 String title
	 String body
	 Date dateCreated
	 Date lastUpdated
	 static belongsTo = [ Blog ]
Blog bl...
Database ConfigurationdataSource {
pooled = true
driverClassName = "org.hsqldb.jdbcDriver"
username = "sa"
password = ""
}
...
GenerateViews and Controllers
GenerateViews and Controllers
• grails generate-all Blog
grails generate-all BlogEntry
GenerateViews and Controllers
• grails generate-all Blog
grails generate-all BlogEntry
• What happened?
Grails used templa...
GORM Sidebar
• Save, Update, Delete, Get
• Dynamic Finders
http://grails.org/doc/1.0.x/guide/5.%20Object%20Relational%20Ma...
Lab 4
1.Create the Blog Application.
2.Create the Blog and Blog Entry Domain Classes.
3.Create both controllers with Scaff...
Recap
• Installed Grails and validated
• Built firstapp in < 60 secs ;-)
• Explored application structure and conventions
•...
Stage 2 -View Styles
• Layouts
• TagLibs
• Preview (AJAX)
• URL Mappings
• Feeds
• Search
Layout
Layout
Header
Sidebar
Footer
Body
Setup
Resources
(Images, CSS, and JavaScript)
• Copy contents of <GrailsResources>/webapp to the
blog project
Updating the...
TagLibs
• What is a taglib
• Previous Experiences with taglibs
• Grails Taglibs
• EntriesTagLib
BlogEntryViews
List
• BlogEntryList.gsp
• Redirect BlogEntryController. Show to single list
(Reuse)
• EntriesTagLib -
Nice...
BlogEntryViews
Print
• Add Print output.
Need a way to trigger print layout
No Header, Footer, or sidebar
BlogEntryViews
Edit
• BlogEntryEdit.gsp
BlogEntryViews
AJAX Preview
• Add Ajax and Destination
• Add BlogEntryController.Preview to use
preview template
• Create ...
Lab 5
1.Copy Resources and Layouts
2.Setup the new BlogEntry list display
3.Redirect Show to use new list view
4.Create En...
URL Mappingclass UrlMappings {
static mappings = {
"/$controller/$action?/$id?"{
	 constraints {
	 	 	 // apply constraint...
UrlMapping
• Change the Header and Byline
• blog/list.gsp add to the link
params="[blog: blogInstance.blogid]"
• blog/show...
Permalink
• Add Permalink Generation to BlogEntry
public String toPermalink() {
def sdf = new java.text.SimpleDateFormat("...
Permalink
• Nice Title Codec
• Add BlogEntry Action DisplayEntry
Insert from <GrailsResources>/controllers/
BlogEntryContr...
Plugins
A plugin is a Grails extension point. Conceptually, it is
similar to the plugins found in modern IDEs.
A plugin is...
Feeds
• Install the Feeds Plugin
grails install-plugin feeds
• Create a Feed Controller
grails create-controller feed
http...
Feeds
• Add Link to sidebar
http://grails.org/Feeds+Plugin
<ul>
<li><g:link controller='feed'>
<img src="${createLinkTo(di...
Search
• Install Grail’s Searchable Plugin
grails install-plugin searchable
• Make BlogEntry searchable
static searchable ...
Searchable
• Make Blog Searchable
• http://localhost:8080/blog/seachable
static searchable = {
only = ["blogid", "title", ...
Searchable
• Let’s Add a seach box to the application.
• Copy <GrailsResources>/view/blog/search.gsp
<div style="float: ri...
Lab 6
1.Setup UrlMappings
http://localhost:8080/blog/jim and http://localhost:8080/blog/jim/yyyy/mm/dd
2.Create BlogEntry ...
Recap
• Installed Grails and validated
• Built firstapp in < 60 secs ;-)
• Explored application structure and conventions
•...
Stage 3 - Security
• Discuss Security topics:
User, Roles, Permissions, Realms
• Define User and Security Requirements
• Di...
Security Topics
High Level: User (Subject, Principals) Roles, Permissions, Realms
Security Topics
High Level: User (Subject, Principals) Roles, Permissions, Realms
User / Subject
Security Topics
High Level: User (Subject, Principals) Roles, Permissions, Realms
User / Subject Principals
• Username: ji...
Security Topics
High Level: User (Subject, Principals) Roles, Permissions, Realms
User / Subject Principals
• Username: ji...
Security Topics
High Level: User (Subject, Principals) Roles, Permissions, Realms
User / Subject Principals
• Username: ji...
Security Topics
High Level: User (Subject, Principals) Roles, Permissions, Realms
User / Subject Principals
• Username: ji...
User and Security Requirements
• User should have a name, email, password
• Blog has a User
• Only the User or an Administ...
Security Options
• Spin your own (Loads of work & error prone)
• Use a Security Package
• Grails Plugins
• ACEGI (Spring S...
Security Options
• Spin your own (Loads of work & error prone)
• Use a Security Package
• Grails Plugins
• ACEGI (Spring S...
Security Relationships
JSecurity Plugins
• List available plugins:
grails list-plugins
• Install the JSecurity plugin
grails install-plugin jsecu...
JSecurity Plugins
• List available plugins:
grails list-plugins
• Install the JSecurity plugin
grails install-plugin jsecu...
Enhancing the User Class
• User should have a name, email, password
Enhancing the User Class
• User should have a name, email, password
class JsecUser {
String username
String passwordHash
S...
Enhancing Blog
• Blog has a User
class Blog {
String blogid
String title
String byline
Date dateCreated
Date lastUpdated
J...
Enhancing Blog
• Blog has a User
class Blog {
String blogid
String title
String byline
Date dateCreated
Date lastUpdated
J...
What’s missing
• No Predefined Admin User
Boot Strap Admin & Dilbert
import org.jsecurity.crypto.hash.Sha1Hash
import org.jsecurity.authz.permission.WildcardPermiss...
Boot Strap Admin & Dilbert
import org.jsecurity.crypto.hash.Sha1Hash
import org.jsecurity.authz.permission.WildcardPermiss...
println "Building Admin User"
def adminUser = new JsecUser(username: "admin",
passwordHash: new Sha1Hash("admin").toHex(),...
What’s Missing
• Ability to create a new User
Views & Controller for JSecUser
Views & Controller for JSecUser
• Do you remember how?
Views & Controller for JSecUser
• Do you remember how?
•grails generate-all JSecUser
Views & Controller for JSecUser
• Do you remember how?
•grails generate-all JSecUser
What’s missing
• Password should be hashed
• Auto create blog when new user saved
JsecUserController Enhancement
• Hash the password
• On Save automatically create blog
JsecUserController Enhancement
• Hash the password
• On Save automatically create blog
import org.jsecurity.crypto.hash.Sh...
What’s Missing
• Roles and Permissions aren’t being
enforced.
Enforcement of Roles &
Permissions
• Roles and Permissions are enforced using a
Security Filter, . . .Yes, Filter as in Fi...
Security Filterclass SecurityFilters {
def filters = {	
auth(controller: "(blog|blogEntry)", action: "(create|save)") {
be...
Security Filterclass SecurityFilters {
def filters = {	
auth(controller: "(blog|blogEntry)", action: "(create|save)") {
be...
JsecUserController Enchancementdef save = {
def jsecUserInstance = new JsecUser(params)
	 	 jsecUserInstance.passwordHash ...
JsecUserController Enchancementdef save = {
def jsecUserInstance = new JsecUser(params)
	 	 jsecUserInstance.passwordHash ...
What’s Missing
• User views (List, Show, Edit, Create)
shouldn’t show the password in the clear
• Password label needs to ...
Enhance UserViews. . .
<tr class="prop">
	 <td valign="top" class="name"><label for="username">Username:</label>
	 </td>
	...
Enhance UserViews. . .
<tr class="prop">
	 <td valign="top" class="name"><label for="username">Username:</label>
	 </td>
	...
What’s Missing
• When creating a blog entry the user shouldn’t
have to specify which user the blog is related to.
Blog / User automation
• Remove User fields from the Blog views.
• Update BlogEntryController save.
def save = {
def blogEn...
Update Url Mapping
"/$blog/" {
controller = "blogEntry"
action = "homePage"
}
What’s Missing
• Need a way to logout
• Should be able to Register a new user from the
login screen.
Register New User
<tr>
<td />
<!--
<td><input type="submit" value="Sign in" /></td>
-->
<td><g:actionSubmit value="Sign in...
Congratulations!!!
And to think, this morning you didn’t know
Groovy and Grails.
Recap
• Reviewed Security Concepts: Subject, Principals, Roles,
Permissions, and Realms
• Reviewed Security Options and se...
Groovy & Grails Training
Groovy Essentials (2 days) Grails Essentials (2 days)
•Groovy language basics
•Java Comparison
•T...
Resources
• Introduction to Groovy
• Groovy Basics
• More Advanced Groovy
• Introduction to Grails
• Building the User Int...
Resources
•Grails
–grails.codehaus.org or www.grails.org
–Grails Quick Start
•grails.codehaus.org/Quick+Start
–User Guide
...
Conclusion
• Blog:
http://juddsolutions.blogspot.com
http://jshingler.blogspot.com
• Email:
CJudd@JuddSolutions.com
Shingl...
Gg Code Mash2009 20090106
Gg Code Mash2009 20090106
Upcoming SlideShare
Loading in …5
×

Gg Code Mash2009 20090106

41,142 views

Published on

CodeMash 2009 Groovy and Grails Precompile Presentations by Chris Judd and Jim Shingler

  • Be the first to comment

Gg Code Mash2009 20090106

  1. Chris Judd & Jim Shingler CodeMash 2009 Percompile &
  2. Christopher Judd President/Consultant of leader Creator of open source projects FallME and Fiddle
  3. Jim Shingler Chief Technical Architect President of Genuine Solutions Co-Creator Open Source Project of FallME Co-Author of Beginning Groovy and Grails
  4. Goal: Gain enough Groovy and Grails knowledge to be able to build a modest Grails applications. Install Groovy and Grails Create and Run Groovy Scripts Understand basic Groovy Language Features Create a Scaffolded Web Application Apply a Custom Layout and Styling Install and use Plugins Enable Security
  5. Example Code http://github.com/jshingler/codemash2009precompile/tree/master
  6. Software Used • JDK 1.5 > • Eclipse 3.4 • Groovy plug-in • Groovy 1.5.7 • Grails 1.0.4 • Plug-ins • feeds 1.4 • searchable 0.5.1 • jsecurity 0.4-SNAPSHOT Plus: • Slides • Example Code • Example Resources
  7. Java Platform
  8. What is Java?
  9. What is Java?
  10. What is Java? Virtual Machine
  11. What is Java? Virtual Machine API/Library
  12. What is Java? Virtual Machine API/Library Java Language
  13. What is Java? Virtual Machine API/Library Java LanguageJavaScript
  14. What is Java? Virtual Machine API/Library Java LanguageJavaScript Groovy
  15. What is Java? Virtual Machine API/Library Java LanguageJavaScript Groovy Ruby
  16. What is Java? Virtual Machine API/Library Java LanguageJavaScript Groovy Ruby Python
  17. Language Stack
  18. Java Language Language Stack System (static)
  19. Java Language Language Stack Groovy System (static) Application (Dynamic)
  20. Java Language Language Stack Groovy Domain Specific Languages System (static) Application (Dynamic) Domain
  21. Groovy By Example
  22. import java.util.ArrayList; import java.util.List; public class Student { private String firstName; private String lastName; public Student(String firstName, String lastName) { super(); this.firstName = firstName; this.lastName = lastName; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public static void main(String[] args) { List<Student> students = new ArrayList<Student>(); students.add(new Student("Chris", "Judd")); students.add(new Student("Jim", "Shingler")); students.add(new Student("Joseph", "Nusairat")); System.out.println("Students:"); for (Student student : students) { System.out.println(student.getLastName() + ", " + student.getFirstName()); } } } javac -d classes srcmainjavacomjuddsolutionsgroovybasicsStudent.java java -cp classes com.juddsolutions.groovy.basics.Student Student.class Students: Judd, Chris Shingler, Jim Nusairat, Joseph Java Example
  23. import java.util.ArrayList; import java.util.List; public class Student { private String firstName; private String lastName; public Student(String firstName, String lastName) { super(); this.firstName = firstName; this.lastName = lastName; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public static void main(String[] args) { List<Student> students = new ArrayList<Student>(); students.add(new Student("Chris", "Judd")); students.add(new Student("Jim", "Shingler")); students.add(new Student("Joseph", "Nusairat")); System.out.println("Students:"); for (Students student : students) { System.out.println(student.getLastName() + ", " + student.getFirstName()); } } } Rename to Students.groovy groovy srcmainjavacomjuddsolutionsgroovybasicsStudents.groovy Students: Judd, Chris Shingler, Jim Nusairat, Joseph
  24. Congratulations you are a programmer
  25. Christopher M. Judd President, Consultant, Author 685 Farrington Drive Worthington, Ohio 43085 Phone: (614) 378-4119 Email: cjudd@juddsolutions.com SUMMARY Chris has 12 years of professional experience in object-oriented, web and mobile technologies as well as technical education and leadership. He has experience with all phases of the software development life-cycle, including requirements, analysis, architecture and design, implementation, testing, performance tuning, support, training and project leadership. In addition, he has provided technical instruction to thousands of information technology professionals though instructor led training, mentoring, conferences, user group meetings and co-authoring “Beginning Groovy and Grails”, “Enterprise Java Development on a Budget” and “Pro Eclipse JST”. He has provided services to a diverse group of industries including manufacturing, transportation, government, insurance, publishing, retail, content management, entertainment, service, and technology consulting. EXPERIENCE Java User Group Leader! July 2002 – Preset Central Ohio Java User Group (COJUG) ! Coordinate and advertise monthly meetings on Java related topics. Consultant! Sept 2004 – Sept 2008 Nationwide Insurance ! Assisted in developing, architecting and performance testing a service oriented architecture (SOA) for selling and servicing insurance agreements using IBM’s Insurance Application Architecture (IAA) as the canonical business model. The services coordinated and orchestrated thirty six integration points including three policy administrative systems. The services were used by three front ends that supported agents and customers on the Internet. ! Assisted in developing and architecting an implementation of IBM’s conceptual Insurance Application Architecture (IAA) framework using Rational Application Developer, WebSphere Application Server, DB2 and Rational Software Modeler for UML modeling ! Profiled and performance tested insurance framework using HP Diagnostics Software. ! Architected, Designed and Developed an IAA based product modeler build on top of the Eclipse Platform including Eclipse Modeling Framework (EMF) and Graphical Editing Framework (GEF) ! Mentored a team of developers with no Java or web development experience to build web applications using Groovy and Grails. ! Mentored a team of developers in Java, J2EE, unit testing, configuration management and agile methodologies ! Set up and administered a continuous integration build server which provides code quality and metrics reports using ANT, Maven, Cruise Control, CVS, Subversion and other open source tools Chief Technical O"cer! Jan 2008 – May 2008 gwizMOBILE ! Assisted in developing and architecting a mobile auto trading application and advertisement tool using Groovy, Grails and J2ME. Consultant! June 2003 – Sept 2004 CINTAS ! Mentored a team of 4 developers with almost no Java experience to become productive J2EE developers ! Archited and developed a multi-tier reusable service based J2EE application using JBuilder, WebLogic, Struts, Together and SQL Server for a new document management line of business ! Taught JBuilder, J2EE, StarTeam, Linux, Dreamweaver, Struts and Object-Oriented Programming Groovy Don’t forget to update your resume.
  26. Copy/Paste Compatibility
  27. idiomatic
  28. Convert POJO to POGOimport java.util.ArrayList; import java.util.List; public class Student { private String firstName; private String lastName; public Student(String firstName, String lastName) { super(); this.firstName = firstName; this.lastName = lastName; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public static void main(String[] args) { List<Student> students = new ArrayList<Student>(); students.add(new Student("Chris", "Judd")); students.add(new Student("Jim", "Shingler")); students.add(new Student("Joseph", "Nusairat")); System.out.println("Students:"); for (Students student : students) { System.out.println(student.getLastName() + ", " + student.getFirstName()); } } } Remove visibility modifiers (default is public) Remove constructor Remove accessors and mutators Use named parameter constructor Use properties
  29. Convert POJO to POGO package com.juddsolutions.groovy.basics; import java.util.ArrayList; import java.util.List; public class Student { String firstName; String lastName; public static void main(String[] args) { List<Student> students = new ArrayList<Student>(); students.add(new Student(firstName:"Chris", lastName:"Judd")); students.add(new Student(firstName:"Jim", lastName:"Shingler")); students.add(new Student(firstName:"Joseph", lastName:"Nusairat")); System.out.println("Students:"); for (Students student : students) { System.out.println(student.lastName + ", " + student.firstName); } } } Remove visibility modifiers (default is public) Remove constructor Remove accessors and mutators Use named parameter constructor Use properties
  30. Simplify Code package com.juddsolutions.groovy.basics; import java.util.ArrayList; import java.util.List; public class Student { String firstName; String lastName; public static void main(String[] args) { List<Student> students = new ArrayList<Student>(); students.add(new Student(firstName:"Chris", lastName:"Judd")); students.add(new Student(firstName:"Jim", lastName:"Shingler")); students.add(new Student(firstName:"Joseph", lastName:"Nusairat")); System.out.println("Students:"); for (Students student : students) { System.out.println(student.lastName + ", " + student.firstName); } } } java.util.*, java.net.*, java.io.* as well as groovy.lang.* and groovy.util.* are implicitly imported Typing variables is optional Semicolons and parenthesis are optional Convenience methods Flexible Strings
  31. Simplify Code package com.juddsolutions.groovy.basics; public class Student { String firstName String lastName public static void main(String[] args) { def students = new ArrayList() students.add new Student(firstName:"Chris", lastName:"Judd") students.add new Student(firstName:"Jim", lastName:"Shingler") students.add new Student(firstName:"Joseph", lastName:"Nusairat") println "Students:" for (Student student : students) { println "${student.lastName}, ${student.firstName}" } } } java.util.*, java.net.*, java.io.* as well as groovy.lang.* and groovy.util.* are implicitly imported Typing variables is optional Semicolons and parenthesis are optional Convenience methods Flexible Strings
  32. Collections and Closures package com.juddsolutions.groovy.basics; public class Student { String firstName String lastName public static void main(String[] args) { def students = new ArrayList() students.add new Student(firstName:"Chris", lastName:"Judd") students.add new Student(firstName:"Jim", lastName:"Shingler") students.add new Student(firstName:"Joseph", lastName:"Nusairat") println "Students:" for (Student student : students) { println "${student.lastName}, ${student.firstName}" } } } Use Groovy collection notation Use Groovy closures for looping
  33. Collections and Closures package com.juddsolutions.groovy.basics; public class Student { String firstName String lastName public static void main(String[] args) { def students = [ new Student(firstName:"Chris", lastName:"Judd"), new Student(firstName:"Jim", lastName:"Shingler"), new Student(firstName:"Joseph", lastName:"Nusairat"), ] println "Students:" students.each {student -> println "${student.lastName}, ${student.firstName}" } } } Use Groovy collection notation Use Groovy closures for looping
  34. Scripts package com.juddsolutions.groovy.basics; public class Student { String firstName String lastName public static void main(String[] args) { def students = [ new Student(firstName:"Chris", lastName:"Judd"), new Student(firstName:"Jim", lastName:"Shingler"), new Student(firstName:"Joseph", lastName:"Nusairat"), ] println "Students:" students.each {student -> println "${student.lastName}, ${student.firstName}" } } } Java’s main method is not necessary since Groovy is scriptable
  35. Scripts package com.juddsolutions.groovy.basics; public class Student { String firstName String lastName } def students = [ new Student(firstName:"Chris", lastName:"Judd"), new Student(firstName:"Jim", lastName:"Shingler"), new Student(firstName:"Joseph", lastName:"Nusairat"), ] println "Students:" students.each {student -> println "${student.lastName}, ${student.firstName}" } Java’s main method is not necessary since Groovy is scriptable
  36. VS package com.juddsolutions.groovy.basics; public class Student { String firstName String lastName } def students = [ new Student(firstName:"Chris", lastName:"Judd"), new Student(firstName:"Jim", lastName:"Shingler"), new Student(firstName:"Joseph", lastName:"Nusairat"), ] println "Students:" students.each {student -> println "${student.lastName}, ${student.firstName}" } import java.util.ArrayList; import java.util.List; public class Student { private String firstName; private String lastName; public Student(String firstName, String lastName) { super(); this.firstName = firstName; this.lastName = lastName; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public static void main(String[] args) { List<Student> students = new ArrayList<Student>(); students.add(new Student("Chris", "Judd")); students.add(new Student("Jim", "Shingler")); students.add(new Student("Joseph", "Nusairat")); System.out.println("Students:"); for (Student student : students) { System.out.println(student.getLastName() + ", " + student.getFirstName()); } } }
  37. VS package com.juddsolutions.groovy.basics; public class Student { String firstName String lastName } def students = [ new Student(firstName:"Chris", lastName:"Judd"), new Student(firstName:"Jim", lastName:"Shingler"), new Student(firstName:"Joseph", lastName:"Nusairat"), ] println "Students:" students.each {student -> println "${student.lastName}, ${student.firstName}" } import java.util.ArrayList; import java.util.List; public class Student { private String firstName; private String lastName; public Student(String firstName, String lastName) { super(); this.firstName = firstName; this.lastName = lastName; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public static void main(String[] args) { List<Student> students = new ArrayList<Student>(); students.add(new Student("Chris", "Judd")); students.add(new Student("Jim", "Shingler")); students.add(new Student("Joseph", "Nusairat")); System.out.println("Students:"); for (Student student : students) { System.out.println(student.getLastName() + ", " + student.getFirstName()); } } }
  38. Groovy Basics
  39. What is Groovy? Groovy is an expressive, dynamic, object oriented language built for the JavaVirtual Machine (JVM) with lots of agile and modern language features.
  40. What is Groovy? Groovy is an expressive, dynamic, object oriented language built for the JavaVirtual Machine (JVM) with lots of agile and modern language features. Better Java
  41. What is Groovy? Groovy is an expressive, dynamic, object oriented language built for the JavaVirtual Machine (JVM) with lots of agile and modern language features. Java 3.0Better Java
  42. What is Groovy? Groovy is an expressive, dynamic, object oriented language built for the JavaVirtual Machine (JVM) with lots of agile and modern language features. Java 3.0Better Java • Properties • Closures • Optional Typing • Cool Operators • Operator Overloading
  43. What is Groovy? Groovy is an expressive, dynamic, object oriented language built for the JavaVirtual Machine (JVM) with lots of agile and modern language features. Java 3.0Better Java • Properties • Closures • Optional Typing • Cool Operators • Operator Overloading • Builders • Meta-Programming • Groovy JDK • Domain Specific Languages • Unit Testing
  44. def groovy = [] groovy << java groovy << ruby groovy << python groovy << smalltalk groovy << dynamic groovy << scripting groovy << agile
  45. Groovy is Java
  46. Groovy is Java package com.juddsolutions.groovy.basics; public class Student { String firstName String lastName } def students = [ new Student(firstName:"Chris", lastName:"Judd"), new Student(firstName:"Jim", lastName:"Shingler"), new Student(firstName:"Joseph", lastName:"Nusairat"), ] println "Students:" students.each {student -> println "${student.lastName}, ${student.firstName}" }
  47. Groovy is Java package com.juddsolutions.groovy.basics; public class Student { String firstName String lastName } def students = [ new Student(firstName:"Chris", lastName:"Judd"), new Student(firstName:"Jim", lastName:"Shingler"), new Student(firstName:"Joseph", lastName:"Nusairat"), ] println "Students:" students.each {student -> println "${student.lastName}, ${student.firstName}" } javap Studentgroovyc Student
  48. Groovy is Java package com.juddsolutions.groovy.basics; public class Student { String firstName String lastName } def students = [ new Student(firstName:"Chris", lastName:"Judd"), new Student(firstName:"Jim", lastName:"Shingler"), new Student(firstName:"Joseph", lastName:"Nusairat"), ] println "Students:" students.each {student -> println "${student.lastName}, ${student.firstName}" } javap Studentgroovyc Student public class com.juddsolutions.groovy.basics.Student extends java.lang.Object implements groovy.lang.GroovyObject { public static final java.lang.Class $ownClass; public static java.lang.ref.SoftReference $staticMetaClass; transient groovy.lang.MetaClass metaClass; public static java.lang.Long __timeStamp; public static java.lang.Long __timeStamp__239_neverHappen1228887197896; public com.juddsolutions.groovy.basics.Student(); protected groovy.lang.MetaClass $getStaticMetaClass(); public groovy.lang.MetaClass getMetaClass(); public java.lang.Object invokeMethod(java.lang.String, java.lang.Object); public java.lang.Object getProperty(java.lang.String); public void setProperty(java.lang.String, java.lang.Object); static {}; public java.lang.String getFirstName(); public void setFirstName(java.lang.String); public java.lang.String getLastName(); public void setLastName(java.lang.String); public void setMetaClass(groovy.lang.MetaClass); void super$1$wait(); java.lang.String super$1$toString(); void super$1$wait(long); void super$1$wait(long, int); void super$1$notify(); void super$1$notifyAll(); java.lang.Class super$1$getClass(); boolean super$1$equals(java.lang.Object); java.lang.Object super$1$clone(); int super$1$hashCode(); void super$1$finalize(); static java.lang.Class class$(java.lang.String); }
  49. Groovy is Java package com.juddsolutions.groovy.basics; public class Student { String firstName String lastName } def students = [ new Student(firstName:"Chris", lastName:"Judd"), new Student(firstName:"Jim", lastName:"Shingler"), new Student(firstName:"Joseph", lastName:"Nusairat"), ] println "Students:" students.each {student -> println "${student.lastName}, ${student.firstName}" } javap Student But Java is not Groovy groovyc Student public class com.juddsolutions.groovy.basics.Student extends java.lang.Object implements groovy.lang.GroovyObject { public static final java.lang.Class $ownClass; public static java.lang.ref.SoftReference $staticMetaClass; transient groovy.lang.MetaClass metaClass; public static java.lang.Long __timeStamp; public static java.lang.Long __timeStamp__239_neverHappen1228887197896; public com.juddsolutions.groovy.basics.Student(); protected groovy.lang.MetaClass $getStaticMetaClass(); public groovy.lang.MetaClass getMetaClass(); public java.lang.Object invokeMethod(java.lang.String, java.lang.Object); public java.lang.Object getProperty(java.lang.String); public void setProperty(java.lang.String, java.lang.Object); static {}; public java.lang.String getFirstName(); public void setFirstName(java.lang.String); public java.lang.String getLastName(); public void setLastName(java.lang.String); public void setMetaClass(groovy.lang.MetaClass); void super$1$wait(); java.lang.String super$1$toString(); void super$1$wait(long); void super$1$wait(long, int); void super$1$notify(); void super$1$notifyAll(); java.lang.Class super$1$getClass(); boolean super$1$equals(java.lang.Object); java.lang.Object super$1$clone(); int super$1$hashCode(); void super$1$finalize(); static java.lang.Class class$(java.lang.String); }
  50. Dynamic Static StrongWeak C++ JavaScript Scala
  51. Dynamic Static StrongWeak C++ JavaScript Scala Groovy is: • Strongly typed • Dynamically typed • Optionally typed • Duck typed
  52. Also known as the Groovy JDK extends the classes built into the JDK class library GDK Even final classes like String def p = "cmd /c dir".execute() println p.text java.lang.String
  53. Also known as the Groovy JDK extends the classes built into the JDK class library GDK Even final classes like String def p = "cmd /c dir".execute() println p.text java.lang.String Volume in drive C has no label. Volume Serial Number is 38EC-A476 Directory of C:devlworkspacesgroovy-classgroovy-language-basics 12/15/2008 02:40 PM <DIR> . 12/15/2008 02:40 PM <DIR> .. 12/09/2008 03:12 AM 373 .classpath 12/02/2008 04:42 AM 588 .project 12/02/2008 04:42 AM <DIR> .settings 12/15/2008 02:42 PM <DIR> bin-groovy 12/09/2008 03:12 AM <DIR> build 12/02/2008 06:58 PM <DIR> src 2 File(s) 961 bytes 6 Dir(s) 30,512,635,904 bytes free
  54. Installing Groovy 1. Download from http://groovy.codehaus.org/Download • 1.5.7 - Stable Release • 1.6 beta 2 - Development Release 2. Unzip archive 3. Set GROOVY_HOME environment variable 4. Add %GROOVY_HOME%bin to system path Depends on JDK 1.4 or greater
  55. Installing Groovy 1. Download from http://groovy.codehaus.org/Download • 1.5.7 - Stable Release • 1.6 beta 2 - Development Release 2. Unzip archive 3. Set GROOVY_HOME environment variable 4. Add %GROOVY_HOME%bin to system path Don’t use the installer!!! Depends on JDK 1.4 or greater
  56. Running Groovy scripts shell console groovyConsole groovysh groovy
  57. just include groovy-all-<version>.jar in classpath Deploying
  58. Note: Quality of Groovy support is represented by size
  59. Ant.property(environment:"env") grailsHome = Ant.antProject.properties."env.GRAILS_HOME" includeTargets << new File ( "${grailsHome}/scripts/ War.groovy" ) target ('default':'''Copies a WAR archive to a Java EE application server's deploy directory. Example: grails deploy grails prod deploy ''') { deploy() } target (deploy: "The implementation target") { depends( war ) def deployDir = Ant.antProject.properties.'deploy.dir' Ant.copy(todir:"${deployDir}", overwrite:true) { fileset(dir:"${basedir}", includes:"*.war") } event("StatusFinal", ["Done copying WAR to $ {deployDir}"]) } <groovy> println "Hello World" </groovy> <build> <plugins> <plugin> <groupId>org.codehaus.groovy.maven</groupId> <artifactId>gmaven-plugin</artifactId> <executions> <execution> <goals> <goal>compile</goal> <goal>testCompile</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
  60. Groovy Site - http://groovy.codehaus.org/ Documentation - http://groovy.codehaus.org/Documentation GDK - http://groovy.codehaus.org/groovy-jdk/ Groovy Zone - http://groovy.dzone.com/ Groovy Blogs - http://groovyblogs.org/entries/recent
  61. Web Application Framework Persistable Domains Objects Controllers Views (Groovy Server Pages) Development Environment Spring Hibernate (GORM) SiteMesh Jetty HSQLDB Prototype & Scriptaculous JUnit Gant
  62. Griffon Swing Application Framework
  63. Griffon Swing Application Framework
  64. How do you introduce Groovy to the Enterprise? Unit Testing Automation Builds Prototyping
  65. Lab 1 1.Create a HelloWorld Groovy script passing your name as a parameter. 2.Execute the HelloWorld script. 3.javap the HelloWorld code from Lab 1 to determine the super class. 4.Use either the Groovy Console or Groovy Shell to print out 10 asterisks.
  66. Lab 1 1.Create a HelloWorld Groovy script passing your name as a parameter. 2.Execute the HelloWorld script. 3.javap the HelloWorld code from Lab 1 to determine the super class. 4.Use either the Groovy Console or Groovy Shell to print out 10 asterisks. Hello Chris!!!
  67. Language Basics
  68. Strings Quote def quote = "Double Quote" println "${quote} is a ${quote.class.name}" Single def single = 'Single Quote' println "${single} is a ${single.class.name}" def slashy = /Slashy Quote/ println "${slashy} is a ${slashy.class.name}" Slashy Multiline def multiline = """select * from table where name=value""" println "${multiline} is a ${multiline.class.name}"
  69. Strings Quote def quote = "Double Quote" println "${quote} is a ${quote.class.name}" Single def single = 'Single Quote' println "${single} is a ${single.class.name}" def slashy = /Slashy Quote/ println "${slashy} is a ${slashy.class.name}" Slashy Multiline def multiline = """select * from table where name=value""" println "${multiline} is a ${multiline.class.name}" Don’t have to escape
  70. GString def datetime = "Datetime: ${new Date()}" println "${datetime}" org.codehaus.groovy.runtime.GStringImpl String interpolation
  71. Asserts assert a != null assert a != null, 'a must not be null' An assertion is used to validate an expected condition is true, according to Groovy Truth. If the expected condition is not true, a java.lang.AssertionError is thrown.
  72. Groovy Truth true • Non-empty maps • Non-empty Strings • Non-zero numbers • Non-null object references • Matching regex patterns false • Empty collections • Iterators or Enumerators with no further elements
  73. Groovy Methods Implicitly returns last expression Access modifier is public by default def passwordtize(text) { def password = '' text.each {password += '*'} password }
  74. Closures A block of reusable code. A closure is an object. def sayHello = { println "hello!" } sayHello() //prints "hello!" def sayHelloTo = {name -> println "Hello ${name}!" } sayHelloTo('Chris') //prints "Hello Chris" sayHelloTo 'Chris' //prints "Hello Chris" passing parameters def sayHelloTo = {println "Hello ${it}!" } sayHelloTo 'Jim' //prints "Hello Jim" implicit it
  75. Lists def authors = [] authors.add 'Chris' authors += 'Jim' authors << 'Joseph' println "Authors:" authors.each{ println it } println "type: ${authors.class.name}" // java.util.ArrayList println "first author is ${authors[0]}" println "last author is ${authors.last()}" Array like syntax Connivence methods and operators def books = [] as Set books << "Enterprise Java Development on a Budget" books << "Pro Eclipse JST" books << "Beginning Groovy and Grails" println"nBooks:" books.each {book -> println book} println "type: ${books.class.name}" // java.util.HashSet Alternative types
  76. Ranges A list of sequential values. def numbers = 1..10 assert numbers.size() == 10 numbers.each{ print it } assert numbers.contains(5) println() ('a'..'z').each{ print it } println() for(i in 'a'..'z') { print i }
  77. Ranges A list of sequential values. def numbers = 1..10 assert numbers.size() == 10 numbers.each{ print it } assert numbers.contains(5) println() ('a'..'z').each{ print it } println() for(i in 'a'..'z') { print i } 12345678910 abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz
  78. Maps An unordered collection of key/value pair where the key is unique. def map = ['a':'A', 'b':'B', 'c':'C' ] println map println map.getClass().name // java.util.LinkedHashMap println map['a'] println map.'a' println map.a println map.get('a') println map.getAt('a') println map.get('d', 'D') map.e = 'E' map['f'] = 'F' map.'g' = 'G' map.put('h', 'H') println map
  79. Maps An unordered collection of key/value pair where the key is unique. def map = ['a':'A', 'b':'B', 'c':'C' ] println map println map.getClass().name // java.util.LinkedHashMap println map['a'] println map.'a' println map.a println map.get('a') println map.getAt('a') println map.get('d', 'D') map.e = 'E' map['f'] = 'F' map.'g' = 'G' map.put('h', 'H') println map ["a":"A", "b":"B", "c":"C"] java.util.LinkedHashMap A A A A A D ["a":"A", "b":"B", "c":"C", "d":"D", "e":"E", "f":"F", "g":"G", "h":"H"]
  80. Maps //Print each key/value pair on aseparate line map.each { println "Key: ${it.key}, Value: ${it.value}" } // Print each key/value pair on aseparate line with index map.eachWithIndex { it, i -> println "${i} Key: ${it.key}, Value: ${it.value}" } //Print the key set println "nKeys:" map.keySet().each { println it } // Print the value set println "nValues:" map.values().each { println it } def numbers = [1:'one', 2: 'two', 3:'three'] def all = map + numbers println all
  81. Regular Expressions Operators • match (==~) • find (=~) • pattern (~string) // Matching Operators assert "abc" ==~ 'abc' assert "abc" ==~ /abc/ assert !("abcabc" ==~ /abc/) // Fails – not an exact match assert "abc" ==~ /^a.c/ // Starts with a, 1 char, ends with c assert "abc" ==~ /^a../ // Starts with a, 2 chars assert "abc" ==~ /.*c$/ // One or more chars end with c assert "abc" ==~ ".*c$" // Slashy string is better // Find Operator def matcher = 'Groovy is groovy' =~ /(G|g)roovy/ print "Size of matcher is ${matcher.size()} " println "with elements ${matcher[0]} and ${matcher[1]}." // Pattern Operator def quote = """Now is the time for all good men (and women) to come to the aid of their country""" def pattern = ~/(w+en)/ matcher = pattern.matcher(quote) println "Matches = ${matcher.getCount()}" for(i in matcher.iterator()) { println i }
  82. Regular Expressions Operators • match (==~) • find (=~) • pattern (~string) // Matching Operators assert "abc" ==~ 'abc' assert "abc" ==~ /abc/ assert !("abcabc" ==~ /abc/) // Fails – not an exact match assert "abc" ==~ /^a.c/ // Starts with a, 1 char, ends with c assert "abc" ==~ /^a../ // Starts with a, 2 chars assert "abc" ==~ /.*c$/ // One or more chars end with c assert "abc" ==~ ".*c$" // Slashy string is better // Find Operator def matcher = 'Groovy is groovy' =~ /(G|g)roovy/ print "Size of matcher is ${matcher.size()} " println "with elements ${matcher[0]} and ${matcher[1]}." // Pattern Operator def quote = """Now is the time for all good men (and women) to come to the aid of their country""" def pattern = ~/(w+en)/ matcher = pattern.matcher(quote) println "Matches = ${matcher.getCount()}" for(i in matcher.iterator()) { println i } Size of matcher is 2 with elements ["Groovy", "G"] and ["groovy", "g"]. Matches = 2 men women
  83. Operator Overloading Operator Method a + b a.plus(b) a - b a.minus(b) a * b a.multiply(b) a ** b a.power(b) a / b a.div(b) a % b a.mod(b) a | b a.or(b) a & b a.and(b) a ^ b a.xor(b) a++ or ++a a.next() a-- or --a a.previous() a[b] a.getAt(b) a[b] = c a.putAt(b,c)
  84. a << b a.leftShift(b) a >> b a.rightShift(b) switch(a) { case(b) : } b.isCase(a) ~a a.bitwiseNegate() -a a.negative() +a a.positive() class Person { String firstName String lastName Person spouse String toString() { "${lastName}, ${firstName}" } Person leftShift(partner) { partner.lastName = lastName spouse = partner partner.spouse = this } } def husband = new Person(firstName:"Chris", lastName:"Judd") def wife = new Person(firstName: "Sue", lastName:"Smith") // husband and wife get married husband << wife println wife
  85. a << b a.leftShift(b) a >> b a.rightShift(b) switch(a) { case(b) : } b.isCase(a) ~a a.bitwiseNegate() -a a.negative() +a a.positive() class Person { String firstName String lastName Person spouse String toString() { "${lastName}, ${firstName}" } Person leftShift(partner) { partner.lastName = lastName spouse = partner partner.spouse = this } } def husband = new Person(firstName:"Chris", lastName:"Judd") def wife = new Person(firstName: "Sue", lastName:"Smith") // husband and wife get married husband << wife println wife Judd, Sue
  86. Operators // Spread Operator def strings = ['chris', 'jim', 'joseph'] println strings*.getAt(0) // Elvis Operator def value = null println value == null ? "unknown" : value // Java ternary println value ?: "unknown" // Elvis Operator value = "cool" println value ?: "unknown" // Elvis Operator // Safe Navigation/Dereference Operator def string = null println "String lenth is ${string?.size()}"
  87. Operators // Spread Operator def strings = ['chris', 'jim', 'joseph'] println strings*.getAt(0) // Elvis Operator def value = null println value == null ? "unknown" : value // Java ternary println value ?: "unknown" // Elvis Operator value = "cool" println value ?: "unknown" // Elvis Operator // Safe Navigation/Dereference Operator def string = null println "String lenth is ${string?.size()}" ["c", "j", "j"] unknown unknown cool String length is null
  88. Exception in thread "main" groovy.lang.MissingPropertyException: No such property: b for class: Asserts at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:50) at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.getGroovyObjectProperty(ScriptBytecodeAdapter.java:537) at Asserts.run(Asserts.groovy:5) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:86) at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:230) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:912) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:756) at org.codehaus.groovy.runtime.InvokerHelper.invokePogoMethod(InvokerHelper.java:778) at org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:758) at org.codehaus.groovy.runtime.InvokerHelper.runScript(InvokerHelper.java:401) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:86) at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:230) at groovy.lang.MetaClassImpl.invokeStaticMethod(MetaClassImpl.java:1105) at org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:749) at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethodN(ScriptBytecodeAdapter.java:170) at Asserts.main(Asserts.groovy) Interpreting Call Stacks Find first occurrence of *.groovy
  89. Lab 2 1.Create a list from 1-10.Then find all the odd numbers and print them out. 2.Print out the list of numbers separated by spaces.
  90. Groovy Libraries
  91. Basic unit testing
  92. Groovy Unit Tests Extend GroovyTestCase which extends JUnit TestCase class RangeTest extends GroovyTestCase { def lowerCaseRange = 'a'..'z' def upperCaseRange = 'A'..'Z' void testLowerCaseRange() { assert 26 == lowerCaseRange.size() assertTrue(lowerCaseRange.contains('b')) assertFalse(lowerCaseRange.contains('B')) } void testUpperCaseRange() { assert 26 == upperCaseRange.size() assertTrue(upperCaseRange.contains('B')) assertFalse(upperCaseRange.contains('b')) } void testAlphaRange() { def alphaRange = lowerCaseRange + upperCaseRange assert 52 == alphaRange.size() assert alphaRange.contains('b') assert alphaRange.contains('B') } }
  93. Groovy Unit Tests Extend GroovyTestCase which extends JUnit TestCase class RangeTest extends GroovyTestCase { def lowerCaseRange = 'a'..'z' def upperCaseRange = 'A'..'Z' void testLowerCaseRange() { assert 26 == lowerCaseRange.size() assertTrue(lowerCaseRange.contains('b')) assertFalse(lowerCaseRange.contains('B')) } void testUpperCaseRange() { assert 26 == upperCaseRange.size() assertTrue(upperCaseRange.contains('B')) assertFalse(upperCaseRange.contains('b')) } void testAlphaRange() { def alphaRange = lowerCaseRange + upperCaseRange assert 52 == alphaRange.size() assert alphaRange.contains('b') assert alphaRange.contains('B') } } GroovyTestCase adds: • assertArrayEquals • assertContains • assertEquals • assertInspect • assertLength • assertScript • assertToString
  94. Running Unit Tests Runs in standard JUnit tools like Eclipse and Ant
  95. Running Unit Tests Groovy command-line is unit test aware
  96. Database
  97. import groovy.sql.Sql // Create connection def sql = Sql.newInstance( /jdbc:derby:C:Program FilesSunJavaDBdemodatabasestoursdb/, "APP", "APP", "org.apache.derby.jdbc.EmbeddedDriver") // Execute SQL and iterate over result set sql.eachRow( "select * from CITIES where Language='English' order by COUNTRY") { println "${it.city_name}, ${it.country}" } groovy.sql.SQL Database convenience API
  98. import groovy.sql.Sql // Create connection def sql = Sql.newInstance(/jdbc:derby:C:tempblogs;create=true/, "APP", "APP", "org.apache.derby.jdbc.EmbeddedDriver") // delete table if previously created try { sql.execute("drop table blogs") } catch(Exception e){} // create table sql.execute('''create table blogs ( id varchar(200) not null primary key, title varchar(500) )''') // populate the table def blogs = sql.dataSet("blogs") blogs.add( id:"1", title: 'title 1' ) blogs.add( id:"2", title: 'title 2' ) blogs.add( id:"3", title: 'title 3' ) sql.executeInsert("insert into blogs values('4', 'title 4')") println "Blogs:" //Execute SQL and iterate over result set. sql.eachRow("select * from blogs") { println "${it.id}, ${it.title}" }
  99. I/O
  100. // write file new File(/C:tempstates.txt/).text = "Ohio" // append file def file = new File(/C:tempstates.txt/) file.append("nTexas") Write File
  101. Read File // read file new File(/C:tempstates.txt/).eachLine {line -> println line } // read file into String def contents = new File(/C:tempstates.txt/).text println contents // read file into List def lines = new File(/C:tempstates.txt/).readLines() lines.each { println it }
  102. Read URL def feed = new URL( "http://juddsolutions.blogspot.com/feeds/posts/default").text
  103. Builders
  104. Groovy Builders A combination of Groovy language features such as meta- programming, closures and simplified map syntax for creating nested tree-like structures Name Description AntBuilder Enables the script and execution of Apache Ant tasks DOMBuilder Generates W3C DOMs MarkupBuilder GeneratesXML and HTML NodeBuilder Creates nested trees of objects for handling arbitrary data SwingBuilder Creates Java Swing UIs
  105. def writer = new StringWriter() def builder = new groovy.xml.MarkupBuilder(writer) builder.setDoubleQuotes(true) builder.authors { author(id:"1") { firstName "Chris" lastName "Judd" } author(id:"2") { firstName "Jim" lastName "Shingler" } author(id:"3") { firstName "Joseph" lastName "Nusirat" } } println writer.toString() MarkupBuilders
  106. def writer = new StringWriter() def builder = new groovy.xml.MarkupBuilder(writer) builder.setDoubleQuotes(true) builder.authors { author(id:"1") { firstName "Chris" lastName "Judd" } author(id:"2") { firstName "Jim" lastName "Shingler" } author(id:"3") { firstName "Joseph" lastName "Nusirat" } } println writer.toString() MarkupBuilders <authors> <author id="1"> <firstName>Chris</firstName> <lastName>Judd</lastName> </author> <author id="2"> <firstName>Jim</firstName> <lastName>Shingler</lastName> </author> <author id="3"> <firstName>Joseph</firstName> <lastName>Nusirat</lastName> </author> </authors>
  107. XML Parsing
  108. XML Slurping def xml = """ <authors> <author id="1"> <firstName>Chris</firstName> <lastName>Judd</lastName> </author> <author id="2"> <firstName>Jim</firstName> <lastName>Shingler</lastName> </author> <author id="3"> <firstName>Joseph</firstName> <lastName>Nusirat</lastName> </author> </authors> """ def authors = new XmlSlurper().parseText(xml) authors.author.each {author -> println "${author.@id} - ${author.lastName}, ${author.firstName}" }
  109. XML Slurping def xml = """ <authors> <author id="1"> <firstName>Chris</firstName> <lastName>Judd</lastName> </author> <author id="2"> <firstName>Jim</firstName> <lastName>Shingler</lastName> </author> <author id="3"> <firstName>Joseph</firstName> <lastName>Nusirat</lastName> </author> </authors> """ def authors = new XmlSlurper().parseText(xml) authors.author.each {author -> println "${author.@id} - ${author.lastName}, ${author.firstName}" } 1 - Judd, Chris 2 - Shingler, Jim 3 - Nusirat, Joseph
  110. Lab 3 1.Write a script that downloads and RSS feed and writes the id and title to JavaDB. 2.Write a script to read the JavaDB and create an XML document. Hint:When behind a you will have to set proxy properties: • http.proxyHost=myServer.net • http.proxyPort=80 • http.proxyUser=<user id> • proxyPassword=<user password>
  111. Modern Java Web Development
  112. Java Web Projects What do you need to start a Java?
  113. Java Web Projects • JDK What do you need to start a Java?
  114. Java Web Projects • JDK • Web Container/App Server What do you need to start a Java?
  115. Java Web Projects • JDK • Web Container/App Server What do you need to start a Java?
  116. Java Web Projects • JDK • Web Container/App Server • Build System What do you need to start a Java?
  117. Java Web Projects • JDK • Web Container/App Server • Build System What do you need to start a Java?
  118. Java Web Projects • JDK • Web Container/App Server • Build System • Application Stack What do you need to start a Java?
  119. Java Web Projects • JDK • Web Container/App Server • Build System • Application Stack What do you need to start a Java?
  120. Java Web Projects • JDK • Web Container/App Server • Build System • Application Stack • Persistence Framework What do you need to start a Java?
  121. Java Web Projects • JDK • Web Container/App Server • Build System • Application Stack • Persistence Framework What do you need to start a Java?
  122. Java Web Projects • JDK • Web Container/App Server • Build System • Application Stack • Persistence Framework • Web Framework What do you need to start a Java?
  123. Java Web Projects • JDK • Web Container/App Server • Build System • Application Stack • Persistence Framework • Web Framework What do you need to start a Java?
  124. Java Web Projects • JDK • Web Container/App Server • Build System • Application Stack • Persistence Framework • Web Framework • Unit Test Framework What do you need to start a Java?
  125. Java Web Projects • JDK • Web Container/App Server • Build System • Application Stack • Persistence Framework • Web Framework • Unit Test Framework What do you need to start a Java?
  126. Java Web Projects • JDK • Web Container/App Server • Build System • Application Stack • Persistence Framework • Web Framework • Unit Test Framework • AJAX Framework What do you need to start a Java?
  127. Java Web Projects • JDK • Web Container/App Server • Build System • Application Stack • Persistence Framework • Web Framework • Unit Test Framework • AJAX Framework What do you need to start a Java?
  128. Java Web Projects • JDK • Web Container/App Server • Build System • Application Stack • Persistence Framework • Web Framework • Unit Test Framework • AJAX Framework • Database What do you need to start a Java?
  129. Java Web Projects • JDK • Web Container/App Server • Build System • Application Stack • Persistence Framework • Web Framework • Unit Test Framework • AJAX Framework • Database What do you need to start a Java?
  130. Java Web Projects • JDK • Web Container/App Server • Build System • Application Stack • Persistence Framework • Web Framework • Unit Test Framework • AJAX Framework • Database • Scheduling Framework . What do you need to start a Java?
  131. Java Web Projects • JDK • Web Container/App Server • Build System • Application Stack • Persistence Framework • Web Framework • Unit Test Framework • AJAX Framework • Database • Scheduling Framework . • XML Framework What do you need to start a Java?
  132. Java Web Projects • JDK • Web Container/App Server • Build System • Application Stack • Persistence Framework • Web Framework • Unit Test Framework • AJAX Framework • Database • Scheduling Framework . • XML Framework • Logging Framework What do you need to start a Java?
  133. Java Web Projects • JDK • Web Container/App Server • Build System • Application Stack • Persistence Framework • Web Framework • Unit Test Framework • AJAX Framework • Database • Scheduling Framework . • XML Framework • Logging Framework • View What do you need to start a Java?
  134. Java Web Projects • JDK • Web Container/App Server • Build System • Application Stack • Persistence Framework • Web Framework • Unit Test Framework • AJAX Framework • Database • Scheduling Framework . • XML Framework • Logging Framework • View • IDE . What do you need to start a Java?
  135. Java Development Cycle
  136. Code Java Development Cycle Takes too much time and is too complicated Compile Package Deploy Debug Test
  137. Conclusion Java Web and J2EE development is too complicated and not very agile.
  138. A Solution
  139. A Solution &
  140. What is Grails
  141. Grails is • Web Application Framework • Development Environment • Open Source under Apache 2.0 License • Current version 1.0.4 (1.1 is around the corner) • Best Practices – Convention over configuration – Don’t repeat yourself (DRY) – Default is what you expect (DIWYE) – Agile – Scaffolding – AJAX – Plug-ins – Unit testing – Web Services
  142. Grails Framework • JDK • Web Container/App Server • Build System • Application Stack • Persistence Framework • Web Framework • Unit Test Framework • AJAX Framework • Database • Scheduling Framework • XML Framework • Logging Framework • View • IDE JDK 1.4 GORM
  143. Grails Architecture Java Virtual Machine Java Language Groovy Language Grails Application Libraries Gant Spring GORMSiteMesh DomainControllers Views Services
  144. MVC Application Design Controller GSP Domain DB
  145. Service Applications Controller GSP Domain •Service DB Domain •Service
  146. Default Development Environment JVM Jetty (Web Container) Controller GSP Domain HSQL DB
  147. Production Environment JVM Web Container/App Server Controller GSP Domain DB WAR
  148. Conclusion Java’s capability, flexibility, backwards compatibility and community have lead to it’s unprecedented success. However, these same things have become it’s Achilles heal. The combination of Groovy and Grails simplifies the Java web platform while making developers more productive and agile.
  149. Starting with the end in mind
  150. Starting with the end in mind • Stage 1 - Conventions, MVC • Stage 2 -View, Styling, Feeds, Search • Stage 3 - Security and Users
  151. Prerequisites • Install Grails (Grails 1.0.4) http://grails.org/Download pick the appropriate distribution for your platform. • Unpack / install it. • Set the GRAILS_HOME environment variable and and <GRAILS_HOME>/bin to your path.
  152. Verify Install • at a command / shell prompt type grails
  153. Stage 1 - Conventions, MVC • Grails Application in 60 Seconds or Less, creating your first application • Exploring the Grails Application structure and Conventions • Creating Models,Views, and Controllers • Model Relationships and Constraints • Next Steps
  154. Grails App < 60 secs • Create a working directory • From command / shell prompt in that directory type: grails create-app blog cd blog grails run-app • In a browser goto: http://localhost:8080/blog
  155. Grails App < 60 secs
  156. Congratulations you are a programmer
  157. Christopher M. Judd President, Consultant, Author 685 Farrington Drive Worthington, Ohio 43085 Phone: (614) 378-4119 Email: cjudd@juddsolutions.com SUMMARY Chris has 12 years of professional experience in object-oriented, web and mobile technologies as well as technical education and leadership. He has experience with all phases of the software development life-cycle, including requirements, analysis, architecture and design, implementation, testing, performance tuning, support, training and project leadership. In addition, he has provided technical instruction to thousands of information technology professionals though instructor led training, mentoring, conferences, user group meetings and co-authoring “Beginning Groovy and Grails”, “Enterprise Java Development on a Budget” and “Pro Eclipse JST”. He has provided services to a diverse group of industries including manufacturing, transportation, government, insurance, publishing, retail, content management, entertainment, service, and technology consulting. EXPERIENCE Java User Group Leader! July 2002 – Preset Central Ohio Java User Group (COJUG) ! Coordinate and advertise monthly meetings on Java related topics. Consultant! Sept 2004 – Sept 2008 Nationwide Insurance ! Assisted in developing, architecting and performance testing a service oriented architecture (SOA) for selling and servicing insurance agreements using IBM’s Insurance Application Architecture (IAA) as the canonical business model. The services coordinated and orchestrated thirty six integration points including three policy administrative systems. The services were used by three front ends that supported agents and customers on the Internet. ! Assisted in developing and architecting an implementation of IBM’s conceptual Insurance Application Architecture (IAA) framework using Rational Application Developer, WebSphere Application Server, DB2 and Rational Software Modeler for UML modeling ! Profiled and performance tested insurance framework using HP Diagnostics Software. ! Architected, Designed and Developed an IAA based product modeler build on top of the Eclipse Platform including Eclipse Modeling Framework (EMF) and Graphical Editing Framework (GEF) ! Mentored a team of developers with no Java or web development experience to build web applications using Groovy and Grails. ! Mentored a team of developers in Java, J2EE, unit testing, configuration management and agile methodologies ! Set up and administered a continuous integration build server which provides code quality and metrics reports using ANT, Maven, Cruise Control, CVS, Subversion and other open source tools Chief Technical O"cer! Jan 2008 – May 2008 gwizMOBILE ! Assisted in developing and architecting a mobile auto trading application and advertisement tool using Groovy, Grails and J2ME. Consultant! June 2003 – Sept 2004 CINTAS ! Mentored a team of 4 developers with almost no Java experience to become productive J2EE developers ! Archited and developed a multi-tier reusable service based J2EE application using JBuilder, WebLogic, Struts, Together and SQL Server for a new document management line of business ! Taught JBuilder, J2EE, StarTeam, Linux, Dreamweaver, Struts and Object-Oriented Programming Grails Don’t forget to update your resume.
  158. So What Happened • grails create-app blog created application structure & copied some files • grails run-app started up the Jetty application server and ran the application
  159. App Structure & Conventions A pretty standard application structure, . . . you can pretty well guess the purpose of the files and directories.
  160. Grails commands
  161. Domain Class • Blog and BlogEntry domain class: grails create-domain-class Blog grails create-domain-class BlogEntry • What just happened? Grails created two domain classes (Blog, BlogEntry) and two unit tests (BlogTest, BlogEntryTest)
  162. Blog Properties: • blogid, title, byline, dateCreated, lastUpdated Method: • toString() class blog { String blogid String title String byline Date dateCreated Date lastUpdated String toString () { return "Blog ${id} = ${title}" } }
  163. BlogEntry Properties: • title, body, dateCreated, and lastUpdated Methods: • toString() class BlogEntry { String title String body Date dateCreated Date lastUpdated String toString () { return "BlogEntry ${id} = ${title}" } }
  164. Controller andView • Create the controller. grails create-controller Blog grails create-controller BlogEntry • What Happened? Grails created controller stubs for the domain classes, Blog and BlogEntry, and the corresponding unit tests. Using Convention, the classes are named BlogController, BlogControllerTest, BlogEntryController, and BlogEntryControllerTest
  165. Controller andView • Scaffolding auto generates views and controllers that support basic CRUD (Create, Read, Update, and Delete) operations on domain objects. • Edit BlogController and BlogEntryController, scaffold them by replacing the contents of the controller with: def scaffold = true class BlogController { def scaffold = true }
  166. Controller andView
  167. Controller andView
  168. What’s Missing
  169. What’s Missing • Data validity
  170. What’s Missing • Data validity • Relationships
  171. What’s Missing • Data validity • Relationships • Not Pretty (Stage 2)
  172. What’s Missing • Data validity • Relationships • Not Pretty (Stage 2) • User & Security (Stage 3)
  173. class Blog { String blogid String title String byline Date dateCreated Date lastUpdated static constraints = { title(blank: false, size: 1..128) byline(nullable: true) blogid(blank: false) dateCreated() lastUpdated(nullable: true) } String toString () { return "Blog ${id} = ${title}" } } DataValidation (Constraints) http://www.grails.org/Validation http://www.grails.org/Validation+Reference
  174. Relationships (GORM) http://www.grails.org/GORM http://www.grails.org/GORM+-+Defining+relationships
  175. class Blog { String blogid String title String byline Date dateCreated Date lastUpdated static hasMany = [ blogEntries : BlogEntry] static constraints = { title(blank: false, size: 1..128) byline(nullable: true) blogid(blank: false) lastUpdated(nullable: true) } String toString () { return "Blog ${id} = ${title}" } } Relationships (GORM) http://www.grails.org/GORM http://www.grails.org/GORM+-+Defining+relationships
  176. class BlogEntry { String title String body Date dateCreated Date lastUpdated static belongsTo = [ Blog ] Blog blog static constraints = { title(blank: false, maxSize: 128) body(blank: false, maxSize: 10000) dateCreated() lastUpdated(nullable: true) } String toString () { return "BlogEntry ${id} - ${title}" } } Relationships (GORM) http://www.grails.org/GORM http://www.grails.org/GORM+-+Defining+relationships
  177. Database ConfigurationdataSource { pooled = true driverClassName = "org.hsqldb.jdbcDriver" username = "sa" password = "" } hibernate { cache.use_second_level_cache=true cache.use_query_cache=true cache.provider_class='com.opensymphony.oscache.hibernate.OSCacheProvider' } // environment specific settings environments { development { dataSource { dbCreate = "create-drop" // one of 'create', 'create-drop','update' url = "jdbc:hsqldb:mem:devDB" } } test { dataSource { dbCreate = "update" url = "jdbc:hsqldb:mem:testDb" } } production { dataSource { dbCreate = "update" url = "jdbc:hsqldb:file:prodDb;shutdown=true" } } }
  178. GenerateViews and Controllers
  179. GenerateViews and Controllers • grails generate-all Blog grails generate-all BlogEntry
  180. GenerateViews and Controllers • grails generate-all Blog grails generate-all BlogEntry • What happened? Grails used templates to generate create.gsp, list.gsp, edit.gsp, show.gsp for Blog and BlogEntry. (Where are they) Grails used templates to generate BlogController.groovy and BlogEntryController.groovy (Where are they)
  181. GORM Sidebar • Save, Update, Delete, Get • Dynamic Finders http://grails.org/doc/1.0.x/guide/5.%20Object%20Relational%20Mapping%20(GORM).html#5.4%20Querying%20with%20GORM
  182. Lab 4 1.Create the Blog Application. 2.Create the Blog and Blog Entry Domain Classes. 3.Create both controllers with Scaffolding. 4.Run the application. 5.Add Constraints to Blog and Blog Entry and the relationships between them. 6.Run the application again. 7.Generate theViews and Controllers for Blog and BlogEntry. 8.Examine the views and controllers.
  183. Recap • Installed Grails and validated • Built firstapp in < 60 secs ;-) • Explored application structure and conventions • Create stage 1 of the Blog application, 2 Domain Classes with scaffolded Controllers andViews. • Added DataValidation to the Domain Classes • Created a 1:M relationship between Blog and BlogEntry • Explored generated views and controllers
  184. Stage 2 -View Styles • Layouts • TagLibs • Preview (AJAX) • URL Mappings • Feeds • Search
  185. Layout
  186. Layout Header Sidebar Footer Body
  187. Setup Resources (Images, CSS, and JavaScript) • Copy contents of <GrailsResources>/webapp to the blog project Updating the layout (layouts/main.gsp, layouts/print.gsp, _sidebar.gsp) • Copy contents of <GrailsResources>/views/layouts to blog project • Copy contents of <GrailsResources>/views to blog project
  188. TagLibs • What is a taglib • Previous Experiences with taglibs • Grails Taglibs • EntriesTagLib
  189. BlogEntryViews List • BlogEntryList.gsp • Redirect BlogEntryController. Show to single list (Reuse) • EntriesTagLib - Nice Dates
  190. BlogEntryViews Print • Add Print output. Need a way to trigger print layout No Header, Footer, or sidebar
  191. BlogEntryViews Edit • BlogEntryEdit.gsp
  192. BlogEntryViews AJAX Preview • Add Ajax and Destination • Add BlogEntryController.Preview to use preview template • Create BlogEntry Preview Template
  193. Lab 5 1.Copy Resources and Layouts 2.Setup the new BlogEntry list display 3.Redirect Show to use new list view 4.Create EntriesTagLib for title and niceDate 5.Review Print Layout and add Trigger to BlogEntry List 6.Setup new BlogEntry EditView 7.Add Preview Functionality
  194. URL Mappingclass UrlMappings { static mappings = { "/$controller/$action?/$id?"{ constraints { // apply constraints here } } "/$blog/$year/$month?/$day?/$id?" { controller = "blogEntry" action = "displayEntry" constraints { year(matches: /d{4}/) month(matches: /d{2}/) day(matches: /d{2}/) } } "/$blog/" { controller = "blogEntry" action = "list" } "500"(view:'/error') } }
  195. UrlMapping • Change the Header and Byline • blog/list.gsp add to the link params="[blog: blogInstance.blogid]" • blog/show.gsp add to the edit link <input type="hidden" name="blog" value="${blogInstance?.blogid}" />
  196. Permalink • Add Permalink Generation to BlogEntry public String toPermalink() { def sdf = new java.text.SimpleDateFormat("yyyy/MM/dd") return "/${blog?.blogid}/${sdf.format(dateCreated)}/${title.encodeAsNiceTitle()}.html" }
  197. Permalink • Nice Title Codec • Add BlogEntry Action DisplayEntry Insert from <GrailsResources>/controllers/ BlogEntryController.displayEntry.txt // strip all non word chars, convert to lowercase... class NiceTitleCodec { static encode = { str -> return str.toString().replaceAll("W", "-").toLowerCase() } }
  198. Plugins A plugin is a Grails extension point. Conceptually, it is similar to the plugins found in modern IDEs. A plugin is a technique to encapsulate functionality that can be reused across multiple applications. Grails has a rich plugin community at last count, over 100 plugins for a partial list. See: http://grails.org/Plugins http://grails.org/Plugins http://www.grails.org/The+Plug-in+Developers+Guide
  199. Feeds • Install the Feeds Plugin grails install-plugin feeds • Create a Feed Controller grails create-controller feed http://grails.org/Feeds+Plugin def index = { redirect(action:list,params:params) } def list = { render(feedType:"rss", feedVersion:"2.0"){ title="CM Blogs" link="http://localhost:8080/blog/feed" description="Demo Blog Feed from CodeMash 2009" def blogs = BlogEntry.list([max: 5, sort: "dateCreated", order: "desc"]) blogs.each{blogEntry -> entry(blogEntry.title) { link="http://localhost:8080/blog/blogEntry/show/${blogEntry.id}" blogEntry.body } } } }
  200. Feeds • Add Link to sidebar http://grails.org/Feeds+Plugin <ul> <li><g:link controller='feed'> <img src="${createLinkTo(dir:'images',file:'feed-icon-16x16.jpg')}" alt="RSS"/>RSS </g:link> </li> <li><a class="home" href="${createLinkTo(dir:'')}">Home</a></li> </ul>
  201. Search • Install Grail’s Searchable Plugin grails install-plugin searchable • Make BlogEntry searchable static searchable = { only = ["title", "body", "dateCreated", "blogs"] blog(component: true) } def indexedFields() { def fields = [:] // strip html before storing in index fields.title = title.replaceAll("<.*?>","") fields.body = body.replaceAll("<.*?>","") return fields }
  202. Searchable • Make Blog Searchable • http://localhost:8080/blog/seachable static searchable = { only = ["blogid", "title", "byline"] root : false }
  203. Searchable • Let’s Add a seach box to the application. • Copy <GrailsResources>/view/blog/search.gsp <div style="float: right; position: relative; margin-right: 7px; font-size: medium; "> <g:form url='[controller: "blog", action: "search"]' id="searchableForm" name="searchableForm" method="get"> <g:textField name="query" value="${params.query}" size="25"/> <input type="submit" value="Search" /> </g:form> </div>
  204. Lab 6 1.Setup UrlMappings http://localhost:8080/blog/jim and http://localhost:8080/blog/jim/yyyy/mm/dd 2.Create BlogEntry PermaLink 3.Setup RSS Feed 4.Setup Search Functionality
  205. Recap • Installed Grails and validated • Built firstapp in < 60 secs ;-) • Explored application structure and conventions • Create stage 1 of the Blog application, 2 Domain Classes with scaffolded Controllers andViews. • Added DataValidation to the Domain Classes • Created a 1:M relationship between Blog and BlogEntry • Explored generated views and controllers
  206. Stage 3 - Security • Discuss Security topics: User, Roles, Permissions, Realms • Define User and Security Requirements • Discuss Security Options • Build it out
  207. Security Topics High Level: User (Subject, Principals) Roles, Permissions, Realms
  208. Security Topics High Level: User (Subject, Principals) Roles, Permissions, Realms User / Subject
  209. Security Topics High Level: User (Subject, Principals) Roles, Permissions, Realms User / Subject Principals • Username: jim •Account Number • PGP Key
  210. Security Topics High Level: User (Subject, Principals) Roles, Permissions, Realms User / Subject Principals • Username: jim •Account Number • PGP Key Role • User •Administrator
  211. Security Topics High Level: User (Subject, Principals) Roles, Permissions, Realms User / Subject Principals • Username: jim •Account Number • PGP Key Role • User •Administrator Permission • blog (jim) : create, update, delete
  212. Security Topics High Level: User (Subject, Principals) Roles, Permissions, Realms User / Subject Principals • Username: jim •Account Number • PGP Key Role • User •Administrator Permission • blog (jim) : create, update, delete Realm: database, LDAP, . . .
  213. User and Security Requirements • User should have a name, email, password • Blog has a User • Only the User or an Administrator can modify a Blog / Blog Entry • Users shouldn’t be able to modify each others blogs
  214. Security Options • Spin your own (Loads of work & error prone) • Use a Security Package • Grails Plugins • ACEGI (Spring Security) • JSecurity • . . . • Integrate some other package http://grails.org/Plugins#Security%20Plugins http://www.jsecurity.org
  215. Security Options • Spin your own (Loads of work & error prone) • Use a Security Package • Grails Plugins • ACEGI (Spring Security) • JSecurity • . . . • Integrate some other package http://grails.org/Plugins#Security%20Plugins http://www.jsecurity.org
  216. Security Relationships
  217. JSecurity Plugins • List available plugins: grails list-plugins • Install the JSecurity plugin grails install-plugin jsecurity 0.4-SNAPSHOT • Setup JSecurity grails quick-start • Let’s Explore Domain Classes,Views,Tag Libs http://www.grails.org/JSecurity+Plugin http://www.grails.org/JSecurity+Plugin+-+Quick+Start
  218. JSecurity Plugins • List available plugins: grails list-plugins • Install the JSecurity plugin grails install-plugin jsecurity 0.4-SNAPSHOT • Setup JSecurity grails quick-start • Let’s Explore Domain Classes,Views,Tag Libs http://www.grails.org/JSecurity+Plugin http://www.grails.org/JSecurity+Plugin+-+Quick+Start VERY IMPORTANT: We need this specific version.
  219. Enhancing the User Class • User should have a name, email, password
  220. Enhancing the User Class • User should have a name, email, password class JsecUser { String username String passwordHash String fullName String email static constraints = { username (blank: false) fullName (blank: false) email (blank: false, email: true) } String toString() { return "User ${id} - ${fullName}" } }
  221. Enhancing Blog • Blog has a User class Blog { String blogid String title String byline Date dateCreated Date lastUpdated JsecUser user static hasMany = [ blogEntries : BlogEntry] static constraints = { title(blank: false, size: 1..128) byline(nullable: true) blogid(blank: false) dateCreated() lastUpdated(nullable: true) } static searchable = { only = ["blogid", "title", "byline"] root : false } String toString () { return "Blog ${id} = ${title}" } }
  222. Enhancing Blog • Blog has a User class Blog { String blogid String title String byline Date dateCreated Date lastUpdated JsecUser user static hasMany = [ blogEntries : BlogEntry] static constraints = { title(blank: false, size: 1..128) byline(nullable: true) blogid(blank: false) dateCreated() lastUpdated(nullable: true) } static searchable = { only = ["blogid", "title", "byline"] root : false } String toString () { return "Blog ${id} = ${title}" } }
  223. What’s missing • No Predefined Admin User
  224. Boot Strap Admin & Dilbert import org.jsecurity.crypto.hash.Sha1Hash import org.jsecurity.authz.permission.WildcardPermission class BootStrap { def init = { servletContext -> def basicPermission = new JsecPermission(type: "org.jsecurity.authz.permission.WildcardPermission", possibleActions: "*").save() def adminRole = new JsecRole(name: "administrator").save() def userRole = new JsecRole(name: "user").save() new JsecRolePermissionRel( role: adminRole, permission: basicPermission, target: "*", actions: "*").save() new JsecRolePermissionRel( role: userRole, permission: basicPermission, target: "blog:create,save", actions: "*").save() new JsecRolePermissionRel( role: userRole, permission: basicPermission, target: "blogEntry:create,save", actions: "*").save() new JsecRolePermissionRel( role: userRole, permission: basicPermission, target: "jsecUser:create,save", actions: "*").save()
  225. Boot Strap Admin & Dilbert import org.jsecurity.crypto.hash.Sha1Hash import org.jsecurity.authz.permission.WildcardPermission class BootStrap { def init = { servletContext -> def basicPermission = new JsecPermission(type: "org.jsecurity.authz.permission.WildcardPermission", possibleActions: "*").save() def adminRole = new JsecRole(name: "administrator").save() def userRole = new JsecRole(name: "user").save() new JsecRolePermissionRel( role: adminRole, permission: basicPermission, target: "*", actions: "*").save() new JsecRolePermissionRel( role: userRole, permission: basicPermission, target: "blog:create,save", actions: "*").save() new JsecRolePermissionRel( role: userRole, permission: basicPermission, target: "blogEntry:create,save", actions: "*").save() new JsecRolePermissionRel( role: userRole, permission: basicPermission, target: "jsecUser:create,save", actions: "*").save() Note: If you are using a persistent datastore (DB), NON-Memory, Then you should put guard conditions around the bootstrapping of Permission, Roles, and Users
  226. println "Building Admin User" def adminUser = new JsecUser(username: "admin", passwordHash: new Sha1Hash("admin").toHex(), fullName: "Admin User", email: "admin@admin.com").save() new JsecUserRoleRel(user: adminUser, role: adminRole).save() def blog = new Blog(title: "Blog: ${adminUser.fullName}", blogid: adminUser.username, user: adminUser) blog.save() def dilbert = new JsecUser(username: "dilbert", passwordHash: new Sha1Hash("password").toHex(), fullName: "Scott Adams", email: "dilbert@dilbert.com").save() new JsecUserRoleRel(user: dilbert, role: userRole).save() new JsecUserPermissionRel(user: dilbert, permission: basicPermission, target: "jsecUser:edit,update:${dilbert.id}",actions: "*").save() new JsecUserPermissionRel(user: dilbert, permission: basicPermission, target: "blog:edit,update:${dilbert.id}", actions: "*").save() new JsecUserPermissionRel(user: dilbert, permission: basicPermission, target: "blogEntry:edit,update:${dilbert.id}", actions: "*").save() // Add Blog new Blog(title: "Blog: ${dilbert.fullName}", blogid: dilbert.username, user: dilbert).save() } . . .
  227. What’s Missing • Ability to create a new User
  228. Views & Controller for JSecUser
  229. Views & Controller for JSecUser • Do you remember how?
  230. Views & Controller for JSecUser • Do you remember how? •grails generate-all JSecUser
  231. Views & Controller for JSecUser • Do you remember how? •grails generate-all JSecUser
  232. What’s missing • Password should be hashed • Auto create blog when new user saved
  233. JsecUserController Enhancement • Hash the password • On Save automatically create blog
  234. JsecUserController Enhancement • Hash the password • On Save automatically create blog import org.jsecurity.crypto.hash.Sha1Hash class JsecUserController { . . . def save = { def jsecUserInstance = new JsecUser(params) jsecUserInstance.passwordHash = new Sha1Hash(jsecUserInstance.passwordHash).toHex() if(!jsecUserInstance.hasErrors() && jsecUserInstance.save()) { // Add Blog new Blog(title: "Blog: ${jsecUserInstance.fullName}", blogid: jsecUserInstance.username, user: jsecUserInstance).save() flash.message = "User ${jsecUserInstance.id} created" redirect(action:show,id:jsecUserInstance.id) } else { render(view:'create',model:[jsecUserInstance:jsecUserInstance]) } } . . . }
  235. What’s Missing • Roles and Permissions aren’t being enforced.
  236. Enforcement of Roles & Permissions • Roles and Permissions are enforced using a Security Filter, . . .Yes, Filter as in Filter interceptor • Also need to add Role and Permission when saving a new user.
  237. Security Filterclass SecurityFilters { def filters = { auth(controller: "(blog|blogEntry)", action: "(create|save)") { before = { // This just means that the user must be authenticated. He does // not need any particular role or permission. accessControl { true } } } jsecUser(controller: "jsecUser", action: "(edit|update|delete)") { before = { accessControl { def userId = 0 if (params.id) { userId = JsecUser.get(params.id).id } role("administrator") || permission("jsecUser:${actionName ?: 'list'}:${userId}") } } } blog(controller: "(blog|blogEntry)", action: "(edit|update|delete)") { before = { accessControl { def userId = 0 def blogId = 0 def blog if (params.id) { blog = Blog.get(params.id) userId = blog.user.id } role("administrator") || permission("blog:${actionName ?: 'list'}:${userId}") }}}} http://grails.org/Filters
  238. Security Filterclass SecurityFilters { def filters = { auth(controller: "(blog|blogEntry)", action: "(create|save)") { before = { // This just means that the user must be authenticated. He does // not need any particular role or permission. accessControl { true } } } jsecUser(controller: "jsecUser", action: "(edit|update|delete)") { before = { accessControl { def userId = 0 if (params.id) { userId = JsecUser.get(params.id).id } role("administrator") || permission("jsecUser:${actionName ?: 'list'}:${userId}") } } } blog(controller: "(blog|blogEntry)", action: "(edit|update|delete)") { before = { accessControl { def userId = 0 def blogId = 0 def blog if (params.id) { blog = Blog.get(params.id) userId = blog.user.id } role("administrator") || permission("blog:${actionName ?: 'list'}:${userId}") }}}} http://grails.org/Filters
  239. JsecUserController Enchancementdef save = { def jsecUserInstance = new JsecUser(params) jsecUserInstance.passwordHash = new Sha1Hash(jsecUserInstance.passwordHash).toHex() if(!jsecUserInstance.hasErrors() && jsecUserInstance.save()) { new Blog(title: "Blog: ${jsecUserInstance.fullName}", blogid: jsecUserInstance.username, user: jsecUserInstance).save() def userRole = JsecRole.findByName("user") new JsecUserRoleRel(user: jsecUserInstance, role: userRole).save() def basicPermission = JsecPermission.findByType("org.jsecurity.authz.permission.WildcardPermission") new JsecUserPermissionRel( user: jsecUserInstance, permission: basicPermission, target: "jsecUser:edit,update:${jsecUserInstance.id}", actions: "*").save() new JsecUserPermissionRel( user: jsecUserInstance, permission: basicPermission, target: "blog:edit,update:${jsecUserInstance.id}", actions: "*").save() new JsecUserPermissionRel( user: jsecUserInstance, permission: basicPermission, target: "blogEntry:edit,update:${jsecUserInstance.id}", actions: "*").save() flash.message = "User ${jsecUserInstance.id} created" redirect(action:show,id:jsecUserInstance.id) } else { render(view:'create',model:[jsecUserInstance:jsecUserInstance]) } }
  240. JsecUserController Enchancementdef save = { def jsecUserInstance = new JsecUser(params) jsecUserInstance.passwordHash = new Sha1Hash(jsecUserInstance.passwordHash).toHex() if(!jsecUserInstance.hasErrors() && jsecUserInstance.save()) { new Blog(title: "Blog: ${jsecUserInstance.fullName}", blogid: jsecUserInstance.username, user: jsecUserInstance).save() def userRole = JsecRole.findByName("user") new JsecUserRoleRel(user: jsecUserInstance, role: userRole).save() def basicPermission = JsecPermission.findByType("org.jsecurity.authz.permission.WildcardPermission") new JsecUserPermissionRel( user: jsecUserInstance, permission: basicPermission, target: "jsecUser:edit,update:${jsecUserInstance.id}", actions: "*").save() new JsecUserPermissionRel( user: jsecUserInstance, permission: basicPermission, target: "blog:edit,update:${jsecUserInstance.id}", actions: "*").save() new JsecUserPermissionRel( user: jsecUserInstance, permission: basicPermission, target: "blogEntry:edit,update:${jsecUserInstance.id}", actions: "*").save() flash.message = "User ${jsecUserInstance.id} created" redirect(action:show,id:jsecUserInstance.id) } else { render(view:'create',model:[jsecUserInstance:jsecUserInstance]) } } Look Familiar? Take a look at: BootStrap.groovy
  241. What’s Missing • User views (List, Show, Edit, Create) shouldn’t show the password in the clear • Password label needs to be adjusted.
  242. Enhance UserViews. . . <tr class="prop"> <td valign="top" class="name"><label for="username">Username:</label> </td> <td valign="top" class="value ${hasErrors(bean:jsecUserInstance,field:'username','errors')}"> <input type="text" id="username" name="username" value="${fieldValue(bean:jsecUserInstance,field:'username')}" /></td> </tr> <tr class="prop"> <td valign="top" class="name"><label for="passwordHash">Password:</label> </td> <td valign="top" class="value ${hasErrors(bean:jsecUserInstance,field:'passwordHash','errors')}"> <input type="password" id="passwordHash" name="passwordHash" value="${fieldValue(bean:jsecUserInstance,field:'passwordHash')}" /></td> </tr> . . .
  243. Enhance UserViews. . . <tr class="prop"> <td valign="top" class="name"><label for="username">Username:</label> </td> <td valign="top" class="value ${hasErrors(bean:jsecUserInstance,field:'username','errors')}"> <input type="text" id="username" name="username" value="${fieldValue(bean:jsecUserInstance,field:'username')}" /></td> </tr> <tr class="prop"> <td valign="top" class="name"><label for="passwordHash">Password:</label> </td> <td valign="top" class="value ${hasErrors(bean:jsecUserInstance,field:'passwordHash','errors')}"> <input type="password" id="passwordHash" name="passwordHash" value="${fieldValue(bean:jsecUserInstance,field:'passwordHash')}" /></td> </tr> . . . Go ahead and make the corresponding adjustments to the other user views as appropriate. (list.gsp, create.gsp, show.gsp, edit.gsp)
  244. What’s Missing • When creating a blog entry the user shouldn’t have to specify which user the blog is related to.
  245. Blog / User automation • Remove User fields from the Blog views. • Update BlogEntryController save. def save = { def blogEntryInstance = new BlogEntry(params) if (blogEntryInstance.hasErrors()) { render(view:'create',model:[blogEntryInstance:blogEntryInstance]) return } else { def subject = SecurityUtils.subject def user = JsecUser.findByUsername(subject.principal) def blog = Blog.findByUser(user) log.debug "Adding new entry to blog ${blog?.title}" blog?.addToBlogEntries(blogEntryInstance)?.save() blogEntryInstance.save() flash.message = "BlogEntry ${blogEntryInstance.id} created" redirect(action:show,id:blogEntryInstance.id) } }
  246. Update Url Mapping "/$blog/" { controller = "blogEntry" action = "homePage" }
  247. What’s Missing • Need a way to logout • Should be able to Register a new user from the login screen.
  248. Register New User <tr> <td /> <!-- <td><input type="submit" value="Sign in" /></td> --> <td><g:actionSubmit value="Sign in" action="signIn" /> <g:actionSubmit value="Register" action="register" /></td> </tr> </tbody> login.gsp . . . def register = { redirect(controller: 'jsecUser', action: 'create') } . . . AuthController.groovy
  249. Congratulations!!! And to think, this morning you didn’t know Groovy and Grails.
  250. Recap • Reviewed Security Concepts: Subject, Principals, Roles, Permissions, and Realms • Reviewed Security Options and setup JSecurity Plugin • Enhanced the JsecUser Class and related it to Blog • Boot Strapped the Admin user are setup Roles and Persmissions • Generated JsecUserViews and Controller • User SecurityFilters to enforce Roles and Permissions • Created ability to Logout, Login / Register
  251. Groovy & Grails Training Groovy Essentials (2 days) Grails Essentials (2 days) •Groovy language basics •Java Comparison •Tools and IDEs •Language constructs •Groovy Strings •Closures •Collections •Scripting •Groovy Libraries •Unit Testing •XML (Markup Builders/Parsing) •JDBC •I/O •Advanced Groovy language features •Meta-programming •Expando •Domain Specific Languages •Advanced Unit Testing Free Groovy & Grails Overview (1 1/2 hours) •Grails basics •Conventions •MVC •Architecture •Environments •Scaffolding •Domain Model •GORM •Saving, deleting, updating •Dynamic finders •Querying •Constraints •Relationships •Controllers •Writing actions •Binding data •Flash scope •Pagination •Interception and Filtering •Views •Layouts and templates •Groovy Server Pages (GSP) •Adding AJAX •Services and Jobs •Plug-ins •Finding and Installing •Creating •Web Services •Authentication and Authorization Groovy & Grails JumpStart (30-60 days)
  252. Resources • Introduction to Groovy • Groovy Basics • More Advanced Groovy • Introduction to Grails • Building the User Interface • Building Domains and Services • Security in Grails • Web 2.0—Ajax and Friends • Web Services • Reporting • Batch Processing • Deploying and Upgrading • Alternative Clients
  253. Resources •Grails –grails.codehaus.org or www.grails.org –Grails Quick Start •grails.codehaus.org/Quick+Start –User Guide •grails.org/doc/1.0.x/ •Books Coming Soon
  254. Conclusion • Blog: http://juddsolutions.blogspot.com http://jshingler.blogspot.com • Email: CJudd@JuddSolutions.com ShinglerJim@gmail.com • LinkedIn: http://www.linkedin.com/in/christophermjudd http://www.linkedin.com/in/jimshingler • Twitter: http://www.twitter.com/jshingler ThankYou for your time

×