Tuesday, April 22, 2008

Sorting multidimensional arrays in Groovy

I didn't find this solution as quickly as I thought I would so I thought I would post about it here to provide some search engine fodder.

If you are dealing with multidimensional arrays in Groovy (ref: http://groovy.codehaus.org/JN1025-Arrays ) and want to sort them you can expand on the sorting concepts for collections in Groovy (ref: http://groovy.codehaus.org/JN1015-Collections ).

If you look in the last reference you will find the example:
def mc= [
compare: {a,b-> a.equals(b)? 0: Math.abs(a)<Math.abs(b)? -1: 1 }
] as Comparator
We can modify this for a multidimensional array. So some excerpts from my code:
println "Pre sort: ${uniqueAges}"
def mc = [
compare: {a, b -> a[0].equals(b[0]) ? 0 : a[0] < b[0] ? -1 : 1 }
] as Comparator
println "Post sort: ${uniqueAges.sort(mc)}"
results in
Pre sort: [[11.2, 5.32], [1.77, 0.01], [3.58, 1.77], [5.32, 1.77], [5.32, 3.58]]
Post sort: [[1.77, 0.01], [3.58, 1.77], [5.32, 1.77], [5.32, 3.58], [11.2, 5.32]]
or
 println "Pre sort: ${ageZoneList}"
def mc2 = [
compare: {a, b -> a[0][0].equals(b[0][0]) ? 0 : a[0][0] < b[0][0] ? -1 : 1 }
] as Comparator
println "Post sort: ${ageZoneList.sort(mc2)}"
results in
Pre sort: [[[5.32, 11.2], [163.5, 189.62, "Late Miocene"]], [[0.01, 1.77], [0.05, 105.58, "Pleistocene"]], [[1.77, 3.58], [114.82, 123.68, "Late Pliocene"]], [[1.77, 5.32], [103.13, 163.53, "Pliocene"]], [[3.58, 5.32], [137.16, 156.19, "Early Pliocene"]]]
Post sort: [[[0.01, 1.77], [0.05, 105.58, "Pleistocene"]], [[1.77, 3.58], [114.82, 123.68, "Late Pliocene"]], [[1.77, 5.32], [103.13, 163.53, "Pliocene"]], [[3.58, 5.32], [137.16, 156.19, "Early Pliocene"]], [[5.32, 11.2], [163.5, 189.62, "Late Miocene"]]]


Note that in Groovy multidimensional arrays need not have the same exact length at each level as noted in the Array reference above. This does mean that you need to take care with respect to iterating your indexes if your array is triangular. This is not likely the most efficient search for a large multidimensional array, but for simple sorts on smaller examples its working well for me. I would appreciate references for quicker sorts if people have them.

take care
Doug

Monday, April 21, 2008

Spaces in REST URLs

So I need to deal with spaces in REST URL's. Something like:

.../timescale/Late Jurassic

I'd rather not allow these types of URL's (since I don't think the spec even allows them) and was thinking about the programming and also community practices issues this raises. If a person wants a space they likely should use "%20", however this just doesn't look good and I believe gets confusing.

I could simply allow the community to create such URL's even though I believe them wrong and then attempt to resolve them in my Grails application with:

someString.replaceAll("%20", " ")

since firefox and I suspect other browsers will convert the spaces to "%20" for the user.

This seems a poor approach though since if someone puts two spaces into the URL or somehow a tab gets in things get ugly fast. A person just has far too many bad issues to deal with.

Forcing the community to use camel case (here I will use lower camel case but one could use upper camel case) would require a URL like:

.../timescale/lateJurasic

where I could split the parameter in Groovy with:

someString.replaceAll("([A-Z])", " $1").trim()

so "lateJurassic" becomes "late Jurassic" which is what is in my database (actually "Late Jurassic" but I can case insensitive search) since that is the "proper" form of the name.

This puts the burden of creating a camel case representation of "Late Jurassic" on the client end of the application (ie, make this someone else's problem, which is always a good thing).

I suspect this is just a case where the best resource identifier in the database is not always the best resource identifier for the REST URL representation. It would seem then that apply a best practice approach one would use a camel case representation. This might be a situation where using upper camel case is better yet since the proper cases on the name is "Late Jurassic" resulting in a URL:

.../timescale/LateJurassic

That is still fine since the .trim() call will remove the leading space still in the above code. I'd love to hear other thoughts on such mappings.

take care
Doug

Monday, April 14, 2008

Javascript comparison of WebKit and Firefox 3 Beta 5 on Ubuntu

This weekend I had a small pet project I did that gave me a need for a webkit based browser on Linux (Ubuntu 7.04). While I could have used Konqueror I was more interested in a later source base and so downloaded the WebKit r31738 source from http://www.webkit.org. Actually, after a couple simple apt-get install for the development library this source package will compile just fine on a rather stock Ubuntu 7.04 and runs well (Ref: http://live.gnome.org/WebKitGtk ). The default UI shell for the webkit core is ultra basic but all I need for testing against this rendering engine. One can use webkit as the engine for Epiphany (http://live.gnome.org/Epiphany/WebKit ) if you want a nicer wrapper.

I was curious to try this new engine (more specifically it's javascript aspect) against my current favorite browser Firefox in the form of Firefox 3 Beta 5 (http://www.mozilla.com/en-US/firefox/all-beta.html ). A tried both the Dromaeo test suite (still in early release, review notes at: http://wiki.mozilla.org/Dromaeo ) and Sunspider from: http://webkit.org/perf/sunspider-0.9/sunspider.html. My platform is rather paltry Athlon 64 3200+ and 2 gigs of memory running the afore mentioned Ubuntu 7.04.

Firefox 3 Beta 5:
http://dromaeo.com/?id=5552 (3282.80ms)
http://dromaeo.com/?id=5560 (3287.60ms)
SunSpider: 6794.0ms

WebKit
http://dromaeo.com/?id=5556 (3260.60ms)
http://dromaeo.com/?id=5563 (3225.40ms)
SunSpider: 5794.8ms


In the Dromaeo test there is for all practical purposes no difference between the two javascript engines. Sunspider showed a 1.17 factor favor toward the Webkit engine. There has been a lot of recent new traffic over acid3 testing and other performance metrics (http://ajaxian.com/archives/where-is-firefox-on-acid-3-here ). The Firefox ecosystem around its amazing set of add-ones (https://addons.mozilla.org/en-US/firefox/ ) is without question a key factor for me. The Mozilla foundations strong effort on standards, highly open and extensible platform win over a few percentage points from a Javascript benchmark. The acid3's focus on DOM scripting is important to me and so I would like to see that arrive in the Gecko engine though some of the comments of Mike Shaver (http://shaver.off.net/diary/2008/03/27/the-missed-opportunity-of-acid-3/ ) and Rob Sayre (http://blog.mozilla.com/rob-sayre/2008/03/26/acid3-is-basically-worthless/ ) regarding this do make sense to me.

I'm a loyal Firefox user and nothing I have seen from the Webkit camp has yet to give me any pause, though I am glad they are there. We need competition and pressure to drive development forward. It's always good to compare and I am still in a situation where as a developer I need to have various engines around for testing. I also played around with the new Next-Generation Java Plug-in (https://jdk6.dev.java.net/plugin2/ ) and was very impressed with it as well. Especially the easy javascript to applet communication the new plugin delivers.

take care
Doug

Wednesday, March 26, 2008

Grails datasource in resource.xml


So I have the need for a couple extra datasources in my grails application. This turned out to take a bit more research than I first thought it would, though likely just due to my lack of much heavy duty spring experience so far. Basically I just want access to another database resource that is NOT my main datasource used by the hibernate ORM. My domain classes for this application are separate from my need to access this other datasource which I would do just via SQL calls.

A quick review of the Nabble list gave me a couple of leads:
http://www.nabble.com/dataSource-on-ApplicationBootStrap-td11441836.html#a11441836
http://www.nabble.com/multiply-datasources--td10038844.html#a10038844

I created the following entry in resource.xml located in GRAILS_APP/web-app/WEB-INF/spring directory. Create this path and file if it doesn't already exist. The full XML document is like:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">

<bean id="dataSourceJanus" class="org.springframework.jdbc.datasource.SingleConnectionDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="'jdbc:oracle:thin:@xxx.xxx.xxx.xxx:1521:janware"/>
<property name="username" value="NAME"/>
<property name="password" value="PASSWORD"/>
</bean>
</beans>


though you may only need the bean entry if the file already exists of course. Thanks Alex (again) for finding my insanely stupid typo in this file. I stared for hours (sad to say) at it.

The only tricky part is that you can not directly reference the new datasource ( here called dataSourceJanus in my example) in say your controller class. Rather you will need to implement ApplicationContextAware. So you will have something like:

//  Needed for datasource 
import org.springframework.jdbc.core.JdbcTemplate
import groovy.sql.Sql


// Spring
import org.springframework.beans.BeansException
import org.springframework.context.ApplicationContext
import org.springframework.context.ApplicationContextAware
import org.codehaus.groovy.grails.commons.GrailsApplication

class FacetController implements ApplicationContextAware {

GrailsApplication grailsApplication
ApplicationContext appCtx

def void setApplicationContext(ApplicationContext arg0) throws BeansException {
appCtx = arg0;
}

...

This will get you your application context object. Now it's rahter straight forward to use:

def showFacets = {
def jt = new JdbcTemplate(appCtx.dataSourceJanus)
def sqlString = "select latitude_degrees, longitude_degrees from hole where leg like '101' and site like '631' and hole like 'A'"
response.contentType = "text/plain"
jt.queryForList(sqlString).each {
response.outputStream << "${it.latitude_degrees} ${it.longitude_degrees}"
}
}

That is just a dead simple method to call the datasource (bold) and writes directly to the output stream. Not the org.springframework.jdbc.core.JdbcTemplate import in the previous code sample along with the other imports used for the application context. Obviously you will likely return to a view or render a JSON serialization or some such in your method rather than write directly to the outputStream.

If you place def jt = new JdbcTemplate(appCtx.dataSourceJanus) outside the scope of the method you get a null reference at start up. So it seems this should be scoped inside the method that uses it. However, this logic might be better moved into a service class anyway depending on how much you will use it.

Some additional good reading on this includes:
Datasources: http://docs.codehaus.org/display/GRAILS/DataSources+New
Using JNDI resources instead: http://docs.codehaus.org/display/GRAILS/JNDI+Data+Sources
Spring Bean Builder: http://grails.org/Spring+Bean+Builder
Application Context: http://grails.org/Services

If you review and follow some of the thread in the Nabble site, you will see that seems one could in fact use dynamic methods with this new datasource if you do a few extra steps. I have not done this but it appears to involve making some entries in the hibernate.cfg.xml file. Reference http://www.nabble.com/How-to-get-multi-dataSource-in-grails--td12291409.html#a12291409 for some comments I found on trying to do this. There does seem to be some issues I am hearing about having/using dynamic methods on multiple datasource though, so I am not sure how this all plays out.

For my needs however, just having an SQL resource that I could use the very nice Groovy SQL capacity with.

enjoy
Doug

Thursday, December 06, 2007

Flot plotting in Grails:

I came across the FLOT package (Ref: http://code.google.com/p/flot/ ) while reading Ajaxian (Ref: http://ajaxian.com/archives/plotting-in-jquery ). Flot uses the jQuerry package (Ref: http://jquery.com/ ) to do client side plotting. I wanted to see how this works when dropped into Grails. As expected the results are quite nice.

The set up is rather easy. Obtain the jquery.flot-0.1.js and jquery-1.2.1.min.js files (your versions will obviously change with the march of time) and place these in your web-app/js directory of your grails project.
You will need to reference these in your GSP page HEAD tag with something like:

  <g:javascript library="jquery-1.2.1.min"/>
<g:javascript library="jquery.flot-0.1"/>


At this point your are basically done. You can review the URL's at the top of this page for better information straight from the source. Basically, you will need to place into the BODY tag of your GSP something like the following:

 <div id="placeholder2" style="margin-left:100px;width:600px;height:300px;"></div>

<script id="source2" language="javascript" type="text/javascript">
$(function () {
var d1 = [];
for (var i = 0; i < 14; i += 0.5)
d1.push([i, Math.sin(i)]);

var d2 = ${array};

$.plot($("#placeholder2"), [ d1, d2 ]);
});
</script>

Here is the only interesting aspect of all this. The line var d2 = ${array} is referencing a list from the controller:

  def jflotPlot = {
def array = [[4, 6], [5, 7], [9, 2]]
[array: array]
}


Likely your controller will get more interesting data. ;) This is just a really quick and dirty copy paste job of the examples from the above references into a Grails app. Flot can already at version 0.1 do more types and plots and zooming and other very slick features (see the demos at the flot site ). Integration with Grails is quick and easy.

enjoy
Doug

Wednesday, November 14, 2007

Grails + ROME + geoRSS

Grails + ROME + geoRSS

If you are looking to do some RSS/ATOM feeds in Grails you likely are looking at either at the examples that Glen Smith has done (ref: http://blogs.bytecode.com.au/glen/2006/12/22/1166781151213.html ) or to work with the Feeds plugins (ref: http://grails.org/Feeds+Plugin ) by Marc Palmer. Both are excellent places to start.

What I want to talk about there is adding geospatial data to a RSS feed in the Grails framework by building off this work. The above efforts leverage off the ROME package from http://rome.dev.java.net. For geospatial elements there is the GeoRSS Module for ROME by Marc Wick (ref: http://georss.geonames.org ).

Adding this ability to a Grails project is rather easy. Obviously you need to have the Rome and GeoRSS jar files from these referenced sites in your project lib directory. From there you can do something like the following. Please note these examples are based on the work of these previously mentioned individuals and the credit is theirs. I just glued things together.

So likely you will end up with something like this in your controller:

  // some import for this..   (watch me polute my namespace) ;)
import com.sun.syndication.feed.synd.*;
import com.sun.syndication.io.SyndFeedOutput;
import com.sun.syndication.feed.module.georss.*;
import com.sun.syndication.feed.module.georss.geometries.*;


def supportedFormats = ["rss_0.90", "rss_0.91", "rss_0.92", "rss_0.93", "rss_0.94", "rss_1.0", "rss_2.0", "atom_0.3"]

def rss = {
render(text: getFeed("atom_0.3"), contentType: "text/xml", encoding: "UTF-8")
}

def all = {
def format = params.id
if (supportedFormats.contains(format)) {
render(text: getFeed(format), contentType: "text/xml", encoding: "UTF-8")
} else {
response.sendError(response.SC_FORBIDDEN);
}
}

def getFeed(feedType) {

def ageModels = AgeModel.list()
def jdb = Sql.newInstance('[ WE ARE MAKING SQL CALLS SO THE CONNECT STRING GOES HERE. GORM WOULD BE NICER, BUT NOT AN OPTION FOR ME')

def entries = []
ageModels.each {ageModel ->
List functionData = jdb.rows("select latitude_degrees, longitude_degrees from hole where leg like ${ageModel.leg} and site like ${ageModel.site} and hole like '${ageModel.hole}'")
def locationString = functionData[0][1] + ", " + functionData[0][0]

def desc = new SyndContentImpl(type: "text/plain", value: "Entry for leg " + ageModel.leg + " locate at " + locationString + ageModel.rating + " " + ageModel.status);
def entry = new SyndEntryImpl(title: ageModel.leg + "_" +ageModel.site + ageModel.hole + " - " + ageModel.user,
link: 'http://localhost:8080/janusAmp/rest/lsh/' + ageModel.leg + "/" + ageModel.site+ "/"+ageModel.hole,
publishedDate: ageModel.date, description: desc);

// Select the style of encoding you want to do.
// def geoRSSModule = new W3CGeoModuleImpl()
// def geoRSSModule = new GMLModuleImpl()
def geoRSSModule = new SimpleModuleImpl()
geoRSSModule.setPosition(new Position(functionData[0][0], functionData[0][1]));
entry.getModules().add(geoRSSModule);
entries.add(entry);
}

SyndFeed feed = new SyndFeedImpl(feedType: feedType, title: 'Recently added age models',
link: 'http://www.chronos.org', description: 'List of age models from Janus data',
entries: entries);

StringWriter writer = new StringWriter();
SyndFeedOutput output = new SyndFeedOutput();
output.output(feed, writer);
writer.close();

return writer.toString();
}

The only thing different than what Glen, shows in his blog is the addition of the bold lines to add in the geoRss element. The result... geospatially enabled RSS feeds in the Grails framework (and anywhere else for Groovy and Java of course)

A few things to note:
a) While Google Earth and Google Maps should read this output I had some issues with the resulting files. Running things through the validator at: http://cite.opengeospatial.org/test_engine/georss_validator/ one gets some errors related to the namespaces. I noticed that the examples for RSS feeds at http://georss.org/ even had some issues. While the ATOM version validates ok the RSS based feed errors out in the same way that my generated feeds do. Likely this is an issue with ROME and if I track down the issue I will follow up on it. Until the feeds validate these feeds do not appear to work in Google Earth or Maps.
b) However, you can generate the rss version 2 feed with the SimpleModuleImpl() from the georss jar file and that will translate correctly with the rss to kml style sheet found at http://www.kovacevic.nl/hacks/kml/georss2kml.xsl (ref: http://www.kovacevic.nl/blog ).

RSS to KML via XSL in Grails:

So you can drop into your controller something like:
  def kml = {
def xslPath = getAppPathService.serviceMethod().toString() + "georss2kml.xsl"
def kmlxsl = new File(xslPath).getText().toString()
def rssxml = getFeed("rss_2.0")

def mywriter = new StringWriter()

def factory = TransformerFactory.newInstance()
def transformer = factory.newTransformer(new StreamSource(new StringReader(kmlxsl)))
transformer.transform(new StreamSource(new StringReader(rssxml)), new StreamResult(mywriter))

render(text: mywriter.toString(), contentType: "text/xml", encoding: "UTF-8")
}
you make also need the following in your code for XSL support:
//  for the XSLT transform
import javax.xml.transform.TransformerFactory
import javax.xml.transform.stream.StreamResult
import javax.xml.transform.stream.StreamSource

into your controller where AppPathService is (not mine.. but I don't have the reference for this.. bad me)

 import org.codehaus.groovy.grails.commons.*
import org.apache.commons.logging.*

import org.springframework.beans.BeansException
import org.springframework.context.ApplicationContext
import org.springframework.context.ApplicationContextAware

class GetAppPathService implements ApplicationContextAware {

GrailsApplication grailsApplication
ApplicationContext appCtx

boolean transactional = true

def void setApplicationContext(ApplicationContext arg0) throws BeansException {
appCtx = arg0;
}
def serviceMethod() {
String applicationPath = "${appCtx?.getServletContext()?.getRealPath("/")}"
return applicationPath
}
}
What the KML does is load in the XSL file (it's looking at the root of the response which will be your web-apps directory. You can move and alter this as you wish. Of course you could simple place the XSL in the controller too like at http://groovy.codehaus.org/Processing+XML+with+XSLT which is what kml method is based on. I like this this way a bit better. At this point you should be generating KML from this and Google Earth and Google Maps should load and monitor this URL just fine.

I do want the get the GeoRSS feed vaildating though and will work on that effort as noted.

enjoy
Doug

Monday, November 12, 2007

Checking REST and RSS style feeds

Continuing to do work with REST in Grails as well as RSS feeds. One issue is testing some of these URL's. In my last post I spoke about a groovy client using Apache's http client package which is quite nice for doing testing with. I also ran across this Firefox extension (RestTest) which is quite handy.

I also found this to a nice tool for testing RSS feeds with since it's not hard to get into a situation these days where your browser will either try and show you the RSS styled up or even redirect you to Google Reader or some other RSS reader. You can put the RSS/ATOM URL into this extensions interface and simply retrieve the XML of your feed for inspection during coding.

On the topic of RSS/ATOM and Grails check out the Feeds Plugin at the Grails site.