Saturday, July 12, 2008

Memory leak when using external configuration with Grails?

Reported as Jira issue: http://jira.codehaus.org/browse/GRAILS-3252


Few days ago I added some changes to grails tutorials and suddenly it started to fail due the out of memory error. After some investigation this is my conclusion.

It seems that there is a memory leak when using external configuration file to handle certain parts of your grails application. This happened to me with Grails version 1.0 and I am able to repeat it on Axis delivered with Grails and Tomcat 5. I didn't tried with other jsp containers.

Follows short description how to create simple application to reproduce this bug. I use tag lib and didn't try if the same thing happens without tag lib.

Create new grails application: grails create-app memory-leak.

Then create new tag lib MemoryLeakTagLib.groovy. Content of this tag lib is:

class MemoryLeakTagLib {
def displayExternal = {attrs, body ->
if (grailsApplication.config.t1.value) {
out << body()
}
if (grailsApplication.config.t2.value) {
out << body()
}
if (grailsApplication.config.t3.value) {
out << body()
}
if (grailsApplication.config.t4.value) {
out << body()
}
if (grailsApplication.config.t5.value) {
out << body()
}
if (grailsApplication.config.t6.value) {
out << body()
}
if (grailsApplication.config.t7.value) {
out << body()
}
if (grailsApplication.config.t8.value) {
out << body()
}
}
}

Then create controller: grails create-controller home.

Content of the controller is:

class HomeController {
def index = {
render (view:'home')
}
}

Now create home.gsp file within folder views/home/.

Content of the home.gsp is:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="layout" content="main" />
<title>Memory leak</title>
</head>
<body>
Will same situation repeat?
<g:displayExternal>
a
</g:displayExternal>
<g:displayExternal>
a
</g:displayExternal>
<g:displayExternal>
a
</g:displayExternal>
<g:displayExternal>
a
</g:displayExternal>

</body>
</html>

Now in your HOME/.grails directory create file memory-leak-config.groovy file with the following content:

t1 {
value=true
}

t2 {
value=true
}

t3 {
value=true
}

t4 {
value=true
}

t5 {
value=true
}
t6 {
value=true
}
t7 {
value=true
}
t8 {
value=true
}

Now update Config.groovy file to also read external configuration files. Snippet how it should look like is:

 grails.config.locations = ["file:${userHome}/.grails/${appName}-config.groovy"]


if(System.properties["${appName}.config.location"]) {
grails.config.locations << "file:" + System.properties["${appName}.config.location"]
}

Now if I didn't forget some file change you should be able to start application. Open browser and point it to: http://localhost:8080/memory-leak/home First you will notice is that page is loading very long. Then while monitoring memory consumption of Tomcat or Axis refresh page few times. You will see that memory consumption is increasing. And it is never returned to the initial state. If you refresh this page constantly for 10 minutes you should run out of memory.

Well, if you didn't visit grails tutorials yet, you can do it now. It already can stand more than 80 hits (it was running out of memory after 80 hits).

Wednesday, July 9, 2008

Be careful when developing on Windows but hosting on Linux

I know this is kind of old and obvious but any way I had the problem with paths that are not case sensitive on Windows but case sensitive on Linux. I hit this problem while I used grails controller with the name LearningCenterController and had my gsp pages in folder named learningcenter.

Simple code from controller like this one:

def index = {
render (view:'about')
}

worked fine on Windows. Then I deployed changes to my VPS hosting provider and there I had a problem with error reported: file not exists. And of course, this happened because folder names are case sensitive on Linux.

So nothing special but only good well known story: be careful when developing on Windows but deploying on Linux.

And by the way did you already visited grails tutorials? ;)

Monday, July 7, 2008

Experience with Act as Taggable Plugin

While working on grails tutorials site I have also used Act as Taggable plugin. In this post I will try to describe my experience while using this plugin. Although plugin is in alpha phase it gives you solid ground to implement tag cloud. At least you need not to start from the scratch.

First step is of course to install plugin. Download latest version from google code svn repository of Act as Taggable Plugin. Then in the console type:

grails install-plugin grails-acts-as-taggable-0.1.zip 
That line will install plugin. To mark some domain class as taggable add implements Taggable to that domain class. Other basics you can find in act as taggable tutorial on the grails home page.

Let us have a deeper look at what this plugin offers.

If you inspect the code you will see that there are two domain classes Tag and Tagging. This means that this plugin will add two tables into your database. Class Tag represents tag and has only one property: name. Class Tagging is used as connection between Tag and any Taggable class. Interesting property here is String taggableType. This property represents magic how to connect any tag with any taggable domain class. This property equals to the class name of the taggable domain class. This way you are able to connect same or different set of tags to different taggable classes.

Beside those two domain classes there are two more groovy classes: Taggable (already mentioned in previous section) interface and TaggableMixin. Taggable interface is just interface with no methods but it is heavily used within TaggableMixin to add additional methods to all classes that implements this interface. It is really good to have a look at the TaggableMixin class.

TaggableMixin defines four closures: addTag, getTags, setTags, removeTags, and removeTag. Method getTags will return list of all tags for the calling Taggable instance. But as it uses join(" ") to separate tag names, if you have tags with the spaces those tags will be separated into multiple tags. This was not behavior I needed so I added additional closure getTagsAsList. This closure does the same thing as getTags but will not split your tag if it has space. The code of the closure is:

Taggable.metaClass.getTagsAsList = { ->
def taggings = Tagging.findAllWhere( taggableId: delegate.id, taggableType: delegate.class.toString())

def result = taggings.inject([]) {list, tagging ->
list.add(tagging.tag.name)
return list
}

return result
}

Next thing you will probably need is list of tags in this form: [tagName:count, tagName:count,...]. Taggable plugin currently does not offer method that will do it for you so I have created one for me. I didn't put it into source of taggable plugin because I want to minimize merging problems when new version of plugin is released. Code looks like this:

def tagGrouping = Tagging.executeQuery("select distinct t.tag.name, count(t.tag.id) from Tagging t group by t.tag.id")

def values = tagGrouping.inject([:]) {val, obj ->
val.put(obj[0], obj[1])
return val
}

Note that I didn't add control where taggalbeType = 'class of taggable instance'. If you need it just add that line. I think that this method should be part of the TaggableMixin too.

Further on what you will probably need is to get all instances (or subset of them) tagged with provided tag and total number of those instances. So for example you want to get all tutorials tagged with GORM tag. As such query is currently not supported within plugin I have created my methods. Lines of code you can use are:

def tls = Tagging.executeQuery
("select distinct t from TutorialLink t, Tagging tgg, Tag tg
where tg.name = ? and tgg.tag = tg and tgg.taggableType = ? and tgg.taggableId=t.id
order by t.dateCreated desc"
, [params.selectedTag, TutorialLink.class.toString()], [max:max,offset:offset])

def total = Tagging.executeQuery
("select count(t) from TutorialLink t, Tagging tgg, Tag tg
where tg.name = ? and tgg.tag = tg and tgg.taggableType = ? and tgg.taggableId=t.id
order by t.dateCreated desc"
, [params.selectedTag, TutorialLink.class.toString()])[0]

I must admit that these lines are more specialized for grails tutorials but they can be generalized with the minimum effort.

As you can see I took Act as Pluggable plugin and made it more user friendly by adding few simple methods. Hopefully these methods will be soon available in the official plugin. Usage of plugin is simple and gives you excellent base to increase your productivity.

Friday, July 4, 2008

Is development of CRUD apps faster with Grails than with Swing?

To make my point clear immediately at the beginning. I am not claiming that creation of fat rich client is easier in some web framework than with Java or .NET. I am talking about simple CRUD application with three domain objects, and two features that cannot be directly connected with CRUD.

So problem is following. There are three domain objects that should be stored into local database. Domain objects are Calculation, Shop and Item. Relationship between domain is displayed on the following picture:

calculation

So each calculation is made for exactly one shop and can contain number of items. Pretty straightforward domain model. Additional requirements are that ordinal number of Calculation is increased per Shop instance and you are able to print report for each Calculation.

So what are the tools necessary to create simple CRUD application for mentioned domain model. I decided for Swing, Hibernate, HSQLDB, Jasper reports. So how the work goes:

In Java:

As first step you create domain classes and then using some examples on the Internet create hibernate mapping files and hibernate configuration file. Next step is to reuse some your local component that handles SessionFactory initialization or you just find example on the Internet and copy/paste that example. More or less even these simple steps already can bring some headache (e.g. if you mistype property name of your domain object in XML file). And yes I know, probably there is number of tools that can help me with this configuration and I heard about Hibernate annotations too :)

After your domain object is created and database is automatically generated for you real fun begins. You need to create Swing application. You need main frame, dialogs and panels (even reused) to CRUD Shop domain objects and the same thing for Calculation and Items that are part of Calculation. As you need tables to display list of domain objects you have to create corresponding table models, connect listeners to buttons and so on. Everybody that have some experience with Java Swing know that although this is more or less simple and straightforward process it does not mean it will work from the first try. And the most often it will not.

When set of your screens is ready you still need to wire it up with domain and Hibernate (DB). You have to cope with hibernate sessions, lazy loading...

When your application supports all CRUD operations the end is near. You just need to create Jasper report and it is easy with the help of iReport.

Now when you see all steps necessary what would be your estimation for such application. I would say 2-3 days (well I did it in my free time).

In Grails:

Now let us see how all these steps are handled in Grails. Thanks to the GORM, scaffolding and plugins (Jasper plugin particularly) we will see that it is significantly faster with the Grails.

To start first you need to create new Grails application. For this it is enough to type grails create-app.

When your application is created using grails create-domain-class you can generate necessary domain classes. When domain classes are generated you add code for properties and relationships between domain objects. Having this you don't need to worry about Hibernate configuration because Grails will do that automatically for you.

Now when domain objects are ready we need to create user interface of application.

Well creating web user interface can really take time. You need to type generate-all for each domain object or if you are lazy you can reuse UberGenerateAll script. And your user interface is mainly finished (actually you can keep it that way if you want and still you will have nice fully functional web application). If you want you can update generated pages (e.g. remove ids from tables, maybe copy/paste few buttons). More or less easy work. You need to add little bit of behavior to the controllers or domain classes but this work can be only faster with Groovy than it was with Java.

To create report you can reuse Jasper Reports plugin for Grails. This means even all necessary dependencies will be resolved for you :)

And actually simple CRUD application is finished.

Conclusion

While I worked on Java implementation of described application I was thinking why it cannot be easy as with Grails. Anyway I was just repeating steps that I did number of times. Domain classes, Hibernate, Swing, JTables, dialogs. When I finished Java application I generated new Grails application and had basic behavior done in less than hour. It is just great and unbelievable. I didn't do final touches to the Grails application because anyway I didn't need this application in Grails.

But I was thinking, if I use embedded Jetty, embedded browser in Java frame, wouldn't it be easier to finish this application :) Maybe next time I will try.

But another idea that came to my mind is what if we could reuse GORM in the standalone applications, why not to implement scaffolding for Swing front end...

More or less I believe that Grails is excellent web framework that boost your speed and agility. The main problem with Grails is that you are going so fast forward that very often you are forgetting to write tests :) Believe me, I have experienced this on grails tutorials.

Thursday, July 3, 2008

Jasper Reports and JDK vs JRE

Although it was clear to me what happened immediately as I saw stacktrace, I was surprised that it didn't came to my mind during development. One of the tasks I had was to create report in the very simple application. As I wasn't sure about structure of the report and all the fields that should appear in the report I have decided to use jrxml file. jrxml file is XML definition of report and to display it you have to compile it during runtime. The code to do this is actually very simple:

JasperReport report = JasperCompileManager.compileReport("report.jrxml");
When you have instance of the report it is enough to use JasperFillManager to fill it with data.Another possibility is to compile jrxml file to jasper report. This will generate jasper, binary version of the report. When you have compiled report of course you don't have to compile it during runtime.Well, more or less I had XML version of the report, created installation using Null Soft installer, installed it on my computer and everything worked fine. I could create domain objects and display and print reports. So I was happy and delivered the installation to customer (in this case my mom). She installed application without problems, entered necessary data and tried to open report. And then to my surprise report didn't opened but there was message about unexpected error. As soon as I saw the stacktrace it was clear that actually she does not have java installed with JDK but as JRE.And of course JRE is not delivered with compiler and therefore application was not able to compile report. As soon as I changed application to read compiled report everything worked fine. So if you plan to deliver Java application to standard user computers, don't forget to test application on computers where only JRE is installed.