GORM Standalone

view it on Blogger


A fully working GORM Standalone example

...with downloadable working project



While developing the Swing GUI for our Less Compiler, we implemented a work space system that need saving on a file DB. We've been using Grails for a while now, so just the thought to go back to common Java persistency gave me the shivers. Literally. But if you're reading this post you probably already know the sensation.
So we began to look around the web to find out how to use GORM standalone. There's a lot stuff, good tips and a lot of people who's asking for it. Strangely enough we found some difficulties anyway making it work. Mainly because we use Spring quite a lot, but we really don't know so much about Spring and Spring configuration, and that's because there's always a framework taking care of it for you, at most you have to learn how to configure beans. After all, that's the beauty of Spring, you don't even need to know that you're using it... sometimes it feels a bit like magic, especially using Grails. 
But we encountered another problem... while we found a lot of examples of appcontext configurations that put us on the right path to accomplish it, none of them was working "out of the box", there was no list of minimal needed libraries, and most of all there was no working sample to download anywhere. We found some that needed maven dependencies, but even after making that work the sample just didn't. 
So after we finally got it up and running we felt it was needed to share it with all those people who where asking the same question. After all you want GORM because it's simple to use and not time consuming to configure... if you have to spend a day figuring out how to do that you'll probably switch back to JPA and hope it won't take too much time 'till you can go back to using Grails.

Why GORM?

Since you're reading this article we can assume that you already know... if you don't, read this post, but most of all start using Grails! for your web apps. You'll never want to go back losing your precious time doing something that doesn't really need your intelligence to be done

Why not GORM Standalone?

Ok! It's a strange question to ask in this article... but doing some research we encountered a project that could make all our efforts to make this work simply useless... it seems that codehaus is developing Grails equivalent for desktop apps... Griffon!
I'm really excited by this news, but unluckily the project is not there yet.
Although, soon Griffon will be mature enough to be really effortless to use, and will include GORM support via plugins. So right now complete GORM support is not there, but if you're planning like us a new desktop application and you are here just because you want to start in the right direction including something useful and productive like GORM, maybe you should start looking at Griffon instead. You'll be introducing a lot of other cool stuff, useful and productive. I think it can pay to leave out GORM for now and wait for when they'll integrate it for you.
So, if reading this example you feel that there's something that could have been looked into more deeply, like transaction manager injection, it's because as soon as we found out about Griffon we stopped developing and started looking into it to see if it's more productive to restart from scratch with it. We'll let you know what we found in the next posts. 

How to make it works

Libraries

First of all you'll need Grails libraries related to GORM and their dependencies. You'll find them in your Grails home, but if you want to spare yourself an head hake trying to figure the minimal set needed, in the downloadable example you'll find all the lib you need took from Grails 1.1.2, a bit old as Grails version, but more than sufficient for GORM.

Configuration

The next step is to configure your application context. In this example there's the minimal you'll need. 
The data-source is configured to use HyperSQL DB, change it to whatever you need, but if you where planning to use it too you'll just need to change DB url property.
Then change base-package property of gorm:sessionFactory to match the package for your domain classes

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:gorm="http://grails.org/schema/gorm"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.0.xsd
http://grails.org/schema/gorm
http://grails.org/schema/gorm/gorm.xsd"

>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
<property name="url" value="jdbc:hsqldb:todos;shutdown=true"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<list>
<value>messages</value>
</list>
</property>
</bean>
<gorm:sessionFactory
base-package="todo.domain"
data-source-ref="dataSource"
message-source-ref="messageSource">
<property name="hibernateProperties">
<util:map>
<entry key="hibernate.hbm2ddl.auto" value="update"/>
</util:map>
</property>
</gorm:sessionFactory>
</beans>

Init context

Add this code to your main

ApplicationContext context = 
new ClassPathXmlApplicationContext("META-INF/applicationContext.xml");

Write your domain class

Write your domain classes like you would on Grails, no need to set Long id field as primary key, constraint fully working, and so on. You'll just need some additional libraries for some particular validations, like email, and to add @grails.persistence.Entity annotation on your class.

package todo.domain
import grails.persistence.Entity

@Entity
class Todo {
String descr
Boolean done

static constraints = {
descr
(size: 1..100)
}
}

Use GORM!

Here you see an helper groovy class that uses GORM for all persistence. 
To make it work you'll need to inject session factory bean like this def sessionFactory
For delete and save operations you'll need a transaction DomainClass.withTransaction{...}
And then you'll need to validate your instances yourself. Grails is a web app, so validation doesn't simply throw exceptions, but builds Spring field errors. If you need to throw Exceptions don't worry, it's a couple of lines of code.

package todo
import java.text.MessageFormat
import todo.domain.*

class TodoHelper {
def sessionFactory

def getList() {
return Todo.list()
}

def deleteCompleted() {
Todo.withTransaction{
def todos = Todo.findAllByDone(new Boolean(true))
todos
?.each{
it
.delete()
}
}
}

def updateTodo(descr,done,id) {
Todo.withTransaction{
def todo = null;
if (id) {
todo
= Todo.get(id)
} else {
todo
= new Todo()
}
todo
.descr = descr
todo
.done = done

if (todo.validate()) {
todo
.save()
} else {
todo
?.errors?.allErrors?.each {
throw new Exception(new MessageFormat(it?.defaultMessage)?.format(it?.arguments))
}
}
}
}

}

Use dynamic methods from Java in NetBeans

While in groovy you can use GORM at full power, domain class static methods, criteria builders and dynamic methods like Book.findAllByTitle, from Java that won't be available.
You can easily make a groovy helper class with all you need, but if you're developing with a Swing framework sooner or later you'll need at least to get your instance id. Luckily that's the only thing you'll have available from pure Java. The only thing that could be tricky is if your using NetBeans IDE. For some reason if you clean and build your project it will give an error complaining that your domain class doesn't have getId method. That happens because until your domain class is built that method won't exist. A work around is to add this code to your build.xml so that in -post-clean, before building again, it will compile every groovy class you have in your project.

<target name="-set-includes" depends="">
<property name="javac.includes" value="**/*.groovy" />
</target>
<target name="-post-clean" depends="-set-includes,compile-single">
<echo level="info" message="-post-clean"/>
<echo level="info" message="${src.dir}"/>
<echo level="info" message="${build.dir}"/>
</target>


and that's it

with this few steps you should be able to fire up GORM in any application you need almost out of the box
Hope you found this useful
Let us know if you think there's something important missing

Posted on 25 April 2012 | 11:55 pm

2 Commenti

Thank you Bryan for the notification. We uploaded a new version of the archive with complete sources and build file. Let us know if there are other problems. Thanks

Posted on 6 August 2012 | 9:25 pm

This entry and download looked to be exactly what I was looking for to integrate GORM into a java project I am working on. However, the src/ directory is incomplete without the groovy and java files and there is no build file. The binary works as advertised, but I am trying to dig in a little deeper for my own work. Could you fill out the sample as it would be a huge help? Thanks!

Posted on 1 August 2012 | 5:53 pm

Leave a comment