|
Page 2 of 4
Developing a Grails Application: Application Structure
For years I have been planning to develop an application that
will help me manage my clothes—an application that will tell
me where my favorite t-shirt is placed, if it is washed, if it is
ironed, and so on. One day I intend to make millions selling this
application, but for the time being I'll use it for my Grails example.
The first step is creating a Grails project directory
structure. For that I will create a new directory at C:\groovy\grailsapps
and open a command prompt window at that level. Here, execute the
command grails create-app. You will be asked
to enter an application name. Enter ClothesMgt.
Grails will display all the directories and files it has created for
you. Figure 1 shows the resulting directory structure.
Figure 1: Grails project directory structure
The command will result in the creation of about 800 KB of
files and directories. The idea here is that the framework is going
with established Web application development conventions, so it creates
files and directories that would be useful in a majority of Web
applications. Although some may not like this idea of being forced into
a certain structure, this auto-generation based on conventions is where
the RAD features of Grails come from.
If you take a closer look at these directories, you will see
that there are directories for things like controllers, views, tests,
configuration files, and tag libraries. You will also find some basic
JavaScript and CSS files in place. So the basic structure of you app is
now in place. You just fill in the blanks and the application will be
ready.
Note that the commands that autogenerate directories and files
are optional. You can do all the file and directory creation manually.
If you are familiar with Apache Ant, you can even open up the file \src\grails\build.xml
in the GRAILS_HOME directory and look at
exactly what each Grails command is trying to achieve.
Database
For this example I will use a MySQL database named Clothes_Grails
running on localhost. An HSQL database comes
built-in with Grails and can be useful for testing simple applications
or just trying out Grails. If you use the HSQL DB, you will not have to
execute the next few steps. I am using MySQL to demonstrate how easily
you can use any database other than HSQL.
Download the MySQL driver from http://www.mysql.com/products/connector/j/
and place the mysql-connector-java-<version
number>-stable-bin.jar file in the ClothesMgt\lib
directory. Next you need to edit the file ClothesMgt\grails-app\conf\ApplicationDataSource.groovy.
The contents of the file will now be similar to the following:
class ApplicationDataSource {
boolean pooling = true
String dbCreate = "create-drop"
String url = "jdbc:mysql://localhost/Clothes_Grails"
String driverClassName = "com.mysql.jdbc.Driver"
String username = "grails"
String password = "groovy"
}
Now let's take a look at how you can make use of this database
and object relational mapping.
Domain Classes
Grails' Object Relational Mapping (GORM) capability uses
Hibernate 3 internally, but you do not need to be aware of, or change,
any Hibernate settings. Grails has something called "domain classes,"
whose objects are mapped to the database. You can link domain classes
using relationships, and they also provide very powerful dynamic
methods for CRUD (Create/Read/Update/Delete) operations.
For this example let's create three domain classes named
Shirt, Trouser, and Cabinet. To create a domain class, just run the
command grails create-domain-class. Remember
to run this command within your project directory and not in the
directory above it. This is a common mistake that, although I have
cautioned you, you will commit at least once.
The only input you must provide to the create-domain-class
command is the class name. Run the command three times, giving Shirt,
Trouser, and Cabinet as the names of the three domain classes. Grails
will now create the domain classes in the directory grails-app/domain/.
These will have just two properties id and version.
I will add properties to the classes to make them more representative
of a shirt, trouser, and a cabinet.
Listing 1: Cabinet.groovy
class Cabinet {
Long id
Long version
String name
String location
def relatesToMany = [ shirts : Shirt, trousers : Trouser ]
Set shirts = new HashSet()
Set trousers = new HashSet()
String toString() { "${this.class.name} : $id" }
boolean equals(other) {
if(other?.is(this))return true
if(!(other instanceof Cabinet)) return false
if(!id || !other?.id || id!=other?.id) return false
return true
}
int hashCode() {
int hashCode = 0
hashCode = 29 * (hashCode + ( !id ? 0 : id ^ (id >>> 32)) )
}
}
Listing 2: Trouser.groovy
class Trouser {
Long id
Long version
String name
String color
Cabinet cabinet
def belongsTo = Cabinet
String toString() { "${this.class.name} : $id" }
boolean equals(other) {
if(other?.is(this))return true
if(!(other instanceof Trouser)) return false
if(!id || !other?.id || id!=other?.id) return false
return true
}
int hashCode() {
int hashCode = 0
hashCode = 29 * (hashCode + ( !id ? 0 : id ^ (id >>> 32) ) )
}
}
Listing 3: Shirt.groovy
class Shirt {
Long id
Long version
String name
String color
Cabinet cabinet
def belongsTo = Cabinet
String toString() { "${this.class.name} : $id" }
boolean equals(other) {
if(other?.is(this))return true
if(!(other instanceof Shirt)) return false
if(!id || !other?.id || id!=other?.id) return false
return true
}
int hashCode() {
int hashCode = 0
hashCode = 29 * (hashCode + ( !id ? 0 : id ^ (id >>> 32)))
}
}
The only lines I have added are the ones where I declare the
field names and color and then when I declare the relationship between
Cabinet and Shirt and Trouser. Every Shirt and Trouser belongs to the
Cabinet, and the Cabinet has a set of shirts and trousers. The belongsTo
property is optional in this case, because in a one-many relationship,
Grails always considers the one side as the owner. So you do not need
to explicitly state so. Here I have done that just to make the relation
obvious.
Next let's look at the controller and view part of a Grails
application.
|