Showing posts with label Grails. Show all posts
Showing posts with label Grails. Show all posts

Sunday, April 17, 2011

Building an IVR Survey App with Grails 1

I have been exercising my Grails skills lately while working on an IVR based survey application. Grails is a pretty incredible platform for an IVR application because of Groovy's builder infrastructure. We can exploit Groovy's MarkupBuilder to create XML, specifically VXML, on the fly with minimal effort. I will post more about my progress of the Grails IVR survey application as things progress. I am considering open sourcing the code on github, but I think I need to prove it out a bit first. In Groovy/Grails we can do things like this:

render (contentType:"text/xml") {
    vxml(version:"2.1") {
        form ("", id:"survey") {
            block {
                audio (src: "/ivr-survey/prompt/fetch/${promptInstance.id}")
                prompt (promptInstance.text)
                "goto" (next: "/nextPrompt")
            }
        }
    }
}

Above we can utilize the render method in a Grails controller to respond with XML/VXML and the promptInstance (an instance of a Prompt class) in order to drive the application dynamically based on the current prompt in the call flow. There is quite a bit of stuff going on around the above snippet, so I will dig deeper into the application in the next post.

Tuesday, November 03, 2009

Grails on JBoss AS 5.1.0 GA

Grails is changing the way Java developers approach Web development. If you are not familiar with Grails, it is a Web application platform for the agile and dynamic language, Groovy, that runs on the Java Virtual Machine. There are plenty of available books on Groovy and Grails and there is a plethora of blog posts and online documentation to help you get started with your first Groovy and Grails project. This article will discuss creating a simple Grails application for JBoss AS 5.1.0 GA and demonstrate how simple Java Web development can be.


I have taken some time to explore developing a simple Grails 1.2-M3 application and deploying it on JBoss AS 5.1.0GA. Grails is all about productivity. In a few short steps, I create a simple Web application, generate a Web archive (.war) file and deploy it on JBoss AS 5.1.0 GA.

After Grails 1.2-M3 is installed and properly setup, I open a command prompt and enter

> grails create-app


and when I am prompted, I enter a name for my application.

> demo


A directory is created with the same name as my application. I then navigate to that directory.

> cd demo


Next, I create two domain classes to represent the solution to my business problem, storing company information in a database.

> grails create-domain-class org.axiomaticit.model.Company
> grails create-domain-class org.axiomaticit.model.Address

The above commands create two .groovy files in the directory grails-app/domain/org/axiomaticit/model/, Company and Address. Here is what the Company.groovy file looks like:

package org.axiomaticit.model

class Company {
    static constraints = {

    }
}

Next I open the Company.groovy and Address.groovy files in a text editor or IDE and add some detail. Here is the Company.groovy file after I add some fields and constraints:

package org.axiomaticit.model

class Company {

    String name
    String website

    static hasOne = [address:Address]

    static constraints = {
        name(blank:false)
        website(blank:false, url:true)
        address(nullable:true)
    }

    String toString() {
        "$name"
    }
}

And here is the Address.groovy file:

package org.axiomaticit.model

class Address {

    Company company
    String street1
    String street2
    String city
    String state
    String postalCode

    static constraints = {
        company(nullable:false)
        street1(blank:false)
        street2(blank:true)
        city(blank:false)
        state(blank:false)
        postalCode(blank:false)
    }

    String toString() {
        "$street1 $city, $state"
    }
}

If you are not familiar with Groovy and the conventions of Grails, this might be a little weird to look at. If you are a Java developer, some of the above code looks a lot like what you already know, right? Let's talk about what I just did. I created two classes to represent company information. First, I created a company class with a few important fields like 'name' and 'website'.

String name
String website

Then I created another class, Address, to represent standard US address data.

String street1
String street2
String city
String state
String postalCode

I also added an Address to the Company class,

static hasOne = [address:Address]

and a Company to the Address class.

Company company

Don't get too wrapped up in all the details if you are new to Grails, but what you should understand is that I am building a domain model and creating properties and relationships between persistent entities. The Grails documentation is quite detailed and the user community is also very helpful if you get stuck with the Grails conventions and semantics of Groovy.

Now that I have my domain model, I want to create the controllers and views for my Web application. Controllers and views? Think MVC (Model, View, Controller). So, I go back to my command prompt and enter each command:

> grails generate-all org.axiomaticit.model.Company

> grails generate-all org.axiomaticit.model.Address

The commands above will create a few things based the domain model objects; they create default controllers and views that will support basic CRUD (Create, Read, Update, Delete) functionality. The controllers will be in grails-app/controllers/org/axiomaticit/model/ and the views will exist in grails-app/views/company and grails-app/views/address respectively for each domain model object Company and Address. Let's go ahead and see what I have created and run the application from the command line.

> grails run-app

Once the application starts up, I browse to http://127.0.0.1:8080/demo and test out the application. It might not be everything I wanted, but I have a great starting point, right? Let's deploy this on JBoss AS 5.1.0 GA. Back to the command line to create a Web archive (.war) file.

> grails war

If everything builds properly, I have just created a file, demo-0.1.war, that I can drop into the JBoss deploy directory. I can start up JBoss and point the browser at http://127.0.0.1/demo-0.1 and test out the application. Wow, that took about 10-20 minutes and now I have a fully-functional Web application. Grails is a great platform for proof-of-concept work but because it is based on proven technologies like Spring and Hibernate, many developers are moving Grails applications right into production. Combine Grails with an enterprise level application server like JBoss AS 5.1.0 and you have productivity built on top of dependability.

This is a copy of what I posted at Jboss.org.

Sunday, October 19, 2008

Editable Flex Datagrid and Grails

I have been really digging into Flex lately and I have been complimenting Flex's incredibly nice UI capabilities with services written on Grails. I am extremely impressed with Flex and Grails really helps me get things up and running very quickly (you already know this if you are using Grails). Let's look at a quick example of where I am using one domain class and a few simple Grails actions in a controller in order to provide search and editing capabilities to a simple Flex application based on a datagrid.

The Grails domain class, Item.groovy:

...
class Item {

    String name
    String brand
    String line
}
...

The Grails controller class ItemController.groovy:

...
class ItemController {

    def search = {
        if(!params.max) {
            params.max = 100
        }
        if(!params.name) {
            params.name = ""
        }

        def itemList = Item.findAllByNameLike("$params.name%",[max:params.max])

        render(contentType:"text/xml") {
            items {
                for(i in itemList) {
                    item {
                        id(i.id)
                        name(i.name)
                        brand(i.brand)
                        line(i.line)
                    }
                }
            }
        }
    }

    def save = {
        if(params.id) {
            def item = Item.get(params.id)

            if(item) {
                item.properties = params
                if(!item.hasErrors() && item.save()) {
                    render ""
                }
                else {
                    render ""
                }
            }
        }
    }
}
...


I also added this to the conf/BootStrap.groovy so I would have some data to work with once I started up the Grails applicaiton. The code below creates 1,000 items during start-up:

...
def init = { servletContext ->

    (1..1000).each {
        new Item(name: "Item $it", brand: "My Brand", line: "My Line").save()
    }
}
...

I mostly worked with only 1,000 items, but I increased this up to 100,000 items to put it through some tests and it worked very nicely.

Now let's dive right into the MXML. Here is the entire itemlist.mxml file:

...
<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

<mx:Script>
<![CDATA[

import mx.controls.Alert;
import mx.events.DataGridEvent;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;

[Bindable]
private var itemId:String;

[Bindable]
private var itemName:String;

[Bindable]
private var itemBrand:String;

[Bindable]
private var itemLine:String;

private function sendItemData(event:DataGridEvent):void
{
var myEditor:TextInput = TextInput(event.currentTarget.itemEditorInstance);
itemName = myEditor.text;

itemId = event.currentTarget.editedItemRenderer.data["id"];
itemBrand = event.currentTarget.editedItemRenderer.data["brand"];
itemLine = event.currentTarget.editedItemRenderer.data["line"];

itemSaveService.send();
}

protected function filterList():void
{
itemSearchService.send();
}

private function fault_Handler(event:FaultEvent):void
{
Alert.show(event.fault.message, "Could not load items.");
}
]]>
</mx:Script>

<mx:HTTPService
id="itemSaveService"
method="POST"
url="http://localhost:8080/itemlist/item/save"
resultFormat="e4x"
fault="fault_Handler(event);"
showBusyCursor="true">
<mx:request xmlns="">
<id>{itemId}</id>
<name>{itemName}</name>
<brand>{itemBrand}</brand>
<line>{itemLine}</line>
</mx:request>
</mx:HTTPService>

<mx:HTTPService
id="itemSearchService"
method="GET"
url="http://localhost:8080/itemlist/item/search"
resultFormat="e4x"
fault="fault_Handler(event);"
showBusyCursor="true">
<mx:request xmlns="">
<name>{searchBox.text}</name>
</mx:request>
</mx:HTTPService>

<mx:Panel title="Item List" height="100%" width="100%" paddingTop="10" paddingLeft="10" paddingRight="10">

<mx:Label text="Search:"/><mx:TextInput id="searchBox" enter="filterList();"/>

<mx:DataGrid id="dg" width="100%" height="50%" rowCount="5"
dataProvider="{itemSearchService.lastResult.item}"
editable="true"
itemEditEnd="sendItemData(event);">
<mx:columns>
<mx:DataGridColumn dataField="id" headerText="Id" editable="false"/>
<mx:DataGridColumn dataField="name" headerText="Name"/>
<mx:DataGridColumn dataField="brand" headerText="Brand" editable="false"/>
<mx:DataGridColumn dataField="line" headerText="Line" editable="false"/>
</mx:columns>
</mx:DataGrid>

</mx:Panel>
</mx:Application>
...

Now that all of the code is out on the table, we can start to dissect what is happening with the Flex UI.

When the application starts up:




Once we type in "Item " and press enter:




When we click on a value under the "Name" column in our datagrid:




We have 2 HTTPService's setup to send requests back to our Grails controller at http://localhost:8080/itemlist/item/save and http://localhost:8080/itemlist/item/search. The first service call will send all the item data to the ItemController's save action and the second one will send our search box's text to the ItemController's search action. We have ActionScript functions that handle the "Enter" key press event on the search box and we also have a function that will be called after the datagrid field has been edited.

Most of the code is pretty self explanatory but if you have any questions, feel free to contact me. Also, Marcel Overdijk has some great posts on Grails and Flex that can really help out when you get stuck.