Getting Started with Grails & IntelliJ Part 4
Posted by jt - 13/10/09 at 09:10 pmOne of the things really cool about Grails is the ability of dynamic scaffolding. This enables Grails to create a basic CRUD application over your domain model. I doubt if you would use this for a real production application, but it is a great way to knock out small prototypes. And it will work fine for my Log4Ora project. I only have a few tables to maintain. My goal here was to provide a nice UI for users to maintain the tables. Of course if I ever want to enhance the UI created here, I can. Grails is fully capable of generating just about any html you can dream of. You are not limited to using the dynamic scaffolding.
To get started we will need to add controller classes. To do this from IntelliJ, right click on the controllers folder, and select New/Grails/Grails Controller.
For our project, we will be creating a controller over the following domain classes: Module, ModuleLevel, and ModuleLevelMethod.
IntelliJ will create a stub of the controller for you.
class ModuleController { def index = { } }
To enable dynamic scaffolding, we need to change the controller class as follows:
class ModuleController { def scaffold = true }
That’s all we need to do. Grails will take it from here.
Grails ships with jetty application server. We’ll need to add a run configuration to IntelliJ before we can launch directly from the IDE. From IntelliJ, click on the green run arrow in the tool bar, then click the add icon (+) in the top left. Select Grails Application, and click ok.
I named mine ‘grailsLocal’, and left all the defaults. Grails by default starts on port 8080, you may need to change this if you have another application running on that port.
When you click on run, IntelliJ (via Grails commands) will compile the project, launch the application server. If you left the option for ‘launch browser’, your default browser will open.
If all went ok, you’ll see this screen:
This is the default Grails home screen, with a listing of the available controllers.
If you select the Module Controller, you will see:
You can see our ‘default’ data is loaded into the tables and is displayed on the screen. Lets take a look at some of the other screens, click home, then on the ModuleLevelMethod Controller.
Hmm, we have some ugliness going on here. We’re getting the key(id) values rather than something that would make sense to a person. Luckily, there is an easy way around this. We just need to add toString methods to our domain classes.
Let’s change our LogMethod class as follows:
class LogMethod { String methodCode, methodDescription static constraints = { methodCode(maxSize:30, blank:false, unique:true) methodDescription(maxSize:100) } String toString() { return methodCode } }
We’ll do the same for ModuleLevel:
class ModuleLevel { Module module LogLevel level String loggingEnabled static constraints = { loggingEnabled (inList:['Y', 'N']) } static hasMany = [moduleLevelMethod:ModuleLevelMethod] String toString() { module.getOwner() + ":" + module.getObject() + ":" + level.getLevelCode() } }
Save the files. Grails does a nice job of recompiling when a file changes. Sometimes it will get weird, if it does, just bounce the application server.
You’ll see the previous screen is now using the values we specified in our toString method.

Ok, that looks a lot better. I’m going to go through and add toString methods to the remaining domain classes.
Now let’s perform a functional test. I want to add a new program module called “PACKAGE1″, with an owner of “JOHN”. And I want to enable DEBUG Level messages, and I want them to be written to the log table.
First I need to go to the Module controller, and click create.
After clicking, Create, you’ll be returned to this screen:
Let’s edit it and add a Level.
From the edit screen, I can do this by clicking on Add Module Level.
I found this screen interesting. For Logging Enabled, a drop down is provided based on the list constraint we added to the property in our domain class. While the Level drop down is from the relationship we specified to the LogLevel domain class. We have a similar result for the drop down of the Module property, but in this case it is defaulted to the module we are working. Nicely done.
After clicking create, the application returns to this screen:
At this point, I’ve defined the log level, but have not assigned the log method. We have a similar operation here, just click edit. The following screen is displayed, which has an option to add a log method.
We are taken to a create screen for the Module/Level/Method. Again, it has drop downs:
I think things are looking pretty good. One last thing I don’t care for is the ordering on the last couple screens. For the ModuleLevel views, I think it would be cleaner to list things by module, level, enabled. Let me show you a little trick to clean that up. The dynamic scaffolding will order the properties per the constraints property on the domain class.
Lets change our ModuleLevel class as follows:
class ModuleLevel { Module module LogLevel level String loggingEnabled static constraints = { module() level() loggingEnabled (inList:['Y', 'N']) } static hasMany = [moduleLevelMethod:ModuleLevelMethod] String toString() { module.getOwner() + ":" + module.getObject() + ":" + level.getLevelCode() } }
You’ll see that our view changes as follows:
We now have a fully functional web application. Let’s run “grails stats” again to see how things have changed.
+----------------------+-------+-------+ | Name | Files | LOC | +----------------------+-------+-------+ | Controllers | 4 | 13 | | Domain Classes | 5 | 56 | | Unit Tests | 7 | 77 | | Integration Tests | 1 | 21 | +----------------------+-------+-------+ | Totals | 17 | 167 | +----------------------+-------+-------+
To add the web functionality, our line count increased by 52 lines of code. For the functionality we just gained, I’d have to say that isn’t too shabby.
In this blog series, I’ve only touched the surface of the capabilities of Grails. I hope you’ve found this hopeful, and will take a closer look at Grails the next time you need to build a basic CRUD type application.














A bunch of random technology stuff that has my attention. I work with a lot of Oracle, Java, and dabble with various open source software packages.
October 13th, 2009 at 9:41 pm
Nice post. Good stuff.