Monday, March 23, 2009

Leveraging propertyMissing and toRowResult() on resultSet

NOTE: Instead of using propertyMissing below, use @Delegate as described in this later post: http://reumann.blogspot.com/2009/04/using-groovy-delegate.html

The groovy documentation is good in some areas, and stinks in others. I wish they covered sql and jdbc stuff a bit more. This is probably basic for many of you, but I figure I'll post it anyway.

First off, when returning sql back using Sql.eachRow, I wanted to build a collection of objects I could use directly. You can't use the ResultSet items returned directly, but I did find you can generate a GroovyRowResult object by calling toRowResult on each object. So your eachRow could look like:


def results = []
sql.eachRow(query) {
results << it.toRowResult()
}


Of course the above assumes you want to work the column names as property names directly as they are returned from your sql. This was fine for me, but when dealing with the results, I wanted to call some other properties on each result that would be a composite or calculated from the resulting GroovyRowResult. As an example, I might be getting back firstName and lastName, but I also wanted a "fullName" property comprised of firstName + lastName.

There are probably a lot of ways to do this, but what seemed clean to me was to create a groovy object that I'd stuff each GroovyRowResult into and rely on overriding "propertyMissing" to help me out. My new object acts as an Adapter wrapping the GroovyRowResult. Here's an example:

//Employee.groovy

class Employee {

def row

Employee( row ) {
this.row = row
}

//look up missing property in GroovyRowResult:
def propertyMissing(String prop) {
def result = row."${prop}"
}

String getFullName() {
return this.firstName+" "+this.lastName
}
}


//Usage

def results = []
sql.eachRow("SELECT * FROM Employee") {
results << new Employee( it.toRowResult() )
}

//see it works:
println "first: ${results[0].firstName}"
println "full: ${results[0].fullName}"

Sunday, March 22, 2009

jQuery change select options when other select changes

A common thing to do, but figured I'd post how I do it here. (I wrote this initially for a sample at http://www.learntechnology.net/content/ajax/jquery_options.jsp. In the case below I'm retuning JSON from the server side component (in this case a Stripes actionBean.)

Import your jQuery javascript file. Then in your html or external script:


$(document).ready(function() {
$(function() {
$("select#companies").change(function() {
$.getJSON("Companies.action?emmployees=",{companyID: $(this).val(), ajax: 'true'}, function(j){
var options = '';
for (var i = 0; i < j.length; i++) {
options += '<option value="' + j[i].value + '">' + j[i].label + '</option>';
}
$("select#employees").html(options);
})
})
})
});


My initial select has an id "companies" (ie <select id="companies"). The select to populate is simply defined as:


<select name="employeeID" id="employees"></select>


The server side component just needs to return json with your employees objects with fields "label" and "value"

Wednesday, March 4, 2009

Maven2-Groovy-JUnit-Guice

Here's how I'm currently setting up my testing with groovy and maven, using Guice and JUnit. (I had trouble getting this all to work with TestNG, which is my preferred testing framework, so if someone gets it all working, please let me know.)

I'm usting AtUnit to help out with the Guice/JUnit integration. It makes things very simple.

In your pom.xml build plugins section:


<plugin>
<groupid>org.codehaus.groovy.maven</groupid>
<artifactid>gmaven-plugin</artifactid>
<version>1.0-rc-4</version>
<executions>
<execution>
<goals>
<goal>generateStubs</goal>
<goal>compile</goal>
<goal>generateTestStubs</goal>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>


My groovy tests are located in src/test/groovy (Using Eclipse I then mark this as a source folder also so it's easier to use in a flattened package structure.)

When you look at the AtUnit examples, you'll see several ways to set things up. I like to use my existing Guice module class that I've already created, so I start out with a TestBase class that my tests will extend...


public class TestBase implements Module {

public void configure(Binder binder) {
binder.install(new MyGuiceModule());
}
}


If you don't want to use a Module, you can just do all your binding right in the configure method above and everything will work just fine (and this is the way they demonstrate on the AtUnit site example.)

Now one of my groovy tests:


@RunWith(AtUnit.class)
@Container(Container.Option.GUICE)
public class ExecutionLogTest extends TestBase {

@Inject @Unit ExecutionLogs execLogs;

@Test
public void testExeuctionLogs() {
println "testExeuctionLogs"
//... execLogs.find(... )
}
}


mvn clean install and that's it.

Sunday, March 1, 2009

Finally finished watching SGA Season 5

Finally got caught up watching the last few episodes of Stargate Atlantis. I really liked SGA, although it started getting really old how simple it was for the team to just walk around hive ships without too much trouble. You'd think the wraith could have beefed up security just a tad.

Supposedly another spin off show "Stargate: Universe" will be next http://www.thrfeed.com/2008/08/stargate-univer.html

Blogger Syntax Highliter