Saturday, December 26, 2009

Grails - a decomposed application project

Hi there,

I've been looking around for ways to nicely decompose a large application (an Enterprise Application so to speak) using Grails. It turns out this platform has such a capability already build-in! Interested? Read on...

The basic building blocks of Grails are plugins. There's a plugin for everything: the ORM layer, IoC container, security, twitter access - you name it! So how is this going to help us decompose a large enterprise-grade application? Well, we're going to compose it from... plugins!

Here's a step-by-step instruction on how to create the main application along with one additional pluging. Other plugins can be added exactly the same way as the single one mentioned here.
  1. Create a grails application (we're going to name it "myapp" here) using standard Grails command grails create-app myapp
  2. Do not change the folder just yet to myapp - instead issue the following Grails command: grails create-plugin myapp-plugin
  3. cd to myapp
  4. Add the line plugins.myapp-plugin=0.1 to application.properties (that's in the main application, not in the plugin!)
  5. cd to grails-app/conf
  6. Add the following line to BuildConfig.groovy: grails.plugin.location.'myapp-plugin' = '../myapp-plugin'
  7. cd out of the application and into the myapp-plugin folder
  8. Issue grails package-plugin command to create plugin.xml
  9. cd back to your application and run it as usual using grails run-app
That's it! Whenever you make changes to your plugin they will be automatically picked up just as if they were a part of your main application which is the greatest feature ever!

Have fun!

Friday, December 25, 2009

Groovy - dumping object's properties

Marry Christmas! This is the Christmas Eve and what follows is a Christmas Present for you!

Have you ever used BeanUtils from Apache to query the properties of an object? Was that easy? Well I did that and what I ended up was completely unreadable and chaotic. But there's good news! Here's how it's doable in Groovy:
object.properties
That's it! Groovy exposes the map of properties as a predefined property called "properties". Ain't that cool? Let's see how we would go about printing all the values of object's properties along with their names:
println object.properties.collect{it}.join('\n')
Here's what it's doing: it gets the map of properties, turns it into a list (collect{it}) and joins them with a new line character.

Did you notice that "class" is also one of the properties? That's nasty! How about filtering it out?
println object.properties.findAll{it.key != 'class'}.join('\n')
Now that's much better, but good only for one or two names to filter. How about a more general solution?
def filtered = ['class', 'active']
println object.properties
.collect{it}
.findAll{!filtered.contains(it.key)}
.join('\n')

That's much much better but still, if the object has like 15 properties looking them up is a pain if they are not sorted. Let's do something about it:
def filtered = ['class', 'active']

println object.properties
.sort{it.key}
.collect{it}
.findAll{!filtered.contains(it.key)}
.join('\n')

And there it is! A list of key=value (value taken from object's toString()) separated by a new-line character for easier browsing :)

I hope this will help you out with your Groovy adventures!

Have a nice holiday!

Sunday, December 20, 2009

Deploying Grails application on Tomcat6 on Ubuntu

Hi,

I've just had a few moments of struggle deploying my Grails application onto Tomcat installed via apt-get in Ubuntu. Thanks to the Ubuntu forum it didn't morph into a war :)

After apt-get install tomcat6 and putting my application into the webapps folder I've restarted Tomcat using the usual script but could not access my application at all. The log said something like this:

SEVERE: Exception sending context destroyed event to listener instance of class org.codehaus.groovy.grails.web.util.Log4jConfigListener
java.security.AccessControlException: access denied (java.util.PropertyPermission grails.env read)

After a few minutes of search I found the answer. By default Tomcat on Debian and Ubuntu uses a security manager that prevents application to access environment variables. Why this is the case I don't know but it is. And it is easy to turn it off. Just edit the file /etc/default/tomcat6 and change the line that reads

#TOMCAT6_SECURITY=yes

into

TOMCAT6_SECURITY=no

and live is good again.

Hope this helps!

Friday, December 18, 2009

Grails - the search is over

Recently I've been crushed with the simplicity of Grails framework. For those of you who don't know what's this thing is all about please check the Grails web site - it's well worth your while!

Here are some highlights I've checked out during the evaluation process:
  • Grails combines the best open source technologies into one easy to use framework (Spring IoC, Hibernate, Spring MVC, Spring WebFlow)
  • Additional integrations are as easy as one-line plugin installation (Jabber integration, JMS integration, additional view capabilities, JavaMelody monitoring - just to name a few)
  • ActiveRecord pattern as well as dynamic finders rock!

Stay tuned for some working examples. I'll post them during the weekend.

Monday, December 7, 2009

Transcoding AVCHD using latest FFMPEG build

Recently I found myself arguing with ffmpeg to accept the fact that my template for libx264 is in fact where I know it is. Some time ago it was pretty simple - you just had to copy the template into the current directory and use the form -vpre ./preset to make ffmpeg use it. Unfortunately after last update of ffmpeg this is not the case anymore...

After some time I've finally figured it out. Due to some incompatibility between the Linux version and Win32 binary the only place where ffmpeg is actually properly looking for those templates is

%HOME%/.ffmpeg

To that end I've created the following batch script and copied the ffmpeg's x264 templates to a subfolder .ffmpeg where my ffmpeg binary lives:
@echo off
SETLOCAL
SET HOME=%~d0/
ffmpeg.exe %*
ENDLOCAL

And that's it! Now ffmpeg thinks that the home folder is where it lives and I don't have to pollute my home folder with stuff that doesn't belong there.

You can download the latest FFMPEG binaries from here (you want the "static" version for this setup).

Have fun!


Code coverage and Enum types

Hi,

I've been trying really hard to achieve 100% code coverage on one of the projects I'm working on right now. Pretty much all my business code showed the desired code coverage right up to the point where I introduced enumeration.

First let me explain why I wanted to get to the 100% in the first place.

Whenever I'm writing code that should be covered by unit tests (which is pretty much always nowadays) I'd like to be reminded (by either the code coverage results in CI or by the IDE) that some of the edge cases have not been tested yet. I know this might sound bad in the first place because I should only write as much code as required to satisfy the test I wrote but still - there are cases where the business code I produced does a little bit more than what's in the test. So it's a good idea to keep the 100% test coverage at all times so that once it drops below this magic number I'll notice immediately that something has been skipped.

Back to enumerations.

Those guys contain synthetic methods generated by the compiler (like valueOf and values) that do exist in the byte code but have no corresponding lines in the code itself. This means that there's more that meets the eye from the code's perspective but the code coverage tools I use (Cobertura and EclEmma) know only about byte code and they couldn't care less if the method they are testing came from the code itself or if it was dynamically generated by the compiler.

To that end, whenever I use an Enum the overall coverage drops like stone which simply looks awful.



But there's hope! One line of stupid test and all is green again.

MyEnum.valueOf(MyEnum.VALUE.toString());








I admit that the actual value of this test is minimum but the real reason to do that is to allow yourself the luxury to always react on the drop of coverage below 100% instead of manually checking every time if what's missing is really something we don't care about.

I hope this helps.