SQL Zone is brought to you in partnership with:

Harshad has posted 1 posts at DZone. You can read more from them at their website. View Full User Profile

Build a Simple Grails App Using Oracle JDeveloper

04.08.2008
| 14280 views |
  • submit to reddit
New to Grails? Want to know what it's all about? Oracle JDeveloper provides ample indirect support to help you learn and use Grails, as this article shows. Below follows a reprint of a recent article on Grails and JDeveloper, written by Harshad Oak. Harshad (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). -- Geertjan Wielenga, JavaLobby Zone Leader

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:

  1. Select Tools -> External Tools.
  2. In the dialog box that appears, click the New button.
  3. Select External Program as the tool type.
  4. 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:

  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. list.gsp iterates through the speakerList, using the GSP tag each time.
  6. 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.

Copyright © 2008, Oracle. All rights reserved. Originally published by Oracle Technology Network.
Published at DZone with permission of its author, Harshad Oak.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)