Creating our First Grails Application (e.g. racetrack)
command prompt> grails create-app racetrack
command prompt> cd racetrack
command prompt\racetrack> grails run-app
Open your browser to http://localhost:8080/racetrack/
Create-Domain-Class
racetrack> grails create-domain-class Race
class Race {
String name
Date startDateTime
String city
String state
Float distance
Float cost
Integer maxRunners = 100000
static hasMany = [registrations:Registration]
}
racetrack> grails create-domain-class Registration
class Registration {
Race race
String name
Date dateOfBirth
String gender = 'F'
String emailAddress
String postalAddress
Date createdAt = new Date()
static belongsTo = Race
static optionals = ["postalAddress" ]
}
Relationship Counseling
One to Many Relationships
class Race {
//...
static hasMany =[registrations:Registration]
}
class Registration {
//...
Race race
static belongsTo = Race
}
create-controller
racetrack> grails create-controller Race
class RaceController {
//def index = { }
def scaffold = Race
}
racetrack> grails create-controller Registration
class RegistrationController {
def scaffold = Registration
}
racetrack> grails run-app
Open your browser to http://localhost:8080/racetrack/
Scaffolding
Grails has a scaffolding framework that generates applications with create, read, update, and delete (CRUD) functionality with very little code, allowing you to focus on defining the Groovy domain by creating classes with properties, behaviors, and constraints. At either runtime or development time, Grails can generate the controller behavior and GSP views associated with the domain classes for CRUD functionality. At the same time, it can even generate a database schema, including tables for each of the domain classes.
DataSource Configuration
dataSource {
pooled = true
driverClassName = "org.hsqldb.jdbcDriver" // "com.mysql.jdbc.Driver"
username = "sa“ // root
password = "“ // root
// dialect = "org.hibernate.dialect.MySQL5InnoDBDialect"
}
hibernate {
cache.use_second_level_cache=true
cache.use_query_cache=true
cache.provider_class='com.opensymphony.oscache.hibernate.OSCacheProvider'
}
environments {// environment specific settings
development {
dataSource {
dbCreate = "create-drop" // one of 'create', 'create-drop','update'
url = "jdbc:hsqldb:mem:devDB“ // "jdbc:mysql://localhost:3306/testdb"
}
}
test {
dataSource {
dbCreate = "update"
url = "jdbc:hsqldb:mem:testDb"
}
}
production {
dataSource {
dbCreate = "update"
url = "jdbc:hsqldb:file:prodDb;shutdown=true"
}
}
}
Note: For the mysql configuration uncommented dataSource properties for mysql
mysql> describe race;
+----------------+-------------+----+---+-------+---------------+-------------------
| Field | Type |Null | Key |Default | Extra |
+----------------+-------------+----+---+-------+---------------+------------
|id | bigint(20) | NO |PRI | NULL | auto_increment
|version | bigint(20) | NO | | | |
|distance | float | NO | | | |
|max_runners | int(11) | NO | | | |
|start_date_time| datetime | NO | | | |
|state | varchar(255) | NO | | | |
|cost | float | NO | | | |
|name | varchar(255) | NO | | | |
|city | varchar(255) | NO | | | |
+----------------+-------------+----+---+-------+---------------+------------
mysql> describe registration;
+----------------+-------------+----+---+-------+---------------+------------+------
| Field | Type |Null |Key |Default | Extra |
+----------------+-------------+----+---+-------+---------------+------------+------
|id | bigint(20) | NO |PRI | NULL | auto_increment
|date_of_birth | datetime | NO | | | |
|version | bigint(20) | NO | | | |
|gender | varchar(255) | NO | | | |
|postal_address | varchar(255) | YES | | NULL | |
|email_address | varchar(255) | NO | | | |
|created_at | datetime | NO | | | |
|race_id | bigint(20) | YES |MUL | NULL | |
|name | varchar(255) | NO | | | |
+-----------------+------------+----+---+-------+---------------+------------+------
9 rows in set (0.00 sec)
If database schema already exist , we can map table fields with our domain class
class Race {
//…
static hasMany = [registrations:Registration]
static mapping = {
table ‘race_tbl‘ // map existing table with domain class
columns { // map Columns
id column: 'OID‘
name column: ‘name’
startDateTime column: ‘cr_time’
city column: ‘city’
state column: ‘st’
distance column: ‘distance’
cost column: ‘prize’
}
}
}
Adding Custom constraints ::
class Race {
//...
static constraints = {
name(maxLength:50,blank:false)
//startDateTime(min:new Date())
city(maxLength:30,blank:false)
distance(min:3.1f,max:100f)
cost(min:0f,max:999.99f)
startDateTime(validator: {return (it > new Date())})
//custom validator
}
}
Grails creates a new controller instance for each request, and the
controller only lives long enough to process that request.
you can write your custom code by adding methods in controller and gsp pages to rendering the ouput result
Fun with URLs
http://localhost:8080/racetrack/race/show/2
class RaceController {
//... //View : racetrack/race/show
def show = {
[ race : Race.get( params.id ) ]
}
def save = {
def race = new Race()
race.properties = params
if(race.save()) {
redirect(action:show,id:race.id)
}
else {
render(view:'create',model:[race:race])
}
}
}
command prompt> cd racetrack
command prompt\racetrack> grails run-app
Open your browser to http://localhost:8080/racetrack/
Directory Structure
From this information, we can see that we’re basically working with two types of data –races and registrations – and that there’s a one-to-many relationship between those entities. That information will form the basis of our domain model, and the various data elements on the form will become the attributes of
our domain classes.Create-Domain-Class
racetrack> grails create-domain-class Race
class Race {
String name
Date startDateTime
String city
String state
Float distance
Float cost
Integer maxRunners = 100000
static hasMany = [registrations:Registration]
}
racetrack> grails create-domain-class Registration
class Registration {
Race race
String name
Date dateOfBirth
String gender = 'F'
String emailAddress
String postalAddress
Date createdAt = new Date()
static belongsTo = Race
static optionals = ["postalAddress" ]
}
Relationship Counseling
One to Many Relationships
class Race {
//...
static hasMany =[registrations:Registration]
}
class Registration {
//...
Race race
static belongsTo = Race
}
create-controller
racetrack> grails create-controller Race
class RaceController {
//def index = { }
def scaffold = Race
}
racetrack> grails create-controller Registration
class RegistrationController {
def scaffold = Registration
}
racetrack> grails run-app
Open your browser to http://localhost:8080/racetrack/
Scaffolding
Grails has a scaffolding framework that generates applications with create, read, update, and delete (CRUD) functionality with very little code, allowing you to focus on defining the Groovy domain by creating classes with properties, behaviors, and constraints. At either runtime or development time, Grails can generate the controller behavior and GSP views associated with the domain classes for CRUD functionality. At the same time, it can even generate a database schema, including tables for each of the domain classes.
DataSource Configuration
dataSource {
pooled = true
driverClassName = "org.hsqldb.jdbcDriver" // "com.mysql.jdbc.Driver"
username = "sa“ // root
password = "“ // root
// dialect = "org.hibernate.dialect.MySQL5InnoDBDialect"
}
hibernate {
cache.use_second_level_cache=true
cache.use_query_cache=true
cache.provider_class='com.opensymphony.oscache.hibernate.OSCacheProvider'
}
environments {// environment specific settings
development {
dataSource {
dbCreate = "create-drop" // one of 'create', 'create-drop','update'
url = "jdbc:hsqldb:mem:devDB“ // "jdbc:mysql://localhost:3306/testdb"
}
}
test {
dataSource {
dbCreate = "update"
url = "jdbc:hsqldb:mem:testDb"
}
}
production {
dataSource {
dbCreate = "update"
url = "jdbc:hsqldb:file:prodDb;shutdown=true"
}
}
}
Note: For the mysql configuration uncommented dataSource properties for mysql
mysql> describe race;
+----------------+-------------+----+---+-------+---------------+-------------------
| Field | Type |Null | Key |Default | Extra |
+----------------+-------------+----+---+-------+---------------+------------
|id | bigint(20) | NO |PRI | NULL | auto_increment
|version | bigint(20) | NO | | | |
|distance | float | NO | | | |
|max_runners | int(11) | NO | | | |
|start_date_time| datetime | NO | | | |
|state | varchar(255) | NO | | | |
|cost | float | NO | | | |
|name | varchar(255) | NO | | | |
|city | varchar(255) | NO | | | |
+----------------+-------------+----+---+-------+---------------+------------
mysql> describe registration;
+----------------+-------------+----+---+-------+---------------+------------+------
| Field | Type |Null |Key |Default | Extra |
+----------------+-------------+----+---+-------+---------------+------------+------
|id | bigint(20) | NO |PRI | NULL | auto_increment
|date_of_birth | datetime | NO | | | |
|version | bigint(20) | NO | | | |
|gender | varchar(255) | NO | | | |
|postal_address | varchar(255) | YES | | NULL | |
|email_address | varchar(255) | NO | | | |
|created_at | datetime | NO | | | |
|race_id | bigint(20) | YES |MUL | NULL | |
|name | varchar(255) | NO | | | |
+-----------------+------------+----+---+-------+---------------+------------+------
9 rows in set (0.00 sec)
If database schema already exist , we can map table fields with our domain class
class Race {
//…
static hasMany = [registrations:Registration]
static mapping = {
table ‘race_tbl‘ // map existing table with domain class
columns { // map Columns
id column: 'OID‘
name column: ‘name’
startDateTime column: ‘cr_time’
city column: ‘city’
state column: ‘st’
distance column: ‘distance’
cost column: ‘prize’
}
}
}
Adding Custom constraints ::
class Race {
//...
static constraints = {
name(maxLength:50,blank:false)
//startDateTime(min:new Date())
city(maxLength:30,blank:false)
distance(min:3.1f,max:100f)
cost(min:0f,max:999.99f)
startDateTime(validator: {return (it > new Date())})
//custom validator
}
}
Grails creates a new controller instance for each request, and the
controller only lives long enough to process that request.
you can write your custom code by adding methods in controller and gsp pages to rendering the ouput result
Fun with URLs
http://localhost:8080/racetrack/race/show/2
class RaceController {
//... //View : racetrack/race/show
def show = {
[ race : Race.get( params.id ) ]
}
def save = {
def race = new Race()
race.properties = params
if(race.save()) {
redirect(action:show,id:race.id)
}
else {
render(view:'create',model:[race:race])
}
}
}
Comments