In this post I will demonstrate one way to use GORM (the Grails ORM) in a desktop application.
Grails is a wonderful web application framework. GORM is one of Grails’ biggest draws for me. However, in order to use Grails with GORM for my projects at work, I really need to be able to use the GORM domain objects from desktop applications as well as the web. I set out to discover how to do this. After many posts on the Grails user mailing list and several frustrating and sleepless nights, I have my first working example.
This example sets up a application that runs a Groovy script that has access to GORM domain classes in the dynamic way that Grails uses them. The domain classes have the id and version fields, as well as the GORM dynamic methods, injected at runtime. I am still not sure that I would want to code an entire Swing application in Groovy, but this is my first step toward being able to use GORM in a desktop application.
In order to follow along with this tutorial you will need to have setup Java (I have only tried Java 5), Groovy (I used 1.0), MySQL (I used 5.0.27-max) and Ant (I used 1.6.5).
Download the Example
The project code will be discussed, however I will not be discussing the libs needed. Just download the example zip file (8.5 MB) to follow along with the tutorial.
The Example Project
Once you have downloaded and extracted the example project you will see that you have the following directories and files:
The src directory as you would expect contains our src files that will be compiled. In this example this contains one file com/jweldin/gormtest/Test.groovy that compiles to com.jweldin.gormtest.Test.class and com.jweldin.gormtest.MyInjectionOperation.class.
The lib directory contains our necessary libraries to build and use the project.
The build.xml file is the ant build file used to build and run the project.
The grails-app directory contains two subdirectories domain and scripts. The grails implementation currently requires all “loaded” groovy files to be located under a directory named grails-app and all domain classes to be located under a directory named domain that is somewhere under the grails-app directory.
The grails-app/scripts directory contains the Main.groovy that is called from our loader class (in this case badly named Test) and would contain any other non-domain groovy scripts.
The grails-app/domain directory contains our domain groovy classes.
Running the Application
The application could be run two ways. You could package the class that loads the domain classes and starts the main script (in this example that class is Test) into a jar alone and run it with the grails-app in the class path. This would allow you to be able to constantly modify the domain groovy files and the called groovy script and then re-run the application without need to actually compile anything. You could also jar up a compiled version of the Test class as well as the grails-app folder containing the un-compiled groovy files and distribute it in a less dynamic form. Perhaps using the first method for development and the second for distribution would be a good idea.
In this example running the build.xml with the default target or the run target builds and runs the application and outputs some simple messages letting you know that the application performed correctly.
If all runs correctly then you should see the following at the end of the ant output:
[java] ----------- [java] Before Main [java] -----------[java] Adding book:The Bible by God [java] Adding book:The Dark Tower: The Gunslinger by Stephen King [java] Adding book:Accounting For Dummies, 3rd Edition by John A. Tracy [java] Adding book:It by Stephen King [java] Adding car:2006 Hyundai Tiburon SOMELONGVINNUMBER [java] Adding car:2001 Dodge Neon SOMEOTHERLONGVINNUMBER [java] Adding person:Jeremie Weldin (Tue Mar 20 02:09:39 EDT 2007) [java] Adding person:John Doe (Sun Dec 25 02:09:39 EST 2005) [java] All of the books: [java] The Dark Tower: The Gunslinger by Stephen King [java] Accounting For Dummies, 3rd Edition by John A. Tracy [java] It by Stephen King [java] All of the cars: [java] 2006 Hyundai Tiburon SOMELONGVINNUMBER [java] 2001 Dodge Neon SOMEOTHERLONGVINNUMBER [java] All of the people: [java] Jeremie Weldin (2007-03-20 02:09:39.0) [java] John Doe (2005-12-25 02:09:39.0) [java] All of the books by Stephen King: [java] The Dark Tower: The Gunslinger by Stephen King [java] It by Stephen King [java] All of the books ordered by name: [java] Accounting For Dummies, 3rd Edition by John A. Tracy [java] It by Stephen King [java] The Dark Tower: The Gunslinger by Stephen King [java] ----------- [java] After Main [java] ----------- [java] Done
You should also see that the tables car, person, book and song have been created in your database.
Next Steps
The next that thing I am going to be working on is getting the GORM classes to be loaded into the classloader used by the initially loaded class and not just in the dynamically loaded groovy script. I have not had to work with classloaders at all until this exercise, but I am hoping it is something relatively easy. I hope to be able to create a class with a static method that would load all of the domain classes, using GORM, for use in the class that calls the method.
** Disclaimer: due to the code being pretty self explanatory I have not gone into detail about the Test.groovy, however I will if someone requests the detail discussion.**