Developer: Java
Introduction to Grails Development
Build a simple Grails
app using Oracle JDeveloper as your IDE.
by Harshad Oak 
Published March 2008
Following the Ruby on Rails (RoR) wave, most software
developers have considered, if not tried out, either ROR or some other
framework that promises to deliver ROR features. The Grails
framework also rode the Rails wave to popularity but is now shaping
into a powerful framework in its own right. Grails uses the Groovy
programming language; Groovy syntax is similar to Java’s, but
it also adopts some concepts from other languages. Like Java, Groovy
generates bytecodes and runs on the Java platform, so it has the power
of Java but also adds a few niceties and simplifications.
In this article you will get an introduction to
developing Grails applications using Oracle JDeveloper as your IDE. You
will also get an overview of Groovy concepts as you go about developing
your Grails application.
Setup
Oracle JDeveloper has one of the simplest installation
procedures of all the IDEs. Download the relevant package, extract it
in a directory of your choice, and you are ready to go. If you are on
Windows, run the jdeveloper.exe file; on Linux run the jdev script. If
you are new to Oracle JDeveloper, I would recommend that you download
Oracle JDeveloper Studio Edition, which includes a JDK—it
should enable you to get Oracle JDeveloper going without any issues on
Windows and Linux.
Oracle JDeveloper does not offer Groovy support out of
the box, but a Groovy extension is available for Oracle JDeveloper
10.1.3. To install this extension, go to Help ->
Check for Updates. In the Update Centers
list, select Open Source and Partners Extensions.
Click Next. In the list that appears,
select Groovy and click Finish.
Groovy will be downloaded and installed as an extension for Oracle
JDeveloper.
The Groovy extension adds the Groovy library to the
Libraries list and also adds the option of creating Groovy
scripts in the New Gallery. The Groovy extension isn’t
available on Oracle JDeveloper 11g as of
Technology Preview 3. (Note that installing the Groovy extension is
optional. To use Grails, you do not need the Groovy extension or even
Groovy itself to be installed on your machine.)
Install Grails
As of this writing the current version of Grails is
1.0.1, and Groovy is currently on 1.5.4. The installation is pretty
straightforward. All you need is JDK 1.4 or above and an appropriate
JAVA_HOME environment variable pointing to the JDK installation. Now download
the latest Grails binary release and extract the contents into a folder
of your choice. Note that because Grails includes the Groovy JAR files,
you do not need to download and install Groovy separately.
Next, create a GRAILS_HOME environment variable that
points to the directory. Add %GRAILS_HOME%\bin to the PATH variable.
Watch out for spelling mistakes and spaces in the environment
variables. I seem to regularly make such mistakes and then spend a long
time trying to work out why the thing won’t work. If you
haven’t set the JAVA_HOME correctly on a Windows machine, you
will get a “System cannot find the path specified”
message. The message provides no clue that the problem is with the
JAVA_HOME and not with the .bat file or the other environment variables.
If you are on Windows, you can also opt to use the
easier .exe-based Grails installer. A .deb installer for Debian-based
flavors of Linux is also available (see the link section at the end of
this article).
Now that Grails is set up, let’s begin
developing a Web application, one that will automate the speaker
registration and paper submissions process for a conference.
Oracle JDeveloper First Steps
All development with Oracle JDeveloper begins with the
creation of an application and a project. Create a new application via File
-> New. Name the application Grails. Select No
Template [All Technologies] as the application template.
Provide confmgt as the application
package prefix and Conference as the
project name.
Grails Conventions and Code: Oracle JDeveloper External
Tools
The core idea behind Grails is that if the developer
just complies with certain conventions, the framework will autogenerate
files, directories, and code for the application. It will also manage
and run the application without asking the developer for instructions
about every little thing. If the developer has adhered to the
conventions, Grails already knows what's to be done under what
circumstances.
With regular Java Web development, you have a lot of
flexibility in terms of how you structure the application, where you
keep the files, what the filenames are, and so on. With Grails,
however, you are expected to comply with the conventions, most of which
are configurable. This takes some getting used to, but it sure saves
you a lot of time and effort, because all the tedious and repeatable
tasks are handled by Grails. Having strict conventions is also very
good because once you have understood the workings of one Grails
application, you can quite easily understand any other, which
isn’t always the case for regular Java Web development.
Grails provides various commands for autogeneration of
code. If you type grails help after your command prompt, you will see a
list of the various Grails commands available. We can integrate these
commands into Oracle JDeveloper by using the External Tools feature:
- Select Tools -> External Tools.
- In the dialog box that appears, click the New
button.
- Select External Program
as the tool type.
- Click Next.
You can now create, edit, and run the Grails application without having
to leave the Oracle JDeveloper environment.
As shown below enter
<your-grails-directory-path>/bin/grails.bat as the
program executable on a Windows machine and
<your-grails-directory-path>/bin/grails on a Linux
machine. State help as the argument. The run
directory is not important in this particular case, because the help
command will produce the desired output, irrespective of where you run
it. However, the run directory is important for most other Grails
commands. Next, specify a tool tip and also decide where you want the
tool link to appear in Oracle JDeveloper. You can make the tools appear
in context menus as well as in buttons in the toolbar.
Figure 1 Oracle JDeveloper
external tool for Grails help command
As shown below, you can also choose to save all files or reload all
open files before the tool executes. Click Finish
to create the new tool. You should now see your new tool listed at the
place you chose; by default, it appears in the Tools menu. Click the
tool, and the Grails help command will be executed, producing a list of
the various Grails commands in the log window. You will create more
tools as you go along.
Figure 2 External tool
settings
Oracle JDeveloper does not yet have an import/export
facility for external tools, so sharing your tools with others in your
team isn’t as straightforward as it could be. However, you
can move external tools in Oracle JDeveloper 10.1.3 to other Oracle
JDeveloper installations, by simply copying the relevant XML from the
jdevhome/system/oracle.jdeveloper.10.1.3.40.66/tools.xml file to the
tools.xml file on the new machine. With Oracle JDeveloper 11g,
there’s no tools.xml file; instead, all preferences are in a
unified file, product-preferences.xml. This file can be found at
C:\Users\username\AppData\Roaming\Oracle
JDeveloper\system11.1.1.0.20.46.84\o.jdeveloper on a Windows Vista
machine.
You might be wondering why you should use external tools
and not just fire the commands from the command prompt. The big
advantage of using external tools is that you can get everything done
right from within the Oracle JDeveloper interface. It is also easier
for Grails novices, because the external tools can be configured to
automatically provide different project directories and paths as
arguments to a command. The external tools’ ability to
autosave files and provide tool tips and prompts further simplifies
things. Once you’ve created external tools and shared them
with your team, you can be sure that each one is firing the correct
commands at the correct locations. Last but not least, using external
tools is just so much easier than having to type out commands after the
prompt.
Create the Grails Application
Grails provides a create-app
command that creates a basic Grails application structure. To execute
this command, create a new external tool with the following tool
parameters:
Program executable: ${env:var=GRAILS_HOME}\bin\grails.bat
Arguments: create-app ${promptl:label=Name}
Run directory: ${workspace.dir}
In the arguments field, specify that Oracle JDeveloper
should give you a prompt where you can specify the application name.
Click the Insert button in the tool
creation wizard to explore various other macros provided by Oracle
JDeveloper. These macros can help you provide dynamic values as input
to the various Grails commands. Because you have specified the
workspace directory as the run directory for the tool, all files and
folders the create-app command generates will be
created in this directory.
Execute the create-app command,
using the external tool, and after the prompt, specify the application
name Conference. In the log, you will see
the many directories and files created by Grails.
Oracle JDeveloper will not display the code, however,
because by default, it looks for project source code in the
<project-directory>/src directory. Because you have
created all your code in the workspace directory itself, you need to
add that directory in Project Properties ->
Project Content -> Java Content. Click the Refresh
button, and the Application Navigator will appear, as shown in Figure 3.
Figure 3 Application Navigator
The basic application structure is now in place. Have a
look at the various directories
and files to see how Grails organizes a Web application. Note that the
empty directories created by Grails aren’t listed in the
Application Navigator. You will see that Grails has created directories
such as views, taglibs, services, and controllers, effectively forcing
developers to organize their code based on its functionality. This is a
good thing for team projects, because you can be sure all members of
the team are following the convention and not just doing their own
thing.
Let’s now get down to creating your custom
application, an application that provides for speaker registration,
speaker login, and paper submission.
Speaker and Paper
Grails provides a powerful persistence mechanism in the
form of GORM
(Grails object-relational mapping), which is based on Hibernate
object-relational persistence. So the developer creates the domain
classes and defines the relationships between them. The persistence is
taken care of by GORM.
Domain classes are at the heart of most data-driven Web
applications you would develop with Grails. Domain classes are special,
not only because of the relationships, rules, and logic they hold but
also because of the capabilities Grails injects into them at runtime.
In our application, we will create two domain classes, Speaker and
Paper, and look at their capabilities. In this example, the domain
classes’ design is fairly simple and not normalized into
smaller units, but you can easily normalize it by creating new domain
classes and setting relationships between them like the ones you have
set in the case of Speaker and Paper.
To create domain classes, you need to use the Grails
command create-domain-class. You will create a
new external tool in Oracle JDeveloper, on exactly the same lines as
the tool created earlier. The following are the only things that change:
Program executable: ${env:var=GRAILS_HOME}\bin\grails.bat
Arguments: create-domain-class ${promptl:label=Name}
Run directory: ${project.dir}
Run the create-domain-class tool.
Enter Speaker at the prompt. A new file,
/grails-app/domain/Speaker.groovy, will be created. Next, create the
Paper domain class. A Paper.groovy file will also be created in the
domain directory. Now you need to define the properties for Speaker and
Paper as well as the relationship between the two.
Open Speaker.groovy in Oracle JDeveloper. If you are
running Oracle JDeveloper 10.1.3 and have installed the Groovy plug-in,
you will see icons marking the .groovy files. Edit the Speaker.groovy
file as shown below.
class Speaker {
// Fields String userid String password String fname String lname String address1 String address2 String city String state String country String bio String company String speakingExp String email String phone String mobile //default values String status = "active" Date lastLoginDate = new Date() Date registerDate = new Date()
// Optional - Can be null def optionals = [ "status", "address2", "company","mobile", "speakingExp"] // One speaker has many papers static hasMany = [papers:Paper]
// Constraints used for validations static constraints = { userid(size:5..10,unique:true) password(size:5..10) fname(size:1..30) lname(size:1..30) email(email:true) phone(size:6..15) city(size:1..20) state(size:1..20) country(size:1..20) address1(size:5..200) bio(size:10..1000) } }
In the Speaker class, you define properties for the information you
want the speaker to provide, the fields that can be null, the
constraints for properties that need to be validated, and the
relationship between the Speaker and Paper classes. The words
optionals, hasMany, and constraints are special settings offered by
Grails. In this example, because of the hasMany setting, Grails will
inject a property of type java.util.Set into Speaker.
Next, modify Paper.groovy as shown below.
class Paper {
// Fields String title String description String comments String status = "active" Date lastModifiedDate = new Date() Date createdDate = new Date() Speaker speaker //Every paper belongs to a speaker def belongsTo = Speaker static constraints = { title(size:5..200) description(minSize:10, maxSize:2000) } def optionals = [ "comments", "status"] }
The belongsTo property tells Grails that each paper belongs to a
speaker. So if the speaker is deleted, that speaker’s
paper(s) will also be deleted. You again use constraints and optionals
in the Paper class.
Now that your domain classes are ready, you will use the
rapid code generation capabilities of Grails to generate various code
files that refer to the applicable domain class and generate code for
the controllers, GUI, and the like. You can essentially generate an
entire create/read/update/delete (CRUD) application for each domain
class by just executing a single command. You will create an external
tool for the generate-all command. The parameters
for this external tool are
Program executable: ${env:var=GRAILS_HOME}\bin\grails.bat
Arguments: all ${promptl:label=Name}
Run directory: ${project.dir}
You need to run the generate-all
tool twice, providing one domain class as the argument each time. The
log will show all the files and directories being created by Grails.
You are now ready to try out the Grails application with CRUD
capabilities for Speaker and Paper. Let’s try running this
autogenerated application before you move on to customizing it. You can
do that the former by simply running the run-app
command. Create an external tool for the run-app
command with the following settings:
Program executable: ${env:var=GRAILS_HOME}\bin\grails.bat
Arguments: run-app
Run directory: ${project.dir}
Grails comes with a built-in Jetty server, and when you
execute the run-app command, the server is
started and your application is deployed on it. Although you can run a
Grails application on any Java EE server, running it on the built-in
server is the easiest option during development. Visit
http://localhost:8080/Conference/ in your browser, and you will find a
Web application that can add, edit, and delete speakers and papers.
DataSource
The data source configuration can be found in the
grails-app/conf/DataSource.groovy file. Grails comes with a built-in
HSQL database that can be configured by use of this file. Note that, by
default, the value for the dbCreate property is
“create-drop.” So every time you restart your
server, the old database will be dropped and a new database will be
created. Change the value to “update” if you want
to retain old values.
To use a database other than HSQL, add the JDBC driver
for the database into the lib directory and then add the connection
string and driver class name into the DataSource.groovy configuration
file. For example, to use Oracle Database 10g
Express Edition as your production database, you would add the Oracle
JDBC thin driver to the lib directory and then edit the
DataSource.groovy file as follows:
production { dataSource { dbCreate = "update" url = "jdbc:oracle:thin:@localhost:1521:XE" driverClassName = "oracle.jdbc.OracleDriver" } }
The creators of Grails have provided for a very common application
development requirement: having to switch between development, testing,
and production databases, so you will see multiple datasource
configurations in the DataSource.groovy file. You can change the
database being used to run the application, by passing an argument
(dev, test, prod) to the run-app command. The
default value is “development” or
“dev.”
grails run-app grails dev run-app grails prod run-app grails test run-app
You now have an application that can be used by a conference organizer
to enter speaker and paper data, but the application certainly
isn’t in shape to be published online and be directly used by
speakers. Let’s understand how Grails works and then
customize the application.
Domains, Controllers, and Views
The working of Grails revolves around domains,
controllers, and views. Let’s analyze one flow in Grails to
figure out how Grails works. The page displayed at
http://localhost:8080/Conference has a link to
http://localhost:8080/Conference/speaker/. Clicking this link takes you
to the speaker list page at
http://localhost:8080/Conference/speaker/list. The steps involved in
this case are as follows:
- Because Grails has certain conventions, you do not
need to tell it that when a request of type X comes in, it has to use
the Y controller. So if the request is in the form /speaker/*, Grails
will automatically look for the SpeakerController in the
/grails-app/controllers directory.
- SpeakerController is a class that was autogenerated
when you ran the generate-all command. This class
defines closures
for various actions. The default is the index action, and the closure
for index is
def index = { redirect(action:list,params:params) }
This closure simply redirects the request to the list action, along
with the parameters it received in the request.
- The list action is as follows:
def list = { if(!params.max) params.max = 10 [ speakerList: Speaker.list( params ) ] }
It fetches the list of speakers and returns a map whose key is
speakerList and value is a list of Speaker objects.
- Because we haven’t mentioned what Grails
should do after this return, conventions again come into the picture.
So for an action named “list” in the
SpeakerController controller, Grails automatically goes to the list.gsp
view in the /views/speaker directory and displays this view.
- list.gsp iterates through the speakerList, using the GSP tag
each time.
- You get a page that displays a speaker list.
Now that we know how the application is working, let’s get
down to modifying the controllers and views for your custom speaker
registration and paper submission custom application.
Customize the Layout
Grails uses SiteMesh
for layouts. These layouts are located in the grails-app/views/layouts
directory. In the list.gsp view we looked at earlier, you will notice
the line
<meta name="layout" content="main"></meta>
This tells Grails to use the layout as stated in main.gsp for this
particular view. So if you want to modify the layout of the page, you
need to edit the main.gsp file. Let’s change the logo from
the Grails logo to the OTN logo that has been placed in the
web-app/images/ directory.
<div class="logo"><img src="${createLinkTo(dir:'images',file:'otn_logo_small.gif')}" alt="OTN" /></div>
By modifying the main.gsp file, you can easily add headers and footers,
associate CSS files, and make other changes to all pages that use this
layout. Note that instead of using the main.gsp approach, GSP layout
can also be handled by use of conventions. So if you create a layout
called grails-app/views/layouts/speaker.gsp, it will be applied to all
views to which the SpeakerController delegates. You can also create
layouts for individual actions, so the layout for the logout action in
the LoginController can be defined in
grails-app/views/layouts/login/logout.gsp.
Login View
With the autogenerated application, the
http://localhost:8080/Conference page gets you a list of controllers.
You instead want a page where a speaker can log in/register to the
application. Your first page has a login form for speakers who have
already registered. The page also has a Register link for those who
want to register. For this, let’s create a
grails-app/views/login/index.gsp view. Oracle JDeveloper does not have
a wizard for creation of GSP files, so you need to create the GSP file
by using General -> File from New
Gallery. GSP files are very similar to JSP files and
consist of HTML and GSP tags. So you can get syntax highlighting for
GSP files by associating the extension .gsp with the file type JSP
Source in Tools -> Preferences -> File
Types. Caution: Do not use the Reformat tool on your JSP
file, because your GSP code will get messed up when Oracle JDeveloper
tries to reformat it by using rules meant for JSPs.
Now edit index.gsp as shown in
Grails\Conference\grails-app\views\login\index.gsp (sample code zip).
Note the use of the GSP tags if,
form,
and link.
As with the other gsp files generated by Grails, the layout is managed
by use of Grails support for SiteMesh.
Register Speaker
Before speakers can log in to the application, they
first need to register. For that you have provided a link that points
to the SpeakerController and the create actionfrom the index.gsp we
created in the above section . The create action in SpeakerController
as well as the create.gsp view have already been autogenerated by
Grails. You need to modify these to suit this requirement.
First modify the
Grails\Conference\grails-app\views\speaker\create.gsp file (
sample code
zip) and get rid of all the fields for which you have defined a default
value and do not want the user to enter data. So we get rid of the
fields lastLoginDate, status, optionals, and registerDate and modify
speakingExp to a text area instead of a text field.
In this GSP, we use the tag hasErrors to display any
validation errors that might occur on submission of the form. Also note
the use of expressions such as ${speaker?.bio?.encodeAsHTML()} that get
the value of the bio field in Speaker and encode the contents as HTML.
Also note the ?. operator, which is intended to take care of the most
common exception thrown in Java, the NullPointerException. With the ?.
operator, if the reference before it is a null reference, the
evaluation of the current expression will stop and null will be
returned.
Note that although we have used a basic text box, Grails
provides the richTextEditor tag, which can get you an easy-to-use HTML
editor instead. The tag uses the rich text editor FCKEditor.
LoginController
To perform the actual login functionality on submission
of the username and password form that you created in the index.gsp
page above, you will create a new controller, LoginController. First
create an external tool for the create-controller
command:
Program executable:
${env:var=GRAILS_HOME}\bin\grails.bat
Arguments: create-controller ${promptl:label=Controller Name}
Run directory: ${project.dir}
Now run the create-controller tool and provide
the controller name as login. Two files,
/grails-app/controllers/LoginController.groovy and
/grails-tests/LoginControllerTests.groovy, will be created. The
LoginController generated has no functionality. Modify it as shown
below.
class LoginController { def index = { if (session?.speaker) { redirect(controller:"paper",action:"index") } } def login = { if (params.userid && params.password) { def speaker = Speaker.findByUseridAndStatus(params.userid, "active") String password = params.password if (speaker != null && speaker.password == password) { session.speaker = speaker speaker.lastLoginDate = new Date() speaker.save() flash.message = "Welcome ${speaker.fname} ${speaker.lname}" redirect(controller:"paper",action:"index") } else { flash.message = "Invalid Login." redirect(action:"index") } } else { flash.message = "Invalid Login." redirect(action:"index") } } def logout = { session.speaker = null flash.message = "You have been logged out" redirect(controller:"login",action:"index") } }
In this controller, you have defined three actions:
- The index action redirects to the index.gsp file.
- The login action checks whether the userid and
password entered are valid.
- The logout action invalidates the speaker object you
have stored in the session during login and takes the user back to the
index page.
In the login action, you make use of Grails dynamic methods and call a findBy
method, findByUseridAndStatus. The reason you can call this method
although there’s no such method present in the Speaker domain
class is that Grails uses Groovy features to provide dynamic methods
and properties that are accessible from your classes without your
defining them or inheriting them from a base class. The dynamic
features available vary, based on whether you’re calling from
a controller, a tag library, or a domain class. The findBy method uses
the properties of the domain class to enable the creation of Grails
query method expressions and returns the first result of the query.
Update Paper
Finally, much as with the Speaker create.gsp file you
saw earlier, you also have to modify other GSP files to get rid of the
fields you do not want the user to view or edit. So remove the status,
lastModifiedDate, and createdDate fields from the GSP files and in the
update action of the PaperController, add the line
paper.lastModifiedDate = new Date(); to store the updated date every
time a change is made. In the save action, add the line paper.speaker =
session?.speaker to associate the paper being created with the speaker
currently logged in.
User Authentication
Because we do not want users to be able to access data
without logging in and by just entering the correct URL and params, you
need to provide for some authentication in controller actions. This can
be easily achieved with interceptors in Grails. Add an interceptor to
the PaperController, using the following code:
def beforeInterceptor = [action:this.&checkUser] def checkUser() { if(!session.speaker) { flash.message = "Please login" redirect(controller:'login', action:'index') return false; } }
The before interceptor used here intercepts processing before the
action is executed and calls the checkUser method. If the speaker
object you set into the session immediately on login in the
LoginController isn’t present, an action of the
PaperController is being accessed without proper login, so the method
returns “false” and the following action is not
executed.
UrlMappings
You want the flow of the app to begin with the login
screen, which can be accessed at
http://localhost:8080/Conference/login/index.gsp. If, instead of using
this URL, you want to map a more simplistic
http://localhost:8080/Conference/ to the login page, edit the
UrlMappings file in the conf directory:
class UrlMappings { static mappings = { "/"(controller:"login") "/$controller/$action?/$id?" { constraints { // apply constraints here } } } }
Here you add the line "/"(controller:"login"), which maps the slash (/)
to the login controller. The login controller goes to the index action
by default, and you get the login page you need.
Final Touches
The views and controllers generated for Speaker and
Paper provide CRUD capabilities for both domain classes. However, in a
real-world scenario, you would not want any new speaker to see a list
of all other speakers or delete speakers, or users to be able to see
the primary keys or edit the status constants or the created or
modified date, and so on. So you need to open view files and make sure
what is being included meets your expectations and the needs of the
application.
Packaging and Deploying
Grails comes with a useful war
command that can package our Grails application into a standard WAR
file that can be deployed on any Java EE application server. The war
external tool will take the following settings:
Program executable:
${env:var=GRAILS_HOME}\bin\grails.bat Arguments:
war Run directory: ${project.dir}
Conclusion
By making a handful of changes to the code autogenerated
by Grails, you now have an application that can register new speakers
and accept their papers. You can see how Grails domain classes possess
immense power to fetch and store data easily; how actions in the
controller classes can be modified to give custom views based on some
additional flow logic; and, finally, how GSP views are more than
capable of generating rich user interfaces with minimal hassles. Grails
is currently in version 1.0.1, and the stability and power of Grails
portend growing adoption of the framework. Although Oracle JDeveloper
does not yet come with special features for Groovy and Grails, Oracle
JDeveloper’s external tools capability enables us to quite
easily set up Oracle JDeveloper for Grails development.
Harshad Oak
(harshad@rightrix.com) is the
founder of Rightrix Solutions and an Oracle ACE Director for Oracle
Fusion Middleware. He's the author of Oracle JDeveloper 10g:
Empowering J2EE Development (Apress, 2004) and Pro Jakarta Commons
(Apress, 2004), and coauthor of Java
2 Enterprise Edition 1.4 Bible (Wiley & Sons,
2003).
|