Tuesday 14 June 2011

Two nice Groovy design patterns

Putting my deep SQL and HSQL roots on hold I took advantage of Hibernate Criteria (via the excellent Groovy builder for super readable code) to safely generate a dynamic query today. I stumbled into two problems:
  1. how to keep things DRY - can I avoid rewriting the same query multiple times when simple things change?
  2. how can I elegantly query associations whose names I do not know in advance?
I was able to resolve both issues quite satisfactory.

Keeping queries DRY

My first attempt was to create a basic query structure as a Groovy closure and then modify it at runtime as the exact query would be known. Couldn't make it work. Fortunately, the second attempt was more successful: I used a simple factory pattern to create the closure dynamically before feeding it into the Criteria Builder:
def createQuery = { Boolean discriminate ->
	 return {
	 	 projections {
	 	 	 sum "property"
	 	 }
	 	 if (discriminate) {
	 	 	 idEq 42
	 	 }
	 }
}
MyClass.createCriteria().list(createQuery(false))

Choosing associations dynamically

In order to reference an association, you have to use its name in the closure as a method call with a closure as the parameter. Suppose you have the name of the property in a string object, how do you call it as a method in the closure ? Using evals could've worked, but that would present a serious security risk. Groovy's GStrings to the rescue:
def discriminateProp = params.prop
def discriminateBy = params.val
def createQuery = { Boolean discriminate ->
	 return {
	 	 projections {
	 	 	 sum "property"
	 	 }
	 	 if (discriminate) {
	 	 	 "${discriminateProp}" {
	 	 	 	 	 idEq discriminateBy.toLong()
	 	 	 }
	 	 }
	 }
}
MyClass.createCriteria().list(createQuery(true))
I still have to wrap my brains around possible security risks of this approach, but at the first glance it seems solid.

Tuesday 7 June 2011

Simulating native Javascript events

I just solved an issue that's been bugging me. When creating Javascript unit tests, I would like to trigger native DOM events. I'm using jQuery and despite what their API documentation says, some events not bound via jQuery cannot be triggered with the standard jQuery commands. So after some googling I've found a function that can be included in my unit tests to trigger those events:
window.simulateMouseEvent = function(eventName, element) {
	var evt = document.createEvent("MouseEvents");
	evt.initMouseEvent(eventName, true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
	var cb = element
	var canceled = !cb.dispatchEvent(evt);
}
So a sample call could look something like this:
simulateMouseEvent("mouseup", $("#myControl")[0]);