SlideShare a Scribd company logo
1 of 256
Download to read offline
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 of Beginning Groovy and Grails
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
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 0.5.1
• jsecurity 0.4-SNAPSHOT
Plus:
• Slides
• Example Code
• Example Resources
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 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
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
Congratulations
you are a
programmer
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.
Copy/Paste Compatibility
idiomatic
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
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
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
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
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
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
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
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
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());
}
}
}
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());
}
}
}
Groovy Basics
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.
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
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
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
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
def groovy = []
groovy << java
groovy << ruby
groovy << python
groovy << smalltalk
groovy << dynamic
groovy << scripting
groovy << agile
Groovy is Java
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}"
}
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
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);
}
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);
}
Dynamic
Static
StrongWeak
C++
JavaScript
Scala
Dynamic
Static
StrongWeak
C++
JavaScript
Scala
Groovy is:
• Strongly typed
• Dynamically typed
• Optionally typed
• Duck typed
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
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
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
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
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 ( "${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>
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
Web Application Framework
Persistable Domains Objects
Controllers
Views (Groovy Server Pages)
Development Environment
Spring
Hibernate (GORM)
SiteMesh
Jetty
HSQLDB
Prototype & Scriptaculous
JUnit
Gant
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 HelloWorld code from Lab 1 to determine the
super class.
4.Use either the Groovy Console or Groovy Shell to
print out 10 asterisks.
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!!!
Language Basics
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}"
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
GString
def datetime = "Datetime: ${new Date()}"
println "${datetime}"
org.codehaus.groovy.runtime.GStringImpl
String interpolation
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.
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
Groovy Methods
Implicitly returns last expression
Access modifier is public by default
def passwordtize(text) {
def password = ''
text.each {password += '*'}
password
}
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
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
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
}
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
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
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"]
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
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
}
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
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)
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
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
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()}"
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
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
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.
Groovy Libraries
Basic unit testing
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')
}
}
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
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 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
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}"
}
I/O
// write file
new File(/C:tempstates.txt/).text = "Ohio"
// append file
def file = new File(/C:tempstates.txt/)
file.append("nTexas")
Write File
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 }
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
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
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
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>
XML Parsing
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}"
}
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
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>
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 need to start a Java?
Java Web Projects
• JDK
• Web Container/App Server
• Build System
• Application Stack
• Persistence Framework
What do you need to start a Java?
Java Web Projects
• JDK
• Web Container/App Server
• Build System
• Application Stack
• Persistence Framework
• Web Framework
What do you need to start a Java?
Java Web Projects
• JDK
• Web Container/App Server
• Build System
• Application Stack
• Persistence Framework
• Web Framework
What do you need to start a Java?
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?
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?
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?
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?
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?
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?
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?
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?
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?
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?
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?
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.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
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
Grails Architecture
Java Virtual Machine
Java Language Groovy Language
Grails
Application
Libraries
Gant
Spring GORMSiteMesh
DomainControllers Views Services
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.
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.
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 and Users
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.
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 Grails Application structure
and Conventions
• Creating Models,Views, and Controllers
• Model Relationships and Constraints
• Next Steps
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
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: 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.
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
App Structure & Conventions
A pretty standard application
structure, . . . you can pretty well
guess the purpose of the files and
directories.
Grails commands
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)
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}"
	 }	
}
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}"
	 }
}
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
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
}
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 = {
	 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
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 = [ 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
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
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"
}
}
}
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 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)
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
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.
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
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 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
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 Dates
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 BlogEntry Preview Template
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
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')
	 }
}
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}" />
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"
}
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()
}
}
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
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
}
}
}
}
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>
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
}
Searchable
• Make Blog Searchable
• http://localhost:8080/blog/seachable
static searchable = {
only = ["blogid", "title", "byline"]
root : false
}
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>
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
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
Stage 3 - Security
• Discuss Security topics:
User, Roles, Permissions, Realms
• Define User and Security Requirements
• Discuss Security Options
• Build it out
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: jim
•Account Number
• PGP Key
Security Topics
High Level: User (Subject, Principals) Roles, Permissions, Realms
User / Subject Principals
• Username: jim
•Account Number
• PGP Key
Role
• User
•Administrator
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
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, . . .
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
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
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
Security Relationships
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
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.
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
String fullName
	 String email
static constraints = {
username (blank: false)
	 	 fullName (blank: false)
	 	 email (blank: false, email: true)
}
	
	 String toString() {
	 	 return "User ${id} - ${fullName}"
	 }
}
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}"
}
}
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}"
}
}
What’s missing
• No Predefined Admin User
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()
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
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()
}
. . .
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.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])
}
}
. . .
}
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 Filter interceptor
• Also need to add Role and Permission when saving
a new user.
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
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
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])
}
}
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
What’s Missing
• User views (List, Show, Edit, Create)
shouldn’t show the password in the clear
• Password label needs to be adjusted.
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>
. . .
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)
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 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)
}
}
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" action="signIn" />
<g:actionSubmit value="Register" action="register" /></td>
</tr>
</tbody>
login.gsp
. . .	
def register = {
redirect(controller: 'jsecUser', action: 'create')
}
. . .
AuthController.groovy
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 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
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)
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
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
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

More Related Content

Similar to Gg Code Mash2009 20090106

Boosting Your Testing Productivity with Groovy
Boosting Your Testing Productivity with GroovyBoosting Your Testing Productivity with Groovy
Boosting Your Testing Productivity with GroovyJames Williams
 
名古屋SGGAE/J勉強会 Grails、Gaelykでハンズオン
名古屋SGGAE/J勉強会 Grails、Gaelykでハンズオン名古屋SGGAE/J勉強会 Grails、Gaelykでハンズオン
名古屋SGGAE/J勉強会 Grails、GaelykでハンズオンTsuyoshi Yamamoto
 
Atlassian Groovy Plugins
Atlassian Groovy PluginsAtlassian Groovy Plugins
Atlassian Groovy PluginsPaul King
 
The curious Life of JavaScript - Talk at SI-SE 2015
The curious Life of JavaScript - Talk at SI-SE 2015The curious Life of JavaScript - Talk at SI-SE 2015
The curious Life of JavaScript - Talk at SI-SE 2015jbandi
 
Groovy & Grails: Scripting for Modern Web Applications
Groovy & Grails: Scripting for Modern Web ApplicationsGroovy & Grails: Scripting for Modern Web Applications
Groovy & Grails: Scripting for Modern Web Applicationsrohitnayak
 
Groovy and Grails in Action - Devoxx 2008 - University - Guillaume Laforge
Groovy and Grails in Action - Devoxx 2008 - University - Guillaume LaforgeGroovy and Grails in Action - Devoxx 2008 - University - Guillaume Laforge
Groovy and Grails in Action - Devoxx 2008 - University - Guillaume LaforgeGuillaume Laforge
 
Pragmatic Parallels: Java and JavaScript
Pragmatic Parallels: Java and JavaScriptPragmatic Parallels: Java and JavaScript
Pragmatic Parallels: Java and JavaScriptdavejohnson
 
Xopus Application Framework
Xopus Application FrameworkXopus Application Framework
Xopus Application FrameworkJady Yang
 
JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE...
JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE...JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE...
JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE...Guillaume Laforge
 
HTML5 for the Silverlight Guy
HTML5 for the Silverlight GuyHTML5 for the Silverlight Guy
HTML5 for the Silverlight GuyDavid Padbury
 
Oscon Java Testing on the Fast Lane
Oscon Java Testing on the Fast LaneOscon Java Testing on the Fast Lane
Oscon Java Testing on the Fast LaneAndres Almiray
 
The Best Way to Become an Android Developer Expert with Android Jetpack
The Best Way to Become an Android Developer Expert  with Android JetpackThe Best Way to Become an Android Developer Expert  with Android Jetpack
The Best Way to Become an Android Developer Expert with Android JetpackAhmad Arif Faizin
 
Groovy - Grails as a modern scripting language for Web applications
Groovy - Grails as a modern scripting language for Web applicationsGroovy - Grails as a modern scripting language for Web applications
Groovy - Grails as a modern scripting language for Web applicationsIndicThreads
 
Smoothing Your Java with DSLs
Smoothing Your Java with DSLsSmoothing Your Java with DSLs
Smoothing Your Java with DSLsintelliyole
 
Groovy DSLs (JavaOne Presentation)
Groovy DSLs (JavaOne Presentation)Groovy DSLs (JavaOne Presentation)
Groovy DSLs (JavaOne Presentation)Jim Driscoll
 
Building a Dynamic Website Using Django
Building a Dynamic Website Using DjangoBuilding a Dynamic Website Using Django
Building a Dynamic Website Using DjangoNathan Eror
 
Modeling Patterns for JavaScript Browser-Based Games
Modeling Patterns for JavaScript Browser-Based GamesModeling Patterns for JavaScript Browser-Based Games
Modeling Patterns for JavaScript Browser-Based GamesRay Toal
 

Similar to Gg Code Mash2009 20090106 (20)

Boosting Your Testing Productivity with Groovy
Boosting Your Testing Productivity with GroovyBoosting Your Testing Productivity with Groovy
Boosting Your Testing Productivity with Groovy
 
名古屋SGGAE/J勉強会 Grails、Gaelykでハンズオン
名古屋SGGAE/J勉強会 Grails、Gaelykでハンズオン名古屋SGGAE/J勉強会 Grails、Gaelykでハンズオン
名古屋SGGAE/J勉強会 Grails、Gaelykでハンズオン
 
Atlassian Groovy Plugins
Atlassian Groovy PluginsAtlassian Groovy Plugins
Atlassian Groovy Plugins
 
Having Fun with Play
Having Fun with PlayHaving Fun with Play
Having Fun with Play
 
The curious Life of JavaScript - Talk at SI-SE 2015
The curious Life of JavaScript - Talk at SI-SE 2015The curious Life of JavaScript - Talk at SI-SE 2015
The curious Life of JavaScript - Talk at SI-SE 2015
 
Groovy & Grails: Scripting for Modern Web Applications
Groovy & Grails: Scripting for Modern Web ApplicationsGroovy & Grails: Scripting for Modern Web Applications
Groovy & Grails: Scripting for Modern Web Applications
 
Groovy and Grails in Action - Devoxx 2008 - University - Guillaume Laforge
Groovy and Grails in Action - Devoxx 2008 - University - Guillaume LaforgeGroovy and Grails in Action - Devoxx 2008 - University - Guillaume Laforge
Groovy and Grails in Action - Devoxx 2008 - University - Guillaume Laforge
 
Pragmatic Parallels: Java and JavaScript
Pragmatic Parallels: Java and JavaScriptPragmatic Parallels: Java and JavaScript
Pragmatic Parallels: Java and JavaScript
 
Xopus Application Framework
Xopus Application FrameworkXopus Application Framework
Xopus Application Framework
 
From Java to Python
From Java to PythonFrom Java to Python
From Java to Python
 
JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE...
JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE...JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE...
JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE...
 
HTML5 for the Silverlight Guy
HTML5 for the Silverlight GuyHTML5 for the Silverlight Guy
HTML5 for the Silverlight Guy
 
Oscon Java Testing on the Fast Lane
Oscon Java Testing on the Fast LaneOscon Java Testing on the Fast Lane
Oscon Java Testing on the Fast Lane
 
The Best Way to Become an Android Developer Expert with Android Jetpack
The Best Way to Become an Android Developer Expert  with Android JetpackThe Best Way to Become an Android Developer Expert  with Android Jetpack
The Best Way to Become an Android Developer Expert with Android Jetpack
 
Groovy - Grails as a modern scripting language for Web applications
Groovy - Grails as a modern scripting language for Web applicationsGroovy - Grails as a modern scripting language for Web applications
Groovy - Grails as a modern scripting language for Web applications
 
L04 Software Design 2
L04 Software Design 2L04 Software Design 2
L04 Software Design 2
 
Smoothing Your Java with DSLs
Smoothing Your Java with DSLsSmoothing Your Java with DSLs
Smoothing Your Java with DSLs
 
Groovy DSLs (JavaOne Presentation)
Groovy DSLs (JavaOne Presentation)Groovy DSLs (JavaOne Presentation)
Groovy DSLs (JavaOne Presentation)
 
Building a Dynamic Website Using Django
Building a Dynamic Website Using DjangoBuilding a Dynamic Website Using Django
Building a Dynamic Website Using Django
 
Modeling Patterns for JavaScript Browser-Based Games
Modeling Patterns for JavaScript Browser-Based GamesModeling Patterns for JavaScript Browser-Based Games
Modeling Patterns for JavaScript Browser-Based Games
 

More from Jim Shingler

HIPAA Solutions on Cloud Foundry
HIPAA Solutions on Cloud FoundryHIPAA Solutions on Cloud Foundry
HIPAA Solutions on Cloud FoundryJim Shingler
 
DevOps is a Journey, Not an Event
DevOps is a Journey, Not an EventDevOps is a Journey, Not an Event
DevOps is a Journey, Not an EventJim Shingler
 
Personal Healthcare IOT on PCF using Spring
Personal Healthcare IOT on PCF using SpringPersonal Healthcare IOT on PCF using Spring
Personal Healthcare IOT on PCF using SpringJim Shingler
 
S1 2GX 2011 - Content Management with a Custom CMS
S1 2GX 2011 - Content Management with a Custom CMS S1 2GX 2011 - Content Management with a Custom CMS
S1 2GX 2011 - Content Management with a Custom CMS Jim Shingler
 
S1 2GX 2011 - Using Grails on a public facing Fortune 500 website
S1 2GX 2011 - Using Grails on a public facing  Fortune 500 website S1 2GX 2011 - Using Grails on a public facing  Fortune 500 website
S1 2GX 2011 - Using Grails on a public facing Fortune 500 website Jim Shingler
 
Griffon In Front Grails In Back
Griffon In Front Grails In BackGriffon In Front Grails In Back
Griffon In Front Grails In BackJim Shingler
 

More from Jim Shingler (6)

HIPAA Solutions on Cloud Foundry
HIPAA Solutions on Cloud FoundryHIPAA Solutions on Cloud Foundry
HIPAA Solutions on Cloud Foundry
 
DevOps is a Journey, Not an Event
DevOps is a Journey, Not an EventDevOps is a Journey, Not an Event
DevOps is a Journey, Not an Event
 
Personal Healthcare IOT on PCF using Spring
Personal Healthcare IOT on PCF using SpringPersonal Healthcare IOT on PCF using Spring
Personal Healthcare IOT on PCF using Spring
 
S1 2GX 2011 - Content Management with a Custom CMS
S1 2GX 2011 - Content Management with a Custom CMS S1 2GX 2011 - Content Management with a Custom CMS
S1 2GX 2011 - Content Management with a Custom CMS
 
S1 2GX 2011 - Using Grails on a public facing Fortune 500 website
S1 2GX 2011 - Using Grails on a public facing  Fortune 500 website S1 2GX 2011 - Using Grails on a public facing  Fortune 500 website
S1 2GX 2011 - Using Grails on a public facing Fortune 500 website
 
Griffon In Front Grails In Back
Griffon In Front Grails In BackGriffon In Front Grails In Back
Griffon In Front Grails In Back
 

Recently uploaded

NO1 Certified Black magic specialist,Expert in Pakistan Amil Baba kala ilam E...
NO1 Certified Black magic specialist,Expert in Pakistan Amil Baba kala ilam E...NO1 Certified Black magic specialist,Expert in Pakistan Amil Baba kala ilam E...
NO1 Certified Black magic specialist,Expert in Pakistan Amil Baba kala ilam E...Amil Baba Dawood bangali
 
Bald Philosopher, a story for entertainment.docx
Bald Philosopher, a story for entertainment.docxBald Philosopher, a story for entertainment.docx
Bald Philosopher, a story for entertainment.docxazuremorn
 
Flying Avocado Cat Cryptocurrency Created, Coded, Generated and Named by Grok...
Flying Avocado Cat Cryptocurrency Created, Coded, Generated and Named by Grok...Flying Avocado Cat Cryptocurrency Created, Coded, Generated and Named by Grok...
Flying Avocado Cat Cryptocurrency Created, Coded, Generated and Named by Grok...TeslaStakeHolder
 
Statement Of Intent - - Copy.documentfile
Statement Of Intent - - Copy.documentfileStatement Of Intent - - Copy.documentfile
Statement Of Intent - - Copy.documentfilef4ssvxpz62
 
Uk-NO1 Amil In Karachi Best Amil In Karachi Bangali Baba In Karachi Aamil In ...
Uk-NO1 Amil In Karachi Best Amil In Karachi Bangali Baba In Karachi Aamil In ...Uk-NO1 Amil In Karachi Best Amil In Karachi Bangali Baba In Karachi Aamil In ...
Uk-NO1 Amil In Karachi Best Amil In Karachi Bangali Baba In Karachi Aamil In ...Amil baba
 
Princess Jahan's Tuition Classes, a story for entertainment
Princess Jahan's Tuition Classes, a story for entertainmentPrincess Jahan's Tuition Classes, a story for entertainment
Princess Jahan's Tuition Classes, a story for entertainmentazuremorn
 
Behind the Scenes The Life of Enzo Zelocchi, a Hollywood Film Producer.pdf
Behind the Scenes The Life of Enzo Zelocchi, a Hollywood Film Producer.pdfBehind the Scenes The Life of Enzo Zelocchi, a Hollywood Film Producer.pdf
Behind the Scenes The Life of Enzo Zelocchi, a Hollywood Film Producer.pdfEnzo Zelocchi Fan Page
 
What Life Would Be Like From A Different Perspective (saltyvixenstories.com)
What Life Would Be Like From A Different Perspective (saltyvixenstories.com)What Life Would Be Like From A Different Perspective (saltyvixenstories.com)
What Life Would Be Like From A Different Perspective (saltyvixenstories.com)Salty Vixen Stories & More
 
A Spotlight on Darla Leigh Pittman Rodgers: Aaron Rodgers' Mother
A Spotlight on Darla Leigh Pittman Rodgers: Aaron Rodgers' MotherA Spotlight on Darla Leigh Pittman Rodgers: Aaron Rodgers' Mother
A Spotlight on Darla Leigh Pittman Rodgers: Aaron Rodgers' Motherget joys
 
Biswanath Byam Samiti Open Quiz 2022 by Qui9 Grand Finale
Biswanath Byam Samiti Open Quiz 2022 by Qui9 Grand FinaleBiswanath Byam Samiti Open Quiz 2022 by Qui9 Grand Finale
Biswanath Byam Samiti Open Quiz 2022 by Qui9 Grand FinaleQui9 (Ultimate Quizzing)
 
THE MEDIC, A STORY for entertainment.docx
THE MEDIC, A STORY for entertainment.docxTHE MEDIC, A STORY for entertainment.docx
THE MEDIC, A STORY for entertainment.docxazuremorn
 
Aesthetic Design Inspiration by Slidesgo.pptx
Aesthetic Design Inspiration by Slidesgo.pptxAesthetic Design Inspiration by Slidesgo.pptx
Aesthetic Design Inspiration by Slidesgo.pptxsayemalkadripial4
 
ECOLUXE pre-ESPYS Ultimate Sports Lounge 2024
ECOLUXE pre-ESPYS Ultimate Sports Lounge 2024ECOLUXE pre-ESPYS Ultimate Sports Lounge 2024
ECOLUXE pre-ESPYS Ultimate Sports Lounge 2024Durkin Entertainment LLC
 
Taken Pilot Episode Story pitch Document
Taken Pilot Episode Story pitch DocumentTaken Pilot Episode Story pitch Document
Taken Pilot Episode Story pitch Documentf4ssvxpz62
 
Fight Scene Storyboard (Action/Adventure Animation)
Fight Scene Storyboard (Action/Adventure Animation)Fight Scene Storyboard (Action/Adventure Animation)
Fight Scene Storyboard (Action/Adventure Animation)finlaygoodall2
 
NO1 Certified kala ilam Expert In Peshwar Kala Jadu Specialist In Peshwar Kal...
NO1 Certified kala ilam Expert In Peshwar Kala Jadu Specialist In Peshwar Kal...NO1 Certified kala ilam Expert In Peshwar Kala Jadu Specialist In Peshwar Kal...
NO1 Certified kala ilam Expert In Peshwar Kala Jadu Specialist In Peshwar Kal...Amil Baba Dawood bangali
 

Recently uploaded (20)

NO1 Certified Black magic specialist,Expert in Pakistan Amil Baba kala ilam E...
NO1 Certified Black magic specialist,Expert in Pakistan Amil Baba kala ilam E...NO1 Certified Black magic specialist,Expert in Pakistan Amil Baba kala ilam E...
NO1 Certified Black magic specialist,Expert in Pakistan Amil Baba kala ilam E...
 
Bald Philosopher, a story for entertainment.docx
Bald Philosopher, a story for entertainment.docxBald Philosopher, a story for entertainment.docx
Bald Philosopher, a story for entertainment.docx
 
Flying Avocado Cat Cryptocurrency Created, Coded, Generated and Named by Grok...
Flying Avocado Cat Cryptocurrency Created, Coded, Generated and Named by Grok...Flying Avocado Cat Cryptocurrency Created, Coded, Generated and Named by Grok...
Flying Avocado Cat Cryptocurrency Created, Coded, Generated and Named by Grok...
 
Statement Of Intent - - Copy.documentfile
Statement Of Intent - - Copy.documentfileStatement Of Intent - - Copy.documentfile
Statement Of Intent - - Copy.documentfile
 
Uk-NO1 Amil In Karachi Best Amil In Karachi Bangali Baba In Karachi Aamil In ...
Uk-NO1 Amil In Karachi Best Amil In Karachi Bangali Baba In Karachi Aamil In ...Uk-NO1 Amil In Karachi Best Amil In Karachi Bangali Baba In Karachi Aamil In ...
Uk-NO1 Amil In Karachi Best Amil In Karachi Bangali Baba In Karachi Aamil In ...
 
Princess Jahan's Tuition Classes, a story for entertainment
Princess Jahan's Tuition Classes, a story for entertainmentPrincess Jahan's Tuition Classes, a story for entertainment
Princess Jahan's Tuition Classes, a story for entertainment
 
Behind the Scenes The Life of Enzo Zelocchi, a Hollywood Film Producer.pdf
Behind the Scenes The Life of Enzo Zelocchi, a Hollywood Film Producer.pdfBehind the Scenes The Life of Enzo Zelocchi, a Hollywood Film Producer.pdf
Behind the Scenes The Life of Enzo Zelocchi, a Hollywood Film Producer.pdf
 
S10_E06-Sincerely,The Friday Club- Prelims Farewell Quiz.pptx
S10_E06-Sincerely,The Friday Club- Prelims Farewell Quiz.pptxS10_E06-Sincerely,The Friday Club- Prelims Farewell Quiz.pptx
S10_E06-Sincerely,The Friday Club- Prelims Farewell Quiz.pptx
 
What Life Would Be Like From A Different Perspective (saltyvixenstories.com)
What Life Would Be Like From A Different Perspective (saltyvixenstories.com)What Life Would Be Like From A Different Perspective (saltyvixenstories.com)
What Life Would Be Like From A Different Perspective (saltyvixenstories.com)
 
A Spotlight on Darla Leigh Pittman Rodgers: Aaron Rodgers' Mother
A Spotlight on Darla Leigh Pittman Rodgers: Aaron Rodgers' MotherA Spotlight on Darla Leigh Pittman Rodgers: Aaron Rodgers' Mother
A Spotlight on Darla Leigh Pittman Rodgers: Aaron Rodgers' Mother
 
Biswanath Byam Samiti Open Quiz 2022 by Qui9 Grand Finale
Biswanath Byam Samiti Open Quiz 2022 by Qui9 Grand FinaleBiswanath Byam Samiti Open Quiz 2022 by Qui9 Grand Finale
Biswanath Byam Samiti Open Quiz 2022 by Qui9 Grand Finale
 
THE MEDIC, A STORY for entertainment.docx
THE MEDIC, A STORY for entertainment.docxTHE MEDIC, A STORY for entertainment.docx
THE MEDIC, A STORY for entertainment.docx
 
Aesthetic Design Inspiration by Slidesgo.pptx
Aesthetic Design Inspiration by Slidesgo.pptxAesthetic Design Inspiration by Slidesgo.pptx
Aesthetic Design Inspiration by Slidesgo.pptx
 
Moveable Feast_Travel-Lifestyle-Culture Quiz.pptx
Moveable Feast_Travel-Lifestyle-Culture Quiz.pptxMoveable Feast_Travel-Lifestyle-Culture Quiz.pptx
Moveable Feast_Travel-Lifestyle-Culture Quiz.pptx
 
ECOLUXE pre-ESPYS Ultimate Sports Lounge 2024
ECOLUXE pre-ESPYS Ultimate Sports Lounge 2024ECOLUXE pre-ESPYS Ultimate Sports Lounge 2024
ECOLUXE pre-ESPYS Ultimate Sports Lounge 2024
 
Taken Pilot Episode Story pitch Document
Taken Pilot Episode Story pitch DocumentTaken Pilot Episode Story pitch Document
Taken Pilot Episode Story pitch Document
 
Fight Scene Storyboard (Action/Adventure Animation)
Fight Scene Storyboard (Action/Adventure Animation)Fight Scene Storyboard (Action/Adventure Animation)
Fight Scene Storyboard (Action/Adventure Animation)
 
S10_E02_How to Pimp Social Media 101.pptx
S10_E02_How to Pimp Social Media 101.pptxS10_E02_How to Pimp Social Media 101.pptx
S10_E02_How to Pimp Social Media 101.pptx
 
Sincerely, The Friday Club - Farewell Quiz-Finals.pptx
Sincerely, The Friday Club - Farewell Quiz-Finals.pptxSincerely, The Friday Club - Farewell Quiz-Finals.pptx
Sincerely, The Friday Club - Farewell Quiz-Finals.pptx
 
NO1 Certified kala ilam Expert In Peshwar Kala Jadu Specialist In Peshwar Kal...
NO1 Certified kala ilam Expert In Peshwar Kala Jadu Specialist In Peshwar Kal...NO1 Certified kala ilam Expert In Peshwar Kala Jadu Specialist In Peshwar Kal...
NO1 Certified kala ilam Expert In Peshwar Kala Jadu Specialist In Peshwar Kal...
 

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
  • 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
  • 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
  • 19. Java Language Language Stack Groovy System (static) Application (Dynamic)
  • 20. Java Language Language Stack Groovy Domain Specific Languages System (static) Application (Dynamic) Domain
  • 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
  • 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.
  • 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()); } } }
  • 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
  • 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); }
  • 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
  • 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.
  • 61. 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
  • 62. Web Application Framework Persistable Domains Objects Controllers Views (Groovy Server Pages) Development Environment Spring Hibernate (GORM) SiteMesh Jetty HSQLDB Prototype & Scriptaculous JUnit Gant
  • 65. How do you introduce Groovy to the Enterprise? Unit Testing Automation Builds Prototyping
  • 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.
  • 67. 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!!!
  • 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}"
  • 70. 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
  • 71. GString def datetime = "Datetime: ${new Date()}" println "${datetime}" org.codehaus.groovy.runtime.GStringImpl String interpolation
  • 72. 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.
  • 73. 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
  • 74. Groovy Methods Implicitly returns last expression Access modifier is public by default def passwordtize(text) { def password = '' text.each {password += '*'} password }
  • 75. 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
  • 76. 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
  • 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 }
  • 78. 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
  • 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
  • 80. 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"]
  • 81. 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
  • 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 }
  • 83. 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
  • 84. 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)
  • 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
  • 86. 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
  • 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()}"
  • 88. 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
  • 89. 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
  • 90. 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.
  • 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') } }
  • 94. 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
  • 95. Running Unit Tests Runs in standard JUnit tools like Eclipse and Ant
  • 96. Running Unit Tests Groovy command-line is unit test aware
  • 98. 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
  • 99. 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}" }
  • 100. I/O
  • 101. // write file new File(/C:tempstates.txt/).text = "Ohio" // append file def file = new File(/C:tempstates.txt/) file.append("nTexas") Write File
  • 102. 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 }
  • 103. Read URL def feed = new URL( "http://juddsolutions.blogspot.com/feeds/posts/default").text
  • 105. 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
  • 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
  • 107. 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>
  • 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}" }
  • 110. 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
  • 111. 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>
  • 113. Java Web Projects What do you need to start a Java?
  • 114. Java Web Projects • JDK 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 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 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 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 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 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 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 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 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 . 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 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 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 What do you need to start a Java?
  • 135. 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?
  • 137. Code Java Development Cycle Takes too much time and is too complicated Compile Package Deploy Debug Test
  • 138. Conclusion Java Web and J2EE development is too complicated and not very agile.
  • 142. 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
  • 143. 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
  • 144. Grails Architecture Java Virtual Machine Java Language Groovy Language Grails Application Libraries Gant Spring GORMSiteMesh DomainControllers Views Services
  • 147. Default Development Environment JVM Jetty (Web Container) Controller GSP Domain HSQL DB
  • 148. Production Environment JVM Web Container/App Server Controller GSP Domain DB WAR
  • 149. 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.
  • 150. Starting with the end in mind
  • 151. Starting with the end in mind • Stage 1 - Conventions, MVC • Stage 2 -View, Styling, Feeds, Search • Stage 3 - Security and Users
  • 152. 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.
  • 153. Verify Install • at a command / shell prompt type grails
  • 154. 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
  • 155. 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
  • 156. Grails App < 60 secs
  • 158. 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.
  • 159. 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
  • 160. App Structure & Conventions A pretty standard application structure, . . . you can pretty well guess the purpose of the files and directories.
  • 162. 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)
  • 163. 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}" } }
  • 164. 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}" } }
  • 165. 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
  • 166. 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 }
  • 171. What’s Missing • Data validity • Relationships
  • 172. What’s Missing • Data validity • Relationships • Not Pretty (Stage 2)
  • 173. What’s Missing • Data validity • Relationships • Not Pretty (Stage 2) • User & Security (Stage 3)
  • 174. 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
  • 176. 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
  • 177. 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
  • 178. 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" } } }
  • 180. GenerateViews and Controllers • grails generate-all Blog grails generate-all BlogEntry
  • 181. 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)
  • 182. 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
  • 183. 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.
  • 184. 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
  • 185. Stage 2 -View Styles • Layouts • TagLibs • Preview (AJAX) • URL Mappings • Feeds • Search
  • 186. Layout
  • 188. 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
  • 189. TagLibs • What is a taglib • Previous Experiences with taglibs • Grails Taglibs • EntriesTagLib
  • 190. BlogEntryViews List • BlogEntryList.gsp • Redirect BlogEntryController. Show to single list (Reuse) • EntriesTagLib - Nice Dates
  • 191. BlogEntryViews Print • Add Print output. Need a way to trigger print layout No Header, Footer, or sidebar
  • 193. BlogEntryViews AJAX Preview • Add Ajax and Destination • Add BlogEntryController.Preview to use preview template • Create BlogEntry Preview Template
  • 194. 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
  • 195. 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') } }
  • 196. 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}" />
  • 197. 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" }
  • 198. 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() } }
  • 199. 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
  • 200. 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 } } } }
  • 201. 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>
  • 202. 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 }
  • 203. Searchable • Make Blog Searchable • http://localhost:8080/blog/seachable static searchable = { only = ["blogid", "title", "byline"] root : false }
  • 204. 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>
  • 205. 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
  • 206. 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
  • 207. Stage 3 - Security • Discuss Security topics: User, Roles, Permissions, Realms • Define User and Security Requirements • Discuss Security Options • Build it out
  • 208. Security Topics High Level: User (Subject, Principals) Roles, Permissions, Realms
  • 209. Security Topics High Level: User (Subject, Principals) Roles, Permissions, Realms User / Subject
  • 210. Security Topics High Level: User (Subject, Principals) Roles, Permissions, Realms User / Subject Principals • Username: jim •Account Number • PGP Key
  • 211. Security Topics High Level: User (Subject, Principals) Roles, Permissions, Realms User / Subject Principals • Username: jim •Account Number • PGP Key Role • User •Administrator
  • 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
  • 213. 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, . . .
  • 214. 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
  • 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 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
  • 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
  • 219. 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.
  • 220. Enhancing the User Class • User should have a name, email, password
  • 221. 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}" } }
  • 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. 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}" } }
  • 224. What’s missing • No Predefined Admin User
  • 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()
  • 226. 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
  • 227. 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() } . . .
  • 228. What’s Missing • Ability to create a new User
  • 229. Views & Controller for JSecUser
  • 230. Views & Controller for JSecUser • Do you remember how?
  • 231. Views & Controller for JSecUser • Do you remember how? •grails generate-all JSecUser
  • 232. Views & Controller for JSecUser • Do you remember how? •grails generate-all JSecUser
  • 233. What’s missing • Password should be hashed • Auto create blog when new user saved
  • 234. JsecUserController Enhancement • Hash the password • On Save automatically create blog
  • 235. 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]) } } . . . }
  • 236. What’s Missing • Roles and Permissions aren’t being enforced.
  • 237. 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.
  • 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. 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
  • 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]) } }
  • 241. 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
  • 242. What’s Missing • User views (List, Show, Edit, Create) shouldn’t show the password in the clear • Password label needs to be adjusted.
  • 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> . . .
  • 244. 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)
  • 245. What’s Missing • When creating a blog entry the user shouldn’t have to specify which user the blog is related to.
  • 246. 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) } }
  • 247. Update Url Mapping "/$blog/" { controller = "blogEntry" action = "homePage" }
  • 248. What’s Missing • Need a way to logout • Should be able to Register a new user from the login screen.
  • 249. 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
  • 250.
  • 251. Congratulations!!! And to think, this morning you didn’t know Groovy and Grails.
  • 252. 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
  • 253. 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)
  • 254. 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
  • 255. 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
  • 256. 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