Showing posts with label Groovy. Show all posts
Showing posts with label Groovy. Show all posts

Tuesday, October 13, 2009

Even more useful: ConfigObjectFactoryBean for Spring



Last week I blogged about a ConfigSlurperPlaceholderConfigurer for Spring. I've now come up with something more useful: a ConfigObjectFactoryBean for Spring!

It just creates a Groovy ConfigObject from the specified arguments (config file locations, environment and default environment).

It's more useful because you can use it to populate Spring's standard PropertyPlaceholderConfigurer and even expose the config properties map as a servlet context attribute using the ServletContextAttributeExporter. To populate the PropertyPlaceholderConfigurer and ServletContextAttributeExporter classes with appropriate beans derived from the ConfigObject (resp, java.util.Properties and java.util.Map), the factory-bean and factory-method attributes of the bean definition are used.

Source code of ConfigObjectFactoryBean can be found below. It includes extensive javadoc with example how to configure it in combination with the PropertyPlaceholderConfigurer and ServletContextAttributeExporter.


import groovy.util.ConfigObject;
import groovy.util.ConfigSlurper;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;

/**
* {@link org.springframework.beans.factory.FactoryBean} that exposes a
* {@link groovy.util.ConfigObject} object loaded using a Groovy
* {@link groovy.util.ConfigSlurper}.
*
* Supports the concept of per environment configuration via "environment"
* and "defaultEnvironment" properties. The "environment" property will be
* typically set using a system property.
*
* Can be used in combination with a
* {@link org.springframework.beans.factory.config.PropertyPlaceholderConfigurer}
* as demonstrated in the example below.
*
* Example XML context definition:
*
* <bean id="configObject" class="com.footdex.beans.factory.config.ConfigObjectFactoryBean">
* <property name="targetClass" value="javax.persistence.Persistence" />
* <property name="targetClass" value="javax.persistence.Persistence" />
* <bean>
*
* <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
* <property name="properties">
* <bean factory-bean="configObject" factory-method="toProperties" />
* </property>
* </bean>
*
* <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
* <property name="driverClassName"><value>${dataSource.driverClassName}</value></property>
* <property name="url"><value>${dataSource.url}</value></property>
* <property name="username"><value>${dataSource.username}</value></property>
* <property name="password"><value>${dataSource.password}</value></property>
* </bean>
*
* Example config.groovy:
*
* dataSource {
* driverClassName = "org.hsqldb.jdbcDriver"
* username = "sa"
* password = ""
* }
* environments {
* development {
* dataSource {
* url = "jdbc:hsqldb:mem:devDB"
* }
* }
* test {
* dataSource {
* url = "jdbc:hsqldb:mem:testDb"
* }
* }
* production {
* dataSource {
* url = "jdbc:hsqldb:file:prodDb;shutdown=true"
* password = "secret"
* }
* }
* }
*
* {@link groovy.util.ConfigObject} properties can be exposed as servlet
* context attribute easily:
*
* <bean class="org.springframework.web.context.support.ServletContextAttributeExporter">
* <property name="attributes">
* <map>
* <entry key="configProperty">
* <bean factory-bean="configObject" factory-method="flatten" />
* </entry>
* </map>
* </property>
* </bean>
*
* And than can be accessed in jsp's like ${configProperty["sample.foo"]}.
*
* @author Marcel Overdijk
* @see #setEnvironment
* @see #setDefaultEnvironment
* @see #setLocations
* @see groovy.util.ConfigObject
* @see groovy.util.ConfigSlurper
*/
public class ConfigObjectFactoryBean implements FactoryBean, InitializingBean {

private String environment;
private String defaultEnvironment;
private Resource[] locations;
private ConfigObject config;

private String getEnvironment() {
if (this.environment == null || this.environment.trim().length() == 0) {
return this.defaultEnvironment;
}
else {
return this.environment;
}
}

public void setEnvironment(String environment) {
this.environment = environment;
}

public void setDefaultEnvironment(String defaultEnvironment) {
this.defaultEnvironment = defaultEnvironment;
}

public void setLocation(Resource location) {
this.locations = new Resource[] { location };
}

public void setLocations(Resource[] locations) {
this.locations = locations;
}

@PostConstruct
public void yeah() {
System.out.println("yeah!");
}

@Override
public void afterPropertiesSet() throws Exception {
config = new ConfigObject();
ConfigSlurper configSlurper = new ConfigSlurper(getEnvironment());
for (Resource location : locations) {
config.merge(configSlurper.parse(location.getURL()));
}
}

@Override
public Object getObject() throws Exception {
return this.config;
}

@Override
public Class getObjectType() {
return ConfigObject.class;
}

@Override
public boolean isSingleton() {
return true;
}
}

Wednesday, October 7, 2009

ConfigSlurperPlaceholderConfigurer for Spring



Lately I'm working on Spring 3.0 hobby project in my spare time. Frequent readers of my blog or followers me on Twitter might think: Why plain Spring and not just Grails? So let me explain that first:


  1. I love Grails (and Groovy), and if I could make the decision I would use it on every project! But...

  2. I want to host my hobby project cheap, and even Amazon EC2/AWS is to expensive currently. So I decided to host my application on Google App Engine. And to be honest, Grails support for GAE is just alpha/beta state in my opinion (I hope it will change one day). So Grails was not an option.

  3. I've been coding Groovy and Grails for a while now and also doing commercial projects. But I have the feeling my basic Java and Spring knowledge might become a little bit rusty. And to face the facts, there is a change that one of my next clients will not use Groovy/Grails, but just Java and one of the 1,000,000 Java frameworks outhere. So with my hobby project I will be up to date with the latest Java and Spring 3.0 expertise!



But let's get back to the title of this post: ConfigSlurperPlaceholderConfigurer for Spring. In my hobby project I needed the concept of per environment configuration. Yes, in Grails you have it out-of-the-box but in Spring not.

I searched the web and found some interesting thoughts:


What I like about Grails' concept of per environment configuration is that you can define global config properties and just override them in a specific environment if needed. So if 90% of my properties are the same for each environment I don't need to specify them for all environment but just once.

This concept was not supported by the RuntimeEnvironmentPropertiesConfigurer, and also not by the GroovyPlaceholderConfigurer. I know the GroovyPlaceholderConfigurer uses a Groovy ConfigSlurper and this does support per environment configuration (Grails uses it!). So I decided to create a proper ConfigSlurperPlaceholderConfigurer which also supports different environments using a system property. At the end this is how my Spring config now looks:

Example XML context definition:

<bean class="org.springframework.beans.factory.config.ConfigSlurperPlaceholderConfigurer">
<property name="environment" value="#{systemProperties['runtime.environment']}" />
<property name="defaultEnvironment" value="production" />
<property name="location" value="/WEB-INF/config.groovy" />
</bean>

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName"><value>${dataSource.driverClassName}</value></property>
<property name="url"><value>${dataSource.url}</value></property>
<property name="username"><value>${dataSource.username}</value></property>
<property name="password"><value>${dataSource.password}</value></property>
</bean>


Example config.groovy:

dataSource {
driverClassName = "org.hsqldb.jdbcDriver"
username = "sa"
password = ""
}
environments {
development {
dataSource {
url = "jdbc:hsqldb:mem:devDB"
}
}
test {
dataSource {
url = "jdbc:hsqldb:mem:testDb"
}
}
production {
dataSource {
url = "jdbc:hsqldb:file:prodDb;shutdown=true"
password = "secret"
}
}
}


I created a new issue in Spring JIRA to add this to core. If you are interested you can vote for the issue. It also contains the source code if you want to use it in your own project.

Monday, August 10, 2009

Will Rod Johnson be the next Marc Fleury?



Yesterday VMware announced it is going to acquire SpringSource for around $420 million. They expect the deal to be closed in Q3 2009. This means not only acquiring the Spring framework, but also Groovy, Grails, SpringSource tc Server (Apache Tomcat), SpringSource dm Server, Roo, etc.

As a Java developer I'm making use of a lot of SpringSource products (Spring framework, Groovy, Grails) so I'm wondering what this will mean for us. The VMware blog stated that the Spring framework (and I assume the same counts for the other products) will stay open and that Rod Johnson will continue to lead SpringSource. Let's hope Rod will not go on a "Paternity Leave" like Marc Fleury did ;-)

I think a lot of attention will go to cloud computing. Both the VMware blog and SpringSource Team Blog speak a lot about it. To quote Rod Johnson: "Working together with VMware we plan on creating a single, integrated, build-run-manage solution for the data center, private clouds, and public clouds". Also Graeme Rocher (Head of Grails Development - SpringSource) tweeted that we can expect exciting developments around Grails + Cloud coming in the not too distant future.



The VMware SpringSource acquisition also means my latest prophecy that Oracle will buy SpringSource someday needs a slight change... I think Oracle will buy VMware someday.

Thursday, March 12, 2009

Grails Tip of the Day: Always use packages



First of all I must say I'm lazy and I don't like overhead... That's also the reason why I don't use packages for Grails domain classes. Most Grails applications I've build so far consist of no more then 20 domain classes, so I had never the need to separate them in packages. In fact I like to have them in the top folder; no overhead of subfolders.

As Grails 1.1 was released I decided to restart Grails on Sakila. I recreated the domain classes including a "Category" domain class. I generated the default Controller and Views without problems and started the application. When browsing to the list page of the Category domain class I got (GRAILS-4233):


Welcome to Grails 1.1 - http://grails.org/
Licensed under Apache Standard License 2.0
Grails home is set to: D:\Grails\grails-1.1

Base Directory: D:\Grails\projects\grails-on-sakila
Running script D:\Grails\grails-1.1\scripts\RunApp.groovy
Environment set to development
[groovyc] Compiling 2 source files to D:\Users\moverdijk\.grails\1.1\projects\grails-on-sakila\classes
[groovyc] org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed, D:\Grails\projects\grails-on-sakila\grails-app\controllers\CategoryController.groovy: 40: You cannot create an instance from the abstract interface 'groovy.lang.Category'.
[groovyc] @ line 40, column 32.
[groovyc] def categoryInstance = new Category()
[groovyc] ^
[groovyc] D:\Grails\projects\grails-on-sakila\grails-app\controllers\CategoryController.groovy: 46: You cannot create an instance from the abstract interface 'groovy.lang.Category'.
[groovyc] @ line 46, column 32.
[groovyc] def categoryInstance = new Category(params)
[groovyc] ^
[groovyc] D:\Grails\projects\grails-on-sakila\grails-app\controllers\CategoryController.groovy: 40: You cannot create an instance from the abstract interface 'groovy.lang.Category'.
[groovyc] @ line 40, column 32.
[groovyc] def categoryInstance = new Category()
[groovyc] ^
[groovyc] D:\Grails\projects\grails-on-sakila\grails-app\controllers\CategoryController.groovy: 46: You cannot create an instance from the abstract interface 'groovy.lang.Category'.
[groovyc] @ line 46, column 32.
[groovyc] def categoryInstance = new Category(params)
[groovyc] ^
[groovyc] D:\Grails\projects\grails-on-sakila\grails-app\controllers\CategoryController.groovy: 40: You cannot create an instance from the abstract interface 'groovy.lang.Category'.
[groovyc] @ line 40, column 32.
[groovyc] def categoryInstance = new Category()
[groovyc] ^
[groovyc] D:\Grails\projects\grails-on-sakila\grails-app\controllers\CategoryController.groovy: 46: You cannot create an instance from the abstract interface 'groovy.lang.Category'.
[groovyc] @ line 46, column 32.
[groovyc] def categoryInstance = new Category(params)
[groovyc] ^
[groovyc]
[groovyc] 6 errors
Compilation error: Compilation Failed


First thing I thought I made some mistake but this wasn't the case. The problem is that Groovy resolves the Category class to groovy.lang.Category and not to my Grails domain class. This means if you have domain classes with the same name as a class in groovy.lang and don't use packages you will get into troubles.

So from now on I will create/put my Grails artifacts in a package, which is a good practice anyway. When running the Grails command line scripts to create artifacts you can specify the package so Grails automatically creates the package structure: e.g.:
grails create-domain-class org.company.Book


PS: I you want to read more about Groovy Categories have a look at the Groovy User Guide.

Wednesday, November 19, 2008

Grails on NetBeans



Today NetBeans 6.5 was released. The Groovy and Grails support is really nice. I'm using it for a couple of months now since M1 and I'm really satified. If you haven't tried it and working on Grails projects you really should give NetBeans a go!

Can't wait though on better Groovy and Grails support in Eclipse. Let's see what SpringSource will bring us.

Tuesday, November 11, 2008

G2One - the Groovy/Grails company - acquired by SpringSource



Just want to mention I'm really amazed by the latest Groovy/Grails news that SpringSource has acquired G2One - the company (including the developers) behind Groovy/Grails. Congratulations guys!

Perhaps this was the last little push which was needed to get a full enterprise wide adoption of Groovy and Grails.

Also for the community good news. I guess there will be more money and resources available to further improve and enhance both technologies.

Thursday, August 7, 2008

NLGUG Announced



Just like to mention that I've created a space on Google groups to host the Nederlandse Groovy & Grails User Group (NLGUG). It's a Groovy & Grails User Group for people in The Netherlands.

I started this group to start building up a network of Groovy & Grails developers in The Netherlands. If the group grows and people are interested in meeting up this would be great!

So if you are located in The Netherlands and interested in joining, go to http://groups.google.com/group/nlgug.

Saturday, April 26, 2008

Grails wins 2nd prize in JAX Innovation Award



Just read that Grails has won the Second prize (5.000 euro) in the yearly JAX Innovation Award. And that after Groovy won the First prize a year earlier. As Grails developers we know the Grails/Groovy platform is truly innovative compared to other web frameworks, but it is good to see the recognition from such a public award.

The JAX Innovation Award were presented and awarded to the winners during the conferences JAX, SOACON and Eclipse Forum Europe. The three conferences are taking place at the same time in Wiesbaden and represent the most important meeting for professional information technology in Europe.

Thursday, April 24, 2008

Busy time in Grails plugin land: Announcing the OpenID plugin



It are busy times in Grails plugin land. This week the Searchable Plugin 0.4.1, Acegi Plugin 0.2.1, and the Authentication Plugin 1.0 were already released. And I've just added another one myself: the OpenID Plugin

While Marc Palmer was releasing his Authentication plugin, I was working one a OpenID plugin myself. When I was reading through the Authentication plugin documentation I really got inspired by some features of it. So I borrowed/copied some concepts of it to the OpenID plugin. Thanks Marc!

The OpenID plugin does all the plumbing to communicate with OpenID providers (using the OpenID4Java library) to authenticate/identify users for your website. The great thing is that you are in full control where the controller and the OpenID providers will redirect to in case of successfull login or error.

Here is an example:


<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="layout" content="main" />
<title>Login</title>
<openid:css />
</head>
<body>
<div class="nav">
<span class="menuButton"><a class="home" href="${createLinkTo(dir:'')}">Home</a></span>
</div>
</div class="body">

<h1>Login</h1>
<openid:hasLoginError>
<div class="errors">
<ul>
<li></li>
</ul>
</div>
</openid:hasLoginError>
<openid:form success="[action:'loggedin']">
<openid:input size="30" value="http://" /> (e.g. http://username.myopenid.com)
<br/>
<g:submitButton name="login" value="Login" />
</openid:form>
</div>
</body>
</html>



For full documentation see: http://grails.org/OpenID+Plugin

Friday, April 11, 2008

Update on Ext Scaffolding



I'm making some progress on the Ext Scaffolding for Grails.
Currently I can generate all CRUD functionality for a simple domain class with String properties.

It's done by overriding the default scaffolding templates (aka grails install-templates). So when finished the Ext plugin will contain a plugin to install these templates, which then can be used with the generate-all command.

See below some additional screenshots.



Friday, April 4, 2008

Sneak Preview: Ext Scaffolding for Grails



A short post just before the weekend. Have a look at the nice screenshots below, which are the result of Grails Ext Scaffolding templates I'am working on currently. I hope to include the templates in the Grails Ext plugin soon.



Wednesday, March 26, 2008

First experience with Groovy and Grails support in NetBeans 6.1



Recently many blog postings related to NetBeans with Groovy and Grails integration appeared on groovyblogs.org. See Guillaume Laforge's Groovy / Grails support in NetBeans and GlassFish blog entry for a complete summary and links to related postings.

When I was reading those posting I felt it was time to try it out myself.
After downloading the latest NetBeans 6.1 nightly build and installing the Groovy and Grails plugin, I was ready for a testdrive.

Creating a Grails project


Creating a Grails project has never been easier. The NetBeans 6.1 Groovy and Grails plugin contains a New Project wizard for creating a new Grails project.



After creating the project (NetBeans is calling the Grails create-app command underwater), NetBeans displays a nice project structure specially for Grails projects.



See how NetBeans nicely devides all Grails artifact types (like Controllers, Domain classes, Scripts, Services, etc.) in separate folders.

Creating Grails artifacts


The NetBeans 6.1 Groovy and Grails plugin features context menus for creating Grails artifacts like Domain classes etc easily. After clicking the context menu item, a dialog is opened to enter information needed to create the Grails artifact.





After creating the domain class a context menu is available for generating the controller and views.



NetBeans is always calling the Grails commands underwater and this means that when generating the Views from within NetBeans also customized templates can be used. As far as I could find the install-templates command could not be executed from within NetBeans, so you still need the Grails command line.

Code-completion and syntax color highlighting


The NetBeans 6.1 Groovy and Grails plugin offers Groovy code completion and syntax color highlighting. To bad the current version does not yet include code-completion for Grails dynamic methods.



Running a Grails application


From within NetBeans the Grails application can be started (run-app) using a context menu on application level.



Notice also the context menu item to generate a war archive or to see statistics.

Deploying a Grails application to GlassFish


Reading the other blog posting it is also possible to deploy your Grails application in GlassFish, but I didn't tested this myself yet.

Summary


My first experience with the NetBeans 6.1 Groovy and Grails plugin is good. Nice to have those context menu for executing the Grails commands from the IDE. However code completion, and specially for Grails dynamic methods, need to improve to really compete with IntelliJ. But I really believe this will happen in the near future!

Tuesday, March 25, 2008

Groovy User Group on LinkedIn



I just created the Groovy User Group on Linkedin and already 50 members have joined.
If you are interested join this group at http://www.linkedin.com/groupInvitation?groupID=76751&sharedKey=7038BD424E3B.

For Grails there was already a group on LinkedIn. Join this group at http://www.linkedin.com/groupInvitation?groupID=39757&sharedKey=40CA861F1941.

Friday, February 15, 2008

Grails adaptive AJAX support with the Yahoo! UI Library



Grails ships out of the box with adaptive AJAX support.
By default Grails uses the Prototpe library when invoking AJAX request using the Grails remoteLink, formRemote and submitToRemote AJAX tags.

Not only is Grails providing an easy way of integrating AJAX functionality in your pages, but it also allows you to switch to another AJAX library if needed. This is what we mean with adaptive AJAX support.

One of the use cases to switch to another AJAX library is that this library offers more functionality then the default Prototype library. E.g. you want to use the Yahoo! User Interface Library (YUI) within you application for the autocomplete or calendar functionality. In this case you want the YUI library also to be used for your AJAX tags, so you only depend on YUI and not on both YUI and Prototype.

If you want easy support for YUI in your Grails application then just install the Grails Yahoo! UI Library Plugin which I released today. It downloads and installs automatically the latest YUI 2.4.1 2.5.0 distribution in your application, and registers itself to be used with the adapative AJAX tags. It also contains two helper tags to easily include additional YUI javascript and css files as well.

Note that this plugin does not provide any tags for embedding rich ui components without having to deal with javascript libraries. If you are more interested in such a plugin, have a look at the Grails RichUI Plugin. This plugin contains a set of AJAX components not limited to the YUI library.

For a personal application I want to use the YUI autocomplete and calendar functionality so I'm thinking already of a Grails YUI Widgets Plugin which can be installed on top of the YUI Plugin ...

Tuesday, February 5, 2008

Grails 1.0 released today!



Today the release of Grails 1.0 was announced. See release notes at http://grails.org/1.0+Release+Notes

2008 will be the Grails year!!

Tuesday, January 29, 2008

BlazeDS Test Drive sample in Grails



In my previous blog entry I introduced the Grails Flex Plugin. I got some reactions on this post and one of them was from Alexander Negoda (aka greendog), who had some problems getting BlazeDS Test Drive Sample 5: Updating data to work on Grails.

A good reason for me to implement the sample myself, and write a small tutorial!


  1. I assume you have Grails already installed and know the basics. This plugin requires requires the latest and greatest Grails 1.0-final development build. It is not compatible with Grails 1.0-RC4.

  2. Create a new Grails application by executing grails create-app product from the Grails command line.

  3. From within the product application folder, install the Flex plugin by executing: grails install-plugin flex
    All Flex libraries and configuration files will be copied into your application's web-app folder.

  4. Create the Product domain class by executing: grails create-domain-class product

  5. Open Product.groovy and add properties so your domain class looks like:

    class Product {
    String name
    String description
    String image
    String category
    Double price
    Integer qtyInStock
    }

  6. Create the Product service by executing: grails create-service product

  7. Open ProductService.groovy and change the class so it looks like:

    class ProductService {

    static expose = ['flex-remoting']

    def getProducts() {
    return Product.list();
    }

    def update(Product product) {
    def p = Product.get(product.id)
    if (p) {
    p.properties = product.properties
    p.save()
    }
    }

    }

    Notice that we expose the service as a flex-remoting service.

  8. Now we are finished with the domain and service layer and we can focus on the Flex front-end. Within the application's web-app folder create a file called main.mxml and add the following content:

    <?xml version="1.0" encoding="utf-8"?>
    <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="*" layout="horizontal"
    creationComplete="srv.getProducts()" viewSourceURL="srcview/index.html">

    <mx:RemoteObject id="srv" destination="productService"/>

    <mx:Panel title="Catalog" width="100%" height="100%">
    <mx:DataGrid id="list" dataProvider="{srv.getProducts.lastResult}" width="100%" height="100%"/>
    </mx:Panel>

    <ProductForm product="{Product(list.selectedItem)}"/>

    </mx:Application>

  9. Within the application's web-app folder create a file called ProductForm.mxml and add the following content:

    <?xml version="1.0" encoding="utf-8"?>
    <mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="*"
    title="Details" width="100%" height="100%">

    <Product id="product"
    name="{productName.text}"
    category="{category.text}"
    price="{Number(price.text)}"
    image="{image.text}"
    description="{description.text}"/>

    <mx:RemoteObject id="srv" destination="productService"/>

    <mx:Form width="100%">

    <mx:FormItem label="Name">
    <mx:TextInput id="productName" text="{product.name}"/>
    </mx:FormItem>

    <mx:FormItem label="Category">
    <mx:TextInput id="category" text="{product.category}"/>
    </mx:FormItem>

    <mx:FormItem label="Image">
    <mx:TextInput id="image" text="{product.image}"/>
    </mx:FormItem>

    <mx:FormItem label="Price">
    <mx:TextInput id="price" text="{product.price}"/>
    </mx:FormItem>

    <mx:FormItem label="Description" width="100%">
    <mx:TextArea id="description" text="{product.description}" width="100%" height="100"/>
    </mx:FormItem>

    </mx:Form>

    <mx:ControlBar>
    <mx:Button label="Update" click="srv.update(product);"/>
    </mx:ControlBar>

    </mx:Panel>

  10. Within the application's web-app folder create a file called Product.as and add the following content:

    package
    {
    [Bindable]
    [RemoteClass(alias="Product")]
    public class Product
    {
    public function Product()
    {
    }

    public var id:int;

    public var name:String;

    public var description:String;

    public var image:String;

    public var category:String;

    public var price:Number;

    public var qtyInStock:int;

    }
    }

    Note that the main.mxml, ProductForm.mxml and Product.as files are for 99% a copy from the BlazeDS Test Drive sample. In main.mxml and ProductForm.mxml only the destination id of the RemoteObject was changed. And in Product.as the alias of the RemoteClass and the name of the productId column was changed.

  11. Before we run the example, let's add some data to the embedded HSQLDB database. In your application's BootStrap.groovy class create some records as shown below:

    class BootStrap {

    def init = { servletContext ->
    new Product(name: 'Nokia 6010', category: '6000', image: 'Nokia_6010.gif', price: 99.00, description: 'Easy to use without sacrificing style, the Nokia 6010 phone offers functional voice communication supported by text messaging, multimedia messaging, mobile internet, games and more.', qtyInStock: 21).save()
    new Product(name: 'Nokia 3100 Blue', category: '9000', image: 'Nokia_3100_blue.gif', price: 109.00, description: 'Light up the night with a glow-in-the-dark cover - when it is charged with light you can easily find your phone in the dark. When you get a call, the Nokia 3100 phone flashes in tune with your ringing tone. And when you snap on a Nokia Xpress-on gaming cover, you will get luminescent light effects in time to the gaming action.', qtyInStock: 99).save()
    new Product(name: 'Nokia 3100 Pink', category: '3000', image: 'Nokia_3100_pink.gif', price: 139.00, description: 'Light up the night with a glow-in-the-dark cover - when it is charged with light you can easily find your phone in the dark. When you get a call, the Nokia 3100 phone flashes in tune with your ringing tone. And when you snap on a Nokia Xpress-on gaming cover, you will get luminescent light effects in time to the gaming action.', qtyInStock: 30).save()
    new Product(name: 'Nokia 3120', category: '3000', image: 'Nokia_3120.gif', price: 159.99, description: 'Designed for both business and pleasure, the elegant Nokia 3120 phone offers a pleasing mix of features. Enclosed within its chic, compact body, you will discover the benefits of tri-band compatibility, a color screen, MMS, XHTML browsing, cheerful screensavers, and much more.', qtyInStock: 10).save()
    new Product(name: 'Nokia 3220', category: '3000', image: 'Nokia_3220.gif', price: 199.00, description: 'The Nokia 3220 phone is a fresh new cut on some familiar ideas - animate your MMS messages with cute characters, see the music with lights that flash in time with your ringing tone, download wallpapers and screensavers with matching color schemes for the interface.', qtyInStock: 20).save()
    new Product(name: 'Nokia 3650', category: '3000', image: 'Nokia_3650.gif', price: 200.00, description: 'Messaging is more personal, versatile and fun with the Nokia 3650 camera phone. Capture experiences as soon as you see them and send the photos you take to you friends and family.', qtyInStock: 11).save()
    new Product(name: 'Nokia 6820', category: '6000', image: 'Nokia_6820.gif', price: 299.99, description: 'Messaging just got a whole lot smarter. The Nokia 6820 messaging device puts the tools you need for rich communication - full messaging keyboard, digital camera, mobile email, MMS, SMS, and Instant Messaging - right at your fingertips, in a small, sleek device.', qtyInStock: 8).save()
    new Product(name: 'Nokia 6670', category: '6000', image: 'Nokia_6670.gif', price: 319.99, description: 'Classic business tools meet your creative streak in the Nokia 6670 imaging smartphone. It has a Netfront Web browser with PDF support, document viewer applications for email attachments, a direct printing application, and a megapixel still camera that also shoots up to 10 minutes of video.', qtyInStock: 2).save()
    new Product(name: 'Nokia 6620', category: '6000', image: 'Nokia_6620.gif', price: 329.99, description: 'Shoot a basket. Shoot a movie. Video phones from Nokia... the perfect way to save and share life\u2019s playful moments. Feel connected.', qtyInStock: 10).save()
    new Product(name: 'Nokia 3230 Silver', category: '3000', image: 'Nokia_3230_black.gif', price: 500.00, description: 'Get creative with the Nokia 3230 smartphone. Create your own ringing tones, print your mobile images, play multiplayer games over a wireless Bluetooth connection, and browse HTML and xHTML Web pages. ', qtyInStock: 10).save()
    new Product(name: 'Nokia 6680', category: '6000', image: 'Nokia_6680.gif', price: 222.00, description: 'The Nokia 6680 is an imaging smartphone that', qtyInStock: 36).save()
    new Product(name: 'Nokia 6630', category: '6000', image: 'Nokia_6630.gif', price: 379.00, description: 'The Nokia 6630 imaging smartphone is a 1.3 megapixel digital imaging device (1.3 megapixel camera sensor, effective resolution 1.23 megapixels for image capture, image size 1280 x 960 pixels).', qtyInStock: 8).save()
    new Product(name: 'Nokia 7610 Black', category: '7000', image: 'Nokia_7610_black.gif', price: 450.00, description: 'The Nokia 7610 imaging phone with its sleek, compact design stands out in any crowd. Cut a cleaner profile with a megapixel camera and 4x digital zoom. Quality prints are all the proof you need of your cutting edge savvy.', qtyInStock: 20).save()
    new Product(name: 'Nokia 7610 White', category: '7000', image: 'Nokia_7610_white.gif', price: 399.99, description: 'The Nokia 7610 imaging phone with its sleek, compact design stands out in any crowd. Cut a cleaner profile with a megapixel camera and 4x digital zoom. Quality prints are all the proof you need of your cutting edge savvy.', qtyInStock: 7).save()
    new Product(name: 'Nokia 6680', category: '6000', image: 'Nokia_6680.gif', price: 219.00, description: 'The Nokia 6680 is an imaging smartphone.', qtyInStock: 15).save()
    new Product(name: 'Nokia 9300', category: '9000', image: 'Nokia_9300_close.gif', price: 599.00, description: 'The Nokia 9300 combines popular voice communication features with important productivity applications in one well-appointed device. Now the tools you need to stay in touch and on top of schedules, email, news, and messages are conveniently at your fingertips.', qtyInStock: 26).save()
    new Product(name: 'Nokia 9500', category: '9000', image: 'Nokia_9500_close.gif', price: 799.99, description: 'Fast data connectivity with Wireless LAN. Browse the Internet in full color, on a wide, easy-to-view screen. Work with office documents not just email with attachments and memos, but presentations and databases too.', qtyInStock: 54).save()
    new Product(name: 'Nokia N90', category: '9000', image: 'Nokia_N90.gif', price: 499.00, description: 'Twist and shoot. It is a pro-photo taker. A personal video-maker. Complete with Carl Zeiss Optics for crisp, bright images you can view, edit, print and share. Meet the Nokia N90.', qtyInStock: 12).save()
    }
    def destroy = {
    }
    }

  12. Now run the application by executing grails run-app and when started open a browser and navigate to http://localhost:8080/product/main.mxml





Now enjoy and look at the list of products retrieved during startup of the application. Navigate trough the product list and change the properties on the right side. Pushing the Update button will update the record in the database.

Note that updating causes a long stacktrace in the console window, but the update succeeds anyway. It's a StackOverflowError within HSQLDB; I tested the code on a MySQL database and then there is no error thrown.

Sunday, January 20, 2008

Flex on Grails: Introducing the Grails Flex plugin



I haven't touched this blog for the past months as life has been very busy since my son was born. But now it's time again, as I released the Grails Flex Plugin today.

With the plugin Grails services can be exposed as RPC remoting destinations within BlazeDS - Adobe's server-based Java remoting and messaging technology. These remoting destinations can be used in Flex rich internet applications to communicate with the server to restrieve or send data.

Great thing is you can use all nice features from Grails like reloading, GORM etc. and have a real RIA application on the front-end.

See Grails Flex Plugin for more information and a simple usage example.

Saturday, October 27, 2007

Amazing JetGroovy plugin



First of all I need to say that I'm a happy daily Eclipse user; Eclipse does (almost) everything I want from a Java IDE.
In the past I also used JDeveloper using Oracle's proprietary Application Development Framework (ADF) and experimented a little bit with NetBeans.
But I actually never tried IntelliJ. Maybe because the price tag of $499 and because Eclipse is working good enough for FREE.

IntelliJ IDEA 7.0 was released recently and the fully functional Beta version of the JetGroovy plugin provides excellent Groovy and Grails support.
A lot of people were very enthusiastic about this JetGroovy plugin I gave it a try this evening and I was really amazed as it worked perfectly:

Code completion/assistance


  • Groovy code completion for keywords, classes, fields and methods

  • Cross-resolution between Groovy and Java classes, methods and fields

  • Syntax and error highlighting

  • Groovy-aware refactoring



Grails application and artifact creation

  • Grails applications can be created from using a wizard

  • Grails artifacts (like domain classes, controllers, views etc.) can be created using a wizard



GSP support

  • Groovy code completion

  • Tag completion (both Grails core and custom created tags; even tags with custom namespaces are resolved ;-) !)



When developing Groovy and/or Grails projects then IntelliJ is a real recommendation.
I hope one day we will see the same functionality provided by the Groovy Eclipse plugin.

Wednesday, October 10, 2007

Some great Groovy/Grails news this week



Some really good Groovy and Grails news this week I wanted to mention (or better copy from Graeme Rocher's Blog)

First LinkedIn, a online network of more than 14 million experienced professionals from around the world, are looking for software engineers preferably with Groovy/Grails experience.

Then big ERP software giant SAP announced that they have released a new community driven product called Composition on Rails that allows you to use their SAP NetWeaver Composition Environment to quickly prototype applications using Groovy/Grails.

And today G2One Inc - the Groovy/Grails company was announced. G2One has been founded by Graeme Rocher (Grails Project Lead), Guillaume LaForge (Groovy Project Lead) and Alex Tkachman (Former JetBrains COO) to provide consultancy, training, support and products around Groovy & Grails. Personally I think offering commercial support etc. will help adoption signifantly. And with this Groovy/Grails can be developed further. This is the same as e.g. JBoss and Spring are offering great open source software for free, but still making money to constantly evolve this free software.

Thursday, October 4, 2007

Grails i18n templates plugin released



After my previous post about i18n aware scaffolding templates I decided to create a plugin for those templates. For documentation and installation instructions see http://www.grails.org/I18n+Templates+Plugin