
Today I became a proud dad of my first child. His name is Sten!
Wednesday, September 12, 2007
Monday, September 3, 2007
Grails 1.0 on the horizon

Last week Grails 0.6 was released and the 1.0 release is coming closer every day now!
The 0.6 release contained the following key features:
- Joint Groovy/Java Compilation
- Spring Web Flow Integration
- Support for Spring scopes to allow scoped services
- Improved support for REST with automatic XML/JSON marshalling and RESTful URL mappings
- New Config DSL for configuration not possible by convention
- Refreshed scaffolding interface and branding
- Support for Sitemesh inline decorators
- Controllers can now call tag libraries as methods
- New GSP tags
- Massive improvements to speed of start-up time, unit tests and generation tools
Besides the great Spring Web Flow integration, and out-of-the-box support for rendering XML and JSON responses (formerly known as the Converters plugin), also the scaffolding views were revamped. Scaffolding now provides a professional and good looking user interface. Take a look below!
Posted by
Marcel Overdijk
at
9:45 AM
0
comments
Wednesday, August 1, 2007
Another Sexy Flex Grails Example

Here is another (quick) Flex example which uses Grails on the back-end. It contains all CRUD operations in just one screen. Just follow the steps below to see it for yourself:
- Create a new grails application:
grails create-app flexongrails - Create a new Book domain class:
grails create-domain-class Book
Open the Book domain class and replace the code with:class Book {
String isbn
String title
String author
Float price
String format
static constraints = {
isbn(maxLength:20, unique:true)
title(maxLength:50)
author(maxLength:50)
price(min:0F, max:999F, scale:2)
format(inList:["Hardcover", "Paperback", "e-Book"])
}
} - Create a new Book controller:
grails create-controller Book
Open the Book controller class and replace the code with:class BookController {
def index = { redirect(action:list, params:params) }
// the delete, save and update actions only accept POST requests
// def allowedMethods = [delete:'POST', save:'POST', update:'POST']
def list = {
response.setHeader("Cache-Control", "no-store")
def bookList = Book.list(params)
render(contentType:"text/xml") {
data {
for(i in bookList) {
book {
id(i.id)
isbn(i.isbn)
title(i.title)
author(i.author)
price(i.price)
format(i.format)
}
}
}
}
}
def save = {
def book
if(params.id) {
book = Book.get(params.id)
}
else {
book = new Book()
}
book.properties = params
book.save()
render ""
}
def delete = {
def book = Book.get(params.id)
if(book) {
book.delete()
}
render ""
}
}
What you can see here is that thelistaction return xml data which will be used by Flex. Important is setting the cache control in the response header. Thesaveaction will be used both creating as editing. - Create a new Flex project (in Flex builder) and replace the code in the main mxml file with:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="listService.send()">
<mx:HTTPService id="listService" url="http://localhost:8080/flexongrails/book/list" useProxy="false" method="GET"/>
<mx:HTTPService id="saveService" url="http://localhost:8080/flexongrails/book/save" useProxy="false" method="POST" result="listService.send()">
<mx:request xmlns="">
<id>{book_id.text}</id>
<isbn>{isbn.text}</isbn>
<title>{title.text}</title>
<author>{author.text}</author>
<price>{price.text}</price>
<format>{format.text}</format>
</mx:request>
</mx:HTTPService>
<mx:HTTPService id="deleteService" url="http://localhost:8080/flexongrails/book/delete" useProxy="false" method="POST" result="listService.send()">
<mx:request xmlns="">
<id>{dg.selectedItem.id}</id>
</mx:request>
</mx:HTTPService>
<mx:NumberFormatter id="priceFormatter" precision="2"/>
<mx:Script>
<![CDATA[
[Bindable]
private var formatArray:Array = ["Hardcover", "Paperback", "e-Book"];
private function clearForm():void {
book_id.text = "";
isbn.text = "";
title.text = "";
author.text = "";
price.text = "";
format.selectedIndex = 0;
}
private function formatPrice(item:Object, column:DataGridColumn):String {
return priceFormatter.format(item.price);
}
]]>
</mx:Script>
<mx:VDividedBox x="0" y="0" height="100%" width="100%" paddingLeft="10" paddingRight="10" paddingTop="10" paddingBottom="10">
<mx:Panel width="100%" height="300" layout="absolute" title="Create/Update Book">
<mx:Form x="10" y="10" width="930" height="200">
<mx:FormItem label="ID">
<mx:TextInput width="120" id="book_id" text="{dg.selectedItem.id}" enabled="false"/>
</mx:FormItem>
<mx:FormItem label="ISBN">
<mx:TextInput width="220" id="isbn" text="{dg.selectedItem.isbn}" maxChars="20"/>
</mx:FormItem>
<mx:FormItem label="Title">
<mx:TextInput width="320" id="title" text="{dg.selectedItem.title}" maxChars="50"/>
</mx:FormItem>
<mx:FormItem label="Author">
<mx:TextInput width="320" id="author" text="{dg.selectedItem.author}" maxChars="50"/>
</mx:FormItem>
<mx:FormItem label="Price">
<mx:TextInput width="120" id="price" text="{priceFormatter.format(dg.selectedItem.price)}"/>
</mx:FormItem>
<mx:FormItem label="Format" width="220">
<mx:ComboBox id="format" selectedIndex="{formatArray.indexOf(dg.selectedItem.format)}">
<mx:dataProvider>{formatArray}</mx:dataProvider>
</mx:ComboBox>
</mx:FormItem>
</mx:Form>
<mx:ControlBar horizontalAlign="right">
<mx:Button label="New" click="clearForm()"/>
<mx:Button label="Save" click="saveService.send(); clearForm()"/>
</mx:ControlBar>
</mx:Panel>
<mx:Panel width="100%" height="444" layout="absolute" title="Book List">
<mx:DataGrid x="0" y="0" width="100%" height="100%" id="dg" dataProvider="{listService.lastResult.data.book}">
<mx:columns>
<mx:DataGridColumn width="120" headerText="ID" dataField="id"/>
<mx:DataGridColumn width="220" headerText="ISBN" dataField="isbn"/>
<mx:DataGridColumn width="320" headerText="Title" dataField="title"/>
<mx:DataGridColumn width="320" headerText="Author" dataField="author"/>
<mx:DataGridColumn width="120" headerText="Price" dataField="price" labelFunction="formatPrice"/>
<mx:DataGridColumn width="220" headerText="Format" dataField="format"/>
</mx:columns>
</mx:DataGrid>
<mx:ControlBar horizontalAlign="right">
<mx:Button label="Delete" click="deleteService.send()" enabled="{dg.selectedItem != null}"/>
</mx:ControlBar>
</mx:Panel>
</mx:VDividedBox>
</mx:Application> - Run the Flex application
You now have a basic CRUD Flex application which uses Grails as back-end. The example is very basic and the Grails Book controller isn't responding back any possible validation errors; they just get absorbed. Also for a couple of row retrieving all the rows at once is no problem, but in real life it will me thousands and thousands of records, so also server side paging and ordering is needed. Well, this could be easily implemented in the Book controller (as it is basic Grails functionality) but most of the work will go in the Flex application I think...
For server-side paging/sorting a custom Flex component would be needed which remembers the current page and just submits the required paging and sorting fields to the serve-side. This is independent to Grails as it could be used by any server-side application. I guess I'm not the first one looking into this so I might find something on the internet.
Friday, July 27, 2007
Java Summer Camp in The Netherlands with Rails and Grails

This years Profict Java Summer Camp will host both Charles Nutter and Graeme Rocher to speak about JRuby and Grails.
This Java Summer Camp is hold on August 24 in The Netherlands. I will be there myself and I'm looking forward to meet other Grails users. Exciting!
If you are interested you can find more information on http://javasummercamp.nl.
Posted by
Marcel Overdijk
at
9:07 AM
0
comments
Thursday, July 26, 2007
Sexy Flexy Grails
With Flex you can create rich internet applications with highly interactive GUI's. It offers various methods for talking with server-side components to retrieve and store data. You can use simple HTTP GET/POST services, WEB services, RPC calls or Flex Data Services.
Using HTTP GET/POST or WEB services gives you the freedom to choose the server-side technology: PHP, Servlets, JSP, Ruby on Rails etc.
Mike Potter already has written a small tutorial about integrating Flex and PHP.
I will use Mike's tutorial to show you how easy it is to integrate Flex and Grails.
Prerequisites: I assume you have basic understanding of Flex and Grails and that you have installed them both already.
Where to start:
- First read Mike's tutorial about integrating Flex and PHP. After reading it you will understand that a simple PHP page is used to retrieve/return User records in XML data and to store new User records. In the next steps we will do the same, but then using Grails.
- It's time to create a new Grails application so from the command line type:
grails create-app sexyflexygrails
- Create the User domain class:
grails create-domain-class User
It's not needed to create the User table like in the PHP tutorial. Grails will automatically create the table when you run the application. - Add the Username and Emailaddress properties to the created domain class:
class User {
String username
String emailaddress
} - reate a new controller to retrieve and store data:
grails create-controller User
- Implement the needed logic in the created UserController:
When the index action is called it will check if the Username and Emailaddress parameters are in request parameters, and if so it will create a new User. In any case, the call to the index action will return all Users in the database as XML. Flex will use this XML to display the Users in a table.class UserController {
def index = {
if (params.username && params.emailaddress) {
def user = new User()
user.properties = params
user.save()
}
def userList = User.list()
render(contentType:"text/xml") {
users {
for(i in userList) {
user {
userid(i.id)
username(i.username)
emailaddress(i.emailaddress)
}
}
}
}
}
} - That's it for the server-side Grails part. Start the Grails application with:
grails run-app
- Open a browser and goto http://localhost:8080/sexyflexygrails/user. You will see no data as there is nothing in the database yet. Try adding a new User with http://localhost:8080/sexyflexygrails/user?username=MyUsername&emailaddress=MyUsername@MyCompany.com. This will create the new User in the database and will render the XML in the browser.
- Now start Flex Builder and create a new Flex project. Chooser Other/None as Server type.
- Open the automatically created main mxml file and copy in the MXML code from Mike's tutorial: http://www.adobe.com/devnet/flex/articles/flex2_php_03.html
- In the MXML code change the HTTPService url to: http://localhost:8080/sexyflexygrails/user
- Now run the Flex application and it will use Grails for retrieving and storing the data from the back-end.
In the next weeks I will have a further look at Flex, and see if I can create a small Flex CRUD application that uses Grails at the server-side. I will post my findings here, so stay tuned.
Sunday, March 25, 2007
Google Personalized Homepage
The Google Gadgets directory contains a lot of useful Gadgets and news feeds. If the RSS or Atom feed is not in the directory (yet), you can also directly add an item to your personlized page by pointing to a RSS or Atom url.
Off course I created a new personlized page containing all the news feeds related to Grails, so I can see the latest activity very easily ;-)
If you want to add them to your own personlized page just click the links below:
Grails Announcements
Grails User List
Grails Dev List
Grails JIRA Activity
Grails Build Status
Posted by
Marcel Overdijk
at
2:06 PM
0
comments
Monday, March 12, 2007
Grails Frappr Map
Recently I've created a Grails Frappr Map to see where the Grails users and committers are located. It's just nice to know where people you talk to on the mailing lists live. And maybe you will find out your neighbor is also using Grails!
Posted by
Marcel Overdijk
at
11:12 AM
0
comments

