Sunday, April 13, 2008

User Interface

I hope you enjoyed the screenshots I posted last time. If you could not tell I used Ext JS as my presentation layer. I think Ext JS is the bomb and should be the framework for any web-based applications that require a sophisticated user experience (UX). While I continue to refine the database structure for Siteproducer I thought I would allow you to test out the user experience.

So go ahead and point your browser to http://scottwalter.com/siteproducer-ux/dashboard.html to test out the user experience for Siteproducer.

While your testing the user experience I want to let you know that no server-side code was harmed during the construction of the user experience. As you click through the pages and user interface elements everything you see is the product of html and javascript, nothing more.

One of the reasons why I like Ext JS is that I can quickly show a sophisticated user experience to my customers with very little effort.

cheers for now.

Tuesday, March 25, 2008

Screenshots

In my spare time I have been busy mocking up the user interface with Ext JS. One nice thing about Ext JS is that I can mock up the entire user experience (UX) without having to write any back-end code. This allows me to quickly prototype and change the user experience at will.










Tuesday, March 18, 2008

Using JSON Builder with collections

I was having a particular time, doing what I thought would be an easy task. I wanted to use the JSON Builder that would create JSON syntax that I use with the Ext JS framework. I needed JSON to look like this:

{
success:true,
count:1,
data: [
{id:1,task:'Home Page is waiting to be promoted'}
]
}


However no matter what I tried I couldn't get the "data" array to be generated properly. The data elements within the array were being created outside the array. After enough persistence I was finally able to get it to work with this:

def tasks = .... // an array of tasks

render(builder:'json') {
success(true)
count(tasks.size())
data {
tasks.each {
data(
id: it.id,
task: it.task
)
}
}
}



Notice I had to duplicate "data" twice, once outside of the each loop and once inside. I really don't understand why, I'm just glad I figured it out and I can move on! Hopefully this will help if you are stuck with creating arrays with the JSON Builder.

Sunday, March 16, 2008

State of Siteproducer

Hopefully my posts lately have been helping you out with your understanding of Grails and to some degree Groovy. I want to take this post to talk about my Grails application "Siteproducer". I am using Siteproducer as a learning experience with Grails while at the same time trying to drive adoption of Grails inside my organization. Most likely any posts that I have on this blog are related (even they may not sound like it) to the construction of Siteproducer. As an earlier adopter of Grails I am going through the excitement of learning a new technology. Hopefully this blog will help you with your Grails project.

Goals of Siteproducer:
  1. Create a content management system that I will actually want to use for both personal and professional sites.
  2. Have a professional, usable user experience (UX)
  3. Simplicity is key - creating a page should not require a developer
So what is the current state of Siteproducer? Right now I am working on the domain model. The domain model is critical of any apllication so I'm taking my time with the domain model because I need to get it right! To make sure my domain model is going to work as I expected I'm creating integration tests for each domain object.

After the domain model has been completed I am going to mockup the user experience. I will post screenshots when I get the mockups completed.

cheers.

Using DBUnit with Grails

I usually use DBUnit when writing integration tests that interact with the database. DBUnit allows me to setup an integration test to get the database into a particular state that your test may be expecting. For example if you have an integration test to insert data into a comments table, you may want to pre-load the database with a blog posting. Your integration test case is to test the insertion of comments and not blog posts. You probably already have another test case for insertion of blog posts.

DBUnit comes from the Java world, but since "Groovy is Java" you can effortlessly integrate DBUnit into your Groovy and/or Grails project. For a Grails project simply place the dbunit jar file into the "lib" directory.

When I wrote my first integration test with DBUnit my setup method looked something like this:

def sqlConnection = Sql.newInstance(
'jdbc:mysql://localhost:3306/test3',
'sp', 'sp',
'com.mysql.jdbc.Driver')


However I noticed that my test wasn't very DRY (Don't Repeat Yourself). I have already specified the connection info for my test database inside DataSource.groovy. So now I had to specify my database connection info twice, once inside DataSource.groovy and once inside my test. What would happen if someone downloaded my source code and changed only DataSource.groovy for their enviornment? Well the tests would fail miserably. Also as the number of integrations tests would grow, so would be the number of times I violated the DRY principle.

So how did I overcome these challenges? First of all I created a class called MyIntegrationTestCase that all my integration tests will extend, instead of GroovyTestCase. Actually MyIntegrationTestCase just extends GroovyTestCase. Next instead of hard coding connection info inside MyIntegrationTestCase I read the connection info from DataSouce.groovy.

Here is my class MyIntegrationTestCase:

class MyIntegrationTestCase extends GroovyTestCase {
def dataSourceConfig

def getDBUnitConnection() {
def sqlConnection = Sql.newInstance(dataSourceConfig.url,
dataSourceConfig.username,
dataSourceConfig.password,
dataSourceConfig.driverClassName)
return new DatabaseConnection(sqlConnection.connection)
}

void setUp() {
dataSourceConfig =
ApplicationHolder.application.config.dataSource
}

}


I hope this helps you integrate DBUnit in your Grails applications.

Saturday, March 15, 2008

My favorite Grails Plugins

One of the most powerful features of Grails is their plugin system. Using a simple command "grails install-plugin" you can increase the functionality of your application. Sweetness! The core Grails developers didn't think lightly on plugins, they have a great API to use when you want to write your own plugin.

Here are some of the plugins that I will be using on Siteproducer:

1. Acegi - The Acegi security system is a very comprehensive security system, but sometimes it requires too much configuration.   Following the Grails paradigm "convention over configuration" the Acgei plugin will setup Acegi with very little effort on your part.   The plugin gives you:  login controller, logout controller, registration controller, and crud pages to manage protected resources.  You will be up and running with a secure Grails application in about 5 minutes.

2.  Acts As Taggable - Tagging is all the rage these days and the acts as taggable brings tagging to your domain objects.   The plugin is super simple to use, just add "implements Taggable" to your domain objects and that's it.   Acts As Taggable exposes methods to add tags, delete tags, and list tags on your domain object.

3.  Quartz - Quartz the practically standard mechanism for performing scheduled tasks has made its way to a Grails plugin (it use to be part of Grails core).  Once you have the plugin installed you can easily do scheduled tasks like this:


class FirstJob {
def cronExpression = "0 0 0 ? * *" //midnight, every day

def execute() {
log.info("firstjob executed")
}
}


4.  Searchable - The searchable plugin is a huge time saver!  Searchable adds full-text searching of your domain objects via Lucene and Compass.   One nice thing about the plugin is that you don't have to know a lick about Lucene or Compass and still get all the benefits.   The plugin also supports relationships between your domain objects.  To get your started there is even a bundled search controller so you can verify that when you save your domain objects they are being properly indexed.

5.  WebTest - Unit and Integration testing is great.  But how about testing from end-to-end from the end-users perspective?   WebTest is a great functional testing tool and the Grails plugin for WebTest makes it super simple to create and execute your functional tests.

There are alot more plugins available for your Grails applications.   Feel free to take a look at them at grails.org/plugins.

Wednesday, March 12, 2008

Scripting Deployments

Grails has a whole bunch of commands that you can execute in the form of "grails ". Where you aware those commands that you run are power by Ant? More specifically Gant. You may ask yourself "Gant what is that?" In a nutshell (or any other kind of shell that you like) Gant is Groovy-based build system that uses Ant tasks. So you have all the power of the Ant tasks that you are use to using, but now you can say "Look mom no xml!"

I think ant is a good (but not perfect) build and automation tool. However sometimes its hard to follow the xml logic. Gant brings the power of the Ant tasks with the flexibility of Groovy. Gant has its own website at http://gant.codehaus.org/. If you want to see some Gant scripts look no further than where you have Grails installed (not your grails app, but the grails home). Then have a peek in the "scripts" subdirectory. When you type "grails " Grails will look in two locations: first grails_home/scripts and then the scripts directory inside your Grails application.

I think its pretty cool that you can extend the Grails command line system by just creating a Gant script inside the scripts directory of your application. Here is a simple Gant script that says "hello" that is placed in a file called SayHello.groovy inside the scripts directory of my Grails application:


target(default:"a simple gant script") {
echo( message : "hello world" )
}


To run the script I simple type "grails say-hello". You may have noticed if your Gant script is camel-cased that when you run the script the command name is all lower case and you separate the camel-cased words with the hyphen "-". If you have existing ant scripts you can easily convert them to Gant scripts in a matter of minutes.

Like I mentioned before you can use any Ant task inside a Gant script. However let me rephrase that, "you can use Any core Ant tasks". If you want to use the optional Ant tasks there is a little more work involved. You will need to get the jar file (from the Ant distribution) containing the optional Ant task and place it in either the grails_home/lib directory or the lib directory under your Grails project. You will also need to do the same for any jar files the optional ant task requires. For example the "scp" Ant tasks requries jsc.jar.

I created a Gant script called "DeployApp.groovy", so I can run it as "grails deploy-app". Below is the code for the script that calls the standard Grails task "war" to build the war file of my Grails application and then copies it to a server:


Ant.property(environment:"env")
grailsHome = Ant.antProject.properties."env.GRAILS_HOME"
baseDir = Ant.project.properties.basedir
Ant.property ( file : 'application.properties' )

includeTargets << new File ( "${grailsHome}/scripts/War.groovy" )

args = "scott.war"

target(default: "a simple gant script") {


Ant.property ( file : 'application.properties' )
Ant.property ( file : 'environment.properties' )

def appName = Ant.project.properties.'app.name'
def appVersion = Ant.project.properties.'app.version'

def host = Ant.project.properties.'deployhost'
def port = Ant.project.properties.'deployport'
def username = Ant.project.properties.'deployusername'
def password = Ant.project.properties.'deploypassword'


echo ( message : "starting deployment" )
war()

scp(file:args, todir:"${username}@${host}", password:password,port:port)


Have fun customizing your Grails environment with custom Gant scripts :-)