<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-7651912408580529938</id><updated>2011-09-17T08:46:10.404-05:00</updated><category term='georss'/><category term='atom'/><category term='plotting'/><category term='grails'/><category term='flot'/><category term='groovy'/><category term='root'/><category term='rss'/><title type='text'>Fils</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>42</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-3190485877111547991</id><published>2009-05-01T15:44:00.001-05:00</published><updated>2009-05-01T15:44:10.699-05:00</updated><title type='text'>Varnish Reverse Proxy Accelerator (Ca...</title><content type='html'>&lt;i&gt;Intro:&lt;/i&gt;&lt;br&gt;The need to offer a mechanism to accelerate the performance of web applications could arguably be even more relevant as we move into a a more linked data approach.&amp;nbsp; With the need to possible offer multiple representations of a single resource URI to address needs for XML, RDF or XHTML+RDFa (or microformats) etc. the need to improve performance and address request from cache when possible increases. &lt;br&gt;&lt;br&gt;&lt;i&gt;Related:&lt;/i&gt;&lt;br&gt;Past efforts in this area have involved Apache Connectors to Tomcat (Ref: &lt;a title="http://tomcat.apache.org/connectors-doc/index.html" target="_blank" href="http://tomcat.apache.org/connectors-doc/index.html" id="fb0l"&gt;http://tomcat.apache.org/connectors-doc/index.html&lt;/a&gt; ) and also reviewing Glassfish.&amp;nbsp; Glassfish Portfolio (Ref: &lt;a title="http://www.sun.com/software/products/glassfish_portfolio/" target="_blank" href="http://www.sun.com/software/products/glassfish_portfolio/" id="dm1h"&gt;http://www.sun.com/software/products/glassfish_portfolio/&lt;/a&gt; ) has many elements focused on performance and there is also Galssfish Grizzly (Ref: &lt;a title="https://grizzly.dev.java.net/" target="_blank" href="https://grizzly.dev.java.net/" id="fg0f"&gt;https://grizzly.dev.java.net/&lt;/a&gt; ) which offers some some impressive sounding performance aspects using NIO.&amp;nbsp; &lt;br&gt;&lt;br&gt;&lt;i&gt;Approach:&lt;/i&gt;&lt;br&gt;However, to address needs of maintaining URI persistence and caching what was really needed was a "reverse-proxy accelerator".&amp;nbsp; Given that set of criteria I arrived soon at using Varnish (Ref: &lt;a title="http://varnish.projects.linpro.no/" target="_blank" href="http://varnish.projects.linpro.no/" id="dnyi"&gt;http://varnish.projects.linpro.no/&lt;/a&gt; ).&amp;nbsp; The target application is hosted on Glassfish but obviously Varnish can reverse proxy for a number of machines and any backend talking over http.&amp;nbsp; Indeed, it's this ability that is important to me in order to address my desire to be able to alter systems and networking aspects behind Varnish and have it maintain my URI's in a "Cool URIs" style/approach (Ref: &lt;a title="http://www.w3.org/Provider/Style/URI" target="_blank" href="http://www.w3.org/Provider/Style/URI" id="vj5p"&gt;http://www.w3.org/Provider/Style/URI&lt;/a&gt; ).&amp;nbsp; &lt;br&gt;&lt;br&gt;Following the nice tutorial by Jay Kuri, that is located on that site it is rather easy to get Varnish up and running on Linux and doing reverse proxy and caching.&amp;nbsp;&amp;nbsp;&amp;nbsp; I would like highlight a few things Jay, mentioned in that write up and detail a few aspects I ran into.&amp;nbsp; &lt;br&gt;&lt;br&gt;One of the biggest that Jay, mentions is the issue around Varnish not wanting to cache anything that has a cookie reference.&amp;nbsp; Since almost all web based applications are going to do this as a simple session management approach (even if you are not doing accounts), Varnish by default will not cache your URIs.&amp;nbsp;&amp;nbsp;&amp;nbsp; Jay, goes on to recommend code like:&lt;br&gt;&lt;br&gt;&lt;div style="margin-left: 40px;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (obj.http.Cache-Control ~ "max-age") {&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; unset obj.http.Set-Cookie;&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; deliver;&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;br&gt;&lt;/div&gt;&lt;br&gt;to override this behavior and respond from cache for content.&amp;nbsp; As noted this does mean that is starts to become depending on the content provider/web app developer to issue the commands to inform cache system like Varnish about the behavior we expect from them.&lt;br&gt;&lt;br&gt;&lt;i&gt;Setting behavior in Grails:&lt;/i&gt;&lt;br&gt;Using Grails (Ref: &lt;a title="http://www.grails.org" target="_blank" href="http://www.grails.org" id="t.g8"&gt;http://www.grails.org&lt;/a&gt; ) it's easy to set the format of our return in via the &lt;span style="font-family: Courier New;"&gt;withFormat{}&lt;/span&gt; syntax.&amp;nbsp; Note we would want to make the approapriate entries in our Config.groovy grails.mime.types section (Ref: The "content negotiation" section of &lt;a title="http://www.grails.org/1.0+Release+Notes" target="_blank" href="http://www.grails.org/1.0+Release+Notes" id="y_ix"&gt;http://www.grails.org/1.0+Release+Notes&lt;/a&gt; ) &lt;br&gt;&lt;br&gt;So something like:&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-family: Courier New;"&gt; withFormat {&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; html {&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; response.setHeader("Vary", "Accept")&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; def nowPlusHour = new Date().time + 3600000&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; response.addHeader("Last-Modified", &lt;/span&gt;&lt;br&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; String.format('%ta, %&amp;lt;te %&amp;lt;tb %&amp;lt;tY %&amp;lt;tH:%&amp;lt;tM:%&amp;lt;tS %&amp;lt;tZ', new Date()))&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; response.addHeader("Expires", &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; String.format('%ta, %&amp;lt;te %&amp;lt;tb %&amp;lt;tY %&amp;lt;tH:%&amp;lt;tM:%&amp;lt;tS %&amp;lt;tZ', &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; new Date(nowPlusHour)))&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [allSites: allSites, allAutoSites: onlyAutoSites]&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; rdf {&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; def data = modelAsRDFService.asRDF(AgeModel.findAllByLeg(params.id),&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; "/loc/sites/${params.id}")&lt;/span&gt;&lt;br&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; response.setHeader("Vary", "Accept")&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; response.contentType = "application/rdf+xml"&lt;br&gt;&lt;/span&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; def nowPlusHour = new Date().time + 3600000&lt;/span&gt;&lt;br&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; response.addHeader("Last-Modified", &lt;/span&gt;&lt;br&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; String.format('%ta, %&amp;lt;te %&amp;lt;tb %&amp;lt;tY %&amp;lt;tH:%&amp;lt;tM:%&amp;lt;tS %&amp;lt;tZ', new Date()))&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; response.addHeader("Expires", &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; String.format('%ta, %&amp;lt;te %&amp;lt;tb %&amp;lt;tY %&amp;lt;tH:%&amp;lt;tM:%&amp;lt;tS %&amp;lt;tZ', &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; new Date(nowPlusHour)))&lt;/span&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; response.outputStream &amp;lt;&amp;lt; data&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp; }&lt;/span&gt;&lt;br&gt;&lt;br&gt;In this code we have set the LAST-MODIFIED and EXPIRES header entries. Note in this simple example I have simply pushed the expires time ahead by one hour.&amp;nbsp; You can set this however you wish depending on your view of the relative age your resources can be and still be valid.&lt;br&gt;&lt;br&gt;The VARY header is set to address some linked data best practices.&amp;nbsp; This informs the client that the representation of this resource URI can change based on how we call it.&amp;nbsp; Here it can be requested as HTML&amp;nbsp; (what is in fact XHTML+RDFa in our case..&amp;nbsp; a whole topic in itself) and RDF.&lt;br&gt;&lt;br&gt;There is no builder for RDF, so I simply pass the model to a service that generates and returns this for me. &amp;nbsp; The Export Plugin (Ref: &lt;a title="http://www.grails.org/Export+Plugin" target="_blank" href="http://www.grails.org/Export+Plugin" id="rtcb"&gt;http://www.grails.org/Export+Plugin&lt;/a&gt; ) might be worth looking at if you are looking for various other formats to serialize your data to.&amp;nbsp; I don't set the content type for the HTML in the code above, on review I likely should though by default it is coming back as text/html so that may be fine. &amp;nbsp; &lt;br&gt;&lt;br&gt;Be sure to have your RDF contain a reference to itself and its resource URI if you are doing a linked data approach.&amp;nbsp; &lt;br&gt;&lt;br&gt;There is also likely other response header elements one could consider here based on the reverse proxy and caching needs.&amp;nbsp; A review of &lt;a title="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.4" target="_blank" href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.4" id="e3d4"&gt;http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.4&lt;/a&gt;  and your accelerator package may reveal other setting of value for your particular environment. &lt;br&gt;&lt;br&gt;&lt;i&gt;Using curl to validate behavior:&lt;/i&gt;&lt;br&gt;While I really love Firebug, I found it to not be the easiest to use to verify proper cache behavior by Varnish.&amp;nbsp; Rather, I used (being a bit of CLI lover), curl.&amp;nbsp; A curl request on a resource URI is made using the -D out option to capture the headers.&amp;nbsp; Two consecutive headers are shown below:&lt;br&gt;&lt;br&gt;&lt;span style="font-family: Courier New;"&gt;HTTP/1.1 200 OK&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;X-Powered-By: Servlet/2.5&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;Server: Sun Java System Application Server 9.1&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;Vary: Accept&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;Last-Modified: Fri, 1 May 2009 16:10:00 CDT&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;Expires: Fri, 1 May 2009 17:10:00 CDT&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;Content-Type: image/png&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;Content-Length: 20951&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;Date: Fri, 01 May 2009 19:59:32 GMT&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;b style="font-family: Courier New;"&gt;X-Varnish: 868897910&lt;/b&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;Age: 0&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;Via: 1.1 varnish&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;Connection: keep-alive&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;HTTP/1.1 200 OK&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;X-Powered-By: Servlet/2.5&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;Server: Sun Java System Application Server 9.1&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;Vary: Accept&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;Last-Modified: Fri, 1 May 2009 16:10:00 CDT&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;Expires: Fri, 1 May 2009 17:10:00 CDT&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;Content-Type: image/png&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;Content-Length: 20951&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;Date: Fri, 01 May 2009 19:59:34 GMT&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;b style="font-family: Courier New;"&gt;X-Varnish: 868897911 868897910&lt;/b&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;Age: 2&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;Via: 1.1 varnish&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;Connection: keep-alive&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;br&gt;Note the two values in the X-Varnish response header entry indicating to us that the content came from the previously cached content.&amp;nbsp; If we continually saw only one number here would need to investigate why our request is being passed through to the backend server.&lt;br&gt;&lt;br&gt;&lt;i&gt;Conclusion:&lt;/i&gt;&lt;br&gt;Varnish, with a few considerations related to explicate cache control instructions provides a nice acceleration to web application performance.&amp;nbsp; As a from the start reverse proxy (vs something like Squid which started life as a forward proxy) it plays a valuable roll in linked data approaches by allowing changes to systems and networks behind the scene while allowing URI persistence to be maintained.&amp;nbsp; I've also had no issues with it with respect to 303 redirects on generic documents, also important in linked data approaches.&amp;nbsp; &lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-3190485877111547991?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/3190485877111547991/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=3190485877111547991' title='41 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/3190485877111547991'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/3190485877111547991'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2009/05/varnish-reverse-proxy-accelerator-ca.html' title='Varnish Reverse Proxy Accelerator (Ca...'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><thr:total>41</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-2843445561291157654</id><published>2009-02-16T11:48:00.003-06:00</published><updated>2009-02-16T11:53:00.214-06:00</updated><title type='text'>Neptune Database Services and Scripting:</title><content type='html'>The use of services on the net has on interesting set of issues to address with respect to acting as generic data resources.&amp;nbsp; Doing mash ups with RSS or ATOM feeds or weather or other somewhat periodic and serial data has become rather common.&amp;nbsp; Yahoo Pipes (Ref: &lt;a title="http://pipes.yahoo.com" target="_blank" href="http://pipes.yahoo.com" id="hgdx"&gt;http://pipes.yahoo.com&lt;/a&gt; ) and other such web applications do a good job dealing with these types of data end points.&amp;nbsp; &lt;br&gt;&lt;br&gt;&lt;div style="text-align: left;"&gt;However, when working with scientific data sets and services like those at CHRONOS (Ref: &lt;a title="http://portal.chronos.org/gridsphere/gridsphere?cid=res_dev" target="_blank" href="http://portal.chronos.org/gridsphere/gridsphere?cid=res_dev" id="gc06"&gt;http://portal.chronos.org/gridsphere/gridsphere?cid=res_dev&lt;/a&gt; ) a different set of use issues comes up.&lt;br&gt;&lt;br&gt;Let's look at a basic XML-RPC styled service endpoint for the Neptune database at CHRONOS (Ref: &lt;a title="http://www.chornos.org" target="_blank" href="http://www.chronos.org/" id="vc5m"&gt;http://www.chronos.org&lt;/a&gt; ):&lt;br&gt;&lt;/div&gt;&lt;br&gt;&lt;a title="http://services.chronos.org/xqe/public/chronos.neptune.samples.advanced?callback=displayNexus&amp;amp;time_range=10-20&amp;amp;fossil_group=Diatoms&amp;amp;include_dated=true&amp;amp;serializeAs=wrs&amp;amp;" target="_blank" href="http://services.chronos.org/xqe/public/chronos.neptune.samples.advanced?callback=displayNexus&amp;amp;time_range=33-34&amp;amp;fossil_group=Diatoms&amp;amp;include_dated=true&amp;amp;serializeAs=wrs&amp;amp;" id="eh_v"&gt;http://services.chronos.org/xqe/public/chronos.neptune.samples.advanced?callback=displayNexus&amp;amp;time_range=33-34&amp;amp;fossil_group=Diatoms&amp;amp;include_dated=true&amp;amp;serializeAs=wrs&amp;amp;&lt;/a&gt; &lt;br&gt;&lt;br&gt;Here I have used a service from the XQE engine that has set the time range to 33-34 Ma,&amp;nbsp; fossil group to Diatoms, indicated that only dated items should be used and set the output serialization to web row sets (generic XML).&amp;nbsp; &lt;br&gt;&lt;br&gt;However, let's say by use of a recent example, we wanted to locate all the unique taxon names and drill holes from various time ranges and fossil types from the CHRONSO Neptune database.&amp;nbsp; We now need to loop on a set time times and names and then locate the unique, not full, set of names and locations.&amp;nbsp; We can do this with the service above, but not directly.&amp;nbsp; We need to collect and process a range of calls on that service to achieve this.&amp;nbsp; &lt;br&gt;&lt;br&gt;One could develop a small program in Java, Ruby Groovy or some other language.&amp;nbsp; Dynamic languages like Groovy are especially well suited for such efforts and a a simple script like:&lt;br&gt;&lt;pre&gt;&lt;a name="l1"&gt;&lt;span class="ln"&gt;&lt;/span&gt;&lt;/a&gt;&lt;span class="s1"&gt;&lt;font size="1"&gt;&lt;a style="font-family: Courier New;" name="l8"&gt;&lt;span class="ln"&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family: Courier New;"&gt;&lt;/span&gt;&lt;a style="font-family: Courier New;" name="l10"&gt;&lt;span class="ln"&gt;10   &lt;/span&gt;&lt;/a&gt;&lt;/font&gt;&lt;/span&gt;&lt;font size="1"&gt;&lt;span style="font-family: Courier New;" class="s0"&gt;//Upper Oligocene   Sub-Series/Sub-Epoch    23.8    28.5    Oligocene&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt; &lt;br&gt;&lt;a name="l11"&gt;&lt;span class="ln"&gt;11   &lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s0"&gt;//Lower Oligocene   Sub-Series/Sub-Epoch    28.5    33.7    Oligocene&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt; &lt;br&gt;&lt;a name="l12"&gt;&lt;span class="ln"&gt;12   &lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s0"&gt;//Upper Eocene      Sub-Series/Sub-Epoch    33.7    36.9    Eocene&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt; &lt;br&gt;&lt;a name="l13"&gt;&lt;span class="ln"&gt;13   &lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s0"&gt;//Middle Eocene     Sub-Series/Sub-Epoch    36.9    49      Eocene&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt; &lt;br&gt;&lt;a name="l14"&gt;&lt;span class="ln"&gt;14   &lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s0"&gt;//Lower Eocene      Sub-Series/Sub-Epoch    49      55.05   Eocene&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt; &lt;br&gt;&lt;a name="l15"&gt;&lt;span class="ln"&gt;15   &lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s0"&gt;//Paleocene         Series/Epoch            55.05   65      Paleogene&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt; &lt;br&gt;&lt;a name="l16"&gt;&lt;span class="ln"&gt;16   &lt;/span&gt;&lt;/a&gt; &lt;br&gt;&lt;a name="l17"&gt;&lt;span class="ln"&gt;17   &lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s2"&gt;import &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;sun.net.www.http.HttpClient &lt;br&gt;&lt;a name="l18"&gt;&lt;span class="ln"&gt;18   &lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s2"&gt;import &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;org.apache.commons.httpclient.methods.GetMethod &lt;br&gt;&lt;a name="l19"&gt;&lt;span class="ln"&gt;19   &lt;/span&gt;&lt;/a&gt; &lt;br&gt;&lt;a name="l20"&gt;&lt;span class="ln"&gt;20   &lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s2"&gt;def &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;ageRanges = [&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s3"&gt;'23.8-28.5'&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;, &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s3"&gt;'28.5-35.7'&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;, &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s3"&gt;'33.7-36.9'&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;, &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s3"&gt;'36.9-49'&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;, &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s3"&gt;'49-55.05'&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;, &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s3"&gt;'55.05-65'&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;] &lt;br&gt;&lt;a name="l21"&gt;&lt;span class="ln"&gt;21   &lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s2"&gt;def &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;fossilTypes = [&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s3"&gt;"Diatoms"&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;, &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s3"&gt;"Planktonic+Foraminifera"&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;, &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s3"&gt;"Radiolarians"&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;, &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s3"&gt;"Calcareous+Nannoplankton"&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;] &lt;br&gt;&lt;a name="l22"&gt;&lt;span class="ln"&gt;22   &lt;/span&gt;&lt;/a&gt; &lt;br&gt;&lt;a name="l23"&gt;&lt;span class="ln"&gt;23   &lt;/span&gt;&lt;/a&gt;fossilTypes.each() {type -&amp;gt; &lt;br&gt;&lt;a name="l24"&gt;&lt;span class="ln"&gt;24   &lt;/span&gt;&lt;/a&gt;    ageRanges.each() {range -&amp;gt; &lt;br&gt;&lt;a name="l25"&gt;&lt;span class="ln"&gt;25   &lt;/span&gt;&lt;/a&gt;        &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s2"&gt;def &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;urlxml = &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s3"&gt;"http://services.chronos.org/xqe/public/chronos.neptune.samples.advanced?callback=&lt;br&gt;displayNexus&amp;amp;time_range=$&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;{range}&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s3"&gt;&amp;amp;fossil_group=$&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;{type}&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s3"&gt;&amp;amp;include_synonyms=true&amp;amp;include_dated=true&amp;amp;serializeAs=wrs&amp;amp;"&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt; &lt;br&gt;&lt;a name="l26"&gt;&lt;span class="ln"&gt;26   &lt;/span&gt;&lt;/a&gt; &lt;br&gt;&lt;a name="l27"&gt;&lt;span class="ln"&gt;27   &lt;/span&gt;&lt;/a&gt;        &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s2"&gt;def &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;client = &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s2"&gt;new &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;HttpClient() &lt;br&gt;&lt;a name="l28"&gt;&lt;span class="ln"&gt;28   &lt;/span&gt;&lt;/a&gt;        &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s2"&gt;def &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;get = &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s2"&gt;new &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;GetMethod(urlxml) &lt;br&gt;&lt;a name="l29"&gt;&lt;span class="ln"&gt;29   &lt;/span&gt;&lt;/a&gt;        client.executeMethod(get) &lt;br&gt;&lt;a name="l30"&gt;&lt;span class="ln"&gt;30   &lt;/span&gt;&lt;/a&gt; &lt;br&gt;&lt;a name="l31"&gt;&lt;span class="ln"&gt;31   &lt;/span&gt;&lt;/a&gt;        &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s2"&gt;def &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;xmlSlurped = &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s2"&gt;null&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt; &lt;br&gt;&lt;a name="l32"&gt;&lt;span class="ln"&gt;32   &lt;/span&gt;&lt;/a&gt;        &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s2"&gt;try &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;{ &lt;br&gt;&lt;a name="l33"&gt;&lt;span class="ln"&gt;33   &lt;/span&gt;&lt;/a&gt;            xmlSlurped = &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s2"&gt;new &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;XmlSlurper().parseText(get.getResponseBodyAsString()) &lt;br&gt;&lt;a name="l34"&gt;&lt;span class="ln"&gt;34   &lt;/span&gt;&lt;/a&gt; &lt;br&gt;&lt;a name="l35"&gt;&lt;span class="ln"&gt;35   &lt;/span&gt;&lt;/a&gt;            &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s2"&gt;def &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;entries = xmlSlurped.data.currentRow &lt;br&gt;&lt;a name="l36"&gt;&lt;span class="ln"&gt;36   &lt;/span&gt;&lt;/a&gt;            &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s2"&gt;def &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;legSiteHole = [] &lt;br&gt;&lt;a name="l37"&gt;&lt;span class="ln"&gt;37   &lt;/span&gt;&lt;/a&gt;            &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s2"&gt;def &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;bug = [] &lt;br&gt;&lt;a name="l38"&gt;&lt;span class="ln"&gt;38   &lt;/span&gt;&lt;/a&gt;            entries.each {entry -&amp;gt; &lt;br&gt;&lt;a name="l39"&gt;&lt;span class="ln"&gt;39   &lt;/span&gt;&lt;/a&gt;                legSiteHole += &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s3"&gt;"$&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;{entry.columnValue[&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s4"&gt;3&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;]}&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s3"&gt;_$&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;{entry.columnValue[&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s4"&gt;4&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;]}&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s3"&gt;_$&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;{entry.columnValue[&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s4"&gt;5&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;]}&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s3"&gt;"&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt; &lt;br&gt;&lt;a name="l40"&gt;&lt;span class="ln"&gt;40   &lt;/span&gt;&lt;/a&gt;                bug += &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s3"&gt;"$&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;{entry.columnValue[&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s4"&gt;11&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;]}&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s3"&gt;"&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt; &lt;br&gt;&lt;a name="l41"&gt;&lt;span class="ln"&gt;41   &lt;/span&gt;&lt;/a&gt;            } &lt;br&gt;&lt;a name="l42"&gt;&lt;span class="ln"&gt;42   &lt;/span&gt;&lt;/a&gt; &lt;br&gt;&lt;a name="l43"&gt;&lt;span class="ln"&gt;43   &lt;/span&gt;&lt;/a&gt;            println &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s3"&gt;"Total tax count is $&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;{bug.size()}&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s3"&gt; and total LSH count is $&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;{legSiteHole.size()}&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s3"&gt;"&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt; &lt;br&gt;&lt;a name="l44"&gt;&lt;span class="ln"&gt;44   &lt;/span&gt;&lt;/a&gt;            println &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s3"&gt;"In range " &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;+ range + &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s3"&gt;" of type " &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;+ type + &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s3"&gt;" found " &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;+ bug.unique().size() + &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s3"&gt;" unique &lt;br&gt;taxa in " &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;+ legSiteHole.unique().size() + &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s3"&gt;" unique leg/site/holes"&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt; &lt;br&gt;&lt;a name="l45"&gt;&lt;span class="ln"&gt;45   &lt;/span&gt;&lt;/a&gt;            println range + &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s3"&gt;" " &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;+ bug.unique().size() &lt;br&gt;&lt;a name="l46"&gt;&lt;span class="ln"&gt;46   &lt;/span&gt;&lt;/a&gt;        } &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s2"&gt;catch &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt;(org.xml.sax.SAXParseException e) { &lt;br&gt;&lt;a name="l47"&gt;&lt;span class="ln"&gt;47   &lt;/span&gt;&lt;/a&gt;            println &lt;/span&gt;&lt;span style="font-family: Courier New;" class="s3"&gt;"Exception parsing XML"&lt;/span&gt;&lt;span style="font-family: Courier New;" class="s1"&gt; &lt;br&gt;&lt;a name="l48"&gt;&lt;span class="ln"&gt;48   &lt;/span&gt;&lt;/a&gt;        } &lt;br&gt;&lt;a name="l49"&gt;&lt;span class="ln"&gt;49   &lt;/span&gt;&lt;/a&gt;    } &lt;br&gt;&lt;a name="l50"&gt;&lt;span class="ln"&gt;50   &lt;/span&gt;&lt;/a&gt;} &lt;br&gt;&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;This script uses the Apache Commons HttpClient, but there are many way to do this.&amp;nbsp; The point I am after is not to show a best practice in using Groovy to access services&amp;nbsp; (I'm sure there are many aspects of that code that people could comment on).&amp;nbsp; Rather it is to highlight an issue related to balancing service generality and usefulness.&lt;br&gt;&lt;br&gt;Note I did attempt to use both the XML and the character separated values&lt;br /&gt;version via Yahoo Pipes and also the defunct Google Mashups Editor.&amp;nbsp;&lt;br /&gt;However, the need to have a more programmatic interface to conduct&lt;br /&gt;loops, basic array manipulation and such is beyond what these can do&lt;br /&gt;easily.&amp;nbsp; While it might be possible, I did not find it easy or intuitive.&amp;nbsp; These resource seem more focused on RSS or ATOM sources and simple filtering and counting.&amp;nbsp; &lt;br&gt;&lt;br&gt;Additionally the&lt;br /&gt;Kepler work flow application is a bit of over kill and doesn't yet seem to&lt;br /&gt;work well with REST or XML-RPC style services as well as I feel it should.&amp;nbsp;&amp;nbsp; A heavy focus on WS* and other more heavy duty scientific data flow operations mean it's lightweight rapid service mashup capacity is limited (IMHO).&amp;nbsp; &lt;br&gt;&lt;br&gt;&lt;i&gt;Making a resource or service of general "popular" use may make it of generic interest but can limit its utility on its own to address specific scientific efforts.&lt;/i&gt;&lt;br&gt;&lt;br&gt;Expecting generic services to be of use via the implementation of packages like Yahoo Pipes or Kepler runs into implementation aspects of those tools.&amp;nbsp; Aspects which may make use of them sufficiently complex as too discourage users.&amp;nbsp; &lt;br&gt;&lt;br&gt;However, expecting people to write code like the example above, even in a language like Groovy that makes calling, using and parsing the data rather easy is also potentially unrealistic.&amp;nbsp; Not everyone likes to write code.&lt;br&gt;&lt;br&gt;So, there is a dilemma for service providers of science data like CHRONOS.&amp;nbsp; Make the services too generic and you risk them being of little use to focused research communities.&amp;nbsp; Address the vertical needs of a specific community or tool interface and risk making them of limited utility to others.&amp;nbsp; Additionally addressing the needs of several vertical communities could be taxing from a human resource point of view.&amp;nbsp; &lt;br&gt;&lt;br&gt;One does wonder if the creation of a domain specific language (DSL)&amp;nbsp; might have benefit to address this.&amp;nbsp; If there was enough community interest to justify it's creation a service that consumes and process a DSL would allow a sort of "custom command line interface.&amp;nbsp; &lt;br&gt;&lt;br&gt;The Sloan Digital Sky Survey&amp;nbsp; SkyServer (Ref: &lt;a title="http://cas.sdss.org/astrodr7/en/" target="_blank" href="http://cas.sdss.org/astrodr7/en/" id="lbzv"&gt;http://cas.sdss.org/astrodr7/en/&lt;/a&gt; ) addresses this by simply using SQL as that "DSL" language.&amp;nbsp; The page &lt;a title="http://cas.sdss.org/astrodr7/en/tools/search/sql.asp" target="_blank" href="http://cas.sdss.org/astrodr7/en/tools/search/sql.asp" id="zi8x"&gt;http://cas.sdss.org/astrodr7/en/tools/search/sql.asp&lt;/a&gt;  allows one to structure and submit SQL directly to the database. &amp;nbsp;&amp;nbsp; &lt;br&gt;&lt;br&gt;However, a more focused DSL might be able to address the needs of special research groups while consuming more generic service end points that could be exposed for other to use in similar approaches to the code above, via the DSL or their own approach.&amp;nbsp; &lt;br&gt;&lt;br&gt;Also the development effort in making such a DSL might be able to be spread across multiple efforts making it more appealing from a human resource point of view.&lt;br&gt;&lt;br&gt;Just some ramblings on how to balance generic services (resources) vs the need of special communities for more focused and unique services.&amp;nbsp; Regardless if they are REST, XML-RPC or WS* in nature.&amp;nbsp; &lt;br&gt;&lt;br&gt;&lt;b&gt;Other references:&lt;/b&gt;&lt;br&gt;Kepler Workflow Application: &lt;a title="http://kepler-project.org/" target="_blank" href="http://kepler-project.org/" id="mmcz"&gt;http://kepler-project.org/&lt;/a&gt; &lt;br&gt;Google Mashup Editor&amp;nbsp; &lt;a title="http://code.google.com/gme/" target="_blank" href="http://code.google.com/gme/" id="b95g"&gt;http://code.google.com/gme/&lt;/a&gt; &amp;nbsp; (defunct)&lt;br&gt;XPROC&amp;nbsp; &lt;a title="http://xproc.org/" target="_blank" href="http://xproc.org/" id="rwlu"&gt;http://xproc.org/&lt;/a&gt; &amp;nbsp; and&amp;nbsp; &lt;a title="http://www.w3.org/TR/xproc/" target="_blank" href="http://www.w3.org/TR/xproc/" id="pp.5"&gt;http://www.w3.org/TR/xproc/&lt;/a&gt; &lt;br&gt;GRDDL: &lt;a title="http://www.w3.org/2004/01/rdxh/spec" target="_blank" href="http://www.w3.org/2004/01/rdxh/spec" id="kunm"&gt;http://www.w3.org/2004/01/rdxh/spec&lt;/a&gt;&lt;br&gt;DSL in Groovy:&amp;nbsp; &lt;a title="http://docs.codehaus.org/display/GROOVY/Writing+Domain-Specific+Languages" target="_blank" href="http://docs.codehaus.org/display/GROOVY/Writing+Domain-Specific+Languages" id="bpnh"&gt;http://docs.codehaus.org/display/GROOVY/Writing+Domain-Specific+Languages&lt;/a&gt; &lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-2843445561291157654?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/2843445561291157654/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=2843445561291157654' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/2843445561291157654'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/2843445561291157654'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2009/02/neptune-database-services-and-scripting.html' title='Neptune Database Services and Scripting:'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-1702390272463992626</id><published>2008-12-02T10:52:00.002-06:00</published><updated>2008-12-02T10:54:19.514-06:00</updated><title type='text'>REST SOA and multi-parameter databases</title><content type='html'>&lt;b&gt;Thoughts on REST and SOA's for database access with multiple parameters&lt;/b&gt;&lt;br&gt;&lt;br&gt;Following that a URI represents a "resource" then it can become an involved process to create a REST compliant approach to RDBM's based resources that allow users to define multiple parameters to request results in a Resource Oriented Architecture (ROA) approach.&amp;nbsp; &lt;br&gt;&lt;br&gt;One begins to view "Plain old XML" (POX) defining parameters and constraints passed over HTTP as a REST approach.&amp;nbsp;&amp;nbsp;&amp;nbsp; However, this tends to border on a basic RPC approach.&amp;nbsp; Especially when the endpoint that receives the POX represents a method to run.&amp;nbsp; Thus we are more Services Oriented Architecture (SOA) now than ROA.&lt;br&gt;&lt;br&gt;Alternately a URI template approach quickly becomes complex and also very RPC like when we simply define a syntax for the parsing of a URI into what is honestly still a method call.&amp;nbsp; There is also the issue that even something as simple as .../resource/facetA/facetB is different to our caching and general web architecture stack than ../resource/facetB/facetA even if the result (body) is both associative and commutative in operation with respect to these facets.&amp;nbsp; Arguably a URI doesn't need to be this way, but that seems to imply a URI template again and then it seems there is prior knowledge involved server side. &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;br&gt;&lt;br&gt;One could argue that an&amp;nbsp; aspect of the uniform interface approach in REST is that resources are manipulated via model transforms.&amp;nbsp; So a URI represents a resource and we operate on these resources through application of transformations.&amp;nbsp; Obviously this raises visions of resources as XML and transformations being applied via XSL.&amp;nbsp; Whether this is a valid REST/ROA approach remains as an argument I suspect (or does it?). &amp;nbsp; &lt;br&gt;&lt;br&gt;However, if the goal of the architecture is to allow a user to generate a result based on arbitrary parameters and constraints and then allow the capacity to pass a representation of these results along to another user as a resource then the results of the initial request must result in the generation of a new resource.&amp;nbsp; This new resource being a representation of the various parameters and constraints requested from the database.&amp;nbsp; &lt;br&gt;&lt;br&gt;Defining that as a constraint of the architecture we are looking for then there are perhaps two questions to answer:&lt;br&gt;&lt;br&gt;&lt;ol&gt;&lt;li&gt;If the endpoint we are passing our parameters to is a method then we are RPC and likely should just call ourselves a SOA and move on.&amp;nbsp; &lt;br&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;If "yes" to 1 then could the result of this RPC/SOA call generate a resource that could then be passed along on a ROA side of this architecture?&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;If we believe a REST approach is useful here can we define a "resource" that provided a transform or set of operations results in a set of resources that represent our "results"&lt;/li&gt;&lt;ul&gt;&lt;li&gt;One has to be careful not to "create" something we call a resource that simply is a method anyway and thus violates a ROA approach anyway.&amp;nbsp;&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Does&amp;nbsp; a REST approach imply requesting resources with individual parameters/facets and then any subset/intersection or other transform is duty of the client to perform. The results of any multi-parameter request is a set of resource links,&lt;br /&gt;not the data.&amp;nbsp; The data the client will use (plot, animate, etc.) comes&lt;br /&gt;from those resource links. &lt;br&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;This puts undue (or not) burden on the client for large data sets&lt;/li&gt;&lt;li&gt;This makes passing simple representations of resulting data set to other users/machines problematic.&amp;nbsp; &lt;br&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ol&gt;&lt;br&gt;&lt;i&gt;However, REST is optimized for large-grain hypermedia data transfer (Ref: &lt;a title="http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm" target="_blank" href="http://www.ics.uci.edu/%7Efielding/pubs/dissertation/rest_arch_style.htm" id="v6b4"&gt;http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm&lt;/a&gt; ) and thus one arrives at this point wondering if this posting is discussing a fine grained approach to data that is not the forte of REST.&lt;/i&gt;&lt;br&gt;&lt;br&gt;&lt;i&gt;One has to consider WS* if you are allowing for RPC anyway.&amp;nbsp; &lt;/i&gt;If you are going to open the door for RPC, then why not just take on&lt;br /&gt;the WS* stack and benefit (and suffer) from the formality of that?&amp;nbsp; One can argue about the conspiracy&lt;br /&gt;of tool developers in the evolution of WS* all you want.&amp;nbsp; However, in&lt;br /&gt;the end you are attempting to get a goal achieved and if your goal is fine grained parameter access to database over HTTP then perhaps the SOA/WS*/SOAP approach is what you need (even if it's not what you want). &amp;nbsp; &lt;br&gt;&lt;br&gt;Clearly though WS* brings a level of complexity that is not welcome in many places.&amp;nbsp; So then, as mentioned at the start of this post, one looks to POX over HTTP via POST as an interesting approach. &amp;nbsp; &lt;br&gt;&lt;br&gt;There is nothing that says the result (or an addition by product) of this service call can't include the generation of a resource or that a resource creation could be explicitly requested when passing a representation/resource is desired.&amp;nbsp; The implication being that such a resource is not implicitly generated for each service call.&amp;nbsp; The "Layered System Constraint" allows us to build up more&lt;br /&gt;representations (views) into our resources to accommodate architectural&lt;br /&gt;approaches needed in our effort.&amp;nbsp; &lt;br&gt;&lt;br&gt;A process file representing a workflow to be conducted can be used to pass to others to allow for "gettable" results.&amp;nbsp; Or could be POST'ed back to the server (another server) to generate a "gettable" result.&amp;nbsp; How then is this "workflow document" constructed?&amp;nbsp; JSON ala CouchDB views (Ref: &lt;a title="http://wiki.apache.org/couchdb/Introduction_to_CouchDB_views?action=show&amp;amp;redirect=Views" target="_blank" href="http://wiki.apache.org/couchdb/Introduction_to_CouchDB_views?action=show&amp;amp;redirect=Views" id="inwu"&gt;http://wiki.apache.org/couchdb/Introduction_to_CouchDB_views?action=show&amp;amp;redirect=Views&lt;/a&gt; ), XProc (Ref: &lt;a title="http://www.w3.org/TR/xproc/" target="_blank" href="http://www.w3.org/TR/xproc/" id="upcf"&gt;http://www.w3.org/TR/xproc/&lt;/a&gt; ), GRDDL (Ref: &lt;a title="http://www.w3.org/2004/01/rdxh/spec" target="_blank" href="http://www.w3.org/2004/01/rdxh/spec" id="se7c"&gt;http://www.w3.org/2004/01/rdxh/spec&lt;/a&gt; ) transform links, other?&amp;nbsp; The exact nature of the construction isn't important at this level in the discussion.&amp;nbsp; &lt;br&gt;&lt;br&gt;If application state is the purview of the client, then the client is&lt;br /&gt;free to use any method to maintain that state.&amp;nbsp; Itself, the involved&lt;br /&gt;application server or some other application server. &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br /&gt;Implications for HATEOAS (hypertext as the engine of application state)?&lt;br&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;links can be implicate or explicate&lt;/li&gt;&lt;li&gt;links in mediums other than HTML (examples)&lt;/li&gt;&lt;/ul&gt;&lt;br&gt;So then if the issue of multiple parameters is one that is fine grained and best approached by SOA while a resource driven approach is naturally ROA in nature something like the following can be seen as a zeroth order start on database exposure in a hybrid SOA/ROA approach.&amp;nbsp; &lt;br&gt;&lt;br&gt;&lt;div&gt;&lt;table class="zeroBorder" id="r21p" width="100%" border="0" cellpadding="3" cellspacing="0"&gt;&lt;tbody&gt;&lt;tr valign="top"&gt;&lt;td width="33%"&gt;&lt;b&gt;ROA&lt;/b&gt;&lt;br&gt;&lt;br&gt;Represented by URI's like:&lt;br&gt;&lt;br&gt;.../res/paramter &lt;br&gt;(a large number of resources returned using HATEOAS to navigate the result tree to data)&lt;br&gt;&lt;br&gt;.../res/ID&lt;br&gt;(a single resource data represented based on request type)&lt;br&gt;&lt;br&gt;Can use the standard CRUD REST mapping (and all its good and bad points) to manipulate these resources and mimetype/request type approaches to alter the serialization of the data.&lt;br&gt;&lt;br&gt;&lt;/td&gt;&lt;td width="33%"&gt;&lt;b&gt;ROA with rendered views*&lt;/b&gt;&lt;br&gt;&lt;br&gt;Represented by views on the resources like&lt;br&gt;&lt;br&gt;.../res/age/10&lt;br&gt;(implying all elements 10Ma or older)&lt;br&gt;&lt;br&gt;.../res/depth/345&lt;br&gt;(implying 345 mbsf or deeper)&lt;br&gt;&lt;br&gt;../res/fossilegroup/nanno&lt;br&gt;(resources with data from fossil group Nanno)&lt;br&gt;&lt;br&gt;../res/taxon/X&lt;br&gt;(resources with data about taxon X)&lt;br&gt;&lt;br&gt;.../res/ics2004/earlyjurasic&lt;br&gt;(resource with data from early Jurassic as defined by ICS 2004 timescale)&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;/td&gt;&lt;td width="33%"&gt;&lt;b&gt;SOA (WS*, POX via POST, etc.)&lt;/b&gt;&lt;br&gt;&lt;br&gt;Standard SOA method calls via SOAP envelopes.&amp;nbsp; &lt;br&gt;(lots of baggage)&lt;br&gt;&lt;br&gt;POX over HTTP&lt;br&gt;&lt;br&gt;JSON plus REST&lt;br&gt;&lt;br&gt;or even just pushing .JS in general over to a server ala Perserver or FeatherDB.&amp;nbsp; &lt;br&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;* All these URI examples are based on paleontology/geology approaches associated with the kind of data CHRONOS works with and may be somewhat opaque at first glance. &lt;br&gt;&lt;br /&gt;&lt;br /&gt;&lt;br&gt;&lt;b&gt;&lt;i&gt;Resource Oriented Architecture&lt;/i&gt;&lt;/b&gt;&lt;br&gt;&lt;div id="k-6h" style="padding: 1em 0pt; text-align: center;"&gt;&lt;img style="width: 357px; height: 240px;" src="http://docs.google.com/File?id=dgtb8v9j_359ghvk78g9_b"&gt;&lt;br&gt;&lt;div style="text-align: left;"&gt;"Classic" REST in a ROA approach.&amp;nbsp; URI point to individual resource which return their data.&amp;nbsp; The "view" of the data may change based on the request type and other elements of the web architecture also are there to address caching (e-tags) and other elements of scaling.&amp;nbsp; Implementation wise this could be &lt;a title="Jersey" target="_blank" href="https://jersey.dev.java.net/" id="p_93"&gt;Jersey&lt;/a&gt; or &lt;a title="CouchDB" target="_blank" href="http://incubator.apache.org/couchdb/" id="ydk_"&gt;CouchDB&lt;/a&gt; or many things. &amp;nbsp;&amp;nbsp; &lt;br&gt;&lt;/div&gt;&lt;/div&gt;&lt;br&gt;&lt;b&gt;&lt;i&gt;Resource Oriented Architecture with dynamic creation of views&lt;/i&gt;&lt;/b&gt;&lt;br&gt;&lt;div id="k3i2" style="padding: 1em 0pt; text-align: center;"&gt;&lt;img style="width: 452px; height: 412px;" src="http://docs.google.com/File?id=dgtb8v9j_360hqcj5jct_b"&gt;&lt;br&gt;&lt;div style="text-align: left;"&gt;Adding the ability to create dynamic views is a new level.&amp;nbsp; While CouchDB supports views they have to be registered and indexed.&amp;nbsp; Other packages like Perserver (Ref: &lt;a title="http://www.persvr.org/" target="_blank" href="http://www.persvr.org/" id="mn7."&gt;http://www.persvr.org/&lt;/a&gt; ) and &lt;a title="FeatherDB" target="_blank" href="http://www.fourspaces.com/blog/2008/4/11/FeatherDB_Java_JSON_Document_database" id="e11w"&gt;FeatherDB&lt;/a&gt; allow for views to be dynamically created and run via REST calls. The performance and scalability issues of allowing such dynamic view creation would need to be evaluated.&amp;nbsp;&amp;nbsp; Also the views themselves tend to be Javascript based or based on JSON query/path expression syntax.&amp;nbsp; Though this is not always the case and it should be noted that CouchDB, though requiring prior view creation, supports a wide range of languages for views.&amp;nbsp; &lt;br&gt;&lt;/div&gt;&lt;/div&gt;&lt;b&gt;&lt;i&gt;ROA / SOA hybrid&lt;/i&gt;&lt;/b&gt;&lt;br&gt;&lt;div id="xo48" style="padding: 1em; text-align: center;"&gt;&lt;div id="wo-6" style="padding: 1em 0pt; text-align: center;"&gt;&lt;a href="http://docs.google.com/File?id=dgtb8v9j_362q5zvhkfr_b" target="_blank"&gt;&lt;/a&gt;&lt;div id="g5ff" style="padding: 1em 0pt; text-align: center;"&gt;&lt;a href="http://docs.google.com/File?id=dgtb8v9j_363cpgzx5dq_b" target="_blank"&gt;&lt;img style="width: 100%;" src="http://docs.google.com/File?id=dgtb8v9j_363cpgzx5dq_b"&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;If the goal as stated is to allow fine grained multi-parameter access to a database while leveraging off the scaling and ease of use aspects of REST/ROA then a review of various approaches to a ROA/SOA hybrid is beneficial.&amp;nbsp; Obviously there is a high degree of coupling between the service (method) and client in all these cases.&amp;nbsp; &lt;br&gt;&lt;br&gt;&lt;i&gt;Seq A&amp;nbsp; (One call, all the data returned)&lt;/i&gt;&lt;br&gt;Classic service call as either XML-RPC, WS*, POX over HTTP (RPC), JSON over HTTP (RPC) or however you need to communicate a request to a method and get your results back.&amp;nbsp; Whether the method is directly exposed or a more document centric approach where an XML or JSON package is processed is not relevant.&amp;nbsp; &lt;br&gt;&lt;br&gt;&lt;i&gt;Seq B&amp;nbsp; (One call for ID collection then N calls for matching resources)&lt;/i&gt;&lt;br&gt;Method call made but rather than data a collection of ID's for matching resource are returned.&amp;nbsp; The client then makes further calls for each matching resource.&lt;br&gt;&lt;br&gt;&lt;i&gt;Seq C (One call for ID collection, One call for collection resource, N calls for matching resources)&lt;/i&gt;&lt;br&gt;Method call made which results in the creation of a new resource.&amp;nbsp; The ID of that resource if returned to the client which then calls to it to gather the associated resource ID that are called to return the requested data.&amp;nbsp; &lt;br&gt;&lt;br&gt;&lt;i&gt;Comments on these approaches&lt;/i&gt;&lt;br&gt;Obviously each version is getting more and more complex and involving more and more network calls and the inherit latency that creates.&amp;nbsp; Seq C does result in a new resource that can retried via REST compliant GET and can then return a HATEOAS compliant collection of resources to be retrieved&lt;br&gt;&lt;br&gt;Accessing (opening and closing) N number of resources over the network is also more involved than returning one large document of all the resources combined.&amp;nbsp; The first approach does lend itself well to a scaled out architecture though.&amp;nbsp; One might consider the utility of AtomPub (Ref: http://www.atompub.org/) in this architecture.&lt;br&gt;&lt;br&gt;Not mentioned yet but important especially with creating new resource dynamically is the use of http codes (Ref: &lt;a title="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html" target="_blank" href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html" id="ta3y"&gt;http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html&lt;/a&gt; ).&amp;nbsp; In particular 201 Created or 303 See Other may be relevant.&amp;nbsp; Obviously using the existing web architecture as much as possible has value.&amp;nbsp; The general shunning of the web architecture by WS* services has not been to its benefit in the authors opinion.&amp;nbsp; &lt;br&gt;&lt;br&gt;&lt;i&gt;&lt;b&gt;Conclusion&lt;/b&gt;&lt;/i&gt;&lt;br&gt;The large grained focus of REST makes it hard to accommodate access to database with a large number of parameters and criteria exposed to clients for them to construct queries against.&amp;nbsp; &lt;br&gt;&lt;br&gt;SOA based approaches that are more RPC in nature match this need better but introduce strong coupling between client and server and are generally more complex to create, invoke and evolve.&amp;nbsp; &lt;br&gt;&lt;br&gt;An architecture than combines ROA and SOA approaches is not impractical&lt;br&gt;&lt;br&gt;&lt;ul&gt;&lt;li&gt;A ROA (REST) approach for easy and highly scalable access to data based on basic parameters and a number of pre-defined "views" to the most common queries&lt;/li&gt;&lt;li&gt;Service/method calls to support multi-parameter calls to a data source to allow arbitrarily complex requests&lt;/li&gt;&lt;li&gt;Service/method calls that allow new "views" to be registered when it is felt than they represent a new and potentially popular view to the data or when a passable, REST compliant resource creation is desirable&lt;/li&gt;&lt;/ul&gt;&lt;br&gt;How an implementation of this might be constructed is a future topic.&lt;br&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;take care&lt;br&gt;Doug&lt;br&gt;&lt;br&gt;Refs used for this document:&lt;br&gt;&lt;a title="http://www.slideshare.net/alan.dean/separating-rest-facts-from-fallacies-presentation/" target="_blank" href="http://www.slideshare.net/alan.dean/separating-rest-facts-from-fallacies-presentation/" id="jcwo"&gt;http://www.slideshare.net/alan.dean/separating-rest-facts-from-fallacies-presentation/&lt;/a&gt; &lt;br&gt;&lt;a title="http://josh-in-antarctica.blogspot.com/2008/11/restful-query-urls-cont.html" target="_blank" href="http://josh-in-antarctica.blogspot.com/2008/11/restful-query-urls-cont.html" id="b9.n"&gt;http://josh-in-antarctica.blogspot.com/2008/11/restful-query-urls-cont.html&lt;/a&gt; &lt;br&gt;&lt;a title="http://www.eherenow.com/soapfight.htm" target="_blank" href="http://www.eherenow.com/soapfight.htm" id="kfnn"&gt;http://www.eherenow.com/soapfight.htm&lt;/a&gt; &lt;br&gt;&lt;a title="http://www.informationweek.com/blog/main/archives/2008/08/rest_vs_soap_ro.html" target="_blank" href="http://www.informationweek.com/blog/main/archives/2008/08/rest_vs_soap_ro.html" id="ou6t"&gt;http://www.informationweek.com/blog/main/archives/2008/08/rest_vs_soap_ro.html&lt;/a&gt; &lt;br&gt;&lt;a title="http://www.25hoursaday.com/weblog/2008/08/24/RESTfulJSONBringingRESTAndRPCCloserTogether.aspx" target="_blank" href="http://www.25hoursaday.com/weblog/2008/08/24/RESTfulJSONBringingRESTAndRPCCloserTogether.aspx" id="ecl0"&gt;http://www.25hoursaday.com/weblog/2008/08/24/RESTfulJSONBringingRESTAndRPCCloserTogether.aspx&lt;/a&gt; &lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-1702390272463992626?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/1702390272463992626/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=1702390272463992626' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/1702390272463992626'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/1702390272463992626'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2008/12/rest-soa-and-multi-parameter-databases.html' title='REST SOA and multi-parameter databases'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-8715527164153245709</id><published>2008-11-18T10:44:00.001-06:00</published><updated>2008-11-18T10:45:57.560-06:00</updated><title type='text'>REST via URI's and Body Representations</title><content type='html'>I've been thinking about REST URI's and their structure for a while now and been talking with my friend &lt;a title="Josh" target="_blank" href="http://josh-in-antarctica.blogspot.com/" id="m59e"&gt;Josh&lt;/a&gt; about these.&amp;nbsp; As an exercise to try to codify my own views on this I have written up some of my thoughts on this topic.&amp;nbsp; &lt;br&gt;&lt;br&gt;&lt;b&gt;&lt;i&gt;URI templates:&lt;/i&gt;&lt;/b&gt;&lt;br&gt;First order approach to REST is the URI used each day via GET &lt;br&gt;&amp;nbsp; &lt;br&gt;Good:&lt;br&gt;&lt;ul&gt;&lt;li&gt;Can become book marks (thus IM'd, twitterd, and emailed to ones content)&lt;/li&gt;&lt;li&gt;Simple and easy to code to in a variety of languages and API's&lt;/li&gt;&lt;li&gt;Classic resource representation&lt;/li&gt;&lt;/ul&gt;Bad:&lt;br&gt;&lt;ul&gt;&lt;li&gt;Limited ability to pass multiple parameters&lt;/li&gt;&lt;li&gt;Limited ability to deal with more than one facet&amp;nbsp; (at least with the example template below, any template could be established, but then everyone calling needs to know it)&lt;br&gt;&lt;/li&gt;&lt;li&gt;Require a template even to pass one parameter&lt;/li&gt;&lt;li&gt;Can easily start to try and carry to much info with all sorts of verbs and values&lt;/li&gt;&lt;/ul&gt;&lt;br&gt;So by example a URI template might look like:&lt;br&gt;&lt;br&gt;.../resource/facet&amp;nbsp;&amp;nbsp; (where the facet is some value like ../lithology/sand)&lt;br&gt;&lt;br&gt;Then a template could define something like&lt;br&gt;&lt;br&gt;.../resource/facet/[match]&amp;nbsp;&amp;nbsp; Given a single value after facet, try to match it (equals or substring?)&lt;br&gt;.../resource/facet/[/min/max]&amp;nbsp; Given two values, assume they are a numerical range to search for&lt;br&gt;&lt;br&gt;Of course, the issues already start to build up.&amp;nbsp; In the single value case we could just try to match but if we want a sub-string match then we are assuming we are not in a numerical environment.&amp;nbsp; Or we are requiring the implementation of the service to check for primitive data types which may or may not work.&amp;nbsp; In the second case our min max has to be sure to address numeric primitives (&lt;a title="easy to check" target="_blank" href="http://www.devx.com/tips/Tip/39748?trk=DXRSS_JAVA" id="pgbs"&gt;easy to check&lt;/a&gt; ) but also we may want to address non-numeric ranges (January/March)&lt;br&gt;&lt;br&gt;There is also an interesting use of language that can be done here.&amp;nbsp; Where &lt;i&gt;resource&lt;/i&gt; (singular) requires an id to define a single resource.&amp;nbsp; Conversely, a plural &lt;i&gt;resources&lt;/i&gt; then would indicate an additional facet (either plural or singular) to carry the template forward.&lt;br&gt;&lt;br&gt;So:&lt;br&gt;.../resources/sand&amp;nbsp;&amp;nbsp; (all resources with sand)&lt;br&gt;.../resource/34/sand&amp;nbsp; (sand attribute (facet) of resource 34)&lt;br&gt;&lt;br&gt;The use of singular and plural attributes in URI templates seems logical.&amp;nbsp; As a complete aside I have often wondered if a more &lt;a title="Latin style grammar" target="_blank" href="http://en.wikipedia.org/wiki/Latin_grammar" id="yj-3"&gt;Latin style grammar&lt;/a&gt; would allow more descriptive URI's to be formed since word order is less important and meaning is carried in word itself.&amp;nbsp; Totally impractical though of course.&amp;nbsp; &lt;br&gt;&lt;br&gt;&lt;b&gt;&lt;i&gt;URI templates with representation in the body&lt;/i&gt;&lt;/b&gt;&lt;br&gt;So if our template is not enough, exploit the fact that the web architecture doesn't just pass URI's but additional elements in a request/response including headers and a body(representation).&lt;br&gt;&lt;br&gt;So now our template (../resource/facet) might get a POST call with a payload of XML or &lt;a title="JSON" target="_blank" href="http://blogs.sun.com/enterprisetechtips/entry/configuring_json_for_restful_web" id="kgid"&gt;JSON&lt;/a&gt;  (pick your flavor I guess, how about &lt;a title="Microformats in REST" target="_blank" href="http://microformats.org/wiki/rest" id="t7ni"&gt;Microformats in REST&lt;/a&gt; ).&amp;nbsp; That payload is free to define a wide variety of parameters and actions.&lt;br&gt;&lt;br&gt;Good:&lt;br&gt;&lt;ul&gt;&lt;li&gt;Far more flexible in terms of defining what we want to do with a resource facet&lt;/li&gt;&lt;li&gt;A response payload can define downstream (next) actions to take.&amp;nbsp; Thus giving us a kind of client moderated work flow (ie, 201 created or 303 see other next steps to take)&lt;/li&gt;&lt;/ul&gt;Bad&lt;br&gt;&lt;ul&gt;&lt;li&gt;These workflows really can't be very complex since we are "waiting around" for the completion with our session.&amp;nbsp; Really only good for events which are "quick". *&lt;br&gt;&lt;/li&gt;&lt;li&gt;The XM or JSON schema/language for the payload has to be agreed on before hand (though this is really true of the URI template too)&lt;/li&gt;&lt;/ul&gt;&lt;br&gt;As an aspect of this the service might establish (via the 201 or 303 codes) a new URI that is a GET'able representation of the response of this (complete with etag and everything). The use of status codes (Ref:&lt;br /&gt;&lt;a title="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html" target="_blank" href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html" id="u82_"&gt;http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html&lt;/a&gt; ) needs to be&lt;br /&gt;integral part of any REST approach and REST clients need to realize&lt;br /&gt;that if they are going to use the web architecture to get a resource&lt;br /&gt;they must look for and deal with the status codes of that architecture.&lt;br /&gt;&lt;br&gt;&lt;br&gt;However, there are issues with the service provider caching requests and responses:&lt;br&gt;&lt;br&gt;&lt;ul&gt;&lt;li&gt;How long does the service provider keep this? &lt;br&gt;&lt;/li&gt;&lt;li&gt;A service may be called thousands of times by a single person in a sinle session, it doesn't scale (does it?) to keep and etag them all&lt;br&gt;&lt;/li&gt;&lt;li&gt;Just let the web arch do the caching&lt;/li&gt;&lt;/ul&gt;&lt;br&gt;Perhaps, one might allow this stored representation of the response to be the URI plus the POST'ed request and then if some does a GET on that URI representing this earlier POST request allow whatever web caching there is to address that scaling&amp;nbsp; Ie:&lt;br&gt;&lt;br&gt;POST request to ../resource/facet&amp;nbsp; &lt;br&gt;response could be the actual data with a 201 created URI for future referencing.&amp;nbsp; That new URI, say (../resource/request/[id]) could then in the future be called via GET.&amp;nbsp; All the service provider is storing in that case is the URI plus the request payload, since the results would be rebuilt by the service engine (and then available for near term caching via existing web architecture).&amp;nbsp; Etags (hash sums) could be used to ensure requests are to a specific resource.&amp;nbsp; &lt;br&gt;&lt;div id="zvr_" style="padding: 1em; text-align: center;"&gt;&lt;div id="qifx" style="padding: 1em; text-align: center;"&gt;&lt;img style="width: 640px; height: 454.316px;" src="http://docs.google.com/File?id=dgtb8v9j_353gdkqfjfm_b"&gt;&lt;br&gt;&lt;/div&gt;&lt;/div&gt;One element I have been working to deal with in REST approaches is the whole "hypermedia as engine of application state".&amp;nbsp; It's a guiding principle and yet sometime hard to understand what exactly it is or if an approach is in compliance with it at times.&lt;br&gt;&lt;br&gt;One approach would seem to be to say that all elements of a response must define down stream references as URI's or other (are there other?) hypermedia compliant references.&amp;nbsp; I am not sure if if an img tag or microformat or RDFa embedded content is compliant with this "application state" approach.&amp;nbsp; Also, how exactly does this impact the use use of XML or JSON.&amp;nbsp; While XML could be embedded into XHTML or similar effort done with microformats, does the use of JSON in the response to a REST URI mean that "hypermedia as engine of application state" is not even an option?&amp;nbsp; JSON embedded in XHTML or microformats perhaps might address this but then one argument the JSON proponents make is that they are tossing out the cruft.&amp;nbsp; One could also place the URI into the JSON as a value.&amp;nbsp; (Josh, I think you are looking into this..&amp;nbsp; I will be curious to read about)&lt;br&gt;&lt;br&gt;Indeed it's also interesting to look at &lt;a title="GRDDL" target="_blank" href="http://www.w3.org/TR/2007/NOTE-grddl-scenarios-20070406/" id="y82r"&gt;GRDDL&lt;/a&gt; and note how it approaches the walking and extraction of information (RDF) from documents (like XHTML) when looking at issues of REST.&amp;nbsp; &lt;br&gt;&lt;br&gt;take care&lt;br&gt;Doug&lt;br&gt;&lt;br&gt;Ref: &lt;br&gt;&lt;a title="http://josh-in-antarctica.blogspot.com/2008/10/restful-query-urls.html" target="_blank" href="http://josh-in-antarctica.blogspot.com/2008/10/restful-query-urls.html" id="uvw1"&gt;http://josh-in-antarctica.blogspot.com/2008/10/restful-query-urls.html&lt;/a&gt; &lt;br&gt;&lt;a title="http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven" target="_blank" href="http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven" id="atju"&gt;http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven&lt;/a&gt; &lt;br&gt;&lt;a title="http://oreilly.com/catalog/9780596529260/" target="_blank" href="http://oreilly.com/catalog/9780596529260/" id="nrwu"&gt;http://oreilly.com/catalog/9780596529260/&lt;/a&gt; &lt;br&gt;&lt;a title="http://www.infoq.com/articles/tilkov-rest-doubts" target="_blank" href="http://www.infoq.com/articles/tilkov-rest-doubts" id="b5ju"&gt;http://www.infoq.com/articles/tilkov-rest-doubts&lt;/a&gt; &lt;br&gt;&lt;a title="http://www.infoq.com/articles/mark-baker-hypermedia" target="_blank" href="http://www.infoq.com/articles/mark-baker-hypermedia" id="iem9"&gt;http://www.infoq.com/articles/mark-baker-hypermedia&lt;/a&gt; &lt;br&gt;&lt;a title="http://microformats.org/wiki/rest/json#Proposals" target="_blank" href="http://microformats.org/wiki/rest/json#Proposals" id="qbe4"&gt;http://microformats.org/wiki/rest/json#Proposals&lt;/a&gt; &lt;br&gt;&lt;a title="http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven" target="_blank" href="http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven" id="hlz:"&gt;http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven&lt;/a&gt; &lt;br&gt;&lt;a title="http://www.w3.org/2004/01/rdxh/spec" target="_blank" href="http://www.w3.org/2004/01/rdxh/spec" id="r9z0"&gt;http://www.w3.org/2004/01/rdxh/spec&lt;/a&gt; &lt;br&gt;&lt;br&gt;*&amp;nbsp; With regard to only good for quick work flows..&amp;nbsp; one must agree that it is easy to send in an event that may take a long time to run and simply reqister a message to a queue (ATOM feed perhaps) that has the current status and the next event on status update to undertake.&amp;nbsp; This turns the burden of monitoring and moving messages through the queue to the client in this case, but it does allow for a disconnected work flow in compliance with web architectural approaches.&amp;nbsp; &lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-8715527164153245709?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/8715527164153245709/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=8715527164153245709' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/8715527164153245709'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/8715527164153245709'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2008/11/rest-via-uri-and-body-representations.html' title='REST via URI&amp;#39;s and Body Representations'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-2762660823423696910</id><published>2008-11-06T15:32:00.004-06:00</published><updated>2008-11-06T16:06:07.764-06:00</updated><title type='text'>JSR-311 and JPA with Intellij 8</title><content type='html'>&lt;a title="Intellij 8 recently came out" href="http://www.jetbrains.com/idea/" id="n48b"&gt;IntelliJIDEA 8 recently came out&lt;/a&gt; and I wanted to take the time to try out a couple of interesting technologies as a means to test out the new version.&amp;nbsp; Specifically &lt;a title="JSR-311" target="_blank" href="http://jcp.org/en/jsr/detail?id=311" id="sy0j"&gt;JSR-311&lt;/a&gt; (Via &lt;a title="Jersey" target="_blank" href="https://jersey.dev.java.net/" id="hl.0"&gt;Jersey&lt;/a&gt; ) and &lt;a title="Java Persistence API" target="_blank" href="http://java.sun.com/javaee/overview/faq/persistence.jsp" id="x2c7"&gt;Java Persistence API&lt;/a&gt; (JPA) via &lt;a title="Hibernate" target="_blank" href="http://www.hibernate.org/" id="hvmd"&gt;Hibernate&lt;/a&gt;.&amp;nbsp; I created a simple application using these two technologies.&amp;nbsp;&amp;nbsp; The data store I used in this was a PostgreSQL database with lithological data.&amp;nbsp; Note I actually did this with version 8.0 M1 of IntelliJ (build 8664) and I will go on the assumption nothing changed in this regard to the 8.0 final annouced just this last day or so.&amp;nbsp; &lt;br&gt;&lt;br&gt;The first step was to register up the database as a datasource.&amp;nbsp; Under the TOOLS menu is the DATA SOURCE... menu item.&amp;nbsp; Selecting this allow us to register our database as a source through the dialog below:&lt;br&gt;&lt;br&gt;&lt;div id="z_qe" style="padding: 1em 0pt; text-align: left;"&gt;&lt;img style="width: 572px; height: 670px;" src="http://docs.google.com/File?id=dgtb8v9j_336hrtprwht_b"&gt;&lt;/div&gt;&lt;br&gt;Once this is done we can go ahead and create out new project.&amp;nbsp; You wouldn't have to register a data source first, but for sake of a canonical "10 minute demo" the net seems to love it makes life a bit easier as we are about to see.&lt;br&gt;&lt;br&gt;Go ahead and start a new project with FILE -&amp;gt; NEW PROJECT.&amp;nbsp; Use the default "Create project from scratch" and name your project.&amp;nbsp; We will be building a "Java Module", the default option when creating a project.&amp;nbsp; Pick the default option for the src directory and when you get the "New Project" window selections options like in figure 2 below:&lt;br&gt;&lt;br&gt;&lt;div id="a9tx" style="padding: 1em 0pt; text-align: left;"&gt;&lt;img style="width: 841px; height: 696px;" src="http://docs.google.com/File?id=dgtb8v9j_337gsnznpgz_b"&gt;&lt;/div&gt;&lt;br&gt;I did NOT select "Hibernate" at this stage, though I did select it under the pull down for the "JavaEE Persistence" option.&amp;nbsp; Also, under "Web Application" -&amp;gt; "WebServices" select the "Jersey" option.&lt;br&gt;&lt;br&gt;The project will start to be fleshed out and you will be prompted to import the database schema (assuming you selected the "Import database schema" option).&amp;nbsp; Now select the source you created via the "Data Source Properties" dialog.&amp;nbsp; For me this was "Lith".&amp;nbsp;&amp;nbsp; This database is just a test database for now so it consists of only a few tables with no defined relations at this time.&amp;nbsp; For purposes of this simple demo that should be fine.&amp;nbsp; &lt;br&gt;&lt;br&gt;Go ahead and select a datasource and define a package name for the entities to be generated into.&amp;nbsp; &lt;br&gt;&lt;br&gt;&lt;div id="k6lh" style="padding: 1em 0pt; text-align: left;"&gt;&lt;img style="width: 645px; height: 882px;" src="http://docs.google.com/File?id=dgtb8v9j_338jx8cqjg2_b"&gt;&lt;/div&gt;&lt;br&gt;&lt;br&gt;You will be prompted that the OR mapping is about to be generated, go ahead and let it start. Depending on your database and your machine this will take a minute or so.&amp;nbsp; &lt;br&gt;&lt;br&gt;Once this was generated I was confronted with an Error that the org.hibernate.ejb.HibernatePersistence class/package could not be resolve for its reference in the &lt;i&gt;persistence.xml&lt;/i&gt; file that was generated for us by this process.&amp;nbsp; Long story short I went to http://www.hibernate.org/6.html and downloaded the annotations, entitymanager and core (distribution) packages from here.&amp;nbsp;&amp;nbsp; &lt;br&gt;&lt;br&gt;Setting up the libraries (as is often the case) was the only real tedious part and in the end the library collection looked like the following figure:&lt;br&gt;&lt;i&gt;NOTE:&amp;nbsp;&amp;nbsp; I have to wonder if I would have selected "Hibernate" in the "New Project" dialog above (leaving the import and class generation option unchecked) if Intellij would have imported the Needed Hibernate libraries for me.&lt;br&gt;NOTE 2:&amp;nbsp; Don't forget to add in your database driver too&amp;nbsp; (not that I did that or anything) &amp;nbsp;&amp;nbsp; &lt;/i&gt;&lt;br&gt;&lt;br&gt;&lt;div id="vrr_" style="padding: 1em 0pt; text-align: left;"&gt;&lt;img style="width: 693px; height: 461px;" src="http://docs.google.com/File?id=dgtb8v9j_339wqrt4tf8_b"&gt;&lt;/div&gt;&lt;br&gt;Parallel to all this JPA/Hibernate stuff Intellij has created a simple JSR-311 (Jersey) class for us with the following default structure:&lt;br&gt;&lt;a name="l1"&gt;&lt;span class="s0"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br&gt;&lt;pre&gt;&lt;a name="l7"&gt;&lt;span class="s1"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a style="font-family: Courier New; color: rgb(0, 0, 0);" name="l8"&gt;&lt;span class="s2"&gt;package &lt;/span&gt;&lt;span class="s1"&gt;example; &lt;br&gt;&lt;/span&gt;&lt;/a&gt;&lt;a style="font-family: Courier New; color: rgb(0, 0, 0);" name="l9"&gt; &lt;br&gt;&lt;/a&gt;&lt;a style="font-family: Courier New; color: rgb(0, 0, 0);" name="l10"&gt;&lt;span class="s2"&gt;import &lt;/span&gt;&lt;span class="s1"&gt;com.sun.net.httpserver.HttpServer; &lt;br&gt;&lt;/span&gt;&lt;/a&gt;&lt;a style="font-family: Courier New; color: rgb(0, 0, 0);" name="l11"&gt;&lt;span class="s2"&gt;import &lt;/span&gt;&lt;span class="s1"&gt;com.sun.jersey.api.container.httpserver.HttpServerFactory; &lt;br&gt;&lt;/span&gt;&lt;/a&gt;&lt;a style="font-family: Courier New; color: rgb(0, 0, 0);" name="l12"&gt;&lt;span class="s2"&gt;import &lt;/span&gt;&lt;span class="s1"&gt;java.io.IOException; &lt;br&gt;&lt;/span&gt;&lt;/a&gt;&lt;a style="font-family: Courier New; color: rgb(0, 0, 0);" name="l13"&gt; &lt;br&gt;&lt;/a&gt;&lt;a style="font-family: Courier New; color: rgb(0, 0, 0);" name="l14"&gt;&lt;span class="s2"&gt;import &lt;/span&gt;&lt;span class="s1"&gt;javax.ws.rs.GET; &lt;br&gt;&lt;/span&gt;&lt;/a&gt;&lt;a style="font-family: Courier New; color: rgb(0, 0, 0);" name="l15"&gt;&lt;span class="s2"&gt;import &lt;/span&gt;&lt;span class="s1"&gt;javax.ws.rs.ProduceMime; &lt;br&gt;&lt;/span&gt;&lt;/a&gt;&lt;a style="font-family: Courier New; color: rgb(0, 0, 0);" name="l16"&gt;&lt;span class="s2"&gt;import &lt;/span&gt;&lt;span class="s1"&gt;javax.ws.rs.Path; &lt;br&gt;&lt;/span&gt;&lt;/a&gt;&lt;a style="font-family: Courier New; color: rgb(0, 0, 0);" name="l17"&gt; &lt;br&gt;&lt;/a&gt;&lt;a style="font-family: Courier New; color: rgb(0, 0, 0);" name="l18"&gt;&lt;span class="s0"&gt;// The Java class will be hosted at the URI path "/helloworld"&lt;/span&gt;&lt;span class="s1"&gt; &lt;br&gt;&lt;/span&gt;&lt;/a&gt;&lt;a style="font-family: Courier New; color: rgb(0, 0, 0);" name="l19"&gt;@Path(&lt;span class="s3"&gt;"/helloworld"&lt;/span&gt;&lt;span class="s1"&gt;) &lt;br&gt;&lt;/span&gt;&lt;/a&gt;&lt;a style="font-family: Courier New; color: rgb(0, 0, 0);" name="l20"&gt;&lt;span class="s2"&gt;public class &lt;/span&gt;&lt;span class="s1"&gt;HelloWorld { &lt;br&gt;&lt;/span&gt;&lt;/a&gt;&lt;a style="font-family: Courier New; color: rgb(0, 0, 0);" name="l21"&gt;    &lt;span class="s0"&gt;// The Java method will process HTTP GET requests&lt;/span&gt;&lt;span class="s1"&gt; &lt;br&gt;&lt;/span&gt;&lt;/a&gt;&lt;a style="font-family: Courier New; color: rgb(0, 0, 0);" name="l22"&gt;    @GET &lt;br&gt;&lt;/a&gt;&lt;a style="font-family: Courier New; color: rgb(0, 0, 0);" name="l23"&gt;    &lt;span class="s0"&gt;// The Java method will produce content identified by the MIME Media type "text/plain"&lt;/span&gt;&lt;span class="s1"&gt; &lt;br&gt;&lt;/span&gt;&lt;/a&gt;&lt;a style="font-family: Courier New; color: rgb(0, 0, 0);" name="l24"&gt;    @ProduceMime(&lt;span class="s3"&gt;"text/plain"&lt;/span&gt;&lt;span class="s1"&gt;) &lt;br&gt;&lt;/span&gt;&lt;/a&gt;&lt;a style="font-family: Courier New; color: rgb(0, 0, 0);" name="l25"&gt;    &lt;span class="s2"&gt;public &lt;/span&gt;&lt;span class="s1"&gt;String getClichedMessage() { &lt;br&gt;&lt;/span&gt;&lt;/a&gt;&lt;a style="font-family: Courier New; color: rgb(0, 0, 0);" name="l26"&gt;        &lt;span class="s0"&gt;// Return some cliched textual content&lt;/span&gt;&lt;span class="s1"&gt; &lt;br&gt;&lt;/span&gt;&lt;/a&gt;&lt;a style="font-family: Courier New; color: rgb(0, 0, 0);" name="l27"&gt;        &lt;span class="s2"&gt;return &lt;/span&gt;&lt;span class="s3"&gt;"Hello World"&lt;/span&gt;&lt;span class="s1"&gt;; &lt;br&gt;&lt;/span&gt;&lt;/a&gt;&lt;a style="font-family: Courier New; color: rgb(0, 0, 0);" name="l28"&gt;    } &lt;br&gt;&lt;/a&gt;&lt;a style="font-family: Courier New; color: rgb(0, 0, 0);" name="l29"&gt; &lt;br&gt;&lt;/a&gt;&lt;a style="font-family: Courier New; color: rgb(0, 0, 0);" name="l30"&gt;    &lt;span class="s2"&gt;public static void &lt;/span&gt;&lt;span class="s1"&gt;main(String[] args) &lt;/span&gt;&lt;span class="s2"&gt;throws &lt;/span&gt;&lt;span class="s1"&gt;IOException { &lt;br&gt;&lt;/span&gt;&lt;/a&gt;&lt;a style="font-family: Courier New; color: rgb(0, 0, 0);" name="l31"&gt;        HttpServer server = HttpServerFactory.create(&lt;span class="s3"&gt;"http://localhost:9998/"&lt;/span&gt;&lt;span class="s1"&gt;); &lt;br&gt;&lt;/span&gt;&lt;/a&gt;&lt;a style="font-family: Courier New; color: rgb(0, 0, 0);" name="l32"&gt;        server.start(); &lt;br&gt;&lt;/a&gt;&lt;a style="font-family: Courier New; color: rgb(0, 0, 0);" name="l33"&gt; &lt;br&gt;&lt;/a&gt;&lt;a style="font-family: Courier New; color: rgb(0, 0, 0);" name="l34"&gt;        System.out.println(&lt;span class="s3"&gt;"Server running"&lt;/span&gt;&lt;span class="s1"&gt;); &lt;br&gt;&lt;/span&gt;&lt;/a&gt;&lt;a style="font-family: Courier New; color: rgb(0, 0, 0);" name="l35"&gt;        System.out.println(&lt;span class="s3"&gt;"Visit: http://localhost:9998/helloworld"&lt;/span&gt;&lt;span class="s1"&gt;); &lt;br&gt;&lt;/span&gt;&lt;/a&gt;&lt;a style="font-family: Courier New; color: rgb(0, 0, 0);" name="l36"&gt;        System.out.println(&lt;span class="s3"&gt;"Hit return to stop..."&lt;/span&gt;&lt;span class="s1"&gt;); &lt;br&gt;&lt;/span&gt;&lt;/a&gt;&lt;a style="font-family: Courier New; color: rgb(0, 0, 0);" name="l37"&gt;        System.in.read(); &lt;br&gt;&lt;/a&gt;&lt;a style="font-family: Courier New; color: rgb(0, 0, 0);" name="l38"&gt;        System.out.println(&lt;span class="s3"&gt;"Stopping server"&lt;/span&gt;&lt;span class="s1"&gt;); &lt;br&gt;&lt;/span&gt;&lt;/a&gt;&lt;a style="font-family: Courier New; color: rgb(0, 0, 0);" name="l39"&gt;        server.stop(&lt;span class="s4"&gt;0&lt;/span&gt;&lt;span class="s1"&gt;); &lt;br&gt;&lt;/span&gt;&lt;/a&gt;&lt;a style="font-family: Courier New; color: rgb(0, 0, 0);" name="l40"&gt;        System.out.println(&lt;span class="s3"&gt;"Server stopped"&lt;/span&gt;&lt;span class="s1"&gt;); &lt;br&gt;&lt;/span&gt;&lt;/a&gt;&lt;a style="font-family: Courier New; color: rgb(0, 0, 0);" name="l41"&gt;    } &lt;br&gt;&lt;/a&gt;&lt;a style="font-family: Courier New; color: rgb(0, 0, 0);" name="l42"&gt;}&lt;/a&gt;&lt;/pre&gt;&lt;br&gt;I wont bother to break down the structure or go into the various annotations used in JSR-311.&amp;nbsp; You can Google up quite a bit of material on all that of far higher quality than I could produce.&amp;nbsp; Starting at the Jersey site (&lt;a title="https://jersey.dev.java.net/" href="https://jersey.dev.java.net/" id="qf-e"&gt;https://jersey.dev.java.net/&lt;/a&gt; ) is as good a place as any as I think it's likely the most evolved JSR-311 implementation at this time.&amp;nbsp; &lt;br&gt;&lt;br&gt;For simplicity we will leave the main() method alone and modify a few other elements in this class.&amp;nbsp; First I changed the class level @Path annotation to:&lt;br&gt;&lt;br&gt;&lt;b&gt;@Path("/lith);&lt;/b&gt;&lt;br&gt;&lt;br&gt;and also added in a create and close method for the JPA EntityManagerFactory.&amp;nbsp; For fun I modded the getClicedMessage to parse out the URI path sent to it via a:&lt;br&gt;&lt;br&gt;&lt;b&gt;@Path("location/{latlong}")&lt;/b&gt;&amp;nbsp; annotaion along with a &lt;b&gt;@PathParam("latlong") String latlong&lt;/b&gt; annotation.&amp;nbsp; The later requires the &lt;i&gt;javax.ws.rs.PathParam&lt;/i&gt; import.&amp;nbsp; &lt;br&gt;&lt;br&gt;So our final code looks like this&amp;nbsp; (interesting parts in bold):&lt;br&gt;&lt;br&gt;&lt;span style="font-family: Courier New;"&gt;package example;&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;import com.sun.jersey.api.container.httpserver.HttpServerFactory;&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;import com.sun.net.httpserver.HttpServer;&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;import javax.persistence.EntityManager;&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;import javax.persistence.EntityManagerFactory;&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;import javax.persistence.Persistence;&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;import javax.persistence.Query;&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;import javax.ws.rs.GET;&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;import javax.ws.rs.Path;&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;import javax.ws.rs.PathParam;&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;import javax.ws.rs.ProduceMime;&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;import java.util.List;&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;@Path("/lith")&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;public class HelloWorld {&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;private EntityManagerFactory emf = null;&lt;/b&gt;&lt;/span&gt;&lt;b&gt;&lt;br style="font-family: Courier New;"&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; protected void createEMF() {&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; emf = Persistence.createEntityManagerFactory("NewPeristenceUnit");&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; protected void closeEMF() throws Exception {&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; emf.close();&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;/b&gt;&lt;br style="font-family: Courier New;"&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;public String doQuery(String latlong) {&lt;/b&gt;&lt;/span&gt;&lt;b&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; createEMF();&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; StringBuffer sb = new StringBuffer();&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; EntityManager em = emf.createEntityManager();&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Query query = em.createQuery("select c."+latlong+" from CmpEntity c");&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; List&amp;lt;Double&amp;gt; list = query.getResultList();&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (Double c : list) {&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sb.append(latlong + ": " + c.toString() + "\n");&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try {&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; closeEMF();&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } catch (Exception e) {&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; e.printStackTrace();&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return sb.toString();&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @GET&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @Path("location/{latlong}")&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @ProduceMime("text/plain")&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public String getClichedMessage(@PathParam("latlong") String latlong) {&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return doQuery(latlong);&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;/b&gt;&lt;br style="font-family: Courier New;"&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static void main(String[] args) throws Exception {&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; HttpServer server = HttpServerFactory.create("http://localhost:9998/");&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; server.start();&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.out.println("Server running");&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.out.println("Visit: http://localhost:9998/helloworld");&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.out.println("Hit return to stop...");&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.in.read();&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.out.println("Stopping server");&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; server.stop(0);&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.out.println("Server stopped");&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;span style="font-family: Courier New;"&gt;}&lt;/span&gt;&lt;br&gt;&lt;br&gt;A few things to note:&lt;br&gt;&lt;ul&gt;&lt;li&gt;The List&amp;lt;Double&amp;gt; list = query.getResultList();&amp;nbsp; is not good(tm) as we have an unchecked assignment of java.util.List to java.util.List&amp;lt;java.lang.Double&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Better would be to use something like List&amp;lt;CmpEntity&amp;gt; in this case and alter our query to something like &lt;i&gt;Query query = em.createQuery("select c from CmpEntity c");&lt;/i&gt;&amp;nbsp; However, I ran into some issues with return in my entity class being null.&amp;nbsp; Perhaps I needed to allow certain columns to be null, I am not certain of that, but I was more interested in the path than resolving the query.&amp;nbsp; Likely I will resolve this issue as the next step in this experiment.&amp;nbsp; &lt;br&gt;&lt;/li&gt;&lt;li&gt;Parallel to the aboe the point my List&amp;lt;Double&amp;gt; work since I know that the return from the query is a Double&lt;/li&gt;&lt;li&gt;I altered things a bit in the above example so that I could use both /lith/location/longitude and /lith/location/latitude as calling URI's.&amp;nbsp;&amp;nbsp; This works of course since I know ahead of time what my column names were that I wanted to use for this test and that they were of type Double to address the above two points.&amp;nbsp; This is whay I use the @Path and @PathParam annotations in the getClichedMessage method and strip out and pass along elements of the URI.&amp;nbsp; &lt;br&gt;&lt;/li&gt;&lt;li&gt;Like you would NOT want (ie DO NOT WANT) to use the column names in your mapped data source in your REST URI.&amp;nbsp; You would establish your URI template to whatever degree you wished and then use a more logical approach to generating the structure and content of your services and their replies.&amp;nbsp; This post is talking about the pipeline and is not worried about the very important architectural issue of mapping resources to URI's.&amp;nbsp; Take a look at my friends &lt;a title="Josh's post on that topic" target="_blank" href="http://josh-in-antarctica.blogspot.com/2008/10/restful-query-urls.html" id="gxga"&gt;Josh's post on that topic&lt;/a&gt; and the nice InfoQ &lt;a title="How to GET a cup of Coffee" href="http://www.infoq.com/articles/webber-rest-workflow" id="c.1z"&gt;How to GET a cup of Coffee&lt;/a&gt; posting about all that.&lt;/li&gt;&lt;/ul&gt;&lt;br&gt;One last important point in all this.&amp;nbsp; I got an error: &lt;b&gt;No identifier specified for entity&lt;/b&gt;.&amp;nbsp; When I looked at my generated entity classes all the columns recieved a @Basic and @Column(...) annotation.&amp;nbsp; At least one however needs to have a @Id annotation.&amp;nbsp; Reference the Hibernate FAQ at &lt;a title="http://www.hibernate.org/329.html#A6" href="http://www.hibernate.org/329.html#A6" id="gnrv"&gt;http://www.hibernate.org/329.html#A6&lt;/a&gt; for more info.&amp;nbsp; I had a unique integer column I could do this to and so I alterd my effected entity classes with @Id @Column(...) on one of the methods.&amp;nbsp; You, however, should not see this as I suspect it was due to the fact I never botherd to set a unique key column in that table on my database (don't tell my DBA).&amp;nbsp; &lt;br&gt;&lt;br&gt;That's about it.&amp;nbsp; At this point you should be able to run the project and make calls and get data out.&amp;nbsp; The built in REST client for IntelliJIDEA 8 is quite nice though perhaps not as advanced as the nice &lt;a title="rest-client" href="http://code.google.com/p/rest-client/" id="j04q"&gt;rest-client&lt;/a&gt; project.&amp;nbsp; In my case I parsed out the URI just for the sake of some fun.&amp;nbsp; With all the elements connected one can move on to more interesting "real world" applications of the JSR-311 and JPA API's used in this simple demo.&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-2762660823423696910?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/2762660823423696910/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=2762660823423696910' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/2762660823423696910'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/2762660823423696910'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2008/11/jsr-311-and-jpa-with-intellij-8.html' title='JSR-311 and JPA with Intellij 8'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-4894443734958664303</id><published>2008-06-19T09:32:00.004-05:00</published><updated>2008-06-19T10:53:33.482-05:00</updated><title type='text'>Sproutcore on Ubuntu 8.04</title><content type='html'>I was interested in the Sproutcore (ref: &lt;a href="http://www.sproutcore.com/"&gt;http://www.sproutcore.com&lt;/a&gt;) package that got some attention from the Apple developers conference.  (&lt;a href="http://www.appleinsider.com/articles/08/06/16/apples_open_secret_sproutcore_is_cocoa_for_the_web.html"&gt;AppleInsider&lt;/a&gt; article / &lt;a href="http://twit.tv/mbw94"&gt;MacBreak weekly podcast where Sproutcore is talked about&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;Getting it to work on Ubuntu (verison 8.04 for me) took a few steps I thought I would place here.  Of course first you need to make sure you have Ruby gems and Rails installed.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;apt-get install rubygems rails&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;one items you may miss to install though is the dev package.  Be sure to do&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;apt-get install ruby1.8-dev&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This will show itself when Ruby trys to build native extensions with an error like:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;font-family:courier new;" &gt;extconf.rb:1:in `require': no such file to load -- mkmf (LoadError)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;once you have this done you can do:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;gem install sproutcore&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;and accept all its questions (it will take a while as several packages need to be installed)&lt;br /&gt;&lt;br /&gt;At this point you will need to:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;cd /var/lib/gems/1.8/gems/sproutcore-0.9.10/bin&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;chmod 755 *&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;to make these scripts executable and also add this location to your path with:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;export PATH=/var/lib/gems/1.8/gems/sproutcore-0.9.10/bin:$PATH&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;or just add them to your shell init scripts like .bashrc&lt;br /&gt;&lt;br /&gt;At this point you can start down the tutorial examples at: &lt;a href="http://www.sproutcore.com/documentation/hello-world-tutorial/"&gt;http://www.sproutcore.com/documentation/hello-world-tutorial/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;take care&lt;br /&gt;Doug&lt;br /&gt;&lt;br /&gt;[update]&lt;br /&gt;After talking with my friend &lt;a href="http://josh-in-antarctica.blogspot.com/"&gt;Josh&lt;/a&gt; I thought I should add in a little note pointing to information related to &lt;a href="http://ajaxian.com/archives/an-interview-with-280-north-on-objective-j-and-cappuccino"&gt;Objective-J&lt;/a&gt; by 280North of &lt;a href="http://280slides.com/"&gt;280Slides&lt;/a&gt; development as another data point in some of this Javascript talk.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-4894443734958664303?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/4894443734958664303/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=4894443734958664303' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/4894443734958664303'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/4894443734958664303'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2008/06/sproutcore-on-ubuntu-804.html' title='Sproutcore on Ubuntu 8.04'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-683798762466114214</id><published>2008-06-06T11:27:00.001-05:00</published><updated>2008-06-06T11:30:11.691-05:00</updated><title type='text'>5 Groovy / Grails recommendations</title><content type='html'>So I was asked about what my top five recommendations would be for Groovy/Grails resources so I thought I would post them here to get feed back and other ideas from the community.  I decided to break it up into five categories.&lt;br id="azbk0"&gt;&lt;br id="azbk2"&gt;&lt;b id="emzr0"&gt;1) Web sites&lt;/b&gt;&lt;br id="azbk3"&gt;Of course the top two would have to be the main &lt;a title="Groovy" target="_blank" href="http://groovy.codehaus.org/" id="my4g"&gt;Groovy&lt;/a&gt; and &lt;a title="Grails" target="_blank" href="http://grails.org/" id="onv3"&gt;Grails&lt;/a&gt; sites themselves.  Not just because they are the home of the respective projects but because both truly are good resources with plenty of examples, documentations and links to mailing lists and other resources.   Others not associated with elements already to be placed in following categories might be the &lt;a title="Spring" target="_blank" href="http://www.springframework.org/" id="nej4"&gt;Spring&lt;/a&gt; and &lt;a title="Hibernate" target="_blank" href="http://www.hibernate.org/" id="niia"&gt;Hibernate&lt;/a&gt; sites.  &lt;br id="azbk4"&gt;&lt;br id="azbk5"&gt;&lt;b id="emzr1"&gt;2) Podcasts&lt;/b&gt;&lt;br id="azbk6"&gt;&lt;a title="Sven Haige" target="_blank" href="http://hansamann.wordpress.com/" id="h3if"&gt;Sven Haige&lt;/a&gt;  started the &lt;a title="Grails podcast" target="_blank" href="http://grails.org/Grails+Podcast" id="m2l2"&gt;Grails podcast&lt;/a&gt; and was recently joined by &lt;a title="Glen Smith" target="_blank" href="http://blogs.bytecode.com.au/glen/" id="zd6:"&gt;Glen Smith&lt;/a&gt;.  They do a wonderful job with the podcast and it's a great resource for the community.  &lt;br id="tn5b0"&gt;&lt;a title="The Java Posse" target="_blank" href="http://javaposse.com/" id="z82v"&gt;The Java Posse&lt;/a&gt; is high water mark in technical podcasts and I also enjoy &lt;a title="Software Engineering Radio" target="_blank" href="http://www.se-radio.net/" id="kpcv"&gt;Software Engineering Radio&lt;/a&gt;.  &lt;br id="a2900"&gt;&lt;br id="azbk8"&gt;&lt;b id="emzr2"&gt;3) RSS feeds&lt;/b&gt;&lt;br id="xp620"&gt;There are a lot of blogs, rss feeds, etc. that a person can track down.  The following three aggregate such feeds and provide a good starting point for locating feeds you resonate with:&lt;br id="ugsh0"&gt;&lt;a title="http://groovyblogs.org" target="_blank" href="http://groovyblogs.org" id="p8cu"&gt;http://groovyblogs.org&lt;/a&gt;   &lt;a title="http://groovy.dzone.com/" target="_blank" href="http://groovy.dzone.com/" id="dw6b"&gt;http://groovy.dzone.com/&lt;/a&gt;   &lt;a title="http://www.groovyongrails.com/" target="_blank" href="http://www.groovyongrails.com/" id="nlcq"&gt;http://www.groovyongrails.com/&lt;/a&gt; &lt;br id="xp621"&gt;&lt;br id="xp622"&gt;&lt;b id="emzr3"&gt;4) Software&lt;/b&gt;&lt;br id="xp623"&gt;Focusing on IDE's the first I would have to recommend is &lt;a title="IntelliJ IDEA" target="_blank" href="http://www.jetbrains.com/idea/index.html" id="b92e"&gt;IntelliJ IDEA&lt;/a&gt; as its Grails/Groovy support is top notch.  It's commercial, but well worth the cost and I believe the best of the those out there for Groovy Grails work period.    &lt;br id="osho0"&gt;&lt;br id="osho1"&gt;Following this I would (personally) would go with&lt;a title="Netbeans 6.1" target="_blank" href="http://www.netbeans.org/" id="onzy"&gt;Netbeans 6.1&lt;/a&gt; as it also now has Grails support. However, you need to use &lt;b id="yxpm0"&gt;&lt;i id="yxpm1"&gt;6.1 development builds&lt;/i&gt;&lt;/b&gt;.  The plugin home page is at: &lt;a title="http://plugins.netbeans.org/PluginPortal/faces/PluginDetailPage.jsp?pluginid=6265" target="_blank" href="http://plugins.netbeans.org/PluginPortal/faces/PluginDetailPage.jsp?pluginid=6265" id="nt:b"&gt;http://plugins.netbeans.org/PluginPortal/faces/PluginDetailPage.jsp?pluginid=6265&lt;/a&gt; &lt;br id="osho2"&gt;&lt;br id="osho3"&gt;Eclipse also has support and in fact was the first to do so if I recall correctly.  However, I have not heard much about it and suspect its support has not been a high priority.  Many love &lt;a title="Textmate" target="_blank" href="http://macromates.com/" id="a6q1"&gt;Textmate&lt;/a&gt; (for good reason) and its various bundles and while on the non-IDE side of software one could likely do a lot with &lt;a title="Jedit" target="_blank" href="http://www.jedit.org/" id="uslq"&gt;Jedit&lt;/a&gt; as well (I have).    &lt;br id="m3y10"&gt;&lt;br id="m3y11"&gt;Both &lt;a title="Teamcity" target="_blank" href="http://www.jetbrains.com/teamcity/index.html" id="ggu_"&gt;Teamcity&lt;/a&gt; and &lt;a title="Hudson" target="_blank" href="https://hudson.dev.java.net/" id="otfp"&gt;Hudson&lt;/a&gt; provide build environments and code coverage (by way of plugins for Hudson) for Grails projects.  Hudson requires a little work for setting up Grails builds but there are some nice blog posts on such efforts.  Again the IntelliJ produced Teamcity shines in its Grails support right out of the box.  &lt;br id="xp624"&gt;&lt;br id="xp625"&gt;&lt;b id="vxop0"&gt;5) Books&lt;/b&gt;&lt;br id="xp626"&gt;&lt;i id="u7_n0"&gt;&lt;a title="Groovy in Action" target="_blank" href="http://www.manning.com/koenig/" id="qavy"&gt;Groovy in Action&lt;/a&gt;&lt;/i&gt; is a wonderful resource to have as is &lt;i id="u7_n1"&gt;&lt;a title="The Definitive Guide to Grails" target="_blank" href="http://www.apress.com/book/view/1590597583" id="iesa"&gt;The Definitive Guide to Grails&lt;/a&gt;&lt;/i&gt;.  There are several new Groovy books coming out and more likely to follow as the Groovy/Grails community continues to grow.  &lt;br id="xp627"&gt;&lt;br id="xp628"&gt;Would love to hear other ideas/comments.&lt;br id="xp6210"&gt;Doug&lt;br id="xp6211"&gt;&lt;br id="co2w0"&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-683798762466114214?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/683798762466114214/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=683798762466114214' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/683798762466114214'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/683798762466114214'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2008/06/so-i-was-asked-about-what-my-top.html' title='5 Groovy / Grails recommendations'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-7087642864676983897</id><published>2008-05-20T12:35:00.001-05:00</published><updated>2008-05-20T12:38:07.616-05:00</updated><title type='text'>Fkey template for IntelliJ</title><content type='html'>I've come to really appreciate IntelliJ IDEA.  It's a wonderful IDE and so glad I discovered it as a by product of working with Grails and Groovy.  As I use it more and more I wanted to start to exploit more of its features and also to begin to get the key patterns to memory so I can work a bit faster.  Failing to find an fkey overlay for IntelliJ I made one.  I include a link to the SVG so anyone can modify/improve it as they wish.  If you do improve it, please email me updates so I can include them here.    &lt;br id="azzi0"&gt;&lt;br id="azzi1"&gt;&lt;a title="SVG Fkey template for IntelliJ IDEA" target="_blank" href="http://s3.amazonaws.com/fils/fkeyLetter.svg" id="eto:"&gt;SVG Fkey template for IntelliJ IDEA&lt;/a&gt;    (I would highly recommend the &lt;a title="InkScape" target="_blank" href="http://www.inkscape.org/" id="n:il"&gt;InkScape&lt;/a&gt; SVG editor, if you want to edit this document)&lt;br id="csum"&gt;&lt;br id="t2c0"&gt;I am also linking to the &lt;a title="document page with the  offical IntelliJ PDF key maps" target="_blank" href="http://www.jetbrains.com/idea/documentation/documentation.html" id="i12j"&gt;document page with the  official IntelliJ PDF key maps&lt;/a&gt; documents which list keyboard shortcuts.  This is a nice document I think should be more prominently noted at their web site.    You can add in your own keyboard &lt;a title="short cuts and a blog posting by Ted Young shows an example" target="_blank" href="http://tedyoung.blogsome.com/2008/02/21/intellij-idea-tip-quick-lists/" id="mx:7"&gt;short cuts and there is a blog posting by Ted Young that shows an example&lt;/a&gt; of how to do that.&lt;br id="vdda0"&gt;&lt;br id="vdda1"&gt;I recently noticed the &lt;span id="mwwi0"&gt;&lt;b&gt;Shortcut Key List plugin&lt;/b&gt;&lt;/span&gt; ( &lt;a title="http://plugins.intellij.net/plugin/?id=2391" href="http://plugins.intellij.net/plugin/?id=2391" id="ldmx"&gt;http://plugins.intellij.net/plugin/?id=2391&lt;/a&gt; ) which displays a simple box with short cuts in it.  &lt;br id="y5lp"&gt;&lt;br id="vdda2"&gt;Also there is &lt;span id="mwwi1"&gt;&lt;b&gt;Key Promoter&lt;/b&gt;&lt;/span&gt; (&lt;a title="http://plugins.intellij.net/plugin/?id=1003" href="http://plugins.intellij.net/plugin/?id=1003" id="w40c"&gt;http://plugins.intellij.net/plugin/?id=1003&lt;/a&gt; ) which can look for repetitive actions and ask if you want to assign a key sequence.  I have started to fill in opening in the template above with some of the common things I do.  &lt;br id="vdda3"&gt;&lt;br id="q8xt"&gt;I'd also like to mention a new keyboard that I am totally taken with (as is my 3 month old son).  It is based on the old IBM Model M keyboards.  You can learn more about these keyboards at &lt;a title="http://www.clickykeyboards.com/" target="_blank" href="http://www.clickykeyboards.com/" id="mmsz"&gt;http://www.clickykeyboards.com/&lt;/a&gt; which re-sells old Model M keyboards and also the Wikipedia entry (Ref: &lt;a title="http://en.wikipedia.org/wiki/Model_M_Keyboard" target="_blank" href="http://en.wikipedia.org/wiki/Model_M_Keyboard" id="o6lv"&gt;http://en.wikipedia.org/wiki/Model_M_Keyboard&lt;/a&gt; ).  These are wonderful, if not a little noisy, keyboards that many of you may recall from your first experiences with computers. &lt;br id="c.ee"&gt;&lt;br id="k4vc"&gt;A company called &lt;a title="Unicomp" target="_blank" href="http://pckeyboards.stores.yahoo.net/index.html" id="o_hn"&gt;Unicomp&lt;/a&gt; bought the rights to the buckling spring technology and makes &lt;span id="pa1x0"&gt;&lt;i&gt;brand new USB based versions of the Model M style keyboard&lt;/i&gt;&lt;/span&gt; called the &lt;a title="Customizer" target="_blank" href="http://pckeyboards.stores.yahoo.net/customizer.html" id="tbdq"&gt;Customizer&lt;/a&gt; which is what I picked up and is pictured below.   If you don't know what buckling spring keyboards are give them a look.  In a time when keyboards are getting far too complex for their own good, I'll take a keyboard that just does one thing and does it very well.&lt;br id="a2rd0"&gt;&lt;br id="a2rd1"&gt;take care&lt;br id="a2rd2"&gt;Doug&lt;br id="k5yh"&gt;            &lt;div id="vgwj" style="padding: 1em 0pt; text-align: center;"&gt;&lt;img id="id-2" style="width: 800px; height: 365px;" src="http://docs.google.com/File?id=dgtb8v9j_2926vmgw8dn_b"&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-7087642864676983897?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/7087642864676983897/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=7087642864676983897' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/7087642864676983897'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/7087642864676983897'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2008/05/ive-come-to-really-appreciate-intellij.html' title='Fkey template for IntelliJ'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-5499626280477229170</id><published>2008-04-28T12:16:00.001-05:00</published><updated>2008-04-28T12:17:27.704-05:00</updated><title type='text'>Using IUI in Grails</title><content type='html'>                                    So the first package I used in reviewing phone based UI's from Grails was &lt;a title="CIUI" target="_blank" href="http://clientside.cnet.com/cnet-js-standards/ciui-cnet-iphone-ui/" id="zc3o"&gt;CIUI&lt;/a&gt;.  The other popular one that I found was &lt;a title="IUI" target="_blank" href="http://code.google.com/p/iui/" id="kvtk"&gt;IUI&lt;/a&gt;.  This one seems a bit more advanced or at least feature rich than CIUI.  I should point out it will be interesting to see how move advanced &lt;a title="iPhone" href="http://ajaxian.com/archives/iphone-webkit-goodness-3d-css-transforms-and-ontouch-events" id="f:4e"&gt;iPhone&lt;/a&gt; and HTML 5.0 features are going to play out in all this.  That aside, implementing IUI was only marginally harder than CIUI.  Again we download and place the CSS and JS files into the css and js directories located in [project]/web-app.  In the case of IUI I did have to edit the CSS file to have it correctly locate the images folder (where I placed all the images that come with IUI).  You could make a separate directory for these images as a sub-directory of images and alter the CSS file as you see fit in that case.   Note, this package didn't render well for me outside of the webkit engine.  I did a post on &lt;a title="Webkit javascript performance on Ubuntu" target="_blank" href="http://douglasfils.blogspot.com/2008/04/this-weekend-i-had-small-pet-project-i.html" id="uqo-"&gt;Webkit javascript performance on Ubuntu&lt;/a&gt; that also links to resources for compiling this package on Linux (Mac and Windows builds are available at the &lt;a title="webkit site" target="_blank" href="http://webkit.org" id="l10o"&gt;webkit site&lt;/a&gt; )&lt;br id="f3yk"&gt;&lt;br id="eg4r"&gt;For the case of IUI I used the samples that came with the package as a guide to for all this.  My GSP files looks like:&lt;br id="sppf"&gt;&lt;br id="u:.4"&gt;&lt;pre id="wknv"&gt;&lt;a id="ha1m" name="l1"&gt;&lt;span id="m-2k" class="s0"&gt;&amp;lt;%@ &lt;/span&gt;&lt;span id="ynp9" class="s2"&gt;page &lt;/span&gt;&lt;span id="sx_q" class="s3"&gt;contentType&lt;/span&gt;&lt;span id="jb0-" class="s1"&gt;="&lt;/span&gt;&lt;span id="s37f" class="s4"&gt;text/html;charset=UTF-8&lt;/span&gt;&lt;span id="m.zw" class="s1"&gt;" &lt;/span&gt;&lt;span id="zprx" class="s0"&gt;%&amp;gt;&lt;/span&gt;&lt;span id="lp8j" class="s5"&gt; &lt;br id="obb6"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="qhal" name="l2"&gt;&lt;span id="aacg" class="s6"&gt;&amp;lt;&lt;/span&gt;&lt;span id="bu_u" class="s7"&gt;html&lt;/span&gt;&lt;span id="isu6" class="s6"&gt;&amp;gt;&lt;/span&gt;&lt;span id="qdbq" class="s5"&gt; &lt;br id="sy30"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="zg40" name="l3"&gt;&lt;span id="b99x" class="s6"&gt;&amp;lt;&lt;/span&gt;&lt;span id="gc4z" class="s7"&gt;meta &lt;/span&gt;&lt;span id="rakt" class="s8"&gt;name=&lt;/span&gt;&lt;span id="eiuy" class="s9"&gt;"layout" &lt;/span&gt;&lt;span id="u8he" class="s8"&gt;content=&lt;/span&gt;&lt;span id="hmzd" class="s9"&gt;"iuiLayout"&lt;/span&gt;&lt;span id="wke7" class="s6"&gt;/&amp;gt;&lt;/span&gt;&lt;span id="c0p:" class="s5"&gt; &lt;br id="brcq"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="hrpz" name="l4"&gt; &lt;br id="b836"&gt;&lt;/a&gt;&lt;a id="quw9" name="l5"&gt;&lt;span id="qw5i" class="s6"&gt;&amp;lt;&lt;/span&gt;&lt;span id="qdj0" class="s7"&gt;head&lt;/span&gt;&lt;span id="adux" class="s6"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span id="n-z6" class="s7"&gt;title&lt;/span&gt;&lt;span id="horf" class="s6"&gt;&amp;gt;&lt;/span&gt;&lt;span id="t.3q" class="s5"&gt;IUI test&lt;/span&gt;&lt;span id="w6f8" class="s6"&gt;&amp;lt;/&lt;/span&gt;&lt;span id="y1e-" class="s7"&gt;title&lt;/span&gt;&lt;span id="d2g-" class="s6"&gt;&amp;gt;&lt;/span&gt;&lt;span id="qbjm" class="s5"&gt; &lt;br id="i4-b"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="p66u" name="l6"&gt;    &lt;span id="xs6c" class="s6"&gt;&amp;lt;&lt;/span&gt;&lt;span id="q_0r" class="s7"&gt;meta &lt;/span&gt;&lt;span id="gnis" class="s8"&gt;name=&lt;/span&gt;&lt;span id="snql" class="s9"&gt;"viewport" &lt;/span&gt;&lt;span id="y4d1" class="s8"&gt;content=&lt;/span&gt;&lt;span id="floc" class="s9"&gt;"width=320; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"&lt;/span&gt;&lt;span id="qsr5" class="s6"&gt;&amp;gt;&lt;/span&gt;&lt;span id="b-bv" class="s5"&gt; &lt;br id="hq2:"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="rdpm" name="l7"&gt;&lt;span id="gv.v" class="s6"&gt;&amp;lt;/&lt;/span&gt;&lt;span id="v8ut" class="s7"&gt;head&lt;/span&gt;&lt;span id="lodq" class="s6"&gt;&amp;gt;&lt;/span&gt;&lt;span id="ch-h" class="s5"&gt; &lt;br id="o0tr"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="s0qh" name="l8"&gt; &lt;br id="lhtk"&gt;&lt;/a&gt;&lt;a id="o:sj" name="l9"&gt;&lt;span id="x_s9" class="s6"&gt;&amp;lt;&lt;/span&gt;&lt;span id="nlrt" class="s7"&gt;body &lt;/span&gt;&lt;span id="m-bl" class="s8"&gt;onclick=&lt;/span&gt;&lt;span id="y4q8" class="s9"&gt;"&lt;/span&gt;&lt;span id="zq_o" class="s5"&gt;console.log(&lt;/span&gt;&lt;span id="al65" class="s10"&gt;'Hello'&lt;/span&gt;&lt;span id="mn01" class="s5"&gt;, event.target);&lt;/span&gt;&lt;span id="kpqc" class="s9"&gt;"&lt;/span&gt;&lt;span id="g:7n" class="s6"&gt;&amp;gt;&lt;/span&gt;&lt;span id="sju-" class="s5"&gt; &lt;br id="g_d:"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="z0ec" name="l10"&gt;&lt;span id="dabg" class="s6"&gt;&amp;lt;&lt;/span&gt;&lt;span id="gmrm" class="s7"&gt;div &lt;/span&gt;&lt;span id="p.s4" class="s8"&gt;class=&lt;/span&gt;&lt;span id="h4m:" class="s9"&gt;"toolbar"&lt;/span&gt;&lt;span id="dr4d" class="s6"&gt;&amp;gt;&lt;/span&gt;&lt;span id="jli1" class="s5"&gt; &lt;br id="nz67"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="l:om" name="l11"&gt;    &lt;span id="g7lh" class="s6"&gt;&amp;lt;&lt;/span&gt;&lt;span id="j20q" class="s7"&gt;h1 &lt;/span&gt;&lt;span id="ww33" class="s8"&gt;id=&lt;/span&gt;&lt;span id="k:zd" class="s9"&gt;"pageTitle"&lt;/span&gt;&lt;span id="gxhy" class="s6"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span id="levk" class="s7"&gt;h1&lt;/span&gt;&lt;span id="ohfm" class="s6"&gt;&amp;gt;&lt;/span&gt;&lt;span id="din:" class="s5"&gt; &lt;br id="xqwo"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="pj8m" name="l12"&gt;    &lt;span id="wsp." class="s6"&gt;&amp;lt;&lt;/span&gt;&lt;span id="pi9a" class="s7"&gt;a &lt;/span&gt;&lt;span id="mctc" class="s8"&gt;id=&lt;/span&gt;&lt;span id="w4vs" class="s9"&gt;"backButton" &lt;/span&gt;&lt;span id="fuet" class="s8"&gt;class=&lt;/span&gt;&lt;span id="qmkq" class="s9"&gt;"button" &lt;/span&gt;&lt;span id="y92f" class="s8"&gt;href=&lt;/span&gt;&lt;span id="ldf0" class="s9"&gt;"#"&lt;/span&gt;&lt;span id="h2oy" class="s6"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span id="evbf" class="s7"&gt;a&lt;/span&gt;&lt;span id="e-se" class="s6"&gt;&amp;gt;&lt;/span&gt;&lt;span id="cc2i" class="s5"&gt; &lt;br id="bd.m"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="os6j" name="l13"&gt;    &lt;span id="qh2m" class="s6"&gt;&amp;lt;&lt;/span&gt;&lt;span id="m_nz" class="s7"&gt;a &lt;/span&gt;&lt;span id="z586" class="s8"&gt;class=&lt;/span&gt;&lt;span id="b41v" class="s9"&gt;"button" &lt;/span&gt;&lt;span id="whf-" class="s8"&gt;href=&lt;/span&gt;&lt;span id="dihv" class="s9"&gt;"&lt;/span&gt;&lt;span id="wkay" class="s11"&gt;${&lt;/span&gt;&lt;span id="azy6" class="s12"&gt;createLink(controller: &lt;/span&gt;&lt;span id="lwyy" class="s13"&gt;'iui'&lt;/span&gt;&lt;span id="g6ah" class="s12"&gt;, action: &lt;/span&gt;&lt;span id="txoo" class="s13"&gt;'search'&lt;/span&gt;&lt;span id="y095" class="s12"&gt;)&lt;/span&gt;&lt;span id="gow8" class="s11"&gt;}&lt;/span&gt;&lt;span id="t-ti" class="s9"&gt;"&lt;/span&gt;&lt;span id="yx9a" class="s6"&gt;&amp;gt;&lt;/span&gt;&lt;span id="q1vo" class="s5"&gt;Search&lt;/span&gt;&lt;span id="d29o" class="s6"&gt;&amp;lt;/&lt;/span&gt;&lt;span id="jm2v" class="s7"&gt;a&lt;/span&gt;&lt;span id="teiv" class="s6"&gt;&amp;gt;&lt;/span&gt;&lt;span id="qt9-" class="s5"&gt; &lt;br id="qdqh"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="dw:3" name="l14"&gt;&lt;span id="j.ih" class="s6"&gt;&amp;lt;/&lt;/span&gt;&lt;span id="goav" class="s7"&gt;div&lt;/span&gt;&lt;span id="cc2." class="s6"&gt;&amp;gt;&lt;/span&gt;&lt;span id="rl3b" class="s5"&gt; &lt;br id="ewlr"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="j51n" name="l15"&gt; &lt;br id="ydd-"&gt;&lt;/a&gt;&lt;a id="xxan" name="l16"&gt;&lt;span id="hkvy" class="s6"&gt;&amp;lt;&lt;/span&gt;&lt;span id="w8xt" class="s7"&gt;ul &lt;/span&gt;&lt;span id="lw7s" class="s8"&gt;id=&lt;/span&gt;&lt;span id="op0-" class="s9"&gt;"home" &lt;/span&gt;&lt;span id="nyxi" class="s8"&gt;title=&lt;/span&gt;&lt;span id="mx5h" class="s9"&gt;"Home" &lt;/span&gt;&lt;span id="ykv9" class="s8"&gt;selected=&lt;/span&gt;&lt;span id="nb4f" class="s9"&gt;"true"&lt;/span&gt;&lt;span id="cq3b" class="s6"&gt;&amp;gt;&lt;/span&gt;&lt;span id="x6j." class="s5"&gt; &lt;br id="iti3"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="xtrm" name="l17"&gt;    &lt;span id="ybbq" class="s6"&gt;&amp;lt;&lt;/span&gt;&lt;span id="yr_q" class="s7"&gt;li&lt;/span&gt;&lt;span id="ydm9" class="s6"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span id="lpf8" class="s7"&gt;a &lt;/span&gt;&lt;span id="fz2c" class="s8"&gt;href=&lt;/span&gt;&lt;span id="k3on" class="s9"&gt;"&lt;/span&gt;&lt;span id="q:sx" class="s11"&gt;${&lt;/span&gt;&lt;span id="fxo9" class="s12"&gt;createLink(controller: &lt;/span&gt;&lt;span id="v0_-" class="s13"&gt;'iui'&lt;/span&gt;&lt;span id="k7ht" class="s12"&gt;, action: &lt;/span&gt;&lt;span id="h2w1" class="s13"&gt;'category1'&lt;/span&gt;&lt;span id="nh2e" class="s12"&gt;)&lt;/span&gt;&lt;span id="e95l" class="s11"&gt;}&lt;/span&gt;&lt;span id="x5r6" class="s9"&gt;"&lt;/span&gt;&lt;span id="nlcv" class="s6"&gt;&amp;gt;&lt;/span&gt;&lt;span id="k:0k" class="s5"&gt;Category 1&lt;/span&gt;&lt;span id="d_1i" class="s6"&gt;&amp;lt;/&lt;/span&gt;&lt;span id="nuxt" class="s7"&gt;a&lt;/span&gt;&lt;span id="c2b5" class="s6"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span id="a5vq" class="s7"&gt;li&lt;/span&gt;&lt;span id="af5a" class="s6"&gt;&amp;gt;&lt;/span&gt;&lt;span id="n_tm" class="s5"&gt; &lt;br id="ns55"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="rgmj" name="l18"&gt;    &lt;span id="s.mw" class="s6"&gt;&amp;lt;&lt;/span&gt;&lt;span id="ibvm" class="s7"&gt;li&lt;/span&gt;&lt;span id="u_nl" class="s6"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span id="udse" class="s7"&gt;a &lt;/span&gt;&lt;span id="mmp4" class="s8"&gt;href=&lt;/span&gt;&lt;span id="h7ok" class="s9"&gt;"&lt;/span&gt;&lt;span id="rqm2" class="s11"&gt;${&lt;/span&gt;&lt;span id="w-8:" class="s12"&gt;createLink(controller: &lt;/span&gt;&lt;span id="js3v" class="s13"&gt;'iui'&lt;/span&gt;&lt;span id="nwun" class="s12"&gt;, action: &lt;/span&gt;&lt;span id="qpmq" class="s13"&gt;'category2'&lt;/span&gt;&lt;span id="b841" class="s12"&gt;)&lt;/span&gt;&lt;span id="ycis" class="s11"&gt;}&lt;/span&gt;&lt;span id="zv1:" class="s9"&gt;"&lt;/span&gt;&lt;span id="r33o" class="s6"&gt;&amp;gt;&lt;/span&gt;&lt;span id="d_-r" class="s5"&gt;Category 2&lt;/span&gt;&lt;span id="etuc" class="s6"&gt;&amp;lt;/&lt;/span&gt;&lt;span id="jaew" class="s7"&gt;a&lt;/span&gt;&lt;span id="rumm" class="s6"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span id="pd.h" class="s7"&gt;li&lt;/span&gt;&lt;span id="x5y:" class="s6"&gt;&amp;gt;&lt;/span&gt;&lt;span id="ehqw" class="s5"&gt; &lt;br id="ybv0"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="w4rk" name="l19"&gt;    &lt;span id="lknz" class="s6"&gt;&amp;lt;&lt;/span&gt;&lt;span id="ac55" class="s7"&gt;li&lt;/span&gt;&lt;span id="r-52" class="s6"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span id="w9.7" class="s7"&gt;a &lt;/span&gt;&lt;span id="j.7e" class="s8"&gt;href=&lt;/span&gt;&lt;span id="e4rw" class="s9"&gt;"&lt;/span&gt;&lt;span id="ig62" class="s11"&gt;${&lt;/span&gt;&lt;span id="uh-p" class="s12"&gt;createLink(controller: &lt;/span&gt;&lt;span id="kn59" class="s13"&gt;'iui'&lt;/span&gt;&lt;span id="hghk" class="s12"&gt;, action: &lt;/span&gt;&lt;span id="bf5h" class="s13"&gt;'stats'&lt;/span&gt;&lt;span id="qev-" class="s12"&gt;)&lt;/span&gt;&lt;span id="muoh" class="s11"&gt;}&lt;/span&gt;&lt;span id="gma9" class="s9"&gt;"&lt;/span&gt;&lt;span id="n-vz" class="s6"&gt;&amp;gt;&lt;/span&gt;&lt;span id="axo_" class="s5"&gt;Stats&lt;/span&gt;&lt;span id="lqjo" class="s6"&gt;&amp;lt;/&lt;/span&gt;&lt;span id="qa0j" class="s7"&gt;a&lt;/span&gt;&lt;span id="d0ep" class="s6"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span id="ck12" class="s7"&gt;li&lt;/span&gt;&lt;span id="lpzq" class="s6"&gt;&amp;gt;&lt;/span&gt;&lt;span id="bnqk" class="s5"&gt; &lt;br id="re_k"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="wm2o" name="l20"&gt;    &lt;span id="fv6-" class="s6"&gt;&amp;lt;&lt;/span&gt;&lt;span id="yv.t" class="s7"&gt;li&lt;/span&gt;&lt;span id="j.-2" class="s6"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span id="gzja" class="s7"&gt;a &lt;/span&gt;&lt;span id="rmtz" class="s8"&gt;href=&lt;/span&gt;&lt;span id="ci:2" class="s9"&gt;"&lt;/span&gt;&lt;span id="e-ja" class="s11"&gt;${&lt;/span&gt;&lt;span id="yjj4" class="s12"&gt;createLink(controller: &lt;/span&gt;&lt;span id="o6lh" class="s13"&gt;'iui'&lt;/span&gt;&lt;span id="o7-w" class="s12"&gt;, action: &lt;/span&gt;&lt;span id="v:_0" class="s13"&gt;'settings'&lt;/span&gt;&lt;span id="r2.j" class="s12"&gt;)&lt;/span&gt;&lt;span id="lfn_" class="s11"&gt;}&lt;/span&gt;&lt;span id="o7s4" class="s9"&gt;"&lt;/span&gt;&lt;span id="m:3c" class="s6"&gt;&amp;gt;&lt;/span&gt;&lt;span id="m6dz" class="s5"&gt;Settings&lt;/span&gt;&lt;span id="t243" class="s6"&gt;&amp;lt;/&lt;/span&gt;&lt;span id="jnz0" class="s7"&gt;a&lt;/span&gt;&lt;span id="lzqt" class="s6"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span id="wdlj" class="s7"&gt;li&lt;/span&gt;&lt;span id="cur5" class="s6"&gt;&amp;gt;&lt;/span&gt;&lt;span id="ea2g" class="s5"&gt; &lt;br id="my2m"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="z_8n" name="l21"&gt;    &lt;span id="mkkh" class="s6"&gt;&amp;lt;&lt;/span&gt;&lt;span id="guq4" class="s7"&gt;li&lt;/span&gt;&lt;span id="d2kz" class="s6"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span id="t905" class="s7"&gt;a &lt;/span&gt;&lt;span id="l834" class="s8"&gt;href=&lt;/span&gt;&lt;span id="c7ot" class="s9"&gt;"&lt;/span&gt;&lt;span id="jkpo" class="s11"&gt;${&lt;/span&gt;&lt;span id="hw25" class="s12"&gt;createLink(controller: &lt;/span&gt;&lt;span id="xla2" class="s13"&gt;'iui'&lt;/span&gt;&lt;span id="fcnw" class="s12"&gt;, action: &lt;/span&gt;&lt;span id="xfks" class="s13"&gt;'about'&lt;/span&gt;&lt;span id="e-j6" class="s12"&gt;)&lt;/span&gt;&lt;span id="qq-3" class="s11"&gt;}&lt;/span&gt;&lt;span id="t05b" class="s9"&gt;"&lt;/span&gt;&lt;span id="p9rl" class="s6"&gt;&amp;gt;&lt;/span&gt;&lt;span id="i5kv" class="s5"&gt;About&lt;/span&gt;&lt;span id="mjtp" class="s6"&gt;&amp;lt;/&lt;/span&gt;&lt;span id="w65:" class="s7"&gt;a&lt;/span&gt;&lt;span id="hi85" class="s6"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span id="xiuh" class="s7"&gt;li&lt;/span&gt;&lt;span id="p4xb" class="s6"&gt;&amp;gt;&lt;/span&gt;&lt;span id="kda5" class="s5"&gt; &lt;br id="pb9b"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="h4rw" name="l22"&gt; &lt;br id="a.4n"&gt;&lt;/a&gt;&lt;a id="b:e2" name="l23"&gt;&lt;span id="p6vw" class="s6"&gt;&amp;lt;/&lt;/span&gt;&lt;span id="advx" class="s7"&gt;ul&lt;/span&gt;&lt;span id="mdrp" class="s6"&gt;&amp;gt;&lt;/span&gt; &lt;/a&gt;&lt;a id="f_h." name="l24"&gt;&lt;br id="k:tw"&gt;&lt;/a&gt;&lt;a id="ygn9" name="l25"&gt;&lt;span id="e_zh" class="s6"&gt;&amp;lt;/&lt;/span&gt;&lt;span id="fggj" class="s7"&gt;body&lt;/span&gt;&lt;span id="xo68" class="s6"&gt;&amp;gt;&lt;/span&gt;&lt;span id="smml" class="s5"&gt; &lt;br id="hx5t"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="xj7." name="l26"&gt;&lt;span id="k7.j" class="s6"&gt;&amp;lt;/&lt;/span&gt;&lt;span id="cin9" class="s7"&gt;html&lt;/span&gt;&lt;span id="qhn1" class="s6"&gt;&amp;gt;&lt;/span&gt;&lt;/a&gt;&lt;/pre&gt;&lt;br id="g0mo"&gt;&lt;div id="en5b"&gt;&lt;table id="v:jp" border="0" cellpadding="3" cellspacing="0" width="100%"&gt;&lt;tbody id="a:8u"&gt;&lt;tr id="kq_7"&gt;&lt;td id="pftz" width="50%"&gt;&lt;img id="gb4u" style="width: 357px; height: 572px;" src="http://docs.google.com/File?id=dgtb8v9j_284frs9xrf6_b"&gt;&lt;/td&gt;&lt;td id="g7:j" width="50%"&gt;&lt;div id="jvpq" style="padding: 1em 0pt; text-align: left;"&gt;&lt;img id="mtrz" style="width: 357px; height: 572px;" src="http://docs.google.com/File?id=dgtb8v9j_285fvxxm8ft_b"&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;br id="ft48"&gt;Here I just linked into my &lt;a title="IuiController.groovy" target="_blank" href="Doc?id=dgtb8v9j_286fpzx3bf3" id="iav0"&gt;IuiController.groovy&lt;/a&gt; file to various methods to demonstrate some of the different features IUI has.  The only interesting points in this are that it does demonstrate how to use the &lt;a title="render method" target="_blank" href="http://grails.org/Controller+Dynamic+Methods" id="w7f0"&gt;render method&lt;/a&gt; for cases like this where you need to include attributes and such.  One interesting note was that the render method refused to provide a node named "form" in the XML return.  I assume this is perhaps related to a keyword issue or some such.  However, MarkupBuilder has no issues so where this does NOT work:&lt;br id="z469"&gt;&lt;br id="qsyl"&gt;&lt;pre id="ql:l"&gt;&lt;a id="z2:a" name="l81"&gt;    &lt;span id="xy1i" class="s4"&gt;// shows a form but doesn't work due to keyword issue with "form'?&lt;/span&gt;&lt;span id="k.j_" class="s1"&gt; &lt;br id="ukln"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="juji" name="l82"&gt;    &lt;span id="pds9" class="s0"&gt;def &lt;/span&gt;&lt;span id="jkmn" class="s1"&gt;searchDoesNotWork = { &lt;br id="umez"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="wxuu" name="l83"&gt;        render(contentType: &lt;span id="dl6a" class="s2"&gt;"text/xhtml"&lt;/span&gt;&lt;span id="odkw" class="s1"&gt;) { &lt;br id="c0c9"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="h.s4" name="l84"&gt;            &lt;span id="rorj" class="s2"&gt;"form"&lt;/span&gt;&lt;span id="pc28" class="s1"&gt;(id: &lt;/span&gt;&lt;span id="guwm" class="s2"&gt;"searchForm"&lt;/span&gt;&lt;span id="x8.0" class="s1"&gt;, &lt;/span&gt;&lt;span id="w68x" class="s0"&gt;class&lt;/span&gt;&lt;span id="e48c" class="s1"&gt;: &lt;/span&gt;&lt;span id="sh.f" class="s2"&gt;"dialog"&lt;/span&gt;&lt;span id="e-4n" class="s1"&gt;, action: &lt;/span&gt;&lt;span id="x9dc" class="s2"&gt;"foo"&lt;/span&gt;&lt;span id="g1ne" class="s1"&gt;) { &lt;br id="yr4o"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="w4wk" name="l85"&gt;                fieldset { &lt;br id="kz1l"&gt;&lt;/a&gt;&lt;a id="tm0c" name="l86"&gt;                    h1(&lt;span id="gfpo" class="s2"&gt;"Search the records"&lt;/span&gt;&lt;span id="pim." class="s1"&gt;) &lt;br id="v7dm"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="bcsd" name="l87"&gt;                    a(&lt;span id="ld4v" class="s0"&gt;class&lt;/span&gt;&lt;span id="t07x" class="s1"&gt;: &lt;/span&gt;&lt;span id="st8j" class="s2"&gt;"button leftButton"&lt;/span&gt;&lt;span id="wtra" class="s1"&gt;, type: &lt;/span&gt;&lt;span id="rywy" class="s2"&gt;"cancel"&lt;/span&gt;&lt;span id="jboo" class="s1"&gt;, &lt;/span&gt;&lt;span id="sn::" class="s2"&gt;"Cancel"&lt;/span&gt;&lt;span id="vven" class="s1"&gt;) &lt;br id="q20p"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="qvmz" name="l88"&gt;                    a(&lt;span id="fire" class="s0"&gt;class&lt;/span&gt;&lt;span id="pll9" class="s1"&gt;: &lt;/span&gt;&lt;span id="zs31" class="s2"&gt;"button blueButton"&lt;/span&gt;&lt;span id="ej-e" class="s1"&gt;, type: &lt;/span&gt;&lt;span id="yadg" class="s2"&gt;"submit"&lt;/span&gt;&lt;span id="n7xa" class="s1"&gt;, &lt;/span&gt;&lt;span id="g4tu" class="s2"&gt;"Search"&lt;/span&gt;&lt;span id="r6zp" class="s1"&gt;) &lt;br id="okiu"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="amhw" name="l89"&gt;                    label(&lt;span id="e17b" class="s2"&gt;"First Name"&lt;/span&gt;&lt;span id="qcyl" class="s1"&gt;) &lt;br id="rkp5"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="kp:2" name="l90"&gt;                    input(id: &lt;span id="yvjr" class="s2"&gt;"fname"&lt;/span&gt;&lt;span id="udgn" class="s1"&gt;, type: &lt;/span&gt;&lt;span id="x9gz" class="s2"&gt;"text"&lt;/span&gt;&lt;span id="acg5" class="s1"&gt;, name: &lt;/span&gt;&lt;span id="ax6v" class="s2"&gt;"fname"&lt;/span&gt;&lt;span id="umk1" class="s1"&gt;) &lt;br id="glqp"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="e:3z" name="l91"&gt;                    label(&lt;span id="t7p4" class="s2"&gt;"Last Name"&lt;/span&gt;&lt;span id="dleg" class="s1"&gt;) &lt;br id="upgf"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="c-um" name="l92"&gt;                    input(id: &lt;span id="rz:e" class="s2"&gt;"lname"&lt;/span&gt;&lt;span id="imml" class="s1"&gt;, type: &lt;/span&gt;&lt;span id="vg.d" class="s2"&gt;"text"&lt;/span&gt;&lt;span id="fzlc" class="s1"&gt;, name: &lt;/span&gt;&lt;span id="s_ur" class="s2"&gt;"lname"&lt;/span&gt;&lt;span id="iru_" class="s1"&gt;) &lt;br id="erw."&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="y240" name="l93"&gt;                } &lt;br id="y3xm"&gt;&lt;/a&gt;&lt;a id="id04" name="l94"&gt;            } &lt;br id="plih"&gt;&lt;/a&gt;&lt;a id="m-z6" name="l95"&gt;        } &lt;br id="jftv"&gt;&lt;/a&gt;&lt;a id="wabq" name="l96"&gt;    } &lt;br id="abvr"&gt;&lt;/a&gt;&lt;/pre&gt;this method will:&lt;br id="uwq3"&gt;&lt;pre id="cw3h"&gt;&lt;a id="d98:" name="l100"&gt;    &lt;span id="xyyq" class="s0"&gt;def &lt;/span&gt;&lt;span id="edxx" class="s1"&gt;search = { &lt;br id="xwv."&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="j_oy" name="l101"&gt;        &lt;span id="pylf" class="s0"&gt;def &lt;/span&gt;&lt;span id="jrn6" class="s1"&gt;mywriter = &lt;/span&gt;&lt;span id="mzvo" class="s0"&gt;new &lt;/span&gt;&lt;span id="ojhu" class="s1"&gt;StringWriter() &lt;br id="rwq4"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="w-t_" name="l102"&gt;        &lt;span id="g4bf" class="s0"&gt;def &lt;/span&gt;&lt;span id="mwzi" class="s1"&gt;xml = &lt;/span&gt;&lt;span id="hd9d" class="s0"&gt;new &lt;/span&gt;&lt;span id="esm7" class="s1"&gt;MarkupBuilder(mywriter) &lt;br id="d8la"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="tmmh" name="l103"&gt; &lt;br id="pdsf"&gt;&lt;/a&gt;&lt;a id="ccnu" name="l104"&gt;        &lt;span id="cqyo" class="s4"&gt;// had to do this since the render method seemed to not want to return form (key word?)&lt;/span&gt;&lt;span id="r75t" class="s1"&gt; &lt;br id="o8yh"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="mf2y" name="l105"&gt;        &lt;span id="ycjs" class="s4"&gt;//  this is really how they should dbe done anyway... but I am too lazy to change all the&lt;/span&gt;&lt;span id="yoi:" class="s1"&gt; &lt;br id="ibse"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="path" name="l106"&gt;        &lt;span id="m__3" class="s4"&gt;// examples&lt;/span&gt;&lt;span id="k158" class="s1"&gt; &lt;br id="o6lht"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="bj:y" name="l107"&gt; &lt;br id="i:u_"&gt;&lt;/a&gt;&lt;a id="g9hg" name="l108"&gt;        xml.&lt;span id="ynud" class="s2"&gt;"form"&lt;/span&gt;&lt;span id="vxom" class="s1"&gt;(id: &lt;/span&gt;&lt;span id="l5mp" class="s2"&gt;"searchForm"&lt;/span&gt;&lt;span id="ql65" class="s1"&gt;, &lt;/span&gt;&lt;span id="tmhk" class="s0"&gt;class&lt;/span&gt;&lt;span id="clz3" class="s1"&gt;: &lt;/span&gt;&lt;span id="ublx" class="s2"&gt;"dialog"&lt;/span&gt;&lt;span id="o311" class="s1"&gt;, action: &lt;/span&gt;&lt;span id="xggu" class="s2"&gt;"$&lt;/span&gt;&lt;span id="hyoi" class="s1"&gt;{createLink(controller: &lt;/span&gt;&lt;span id="tewj" class="s2"&gt;'iui'&lt;/span&gt;&lt;span id="wrt1" class="s1"&gt;, action: &lt;/span&gt;&lt;span id="wc7m" class="s2"&gt;'doSearch'&lt;/span&gt;&lt;span id="lplc" class="s1"&gt;)}&lt;/span&gt;&lt;span id="ogb3" class="s2"&gt;"&lt;/span&gt;&lt;span id="vo6b" class="s1"&gt;) { &lt;br id="kev7"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="ljgn" name="l109"&gt;            fieldset { &lt;br id="vh8d"&gt;&lt;/a&gt;&lt;a id="umfq" name="l110"&gt;                h1(&lt;span id="fmad" class="s2"&gt;"Search the records"&lt;/span&gt;&lt;span id="gjnq" class="s1"&gt;) &lt;br id="jihy"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="ivmx" name="l111"&gt;                a(&lt;span id="ft60" class="s0"&gt;class&lt;/span&gt;&lt;span id="riw2" class="s1"&gt;: &lt;/span&gt;&lt;span id="ve-e" class="s2"&gt;"button leftButton"&lt;/span&gt;&lt;span id="d0p:" class="s1"&gt;, type: &lt;/span&gt;&lt;span id="tx53" class="s2"&gt;"cancel"&lt;/span&gt;&lt;span id="w4mz" class="s1"&gt;, &lt;/span&gt;&lt;span id="vwrz" class="s2"&gt;"Cancel"&lt;/span&gt;&lt;span id="beg5" class="s1"&gt;) &lt;br id="j5yh"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="vcpa" name="l112"&gt;                a(&lt;span id="khxj" class="s0"&gt;class&lt;/span&gt;&lt;span id="vk26" class="s1"&gt;: &lt;/span&gt;&lt;span id="r7i:" class="s2"&gt;"button blueButton"&lt;/span&gt;&lt;span id="n166" class="s1"&gt;, type: &lt;/span&gt;&lt;span id="rwcq" class="s2"&gt;"submit"&lt;/span&gt;&lt;span id="r.bh" class="s1"&gt;, &lt;/span&gt;&lt;span id="pkl1" class="s2"&gt;"Search"&lt;/span&gt;&lt;span id="iu41" class="s1"&gt;) &lt;br id="zzh5"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="h_el" name="l113"&gt;                label(&lt;span id="w1hr" class="s2"&gt;"First Name"&lt;/span&gt;&lt;span id="ndgv" class="s1"&gt;) &lt;br id="wbzy"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="mud5" name="l114"&gt;                input(id: &lt;span id="vesa" class="s2"&gt;"fname"&lt;/span&gt;&lt;span id="ugd0" class="s1"&gt;, type: &lt;/span&gt;&lt;span id="z4cb" class="s2"&gt;"text"&lt;/span&gt;&lt;span id="qb9t" class="s1"&gt;, name: &lt;/span&gt;&lt;span id="h6iw" class="s2"&gt;"fname"&lt;/span&gt;&lt;span id="x7u_" class="s1"&gt;) &lt;br id="pkuo"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="zdha" name="l115"&gt;                label(&lt;span id="qsty" class="s2"&gt;"Last Name"&lt;/span&gt;&lt;span id="asa9" class="s1"&gt;) &lt;br id="gilo"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="a4iq" name="l116"&gt;                input(id: &lt;span id="g_:r" class="s2"&gt;"lname"&lt;/span&gt;&lt;span id="tk_a" class="s1"&gt;, type: &lt;/span&gt;&lt;span id="ltbf" class="s2"&gt;"text"&lt;/span&gt;&lt;span id="nuyc" class="s1"&gt;, name: &lt;/span&gt;&lt;span id="z51a" class="s2"&gt;"lname"&lt;/span&gt;&lt;span id="byd5" class="s1"&gt;) &lt;br id="e3ns"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="nvpm" name="l117"&gt;            } &lt;br id="yyv."&gt;&lt;/a&gt;&lt;a id="s:7x" name="l118"&gt;        } &lt;br id="j9.."&gt;&lt;/a&gt;&lt;a id="us5n" name="l119"&gt;        render mywriter.toString() &lt;br id="j7g5"&gt;&lt;/a&gt;&lt;a id="wy5q" name="l120"&gt;    } &lt;br id="n.20"&gt;&lt;/a&gt;&lt;/pre&gt;&lt;br id="r4rw"&gt;In point of fact &lt;span id="z7x6"&gt;&lt;b id="ln9d"&gt;it's likely better form in most cases to use the MarkupBuilder&lt;/b&gt;&lt;/span&gt; as you can incorporate it into code logic easier.  Though for simple cases there seems to be nothing wrong with render.  As with the CIUI example I'll just post up the whole controller file for people to look at (&lt;a title="IUI Controller" target="_blank" href="http://s3.amazonaws.com/fils/IuiController.groovy.html" id="s.ku"&gt;IUI Controller&lt;/a&gt; ).  &lt;br id="e_pp"&gt;&lt;br id="lbwp0"&gt;Note, I did modify the iui.js file line:&lt;br id="lbwp1"&gt;&lt;br id="lbwp2"&gt;&lt;span id="c2nz0"&gt;&lt;i&gt;            req.open(method || "GET", href, true);&lt;/i&gt;&lt;/span&gt;&lt;br id="lbwp3"&gt;&lt;br id="lbwp4"&gt;to &lt;br id="lbwp5"&gt;&lt;br id="lbwp6"&gt;&lt;span id="c2nz1"&gt;&lt;i&gt;            req.open(method || "POST", href, true);&lt;/i&gt;&lt;/span&gt;&lt;br id="lbwp7"&gt;&lt;br id="lbwp8"&gt;&lt;span id="xpsh0"&gt;&lt;i&gt;in order to get the search call to work to my controller&lt;/i&gt;&lt;/span&gt;.  For some reason the URL encoding version would not send back the variables.  I may contact the IUI people about this and see if I can resolve why this occured.  &lt;br id="lbwp9"&gt;&lt;br id="ga-g0"&gt;I was not able to wire up the toggle button to a controller method..  I got the error:&lt;br id="ga-g1"&gt;&lt;br id="ga-g2"&gt;console message: http://localhost:8080/phoneUIGarden/iui#_Settings @35: Can't find variable: settingCallBack&lt;br id="q4wp0"&gt;&lt;br id="vjpr0"&gt;Likely this is something simple (a guess) but I didn't bother to track it down since this was just a "for fun exploration" project.  &lt;br id="ga-g3"&gt;&lt;br id="qprm"&gt;It's easy to see how this could all be extended into a secured area of a site via &lt;a title="Acegi" target="_blank" href="http://grails.org/AcegiSecurity+Plugin" id="d5jv"&gt;Acegi&lt;/a&gt; or &lt;a title="jsecurity" target="_blank" href="http://grails.codehaus.org/JSecurity+Plugin" id="exsq"&gt;jsecurity&lt;/a&gt;  and perhaps even attached to &lt;a title="webflow" target="_blank" href="http://grails.org/WebFlow" id="sxcr"&gt;webflow&lt;/a&gt; .  All fun stuff if I was paid to do that.  This is by no means and in depth review, it's just my 4am feeding hacking to see what is involved in using IUI and CIUI.  I thought I would share since I haven't seen much on using these in the Grails framework.   &lt;br id="vg8p"&gt;&lt;br id="hfh3"&gt;It's obvious that &lt;br id="tpcx"&gt;A) it's simple &lt;br id="wlru"&gt;B) Groovy and Grails are a wonderful language/framework environment to do this in.  &lt;br id="au_v"&gt;C) Someone with more time for this could flesh it all out rather quickly&lt;br id="yb-.0"&gt;&lt;br id="ok2:"&gt;enjoy...&lt;br id="ncdn"&gt;Doug&lt;br id="tmuj"&gt;&lt;br id="q_d:"&gt;&lt;br id="snwf0"&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-5499626280477229170?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/5499626280477229170/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=5499626280477229170' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/5499626280477229170'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/5499626280477229170'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2008/04/using-iui-in-grails.html' title='Using IUI in Grails'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-1559662639980354068</id><published>2008-04-28T12:14:00.001-05:00</published><updated>2008-04-28T12:24:21.777-05:00</updated><title type='text'>Using CIUI in Grails</title><content type='html'>                                                                          So this past weekend I needed a fun yet mindless task one morning during at 4 am.  I have been looking at both &lt;a title="CIUI" target="_blank" href="http://clientside.cnet.com/cnet-js-standards/ciui-cnet-iphone-ui/" id="u35g"&gt;CIUI&lt;/a&gt; and &lt;a title="IUI" target="_blank" href="http://code.google.com/p/iui/" id="moxk"&gt;IUI&lt;/a&gt; and knew they would lend themselves well to being implemented in Grails what with it's oh so easy REST/AJAX style call to the controller layer.  In fact this was ever so easy and so I thought I would mention it here so people would know of these nice packages and add these as tools to their Grails toolbox.  If you are doing this from Linux (Ubuntu in my case) like I am, you may want to use the webkit engine (Ref: &lt;a title="Webkit on Ubuntu performance" target="_blank" href="http://douglasfils.blogspot.com/2008/04/this-weekend-i-had-small-pet-project-i.html" id="fs:x"&gt;Webkit on Ubuntu performance&lt;/a&gt; ).  Especially for the IUI package since it seems to render best in Webkit even over the latest FF3 engine.  &lt;br id="csk8"&gt;&lt;br id="j-32"&gt;Starting with &lt;a title="CIUI" target="_blank" href="http://clientside.cnet.com/cnet-js-standards/ciui-cnet-iphone-ui/" id="gfdz"&gt;CIUI&lt;/a&gt; the approach is easy.  Place the CiUI.css in your [project]/web-app/css and the CiUI.js into the [project]/web-app/js directories.  You may need to scan the CSS file and change image paths and such if you are using images from an other than default location.  &lt;br id="lzb2"&gt;&lt;br id="ldva"&gt;I created a simple controller CiuiController.groovy and an associated GSP page index.gsp.  Into the GSP page be sure to place:&lt;br id="xvq9"&gt;&lt;br id="s48x"&gt;&lt;span id="v0_z"&gt;&lt;b id="otmb"&gt;&amp;lt;link rel="stylesheet" href="${createLinkTo(dir:'css',file:'CiUI.css')}" /&amp;gt;&lt;/b&gt;&lt;/span&gt;&lt;br style="font-weight: bold;" id="bbsl"&gt;&lt;span id="km22"&gt;&lt;b id="gonx"&gt;&amp;lt;g:javascript library="CiUI"/&amp;gt;&lt;/b&gt;&lt;/span&gt;&lt;br id="bt6l"&gt;&lt;br id="ec9q"&gt;to load the CiUI css and js files.  Obviously you can alter the directory paths and such to keep your application file structure in whatever order you wish.&lt;br id="k-y9"&gt;&lt;br id="ekmp"&gt;My whole GSP pages looks like:&lt;br id="d:ge"&gt;&lt;pre id="ymdn"&gt;&lt;a id="ngpd" name="l1"&gt;&lt;span id="tqeh" class="s0"&gt;&amp;lt;&lt;/span&gt;&lt;span id="c13o" class="s1"&gt;html&lt;/span&gt;&lt;span id="u6_n" class="s0"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span id="ki9y" class="s1"&gt;head&lt;/span&gt;&lt;span id="th72" class="s0"&gt;&amp;gt;&lt;/span&gt;&lt;span id="u_te" class="s2"&gt; &lt;br id="rc6s"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="fl45" name="l2"&gt;    &lt;span id="h5y8" class="s0"&gt;&amp;lt;&lt;/span&gt;&lt;span id="efjc" class="s1"&gt;title&lt;/span&gt;&lt;span id="lqws" class="s0"&gt;&amp;gt;&lt;/span&gt;&lt;span id="x9vc" class="s2"&gt;Grails and CiUI Demo&lt;/span&gt;&lt;span id="yrcg" class="s0"&gt;&amp;lt;/&lt;/span&gt;&lt;span id="lbyj" class="s1"&gt;title&lt;/span&gt;&lt;span id="t.b8" class="s0"&gt;&amp;gt;&lt;/span&gt;&lt;span id="sx_k" class="s2"&gt; &lt;br id="a-.l"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="dwow" name="l3"&gt;    &lt;span id="yy5h" class="s0"&gt;&amp;lt;&lt;/span&gt;&lt;span id="efzt" class="s1"&gt;meta &lt;/span&gt;&lt;span id="k0if" class="s3"&gt;name=&lt;/span&gt;&lt;span id="ixkw" class="s4"&gt;"viewport" &lt;/span&gt;&lt;span id="j-d4" class="s3"&gt;content=&lt;/span&gt;&lt;span id="n2n7" class="s4"&gt;"width=320"&lt;/span&gt;&lt;span id="r-0v" class="s0"&gt;/&amp;gt;&lt;/span&gt;&lt;span id="q2y9" class="s2"&gt; &lt;br id="y3pm"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="ywfq" name="l4"&gt;    &lt;span id="nzn2" class="s0"&gt;&amp;lt;&lt;/span&gt;&lt;span id="f853" class="s1"&gt;meta &lt;/span&gt;&lt;span id="ca5e" class="s3"&gt;name=&lt;/span&gt;&lt;span id="qiwa" class="s4"&gt;"viewport" &lt;/span&gt;&lt;span id="p.rn" class="s3"&gt;content=&lt;/span&gt;&lt;span id="cqzj" class="s4"&gt;"initial-scale=1.0, user-scalable=no"&lt;/span&gt;&lt;span id="b6:0" class="s0"&gt;/&amp;gt;&lt;/span&gt;&lt;span id="fsw-" class="s2"&gt; &lt;br id="pvmq"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="c2lz" name="l5"&gt;    &lt;span id="myes" class="s0"&gt;&amp;lt;&lt;/span&gt;&lt;span id="i9la" class="s1"&gt;link &lt;/span&gt;&lt;span id="ljb." class="s3"&gt;rel=&lt;/span&gt;&lt;span id="yri6" class="s4"&gt;"stylesheet" &lt;/span&gt;&lt;span id="adp4" class="s3"&gt;href=&lt;/span&gt;&lt;span id="xjj-" class="s4"&gt;"&lt;/span&gt;&lt;span id="h.6i" class="s5"&gt;${&lt;/span&gt;&lt;span id="xzhn" class="s6"&gt;createLinkTo(dir: &lt;/span&gt;&lt;span id="s5cb" class="s7"&gt;'css'&lt;/span&gt;&lt;span id="f89o" class="s6"&gt;, file: &lt;/span&gt;&lt;span id="eso4" class="s7"&gt;'CiUI.css'&lt;/span&gt;&lt;span id="g0.p" class="s6"&gt;)&lt;/span&gt;&lt;span id="g.by" class="s5"&gt;}&lt;/span&gt;&lt;span id="n:80" class="s4"&gt;"&lt;/span&gt;&lt;span id="kvwe" class="s0"&gt;/&amp;gt;&lt;/span&gt;&lt;span id="k3ai" class="s2"&gt; &lt;br id="ac0-"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="bz0c" name="l6"&gt;    &lt;span id="c-56" class="s8"&gt;&amp;lt;&lt;/span&gt;&lt;span id="c6qz" class="s9"&gt;g:javascript &lt;/span&gt;&lt;span id="t4mg" class="s11"&gt;library&lt;/span&gt;&lt;span id="bo4h" class="s10"&gt;="&lt;/span&gt;&lt;span id="u:8c" class="s12"&gt;CiUI&lt;/span&gt;&lt;span id="meqs" class="s10"&gt;"&lt;/span&gt;&lt;span id="rx:x" class="s8"&gt;/&amp;gt;&lt;/span&gt;&lt;span id="lq7n" class="s2"&gt; &lt;br id="s5d6"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="xk42" name="l7"&gt;&lt;span id="uxkl" class="s0"&gt;&amp;lt;/&lt;/span&gt;&lt;span id="m99y" class="s1"&gt;head&lt;/span&gt;&lt;span id="gsu4" class="s0"&gt;&amp;gt;&lt;/span&gt;&lt;span id="beo1" class="s2"&gt; &lt;br id="r8gq"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="f:w4" name="l8"&gt; &lt;br id="opm9"&gt;&lt;/a&gt;&lt;a id="p3-8" name="l9"&gt;&lt;span id="qj-a" class="s0"&gt;&amp;lt;&lt;/span&gt;&lt;span id="ru.q" class="s1"&gt;body&lt;/span&gt;&lt;span id="pdzg" class="s0"&gt;&amp;gt;&lt;/span&gt;&lt;span id="nsv3" class="s2"&gt; &lt;br id="m:ta"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="pi-2" name="l10"&gt;&lt;span id="n_g0" class="s0"&gt;&amp;lt;&lt;/span&gt;&lt;span id="g.tj" class="s1"&gt;div &lt;/span&gt;&lt;span id="khhm" class="s3"&gt;id=&lt;/span&gt;&lt;span id="f08l" class="s4"&gt;"iphone_header"&lt;/span&gt;&lt;span id="xtye" class="s0"&gt;&amp;gt;&lt;/span&gt;&lt;span id="fucg" class="s2"&gt; &lt;br id="mpc5"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="cx78" name="l11"&gt;    &lt;span id="kz9y" class="s0"&gt;&amp;lt;&lt;/span&gt;&lt;span id="qxhb" class="s1"&gt;div &lt;/span&gt;&lt;span id="vc2d" class="s3"&gt;id=&lt;/span&gt;&lt;span id="dqxt" class="s4"&gt;"iphone_backbutton"&lt;/span&gt;&lt;span id="wzd-" class="s0"&gt;&amp;gt;&lt;/span&gt;&lt;span id="b5lu" class="s2"&gt; &lt;br id="ov9d"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="v6xy" name="l12"&gt;        &lt;span id="hj30" class="s0"&gt;&amp;lt;&lt;/span&gt;&lt;span id="qx.l" class="s1"&gt;img &lt;/span&gt;&lt;span id="ut1z" class="s3"&gt;src=&lt;/span&gt;&lt;span id="ly3n" class="s4"&gt;"images/back-button-tip.png" &lt;/span&gt;&lt;span id="mgvr" class="s3"&gt;border=&lt;/span&gt;&lt;span id="d9so" class="s4"&gt;"0" &lt;/span&gt;&lt;span id="ojq." class="s3"&gt;align=&lt;/span&gt;&lt;span id="t0wo" class="s4"&gt;"left"&lt;/span&gt;&lt;span id="vwjw" class="s0"&gt;/&amp;gt;&lt;/span&gt;&lt;span id="kyy7" class="s2"&gt; &lt;br id="n85."&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="ozjn" name="l13"&gt;        &lt;span id="xn4p" class="s0"&gt;&amp;lt;&lt;/span&gt;&lt;span id="ne-x" class="s1"&gt;a &lt;/span&gt;&lt;span id="ouna" class="s3"&gt;id=&lt;/span&gt;&lt;span id="v9:d" class="s4"&gt;"iphone_backbutton_text" &lt;/span&gt;&lt;span id="at69" class="s3"&gt;href=&lt;/span&gt;&lt;span id="uyyl" class="s4"&gt;"#" &lt;/span&gt;&lt;span id="f.4l" class="s3"&gt;class=&lt;/span&gt;&lt;span id="slrc" class="s4"&gt;"go_back"&lt;/span&gt;&lt;span id="v.cm" class="s0"&gt;&amp;gt;&lt;/span&gt;&lt;span id="xtsm" class="s2"&gt;Back&lt;/span&gt;&lt;span id="a.4h" class="s0"&gt;&amp;lt;/&lt;/span&gt;&lt;span id="uhxt" class="s1"&gt;a&lt;/span&gt;&lt;span id="jfxc" class="s0"&gt;&amp;gt;&lt;/span&gt;&lt;span id="ilno" class="s2"&gt; &lt;br id="kbfj"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="v0x7" name="l14"&gt;    &lt;span id="c6wx" class="s0"&gt;&amp;lt;/&lt;/span&gt;&lt;span id="yish" class="s1"&gt;div&lt;/span&gt;&lt;span id="eq_e" class="s0"&gt;&amp;gt;&lt;/span&gt;&lt;span id="yg70" class="s2"&gt; &lt;br id="f:zl"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="gf.y" name="l15"&gt;    &lt;span id="mog2" class="s0"&gt;&amp;lt;&lt;/span&gt;&lt;span id="k95a" class="s1"&gt;div &lt;/span&gt;&lt;span id="jy40" class="s3"&gt;id=&lt;/span&gt;&lt;span id="wh7s" class="s4"&gt;"iphone_title"&lt;/span&gt;&lt;span id="uvag" class="s0"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span id="em0t" class="s1"&gt;div&lt;/span&gt;&lt;span id="kvbe" class="s0"&gt;&amp;gt;&lt;/span&gt;&lt;span id="fu-7" class="s2"&gt; &lt;br id="ozja"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="ape5" name="l16"&gt;&lt;span id="e7wj" class="s0"&gt;&amp;lt;/&lt;/span&gt;&lt;span id="g2qw" class="s1"&gt;div&lt;/span&gt;&lt;span id="a8:3" class="s0"&gt;&amp;gt;&lt;/span&gt;&lt;span id="m56p" class="s2"&gt; &lt;br id="zau0"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="sm8v" name="l17"&gt; &lt;br id="yh_7"&gt;&lt;/a&gt;&lt;a id="drpy" name="l18"&gt;&lt;span id="zn6y" class="s0"&gt;&amp;lt;&lt;/span&gt;&lt;span id="iurr" class="s1"&gt;div &lt;/span&gt;&lt;span id="z87h" class="s3"&gt;id=&lt;/span&gt;&lt;span id="b8_u" class="s4"&gt;"iphone_body" &lt;/span&gt;&lt;span id="fetc" class="s3"&gt;style=&lt;/span&gt;&lt;span id="tqk9" class="s4"&gt;"&lt;/span&gt;&lt;span id="g3h-" class="s13"&gt;clear&lt;/span&gt;&lt;span id="oq8t" class="s2"&gt;:&lt;/span&gt;&lt;span id="r3ja" class="s14"&gt;both&lt;/span&gt;&lt;span id="p0.c" class="s2"&gt;;&lt;/span&gt;&lt;span id="w.ip" class="s4"&gt;"&lt;/span&gt;&lt;span id="dc-d" class="s0"&gt;&amp;gt;&lt;/span&gt;&lt;span id="qfg:" class="s2"&gt; &lt;br id="tl2a"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="qt1c" name="l19"&gt;    &lt;span id="wrnu" class="s0"&gt;&amp;lt;&lt;/span&gt;&lt;span id="pjd0" class="s1"&gt;ul &lt;/span&gt;&lt;span id="dv1z" class="s3"&gt;class=&lt;/span&gt;&lt;span id="yxj4" class="s4"&gt;"menu"&lt;/span&gt;&lt;span id="cegy" class="s0"&gt;&amp;gt;&lt;/span&gt;&lt;span id="o:j." class="s2"&gt; &lt;br id="trzh"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="g_r5" name="l20"&gt;        &lt;span id="d-xt" class="s0"&gt;&amp;lt;&lt;/span&gt;&lt;span id="ckqm" class="s1"&gt;li&lt;/span&gt;&lt;span id="v_:7" class="s0"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span id="rfvv" class="s1"&gt;a &lt;/span&gt;&lt;span id="zq0j" class="s3"&gt;href=&lt;/span&gt;&lt;span id="yk2e" class="s4"&gt;"&lt;/span&gt;&lt;span id="v7ls" class="s5"&gt;${&lt;/span&gt;&lt;span id="hmsz" class="s6"&gt;createLink(controller: &lt;/span&gt;&lt;span id="p2y5" class="s7"&gt;'ciui'&lt;/span&gt;&lt;span id="dze-" class="s6"&gt;, action: &lt;/span&gt;&lt;span id="rtpr" class="s7"&gt;'page'&lt;/span&gt;&lt;span id="fre-" class="s6"&gt;, id: &lt;/span&gt;&lt;span id="bm8q" class="s7"&gt;'1'&lt;/span&gt;&lt;span id="erp:" class="s6"&gt;)&lt;/span&gt;&lt;span id="tv3x" class="s5"&gt;}&lt;/span&gt;&lt;span id="vtuf" class="s4"&gt;" &lt;/span&gt;&lt;span id="ccbv" class="s3"&gt;class=&lt;/span&gt;&lt;span id="evld" class="s4"&gt;"go_forward" &lt;/span&gt;&lt;span id="sznl" class="s3"&gt;title=&lt;/span&gt;&lt;span id="ihih" class="s4"&gt;"Feeds"&lt;/span&gt;&lt;span id="ypvs" class="s0"&gt;&amp;gt;&lt;/span&gt;&lt;span id="n164" class="s2"&gt; &lt;br id="orwk"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="o.e5" name="l21"&gt;            Groovy and Grails Feeds &lt;br id="gq:l"&gt;&lt;/a&gt;&lt;a id="tf-b" name="l22"&gt;        &lt;span id="jnvk" class="s0"&gt;&amp;lt;/&lt;/span&gt;&lt;span id="l:tp" class="s1"&gt;a&lt;/span&gt;&lt;span id="ehve" class="s0"&gt;&amp;gt;&lt;/span&gt;&lt;span id="u6.o" class="s2"&gt; &lt;br id="ba:o"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="m9y." name="l23"&gt;        &lt;span id="p2mc" class="s0"&gt;&amp;lt;/&lt;/span&gt;&lt;span id="uosl" class="s1"&gt;li&lt;/span&gt;&lt;span id="b-:o" class="s0"&gt;&amp;gt;&lt;/span&gt;&lt;span id="vq.3" class="s2"&gt; &lt;br id="pgs."&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="dv39" name="l24"&gt;    &lt;span id="jjfi" class="s0"&gt;&amp;lt;/&lt;/span&gt;&lt;span id="e8ur" class="s1"&gt;ul&lt;/span&gt;&lt;span id="b-y1" class="s0"&gt;&amp;gt;&lt;/span&gt;&lt;span id="z2_b" class="s2"&gt; &lt;br id="gk2m"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="bws9" name="l25"&gt;&lt;span id="qc0m" class="s0"&gt;&amp;lt;/&lt;/span&gt;&lt;span id="fqcq" class="s1"&gt;div&lt;/span&gt;&lt;span id="pajw" class="s0"&gt;&amp;gt;&lt;/span&gt;&lt;span id="zuy1" class="s2"&gt; &lt;br id="e0fk"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="l1wv" name="l26"&gt; &lt;br id="ncgw"&gt;&lt;/a&gt;&lt;a id="ky4j" name="l27"&gt;&lt;span id="fe4k" class="s0"&gt;&amp;lt;&lt;/span&gt;&lt;span id="uh_q" class="s1"&gt;div &lt;/span&gt;&lt;span id="uhl9" class="s3"&gt;id=&lt;/span&gt;&lt;span id="yz0e" class="s4"&gt;"iphone_footer"&lt;/span&gt;&lt;span id="mxax" class="s0"&gt;&amp;gt;&lt;/span&gt;&lt;span id="gb:t" class="s2"&gt;My footer for CiUI demo&lt;/span&gt;&lt;span id="vtg:" class="s0"&gt;&amp;lt;/&lt;/span&gt;&lt;span id="u0ct" class="s1"&gt;div&lt;/span&gt;&lt;span id="y9va" class="s0"&gt;&amp;gt;&lt;/span&gt;&lt;span id="jg0d" class="s2"&gt; &lt;br id="psk1"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="fxro" name="l28"&gt; &lt;br id="bll7"&gt;&lt;/a&gt;&lt;a id="qzb." name="l29"&gt;&lt;span id="eieo" class="s0"&gt;&amp;lt;&lt;/span&gt;&lt;span id="q11i" class="s1"&gt;div &lt;/span&gt;&lt;span id="l6bq" class="s3"&gt;id=&lt;/span&gt;&lt;span id="a6eu" class="s4"&gt;"iphone_loading_page"&lt;/span&gt;&lt;span id="dg:l" class="s0"&gt;&amp;gt;&lt;/span&gt;&lt;span id="pg-c" class="s2"&gt; &lt;br id="nnhc"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="ke26" name="l30"&gt;    &lt;span id="sam0" class="s0"&gt;&amp;lt;&lt;/span&gt;&lt;span id="d49f" class="s1"&gt;div &lt;/span&gt;&lt;span id="mhv4" class="s3"&gt;id=&lt;/span&gt;&lt;span id="b1o1" class="s4"&gt;'loading' &lt;/span&gt;&lt;span id="wr9r" class="s3"&gt;class=&lt;/span&gt;&lt;span id="se0-" class="s4"&gt;"info_msg"&lt;/span&gt;&lt;span id="d49-" class="s0"&gt;&amp;gt;&lt;/span&gt;&lt;span id="oq6s" class="s2"&gt; &lt;br id="zva-"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="gcy0" name="l31"&gt;        &lt;span id="b1ps" class="s0"&gt;&amp;lt;&lt;/span&gt;&lt;span id="gosu" class="s1"&gt;img &lt;/span&gt;&lt;span id="hr1i" class="s3"&gt;src=&lt;/span&gt;&lt;span id="sn1f" class="s4"&gt;"images/loading.gif"&lt;/span&gt;&lt;span id="m2bm" class="s0"&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span id="ltri" class="s1"&gt;br&lt;/span&gt;&lt;span id="chd7" class="s0"&gt;/&amp;gt;&lt;/span&gt;&lt;span id="rtcx" class="s2"&gt; &lt;br id="d8:5"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="b:-o" name="l32"&gt;        loading... &lt;br id="w670"&gt;&lt;/a&gt;&lt;a id="x9v:" name="l33"&gt;&lt;span id="rtfo" class="s0"&gt;&amp;lt;/&lt;/span&gt;&lt;span id="ztt_" class="s1"&gt;div&lt;/span&gt;&lt;span id="d:uy" class="s0"&gt;&amp;gt;&lt;/span&gt;&lt;span id="axhj" class="s2"&gt; &lt;br id="fiu6"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="x4yj" name="l34"&gt;&lt;span id="x.w1" class="s0"&gt;&amp;lt;/&lt;/span&gt;&lt;span id="q1tz" class="s1"&gt;div&lt;/span&gt;&lt;span id="m7m1" class="s0"&gt;&amp;gt;&lt;/span&gt;&lt;span id="f6r3" class="s2"&gt; &lt;br id="u:n7"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="drw3" name="l35"&gt;&lt;span id="o26u" class="s0"&gt;&amp;lt;/&lt;/span&gt;&lt;span id="yq-h" class="s1"&gt;body&lt;/span&gt;&lt;span id="ytj8" class="s0"&gt;&amp;gt;&lt;/span&gt;&lt;span id="yviv" class="s2"&gt; &lt;br id="mrz6"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="r2va" name="l36"&gt;&lt;span id="wr4v" class="s0"&gt;&amp;lt;/&lt;/span&gt;&lt;span id="as7c" class="s1"&gt;html&lt;/span&gt;&lt;span id="k98d" class="s0"&gt;&amp;gt;&lt;/span&gt;&lt;span id="zjxw" class="s2"&gt; &lt;br id="zrxe"&gt;&lt;br id="mlwc"&gt;&lt;br id="c_92"&gt;&lt;div id="sssb" style="padding: 1em 0pt; text-align: left;"&gt;&lt;img id="zrmi" style="width: 357px; height: 572px;" src="http://docs.google.com/File?id=dgtb8v9j_283dkzz7zcx_b"&gt;&lt;/div&gt;&lt;br id="noe0"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/pre&gt;&lt;br id="o4a."&gt;Next it's just a few simple method calls in the controller.  I decided to have a little fun and used the Groovy XML features to pull down RSS feeds from &lt;a title="Groovy Blogs" target="_blank" href="http://www.groovyblogs.org" id="dalh"&gt;Groovy Blogs&lt;/a&gt;, &lt;a title="Groovy on Grails" target="_blank" href="http://feeds.feedburner.com/groovyongrails" id="fkpt"&gt;&lt;/a&gt;&lt;a title="Groovy on Grails" target="_blank" href="http://www.groovyongrails.com/" id="ymcj"&gt;Groovy on Grails&lt;/a&gt; and &lt;a title="Groovy Zone" target="_blank" href="http://feeds.dzone.com/zones/groovy" id="jjtv"&gt;&lt;/a&gt;&lt;a title="Groovy Zone" target="_blank" href="http://groovy.dzone.com/" id="yyc0"&gt;Groovy Zone&lt;/a&gt;.  There are really only a couple of comments:&lt;br id="us_-"&gt;&lt;br id="g-3t"&gt;1) This whole effort is made very easy by use of the Grails "render" call.  It means that we can do things like:&lt;br id="jsan"&gt;&lt;br id="rdhl"&gt;&lt;pre id="oo9x"&gt;&lt;a id="qrv6" name="l29"&gt;   &lt;span id="pkz5" class="s0"&gt;def &lt;/span&gt;&lt;span id="wjrz" class="s1"&gt;page = { &lt;br id="w-pj"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="fpjs" name="l30"&gt; &lt;br id="grd1"&gt;&lt;/a&gt;&lt;a id="txms" name="l31"&gt;        &lt;span id="nmc2" class="s3"&gt;//  you would make this more dynamic in a real app&lt;/span&gt;&lt;span id="wj.u" class="s1"&gt; &lt;br id="osp1"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="jejf" name="l32"&gt;        &lt;span id="o:en" class="s0"&gt;def &lt;/span&gt;&lt;span id="cowg" class="s1"&gt;feedMap = [&lt;/span&gt;&lt;span id="ghq1" class="s2"&gt;'Groovy Blogs'&lt;/span&gt;&lt;span id="luwk" class="s1"&gt;: &lt;/span&gt;&lt;span id="hhwz" class="s2"&gt;'http://feeds.feedburner.com/groovyblogs'&lt;/span&gt;&lt;span id="w_3q" class="s1"&gt;, &lt;/span&gt;&lt;span id="fadi" class="s2"&gt;'Grroovy on Grails'&lt;/span&gt;&lt;span id="unnt" class="s1"&gt;: &lt;/span&gt;&lt;span id="refi" class="s2"&gt;'http://feeds.feedburner.com/groovyongrails'&lt;/span&gt;&lt;span id="e1j2" class="s1"&gt;, &lt;/span&gt;&lt;span id="y_ty" class="s2"&gt;'Groovy Zone'&lt;/span&gt;&lt;span id="mism" class="s1"&gt;: &lt;/span&gt;&lt;span id="fp4l" class="s2"&gt;'http://feeds.dzone.com/zones/groovy'&lt;/span&gt;&lt;span id="zufi" class="s1"&gt;] &lt;br id="h7pk"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="gt8h" name="l33"&gt; &lt;br id="nc4l"&gt;&lt;/a&gt;&lt;a id="hkkr" name="l34"&gt;        render(contentType: &lt;span id="xmnm" class="s2"&gt;"text/xhtml"&lt;/span&gt;&lt;span id="k9l4" class="s1"&gt;) { &lt;br id="tohb"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="xzo2" name="l35"&gt; &lt;br id="mjcf"&gt;&lt;/a&gt;&lt;a id="mbv9" name="l36"&gt;            &lt;span id="afkj" class="s3"&gt;//  If there are some menu items to show..  show them&lt;/span&gt;&lt;span id="ym70" class="s1"&gt; &lt;br id="gaqf"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="bv5t" name="l37"&gt;            ul(&lt;span id="f-wn" class="s0"&gt;class&lt;/span&gt;&lt;span id="h1ba" class="s1"&gt;: &lt;/span&gt;&lt;span id="wujc" class="s2"&gt;"menu"&lt;/span&gt;&lt;span id="q5vc" class="s1"&gt;) { &lt;br id="xvwk"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="mwc5" name="l38"&gt;                &lt;span id="qpxg" class="s0"&gt;for &lt;/span&gt;&lt;span id="mfaj" class="s1"&gt;(i &lt;/span&gt;&lt;span id="nmp1" class="s0"&gt;in &lt;/span&gt;&lt;span id="r9hp" class="s1"&gt;feedMap.keySet()) { &lt;br id="x:nr"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="q0aa" name="l39"&gt;                    li { &lt;br id="tn25"&gt;&lt;/a&gt;&lt;a id="rthj" name="l40"&gt;                        a(&lt;span id="z8r7" class="s0"&gt;class&lt;/span&gt;&lt;span id="fjcs" class="s1"&gt;: &lt;/span&gt;&lt;span id="hsfs" class="s2"&gt;"go_forward"&lt;/span&gt;&lt;span id="qin5" class="s1"&gt;, title: &lt;/span&gt;&lt;span id="yk1f" class="s2"&gt;"$&lt;/span&gt;&lt;span id="ruix" class="s1"&gt;{i}&lt;/span&gt;&lt;span id="opl9" class="s2"&gt;"&lt;/span&gt;&lt;span id="w9o6" class="s1"&gt;, href: &lt;/span&gt;&lt;span id="ybpr" class="s2"&gt;"$&lt;/span&gt;&lt;span id="ir:x" class="s1"&gt;{createLink(controller: &lt;/span&gt;&lt;span id="pyr0" class="s2"&gt;'ciui'&lt;/span&gt;&lt;span id="kqjr" class="s1"&gt;, action: &lt;/span&gt;&lt;span id="zk7o" class="s2"&gt;'getFeed'&lt;/span&gt;&lt;span id="dt7-" class="s1"&gt;)}&lt;/span&gt;&lt;span id="wk63" class="s2"&gt;/?url=" &lt;/span&gt;&lt;span id="h5we" class="s1"&gt;+ feedMap[i]) { &lt;br id="wfs8"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="r14p" name="l41"&gt;                            div(&lt;span id="ffxz" class="s2"&gt;"$&lt;/span&gt;&lt;span id="gixp" class="s1"&gt;{i}&lt;/span&gt;&lt;span id="j5j7" class="s2"&gt;"&lt;/span&gt;&lt;span id="b4ua" class="s1"&gt;) &lt;br id="noy4"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="idn_" name="l42"&gt;                        } &lt;br id="arpm"&gt;&lt;/a&gt;&lt;a id="yfia" name="l43"&gt;                    } &lt;br id="l5y5"&gt;&lt;/a&gt;&lt;a id="s1mi" name="l44"&gt;                } &lt;br id="ztc2"&gt;&lt;/a&gt;&lt;a id="j-8c" name="l45"&gt;            } &lt;br id="seuc"&gt;&lt;/a&gt;&lt;a id="r:6n" name="l46"&gt;        } &lt;br id="fokl"&gt;&lt;/a&gt;&lt;a id="prj:" name="l47"&gt; &lt;br id="t0gn"&gt;&lt;/a&gt;&lt;a id="lf78" name="l48"&gt;    } &lt;br id="na1l"&gt;&lt;/a&gt;&lt;a id="xs3y" name="l49"&gt; &lt;br id="hj6b"&gt;&lt;/a&gt;&lt;/pre&gt;Check out more on the render method at &lt;a title="http://grails.org/Controller+Dynamic+Methods" target="_blank" href="http://grails.org/Controller+Dynamic+Methods" id="z4uy"&gt;http://grails.org/Controller+Dynamic+Methods&lt;/a&gt;.  For sake of a short blog entry I have just placed the whole controller file on-line (Ref: &lt;a title="CIUI Controller" target="_blank" href="http://s3.amazonaws.com/fils/CiuiController.groovy.html" id="a3o3"&gt;CIUI Controller&lt;/a&gt; )  It's all just a simple zero'th order pass at using CiUI.  There are many extensions that one could do with this (more with templates, webflow, etc.).   I didn't implement the search interface or anything fancy here as this is just a review to see what is involved (practically nothing) in using CIUI in Grails.   I will likely go back and add something like that in and see if I can call back with parameters to my controller.    &lt;br id="nw4-"&gt;&lt;br id="x0ci"&gt;Note however that when generating the mark up in the controller it's likely a bit more "proper" to do something like the following &lt;a title="MarkupBuilder" target="_blank" href="http://groovy.codehaus.org/Creating+XML+using+Groovy%27s+MarkupBuilder" id="a90o"&gt;MarkupBuilder&lt;/a&gt; example.  This is actually an example from the IUI test I did and not used in this CIUI example, however the principle is the same.   &lt;br id="lrax"&gt;&lt;br id="tcbk"&gt;&lt;pre id="end1"&gt;&lt;a id="ebk9" name="l100"&gt;    &lt;span id="vdso" class="s0"&gt;def &lt;/span&gt;&lt;span id="b87r" class="s1"&gt;search = { &lt;br id="gjz1"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="q3bc" name="l101"&gt;        &lt;span id="m6yh" class="s0"&gt;def &lt;/span&gt;&lt;span id="fevz" class="s1"&gt;mywriter = &lt;/span&gt;&lt;span id="ey62" class="s0"&gt;new &lt;/span&gt;&lt;span id="ooru" class="s1"&gt;StringWriter() &lt;br id="i16m"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="c.o2" name="l102"&gt;        &lt;span id="dzte" class="s0"&gt;def &lt;/span&gt;&lt;span id="pcpj" class="s1"&gt;xml = &lt;/span&gt;&lt;span id="opxy" class="s0"&gt;new &lt;/span&gt;&lt;span id="bgu8" class="s1"&gt;MarkupBuilder(mywriter) &lt;/span&gt;&lt;/a&gt;&lt;a id="oey8" name="l103"&gt;&lt;/a&gt;&lt;a id="a8o4" name="l104"&gt;&lt;/a&gt;&lt;a id="j.dz" name="l106"&gt;&lt;span id="a203" class="s1"&gt;&lt;br id="vo8l"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="xexr" name="l107"&gt; &lt;br id="gxrv"&gt;&lt;/a&gt;&lt;a id="scla" name="l108"&gt;        xml.&lt;span id="or-c" class="s2"&gt;"form"&lt;/span&gt;&lt;span id="cgl6" class="s1"&gt;(id: &lt;/span&gt;&lt;span id="qdp7" class="s2"&gt;"searchForm"&lt;/span&gt;&lt;span id="fwu_" class="s1"&gt;, &lt;/span&gt;&lt;span id="a:3v" class="s0"&gt;class&lt;/span&gt;&lt;span id="xtxr" class="s1"&gt;: &lt;/span&gt;&lt;span id="ilqk" class="s2"&gt;"dialog"&lt;/span&gt;&lt;span id="ttzi" class="s1"&gt;, action: &lt;/span&gt;&lt;span id="hcts" class="s2"&gt;"$&lt;/span&gt;&lt;span id="h3ez" class="s1"&gt;{createLink(controller: &lt;/span&gt;&lt;span id="qc8q" class="s2"&gt;'iui'&lt;/span&gt;&lt;span id="duax" class="s1"&gt;, action: &lt;/span&gt;&lt;span id="zskf" class="s2"&gt;'doSearch'&lt;/span&gt;&lt;span id="g:7a" class="s1"&gt;)}&lt;/span&gt;&lt;span id="b9sl" class="s2"&gt;"&lt;/span&gt;&lt;span id="vafd" class="s1"&gt;) { &lt;br id="dqgl"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="k47s" name="l109"&gt;            fieldset { &lt;br id="d6.f"&gt;&lt;/a&gt;&lt;a id="m2-0" name="l110"&gt;                h1(&lt;span id="ah-g" class="s2"&gt;"Search the records"&lt;/span&gt;&lt;span id="azjn" class="s1"&gt;) &lt;br id="uyb4"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="l-b8" name="l111"&gt;                a(&lt;span id="r6lr" class="s0"&gt;class&lt;/span&gt;&lt;span id="c_6n" class="s1"&gt;: &lt;/span&gt;&lt;span id="a3g5" class="s2"&gt;"button leftButton"&lt;/span&gt;&lt;span id="phyg" class="s1"&gt;, type: &lt;/span&gt;&lt;span id="w7m2" class="s2"&gt;"cancel"&lt;/span&gt;&lt;span id="r.ii" class="s1"&gt;, &lt;/span&gt;&lt;span id="bfzj" class="s2"&gt;"Cancel"&lt;/span&gt;&lt;span id="n4m." class="s1"&gt;) &lt;br id="gsnw"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="qeb7" name="l112"&gt;                a(&lt;span id="jd7j" class="s0"&gt;class&lt;/span&gt;&lt;span id="vrve" class="s1"&gt;: &lt;/span&gt;&lt;span id="n:8c" class="s2"&gt;"button blueButton"&lt;/span&gt;&lt;span id="z1kh" class="s1"&gt;, type: &lt;/span&gt;&lt;span id="aju-" class="s2"&gt;"submit"&lt;/span&gt;&lt;span id="w1.y" class="s1"&gt;, &lt;/span&gt;&lt;span id="iev3" class="s2"&gt;"Search"&lt;/span&gt;&lt;span id="j_yc" class="s1"&gt;) &lt;br id="qeuk"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="a-79" name="l113"&gt;                label(&lt;span id="fdte" class="s2"&gt;"First Name"&lt;/span&gt;&lt;span id="zt_2" class="s1"&gt;) &lt;br id="tj10"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="cm0z" name="l114"&gt;                input(id: &lt;span id="umrx" class="s2"&gt;"fname"&lt;/span&gt;&lt;span id="c2wl" class="s1"&gt;, type: &lt;/span&gt;&lt;span id="cogn" class="s2"&gt;"text"&lt;/span&gt;&lt;span id="z8l:" class="s1"&gt;, name: &lt;/span&gt;&lt;span id="d__l" class="s2"&gt;"fname"&lt;/span&gt;&lt;span id="qze:" class="s1"&gt;) &lt;br id="fgo_"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="sfbb" name="l115"&gt;                label(&lt;span id="lruc" class="s2"&gt;"Last Name"&lt;/span&gt;&lt;span id="h3tx" class="s1"&gt;) &lt;br id="vla5"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="p7vy" name="l116"&gt;                input(id: &lt;span id="ztjv" class="s2"&gt;"lname"&lt;/span&gt;&lt;span id="oc_8" class="s1"&gt;, type: &lt;/span&gt;&lt;span id="hivp" class="s2"&gt;"text"&lt;/span&gt;&lt;span id="f:t_" class="s1"&gt;, name: &lt;/span&gt;&lt;span id="o1ld" class="s2"&gt;"lname"&lt;/span&gt;&lt;span id="cq5s" class="s1"&gt;) &lt;br id="kqw3"&gt;&lt;/span&gt;&lt;/a&gt;&lt;a id="dqnd" name="l117"&gt;            } &lt;br id="a-gq"&gt;&lt;/a&gt;&lt;a id="c_qx" name="l118"&gt;        } &lt;br id="t-ad"&gt;&lt;/a&gt;&lt;a id="qdg:" name="l119"&gt;        render mywriter.toString() &lt;br id="e-1t"&gt;&lt;/a&gt;&lt;a id="q2l2" name="l120"&gt;    } &lt;br id="h5-d"&gt;&lt;/a&gt;&lt;/pre&gt;&lt;br id="axvf"&gt;Here we used the Groovy MarkupBuilder to generate our XML outside the render method and then just pass it along.  This means we can push this logic down into a service or at least have a bit better logic to our controller code designs.  &lt;br id="wgjr"&gt;&lt;br id="niuq"&gt;&lt;a title="This youTube video shows what it looks like in action:" target="_blank" href="http://www.youtube.com/watch?v=VN-hxJ7GNA0" id="njz0"&gt;This youTube video shows what it looks like in action&lt;/a&gt; &lt;br id="dq1l"&gt;&lt;br id="frzf"&gt;Implementing these JS/CSS packages inside Grails is trivial.  As the iPhone and Google Android phones become more and more a mechanism for people to obtain information from the web the ability for developers easy represent data in appropriate formats will be more important.   Grails is a wonderfull platform for addressing that.  &lt;br id="wf57"&gt;&lt;br id="u4j8"&gt;enjoy&lt;br id="m6wv"&gt;Doug&lt;br id="szmj"&gt;&lt;br id="y.ja0"&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-1559662639980354068?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/1559662639980354068/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=1559662639980354068' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/1559662639980354068'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/1559662639980354068'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2008/04/using-ciui-in-grails.html' title='Using CIUI in Grails'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-4714678662453189530</id><published>2008-04-25T10:25:00.005-05:00</published><updated>2008-04-28T15:31:43.107-05:00</updated><title type='text'>xrandr with Ubuntu 8.04 and external monitors on laptops</title><content type='html'>So I installed Ubuntu 8.04 onto my Dell Inspiron 700m.  I was impressed with everything it is doing well right out of the box (display, power management, wireless, etc.).&lt;br /&gt;&lt;br /&gt;However, one item I was really looking forward to was xrandr and the ability to dynamically plug in external monitors or projection units.  In trying this I failed to get my external monitor to dynamically configure via xrandr.  However, the solution to this was simple.&lt;br /&gt;&lt;br /&gt;The default xorg.conf was:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Section "Screen" &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  Identifier    "Default Screen"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  Monitor        "Configured Monitor"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  Device          "Configured Video Device"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;EndSection&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I modified this by adding in the subsection display:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Section "Screen" &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   Identifier    "Default Screen"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   Monitor        "Configured Monitor"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   Device          "Configured Video Device"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt; &lt;/span&gt;&lt;span style="font-weight: bold;font-family:courier new;" &gt; SubSection "Display"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:courier new;" &gt;      Virtual   2560  1024&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:courier new;" &gt;  EndSubSection&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt; EndSection&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Next restart X (logout and in, or cntrl-alt backsapce).  Note that for me the entry was 2560 1024 since my internal display is 1280x800 and the external is 1280x1024 so 1280 + 1280 = 2560 and 1024 &gt; 800 so use 1024.  You will need to do the math for your case.&lt;br /&gt;&lt;br /&gt;At this point the "Screen Resolution" application works correctly to set up the displays.  Readers may also be &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_0"&gt;interested&lt;/span&gt; in the article at &lt;a href="http://www.thinkwiki.org/wiki/Sample_Fn-F7_script"&gt;http://www.thinkwiki.org/wiki/Sample_Fn-F7_scrip&lt;/a&gt;t which shows a nice shell script that can be connected to key combinations for all this.&lt;br /&gt;&lt;br /&gt;take care&lt;br /&gt;Doug&lt;br /&gt;&lt;br /&gt;UPDATE April 28th:&lt;br /&gt;&lt;br /&gt;Just a follow up to this posting.  It turns out that in several cases (and low end laptop graphics like mine among them) that doing this will&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;disable DVI and thus not allow you to run compiz&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;For me nice graphics vs dual monitor is a no contest.  I'll take the dynamic xrandr over compiz any day.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-4714678662453189530?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/4714678662453189530/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=4714678662453189530' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/4714678662453189530'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/4714678662453189530'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2008/04/xrandr-with-ubuntu-804-and-external.html' title='xrandr with Ubuntu 8.04 and external monitors on laptops'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-5864011426370686851</id><published>2008-04-22T08:41:00.001-05:00</published><updated>2008-04-22T08:51:42.112-05:00</updated><title type='text'>Sorting multidimensional arrays in Groovy</title><content type='html'>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.&lt;br id="d:r3"&gt;&lt;br id="ussy"&gt;If you are dealing with multidimensional arrays in Groovy (ref: &lt;a title="http://groovy.codehaus.org/JN1025-Arrays" target="_blank" href="http://groovy.codehaus.org/JN1025-Arrays" id="sdhs"&gt;http://groovy.codehaus.org/JN1025-Arrays&lt;/a&gt; ) and want to sort them you can expand on the sorting concepts for collections in Groovy (ref: &lt;a title="http://groovy.codehaus.org/JN1015-Collections" target="_blank" href="http://groovy.codehaus.org/JN1015-Collections" id="i686"&gt;http://groovy.codehaus.org/JN1015-Collections&lt;/a&gt; ).  &lt;br id="hq:b"&gt;&lt;br id="e86v"&gt;If you look in the last reference you will find the example:&lt;br id="n.q3"&gt;   &lt;pre id="a85v" style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;def mc= [&lt;br id="w:.l"&gt;  compare: {a,b-&amp;gt; a.equals(b)? 0: Math.abs(a)&amp;lt;Math.abs(b)? -1: 1 }&lt;br id="y_is"&gt;] as Comparator&lt;br id="wj1h"&gt;&lt;/pre&gt;   We can modify this for a multidimensional array.  So some excerpts from my code:&lt;br id="zmhn"&gt;&lt;pre id="a85v" style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;println "Pre sort: ${uniqueAges}"&lt;br id="uoh-"&gt;def mc = [&lt;br id="s92g"&gt;   compare: {a, b -&amp;gt; a[0].equals(b[0]) ? 0 : a[0] &amp;lt; b[0] ? -1 : 1 }&lt;br id="a2lu"&gt;] as Comparator&lt;br id="j:_n"&gt;println "Post sort: ${uniqueAges.sort(mc)}"&lt;br id="n-v1"&gt;&lt;/pre&gt; results in&lt;br id="eqoi"&gt;&lt;pre id="a85v" style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;Pre sort: [[11.2, 5.32], [1.77, 0.01], [3.58, 1.77], [5.32, 1.77], [5.32, 3.58]]&lt;br id="ru9s"&gt;Post sort: [[1.77, 0.01], [3.58, 1.77], [5.32, 1.77], [5.32, 3.58], [11.2, 5.32]]&lt;/pre&gt;or &lt;br id="tp9d"&gt;&lt;pre id="a85v" style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt; println "Pre sort: ${ageZoneList}"&lt;br id="vtc8"&gt; def mc2 = [&lt;br id="ng6a"&gt;    compare: {a, b -&amp;gt; a[0][0].equals(b[0][0]) ? 0 : a[0][0] &amp;lt; b[0][0] ? -1 : 1 }&lt;br id="m8xm"&gt; ] as Comparator&lt;br id="l3xy"&gt; println "Post sort: ${ageZoneList.sort(mc2)}"&lt;/pre&gt; results in&lt;br id="c7if"&gt;&lt;pre id="a85v" style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;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"]]]&lt;br id="n1pw"&gt;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"]]]&lt;br id="h:or"&gt;&lt;code id="wwja"&gt;&lt;br id="ix9:"&gt;&lt;/code&gt;&lt;/pre&gt; &lt;br id="mna9"&gt;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.&lt;br id="y8iz"&gt;&lt;br id="clw6"&gt;take care&lt;br id="mtwc"&gt;Doug&lt;br id="t.y8"&gt;&lt;br id="a75b"&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-5864011426370686851?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/5864011426370686851/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=5864011426370686851' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/5864011426370686851'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/5864011426370686851'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2008/04/i-didnt-find-this-solution-as-quickly.html' title='Sorting multidimensional arrays in Groovy'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-7091028917839976471</id><published>2008-04-21T11:06:00.001-05:00</published><updated>2008-04-21T11:11:00.128-05:00</updated><title type='text'>Spaces in REST URLs</title><content type='html'>So I need to deal with spaces in REST URL's.  Something like:&lt;br id="oicz"&gt;&lt;br id="nlkf"&gt;&lt;span id="glao" style="font-family: Courier New;"&gt;  .../timescale/Late Jurassic&lt;/span&gt;&lt;br id="z:y8"&gt;&lt;br id="m38k"&gt;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.  &lt;br id="r_1r"&gt;&lt;br id="hkdt"&gt;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:&lt;br id="pi9j"&gt;&lt;br id="u8i3"&gt;&lt;span id="z6lm" style="font-family: Courier New;"&gt;someString.replaceAll("%20", " ")&lt;/span&gt;&lt;br id="s_11"&gt;&lt;br id="hjpy"&gt;since firefox and I suspect other browsers will convert the spaces to "%20" for the user.  &lt;br id="qen2"&gt;&lt;br id="pirh"&gt;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.&lt;br id="nadn"&gt;&lt;br id="jhnc"&gt;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:&lt;br id="e63q"&gt;&lt;br id="s9:q"&gt;&lt;span id="r_jz" style="font-family: Courier New;"&gt;.../timescale/lateJurasic&lt;/span&gt;&lt;br id="dptn"&gt;&lt;br id="qrfi"&gt;where I could split the parameter in Groovy with:&lt;br id="vn4a"&gt;&lt;br id="jp1o"&gt;&lt;span id="s2q5" style="font-family: Courier New;"&gt;someString.replaceAll("([A-Z])", " &lt;font id="wwed" face="Wingdings"&gt;$&lt;/font&gt;1").trim()&lt;/span&gt;&lt;br id="ie.7"&gt;&lt;br id="xcn_"&gt;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.&lt;br id="gu4d"&gt;&lt;br id="w4la"&gt;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).  &lt;br id="vmr_"&gt;&lt;br id="cm_y"&gt;I suspect this is just a case where &lt;span id="g9-g"&gt;&lt;i&gt;the best resource identifier in the database is not always the best resource identifier for the REST URL representation&lt;/i&gt;&lt;/span&gt;.  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:&lt;br id="fjb4"&gt;&lt;br id="fy-b"&gt;&lt;span id="gbe0" style="font-family: Courier New;"&gt; .../timescale/LateJurassic &lt;/span&gt;&lt;br id="om83"&gt;&lt;br id="wlzu"&gt;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.&lt;br id="cu7g"&gt;&lt;br id="stab"&gt;take care&lt;br id="epr3"&gt;Doug&lt;br id="mffz"&gt;&lt;br id="xc2c"&gt;            &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-7091028917839976471?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/7091028917839976471/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=7091028917839976471' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/7091028917839976471'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/7091028917839976471'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2008/04/spaces-in-rest-urls-so-i-need-to-deal.html' title='Spaces in REST URLs'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-3008041994061997275</id><published>2008-04-14T09:19:00.001-05:00</published><updated>2008-04-14T09:21:56.159-05:00</updated><title type='text'>Javascript comparison of WebKit and Firefox 3 Beta 5 on Ubuntu</title><content type='html'>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 &lt;a title="http://www.webkit.org" target="_blank" href="http://www.webkit.org" id="jxo-"&gt;http://www.webkit.org&lt;/a&gt;.  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: &lt;a title="http://live.gnome.org/WebKitGtk" target="_blank" href="http://live.gnome.org/WebKitGtk" id="nf2z"&gt;http://live.gnome.org/WebKitGtk&lt;/a&gt; ).  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 (&lt;a title="http://live.gnome.org/Epiphany/WebKit" target="_blank" href="http://live.gnome.org/Epiphany/WebKit" id="cdu."&gt;http://live.gnome.org/Epiphany/WebKit&lt;/a&gt; ) if you want a nicer wrapper. &lt;br id="ofq_"&gt;&lt;br id="kjhd"&gt;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 (&lt;a title="http://www.mozilla.com/en-US/firefox/all-beta.html" target="_blank" href="http://www.mozilla.com/en-US/firefox/all-beta.html" id="sw41"&gt;http://www.mozilla.com/en-US/firefox/all-beta.html&lt;/a&gt; ).  A tried both the &lt;a title="Dromaeo" target="_blank" href="http://dromaeo.com/" id="w1-o"&gt;Dromaeo&lt;/a&gt; test suite (still in early release, review notes at: &lt;a title="http://wiki.mozilla.org/Dromaeo" target="_blank" href="http://wiki.mozilla.org/Dromaeo" id="i-vw"&gt;http://wiki.mozilla.org/Dromaeo&lt;/a&gt; ) and Sunspider from: &lt;a title="http://webkit.org/perf/sunspider-0.9/sunspider.html" target="_blank" href="http://webkit.org/perf/sunspider-0.9/sunspider.html" id="riif"&gt;http://webkit.org/perf/sunspider-0.9/sunspider.html&lt;/a&gt;.  My platform is rather paltry Athlon 64 3200+ and 2 gigs of memory running the afore mentioned Ubuntu 7.04.  &lt;br id="hxew"&gt;&lt;br id="oscq"&gt;Firefox 3 Beta 5:&lt;br id="mkdh"&gt;&lt;a title="http://dromaeo.com/?id=5552" target="_blank" href="http://dromaeo.com/?id=5552" id="njcl"&gt;http://dromaeo.com/?id=5552&lt;/a&gt;   (3282.80ms)&lt;br id="ak_:"&gt;&lt;a title="http://dromaeo.com/?id=5560" target="_blank" href="http://dromaeo.com/?id=5560" id="g8ic"&gt;http://dromaeo.com/?id=5560&lt;/a&gt; (3287.60ms)&lt;br id="j1cf"&gt;&lt;a title="SunSpider: 6794.0ms" target="_blank" href="http://webkit.org/perf/sunspider-0.9/sunspider-results.html?%7B%223d-cube%22:%5B277,274,283,284,282%5D,%223d-morph%22:%5B241,269,272,268,268%5D,%223d-raytrace%22:%5B229,255,237,238,252%5D,%22access-binary-trees%22:%5B162,178,169,167,181%5D,%22access-fannkuch%22:%5B366,359,364,362,366%5D,%22access-nbody%22:%5B292,290,267,293,288%5D,%22access-nsieve%22:%5B135,165,168,161,158%5D,%22bitops-3bit-bits-in-byte%22:%5B168,174,159,165,165%5D,%22bitops-bits-in-byte%22:%5B192,182,176,179,183%5D,%22bitops-bitwise-and%22:%5B150,139,151,150,139%5D,%22bitops-nsieve-bits%22:%5B239,238,225,224,231%5D,%22controlflow-recursive%22:%5B162,166,134,147,156%5D,%22crypto-aes%22:%5B170,146,162,169,146%5D,%22crypto-md5%22:%5B176,164,172,171,161%5D,%22crypto-sha1%22:%5B163,151,164,150,153%5D,%22date-format-tofte%22:%5B368,366,363,364,377%5D,%22date-format-xparb%22:%5B228,234,247,241,225%5D,%22math-cordic%22:%5B292,305,292,306,309%5D,%22math-partial-sums%22:%5B255,270,238,247,273%5D,%22math-spectral-norm%22:%5B217,211,213,201,202%5D,%22regexp-dna%22:%5B546,537,531,537,538%5D,%22string-base64%22:%5B202,203,190,188,206%5D,%22string-fasta%22:%5B465,445,431,445,469%5D,%22string-tagcloud%22:%5B376,352,356,352,364%5D,%22string-unpack-code%22:%5B495,489,483,497,500%5D,%22string-validate-input%22:%5B261,249,257,268,262%5D%7D" id="bcs1"&gt;SunSpider: 6794.0ms&lt;/a&gt; &lt;br id="a5qv"&gt;&lt;br id="md4l"&gt;WebKit &lt;br id="pg7x"&gt;&lt;a title="http://dromaeo.com/?id=5556" target="_blank" href="http://dromaeo.com/?id=5556" id="kyy5"&gt;http://dromaeo.com/?id=5556&lt;/a&gt;   (3260.60ms)&lt;br id="k3xp"&gt;&lt;a title="http://dromaeo.com/?id=5563" target="_blank" href="http://dromaeo.com/?id=5563" id="vlpq"&gt;http://dromaeo.com/?id=5563&lt;/a&gt; (3225.40ms)&lt;br id="yeyw"&gt;&lt;a title="SunSpider:  5794.8ms" target="_blank" href="http://webkit.org/perf/sunspider-0.9/sunspider-results.html?%7B%223d-cube%22:%5B260,265,261,276,264%5D,%223d-morph%22:%5B240,238,239,237,239%5D,%223d-raytrace%22:%5B232,227,230,231,228%5D,%22access-binary-trees%22:%5B114,115,117,115,114%5D,%22access-fannkuch%22:%5B443,437,451,443,447%5D,%22access-nbody%22:%5B262,255,258,256,261%5D,%22access-nsieve%22:%5B112,112,112,112,113%5D,%22bitops-3bit-bits-in-byte%22:%5B95,96,95,98,96%5D,%22bitops-bits-in-byte%22:%5B157,159,161,162,159%5D,%22bitops-bitwise-and%22:%5B236,237,240,240,240%5D,%22bitops-nsieve-bits%22:%5B168,168,171,167,172%5D,%22controlflow-recursive%22:%5B95,94,94,93,93%5D,%22crypto-aes%22:%5B136,139,136,138,141%5D,%22crypto-md5%22:%5B101,100,100,101,99%5D,%22crypto-sha1%22:%5B106,105,106,105,104%5D,%22date-format-tofte%22:%5B277,284,283,288,284%5D,%22date-format-xparb%22:%5B402,402,406,404,406%5D,%22math-cordic%22:%5B271,268,289,278,282%5D,%22math-partial-sums%22:%5B279,269,274,273,274%5D,%22math-spectral-norm%22:%5B157,159,157,160,162%5D,%22regexp-dna%22:%5B345,342,343,342,345%5D,%22string-base64%22:%5B204,206,206,206,205%5D,%22string-fasta%22:%5B280,279,276,275,279%5D,%22string-tagcloud%22:%5B292,292,298,294,300%5D,%22string-unpack-code%22:%5B265,263,265,265,266%5D,%22string-validate-input%22:%5B246,247,247,246,248%5D%7D" id="vywk"&gt;SunSpider:  5794.8ms&lt;/a&gt; &lt;br id="qhu4"&gt;&lt;br id="i:8q"&gt;&lt;br id="nf5a"&gt;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 (&lt;a title="http://ajaxian.com/archives/where-is-firefox-on-acid-3-here" target="_blank" href="http://ajaxian.com/archives/where-is-firefox-on-acid-3-here" id="zh-9"&gt;http://ajaxian.com/archives/where-is-firefox-on-acid-3-here&lt;/a&gt; ).  The Firefox ecosystem around its amazing set of add-ones (&lt;a title="https://addons.mozilla.org/en-US/firefox/" target="_blank" href="https://addons.mozilla.org/en-US/firefox/" id="q0f4"&gt;https://addons.mozilla.org/en-US/firefox/&lt;/a&gt; ) 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 (&lt;a title="http://shaver.off.net/diary/2008/03/27/the-missed-opportunity-of-acid-3/" target="_blank" href="http://shaver.off.net/diary/2008/03/27/the-missed-opportunity-of-acid-3/" id="piof"&gt;http://shaver.off.net/diary/2008/03/27/the-missed-opportunity-of-acid-3/&lt;/a&gt; ) and Rob Sayre (&lt;a title="http://blog.mozilla.com/rob-sayre/2008/03/26/acid3-is-basically-worthless/" target="_blank" href="http://blog.mozilla.com/rob-sayre/2008/03/26/acid3-is-basically-worthless/" id="eg5v"&gt;http://blog.mozilla.com/rob-sayre/2008/03/26/acid3-is-basically-worthless/&lt;/a&gt; ) regarding this do make sense to me.  &lt;br id="jpl8"&gt;&lt;br id="u8y8"&gt;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 (&lt;a title="https://jdk6.dev.java.net/plugin2/" target="_blank" href="https://jdk6.dev.java.net/plugin2/" id="rv-j"&gt;https://jdk6.dev.java.net/plugin2/&lt;/a&gt; ) and was very impressed with it as well. Especially the easy javascript to applet communication the new plugin delivers.  &lt;br id="s6lm"&gt;&lt;br id="xxwu"&gt;take care&lt;br id="swwh"&gt;Doug&lt;br id="f1-l"&gt;&lt;br id="oms6"&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-3008041994061997275?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/3008041994061997275/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=3008041994061997275' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/3008041994061997275'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/3008041994061997275'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2008/04/this-weekend-i-had-small-pet-project-i.html' title='Javascript comparison of WebKit and Firefox 3 Beta 5 on Ubuntu'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-5727341129658105016</id><published>2008-03-26T14:09:00.001-05:00</published><updated>2008-03-26T14:40:56.936-05:00</updated><title type='text'>Grails datasource in resource.xml</title><content type='html'>                        &lt;br id="hnkg"&gt;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.  &lt;br id="cy:s"&gt;&lt;br id="oxa:"&gt;A quick review of the Nabble list gave me a couple of leads:&lt;br id="pbac"&gt;&lt;a title="http://www.nabble.com/dataSource-on-ApplicationBootStrap-td11441836.html#a11441836" href="http://www.nabble.com/dataSource-on-ApplicationBootStrap-td11441836.html#a11441836" id="d7jk"&gt;http://www.nabble.com/dataSource-on-ApplicationBootStrap-td11441836.html#a11441836&lt;/a&gt; &lt;br id="vr4p"&gt;&lt;a title="http://www.nabble.com/multiply-datasources--td10038844.html#a10038844" href="http://www.nabble.com/multiply-datasources--td10038844.html#a10038844" id="j-b-"&gt;http://www.nabble.com/multiply-datasources--td10038844.html#a10038844&lt;/a&gt; &lt;br id="ai04"&gt; &lt;br id="w21o"&gt;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:&lt;br id="h3ri"&gt;&lt;br id="n.q3"&gt;   &lt;pre id="a85v" style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code id="wwja"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br id="ojmz"&gt;&amp;lt;beans xmlns="http://www.springframework.org/schema/beans"&lt;br id="bvxu"&gt;       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;br id="v8:."&gt;       xsi:schemaLocation="&lt;br id="q5uj"&gt;http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"&amp;gt;&lt;br id="o8ux"&gt;&lt;br id="d355"&gt;  &amp;lt;bean id="dataSourceJanus" class="org.springframework.jdbc.datasource.SingleConnectionDataSource"&amp;gt;&lt;br id="rex2"&gt;        &amp;lt;property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/&amp;gt;&lt;br id="ho_5"&gt;        &amp;lt;property name="url" value="'jdbc:oracle:thin:@xxx.xxx.xxx.xxx:1521:janware"/&amp;gt;&lt;br id="wipn"&gt;        &amp;lt;property name="username" value="NAME"/&amp;gt;&lt;br id="gzg3"&gt;        &amp;lt;property name="password" value="PASSWORD"/&amp;gt;&lt;br id="wpaa"&gt;  &amp;lt;/bean&amp;gt;&lt;br id="xv28"&gt;&amp;lt;/beans&amp;gt;&lt;/code&gt;&lt;br id="t89q"&gt;&lt;/pre&gt;   &lt;br id="w76t"&gt;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.  &lt;br id="xp:l"&gt;&lt;br id="e06r"&gt;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:&lt;br id="xfu9"&gt;&lt;br id="n.q3"&gt;   &lt;pre id="a85v" style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code id="wwja"&gt;//  Needed for datasource &lt;br id="m04-"&gt;import org.springframework.jdbc.core.JdbcTemplate&lt;br id="vw.m"&gt;import groovy.sql.Sql&lt;br id="lx56"&gt;&lt;br id="extj"&gt;&lt;br id="ha7p"&gt;// Spring&lt;br id="wuhx"&gt;import org.springframework.beans.BeansException&lt;br id="szlz"&gt;import org.springframework.context.ApplicationContext&lt;br id="vd9q"&gt;import org.springframework.context.ApplicationContextAware&lt;br id="j3.s"&gt;import org.codehaus.groovy.grails.commons.GrailsApplication&lt;br id="p0ts"&gt;&lt;br id="rs3t"&gt;class FacetController implements ApplicationContextAware {&lt;br id="qq53"&gt;    &lt;br id="bzt."&gt;    GrailsApplication grailsApplication&lt;br id="g7-3"&gt;    ApplicationContext appCtx&lt;br id="r624"&gt;&lt;br id="a0-v"&gt;    def void setApplicationContext(ApplicationContext arg0) throws BeansException {&lt;br id="hhkd"&gt;        appCtx = arg0;&lt;br id="se13"&gt;    }&lt;br id="k4cx"&gt;&lt;br id="oz20"&gt;...&lt;br id="t89q"&gt;&lt;/code&gt;&lt;/pre&gt;   &lt;br id="vnik"&gt;This will get you your application context object.  Now it's rahter straight forward to use:&lt;br id="sbns"&gt;&lt;br id="l8wr"&gt;&lt;pre id="a85v" style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code id="wwja"&gt;def showFacets = {&lt;br id="dym9"&gt;        def jt = new JdbcTemplate(&lt;span id="ewt."&gt;&lt;b id="phvn"&gt;appCtx.dataSourceJanus&lt;/b&gt;&lt;/span&gt;)&lt;br id="ldkz"&gt;        def sqlString = "select latitude_degrees, longitude_degrees from hole where leg like '101' and site like '631' and hole like 'A'"&lt;br id="qmrp"&gt;&lt;/code&gt;&lt;code id="wwja"&gt;        response.contentType = "text/plain"&lt;/code&gt;&lt;br id="fkmq"&gt;&lt;code id="wwja"&gt;        jt.queryForList(sqlString).each {        &lt;br id="jct1"&gt;            response.outputStream &amp;lt;&amp;lt; "${it.latitude_degrees} ${it.longitude_degrees}"&lt;br id="frcp"&gt;        }&lt;br id="o9pm"&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br id="odmr"&gt;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.   &lt;br id="px:p"&gt;&lt;br id="c5hm"&gt;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.  &lt;br id="q0vh"&gt;&lt;br id="l:_s"&gt;Some additional good reading on this includes:&lt;br id="wvrg"&gt;Datasources:  &lt;a title="http://docs.codehaus.org/display/GRAILS/DataSources+New" href="http://docs.codehaus.org/display/GRAILS/DataSources+New" id="s4ii"&gt;http://docs.codehaus.org/display/GRAILS/DataSources+New&lt;/a&gt; &lt;br id="hdjd"&gt; Using JNDI resources instead: &lt;a title="http://docs.codehaus.org/display/GRAILS/JNDI+Data+Sources" href="http://docs.codehaus.org/display/GRAILS/JNDI+Data+Sources" id="qxeh"&gt;http://docs.codehaus.org/display/GRAILS/JNDI+Data+Sources&lt;/a&gt; &lt;br id="m4h4"&gt; Spring Bean Builder:  &lt;a title="http://grails.org/Spring+Bean+Builder" href="http://grails.org/Spring+Bean+Builder" id="bfep"&gt;http://grails.org/Spring+Bean+Builder&lt;/a&gt; &lt;br id="l0me"&gt; Application Context: &lt;a title="http://grails.org/Services" href="http://grails.org/Services" id="c05z"&gt;http://grails.org/Services&lt;/a&gt; &lt;br id="qbl4"&gt;&lt;br id="fkn3"&gt;If you review and follow some of the thread in the Nabble site, you will see that &lt;span id="v.gv"&gt;&lt;b id="hwol"&gt;seems&lt;/b&gt;&lt;/span&gt; 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 &lt;a title="http://www.nabble.com/How-to-get-multi-dataSource-in-grails--td12291409.html#a12291409" href="http://www.nabble.com/How-to-get-multi-dataSource-in-grails--td12291409.html#a12291409" id="l2.7"&gt;http://www.nabble.com/How-to-get-multi-dataSource-in-grails--td12291409.html#a12291409&lt;/a&gt; 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.  &lt;br id="tuft"&gt;&lt;br id="h395"&gt;For my needs however, just having an SQL resource that I could use the very nice &lt;a title="Groovy SQL" href="http://groovy.codehaus.org/Database+features" id="fn4s"&gt;Groovy SQL&lt;/a&gt; capacity with.  &lt;br id="wfq4"&gt;&lt;br id="w2rc"&gt;enjoy&lt;br id="u9ab"&gt;Doug&lt;br id="x1jj"&gt;&lt;br id="jzom"&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-5727341129658105016?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/5727341129658105016/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=5727341129658105016' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/5727341129658105016'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/5727341129658105016'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2008/03/grails-datasource-in-resource.html' title='Grails datasource in resource.xml'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-8159761986586383297</id><published>2007-12-06T12:04:00.000-06:00</published><updated>2007-12-07T13:57:27.161-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='flot'/><category scheme='http://www.blogger.com/atom/ns#' term='grails'/><category scheme='http://www.blogger.com/atom/ns#' term='plotting'/><title type='text'>Flot plotting in Grails:</title><content type='html'>I came across the FLOT package (Ref:  &lt;a title="http://code.google.com/p/flot/" target="_blank" href="http://code.google.com/p/flot/" id="ps3n"&gt;http://code.google.com/p/flot/&lt;/a&gt; ) while reading Ajaxian (Ref: &lt;a title="http://ajaxian.com/archives/plotting-in-jquery" target="_blank" href="http://ajaxian.com/archives/plotting-in-jquery" id="ys.8"&gt;http://ajaxian.com/archives/plotting-in-jquery&lt;/a&gt; ).  Flot uses the jQuerry package (Ref: &lt;a title="http://jquery.com/" target="_blank" href="http://jquery.com/" id="upf7"&gt;http://jquery.com/&lt;/a&gt; ) to do client side plotting.  I wanted to see how this works when dropped into Grails.  As expected the results are quite nice.&lt;br /&gt;&lt;div id="xa77" style="padding: 1em 0pt; text-align: left;"&gt;&lt;img style="width: 711px; height: 547px;" src="http://docs.google.com/File?id=dgtb8v9j_225dk9stmgc" /&gt;&lt;/div&gt;&lt;br /&gt;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.&lt;br /&gt;You will need to reference these in your GSP page HEAD tag with something like:&lt;br /&gt;&lt;br /&gt; &lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;  &amp;lt;g:javascript library="jquery-1.2.1.min"/&amp;gt;&lt;br /&gt;&amp;lt;g:javascript library="jquery.flot-0.1"/&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt; &lt;br /&gt;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:&lt;br /&gt;&lt;br /&gt;  &lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt; &amp;lt;div id="placeholder2" style="margin-left:100px;width:600px;height:300px;"&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;script id="source2" language="javascript" type="text/javascript"&amp;gt;&lt;br /&gt; $(function () {&lt;br /&gt;   var d1 = [];&lt;br /&gt;   for (var i = 0; i &amp;lt; 14; i += 0.5)&lt;br /&gt;   d1.push([i, Math.sin(i)]);&lt;br /&gt;&lt;br /&gt;   var d2 = ${array};&lt;br /&gt;&lt;br /&gt;   $.plot($("#placeholder2"), [ d1, d2 ]);&lt;br /&gt;   });&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;    Here is the only interesting aspect of all this.  The line &lt;b&gt;&lt;i&gt;var d2 = ${array}&lt;/i&gt;&lt;/b&gt; is referencing a list from the controller:&lt;br /&gt;&lt;br /&gt;  &lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;  def jflotPlot = {&lt;br /&gt;      def array = [[4, 6], [5, 7], [9, 2]]&lt;br /&gt;     [array: array]&lt;br /&gt;}&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;  &lt;br /&gt;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 (&lt;a title="see the demos at the flot site" target="_blank" href="http://people.iola.dk/olau/flot/examples/" id="u36r"&gt;see the demos at the flot site&lt;/a&gt; ).  Integration with Grails is quick and easy.&lt;br /&gt;&lt;br /&gt;enjoy&lt;br /&gt;Doug&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-8159761986586383297?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/8159761986586383297/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=8159761986586383297' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/8159761986586383297'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/8159761986586383297'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2007/12/flot-plotting-in-grails-i-came-across.html' title='Flot plotting in Grails:'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-3101496760233931235</id><published>2007-11-14T10:39:00.000-06:00</published><updated>2007-11-16T07:32:01.519-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='atom'/><category scheme='http://www.blogger.com/atom/ns#' term='georss'/><category scheme='http://www.blogger.com/atom/ns#' term='grails'/><category scheme='http://www.blogger.com/atom/ns#' term='rss'/><category scheme='http://www.blogger.com/atom/ns#' term='groovy'/><title type='text'>Grails + ROME + geoRSS</title><content type='html'>&lt;b&gt;Grails + ROME + geoRSS&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;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: &lt;a href="http://blogs.bytecode.com.au/glen/2006/12/22/1166781151213.html" id="pr-0" title="http://blogs.bytecode.com.au/glen/2006/12/22/1166781151213.html"&gt;http://blogs.bytecode.com.au/glen/2006/12/22/1166781151213.html&lt;/a&gt; ) or to work with the Feeds plugins (ref: &lt;a href="http://grails.org/Feeds+Plugin" id="yt2j" title="http://grails.org/Feeds+Plugin"&gt;http://grails.org/Feeds+Plugin&lt;/a&gt; ) by Marc Palmer.  Both are excellent places to start.&lt;br /&gt;&lt;br /&gt;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 &lt;a href="http://rome.dev.java.net/" id="b_4r" title="http://rome.dev.java.net"&gt;http://rome.dev.java.net&lt;/a&gt;.  For geospatial elements there is the GeoRSS Module for ROME by Marc Wick (ref: &lt;a href="http://georss.geonames.org/" id="x8ge" title="http://georss.geonames.org"&gt;http://georss.geonames.org&lt;/a&gt; ).&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;So likely you will end up with something like this in your controller:&lt;br /&gt;&lt;br /&gt;   &lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;  // some import for this..   (watch me polute my namespace) ;)&lt;br /&gt;import com.sun.syndication.feed.synd.*;&lt;br /&gt;import com.sun.syndication.io.SyndFeedOutput;&lt;br /&gt;import com.sun.syndication.feed.module.georss.*;&lt;br /&gt;import com.sun.syndication.feed.module.georss.geometries.*;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    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"]&lt;br /&gt;&lt;br /&gt;    def rss = {&lt;br /&gt;        render(text: getFeed("atom_0.3"), contentType: "text/xml", encoding: "UTF-8")&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    def all = {&lt;br /&gt;        def format = params.id&lt;br /&gt;        if (supportedFormats.contains(format)) {&lt;br /&gt;            render(text: getFeed(format), contentType: "text/xml", encoding: "UTF-8")&lt;br /&gt;        } else {&lt;br /&gt;            response.sendError(response.SC_FORBIDDEN);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    def getFeed(feedType) {&lt;br /&gt;&lt;br /&gt;        def ageModels = AgeModel.list()&lt;br /&gt;        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')&lt;br /&gt;      &lt;br /&gt;        def entries = []&lt;br /&gt;        ageModels.each {ageModel -&amp;gt;&lt;br /&gt;           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}'")&lt;br /&gt;           def locationString = functionData[0][1] + ", " + functionData[0][0]&lt;br /&gt;&lt;br /&gt;            def desc = new SyndContentImpl(type: "text/plain", value: "Entry for leg " + ageModel.leg + " locate at " + locationString + ageModel.rating + " " + ageModel.status);&lt;br /&gt;            def entry = new SyndEntryImpl(title: ageModel.leg + "_" +ageModel.site + ageModel.hole + " - " + ageModel.user,&lt;br /&gt;                    link: 'http://localhost:8080/janusAmp/rest/lsh/' + ageModel.leg + "/" + ageModel.site+ "/"+ageModel.hole,&lt;br /&gt;                    publishedDate: ageModel.date, description: desc);&lt;br /&gt;&lt;br /&gt;&lt;b&gt;             // Select the style of encoding you want to do.&lt;br /&gt;            // def geoRSSModule = new W3CGeoModuleImpl()&lt;br /&gt;            // def geoRSSModule = new GMLModuleImpl()&lt;br /&gt;            def geoRSSModule = new SimpleModuleImpl()&lt;br /&gt;            geoRSSModule.setPosition(new Position(functionData[0][0],  functionData[0][1]));&lt;br /&gt;            entry.getModules().add(geoRSSModule);&lt;br /&gt;            entries.add(entry);&lt;br /&gt;&lt;/b&gt;         }&lt;br /&gt;&lt;br /&gt;        SyndFeed feed = new SyndFeedImpl(feedType: feedType, title: 'Recently added age models',&lt;br /&gt;                link: 'http://www.chronos.org', description: 'List of age models from Janus data',&lt;br /&gt;                entries: entries);&lt;br /&gt;&lt;br /&gt;        StringWriter writer = new StringWriter();&lt;br /&gt;        SyndFeedOutput output = new SyndFeedOutput();&lt;br /&gt;        output.output(feed, writer);&lt;br /&gt;        writer.close();&lt;br /&gt;&lt;br /&gt;        return writer.toString();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;/code&gt; &lt;/pre&gt;   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)&lt;br /&gt;&lt;br /&gt;A few things to note:&lt;br /&gt;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: &lt;a title="http://cite.opengeospatial.org/test_engine/georss_validator/" href="http://cite.opengeospatial.org/test_engine/georss_validator/" id="hma9"&gt;http://cite.opengeospatial.org/test_engine/georss_validator/&lt;/a&gt; one gets some errors related to the namespaces.  I noticed that the examples for RSS feeds at &lt;a title="http://georss.org/" href="http://georss.org/" id="kvsv"&gt;http://georss.org/&lt;/a&gt; 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.&lt;br /&gt;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 &lt;a title="http://www.kovacevic.nl/hacks/kml/georss2kml.xsl" href="http://www.kovacevic.nl/hacks/kml/georss2kml.xsl" id="d:ic"&gt;http://www.kovacevic.nl/hacks/kml/georss2kml.xsl&lt;/a&gt;   (ref: &lt;a title="http://www.kovacevic.nl/blog" href="http://www.kovacevic.nl/blog" id="sua:"&gt;http://www.kovacevic.nl/blog&lt;/a&gt; ).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;RSS to KML via XSL in Grails:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;So you can drop into your controller something like:&lt;br /&gt; &lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;  def kml = {&lt;br /&gt;        def xslPath = getAppPathService.serviceMethod().toString() + "georss2kml.xsl"&lt;br /&gt;        def kmlxsl = new File(xslPath).getText().toString()&lt;br /&gt;        def rssxml = getFeed("rss_2.0")&lt;br /&gt;&lt;br /&gt;        def mywriter = new StringWriter()&lt;br /&gt;&lt;br /&gt;        def factory = TransformerFactory.newInstance()&lt;br /&gt;        def transformer = factory.newTransformer(new StreamSource(new StringReader(kmlxsl)))&lt;br /&gt;        transformer.transform(new StreamSource(new StringReader(rssxml)), new StreamResult(mywriter))&lt;br /&gt;&lt;br /&gt;        render(text: mywriter.toString(), contentType: "text/xml", encoding: "UTF-8")&lt;br /&gt;    }&lt;br /&gt;&lt;/code&gt; &lt;/pre&gt;  you make also need the following in your code for XSL support: &lt;pre&gt;//  for the XSLT transform&lt;br /&gt;import javax.xml.transform.TransformerFactory&lt;br /&gt;import javax.xml.transform.stream.StreamResult&lt;br /&gt;import javax.xml.transform.stream.StreamSource&lt;br /&gt;&lt;/pre&gt; &lt;br /&gt;into your controller where AppPathService is  (not mine..  but I don't have the reference for this..  bad me)&lt;br /&gt;&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt; import org.codehaus.groovy.grails.commons.*&lt;br /&gt;import org.apache.commons.logging.*&lt;br /&gt;&lt;br /&gt;import org.springframework.beans.BeansException&lt;br /&gt;import org.springframework.context.ApplicationContext&lt;br /&gt;import org.springframework.context.ApplicationContextAware&lt;br /&gt;&lt;br /&gt;class GetAppPathService implements ApplicationContextAware {&lt;br /&gt;&lt;br /&gt;   GrailsApplication grailsApplication&lt;br /&gt;    ApplicationContext appCtx&lt;br /&gt;&lt;br /&gt;    boolean transactional = true&lt;br /&gt;&lt;br /&gt;    def void setApplicationContext(ApplicationContext arg0) throws BeansException {&lt;br /&gt;        appCtx = arg0;&lt;br /&gt;    }&lt;br /&gt;    def serviceMethod() {&lt;br /&gt;        String applicationPath = "${appCtx?.getServletContext()?.getRealPath("/")}"&lt;br /&gt;        return applicationPath&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;   &lt;/code&gt; &lt;/pre&gt;   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 &lt;a title="http://groovy.codehaus.org/Processing+XML+with+XSLT" href="http://groovy.codehaus.org/Processing+XML+with+XSLT" id="aejw"&gt;http://groovy.codehaus.org/Processing+XML+with+XSLT&lt;/a&gt; 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.&lt;br /&gt;&lt;br /&gt;I do want the get the GeoRSS feed vaildating though and will work on that effort as noted.&lt;br /&gt;&lt;br /&gt;enjoy&lt;br /&gt;Doug&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-3101496760233931235?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/3101496760233931235/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=3101496760233931235' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/3101496760233931235'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/3101496760233931235'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2007/11/grails-rome-georss-if-you-are-looking.html' title='Grails + ROME + geoRSS'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-672709884952426355</id><published>2007-11-12T14:16:00.001-06:00</published><updated>2007-11-12T14:23:43.235-06:00</updated><title type='text'>Checking REST and RSS style feeds</title><content type='html'>Continuing to do work with REST in &lt;a href="http://www.grails.org/"&gt;Grails&lt;/a&gt; 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 &lt;a href="http://www.xucia.com/#RestTest"&gt;(RestTest)&lt;/a&gt; which is quite handy.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;On the topic of RSS/ATOM and Grails check out the &lt;a href="http://grails.org/Feeds+Plugin"&gt;Feeds Plugin&lt;/a&gt; at the Grails site.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_f5taJtU-20M/Rzi2F72GHRI/AAAAAAAAACA/yJGhNm0dPVk/s1600-h/Screenshot-RESTTest+-+HTTP+Tester.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp3.blogger.com/_f5taJtU-20M/Rzi2F72GHRI/AAAAAAAAACA/yJGhNm0dPVk/s320/Screenshot-RESTTest+-+HTTP+Tester.png" alt="" id="BLOGGER_PHOTO_ID_5132051988468866322" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-672709884952426355?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/672709884952426355/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=672709884952426355' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/672709884952426355'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/672709884952426355'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2007/11/checking-rest-and-rss-style-feeds.html' title='Checking REST and RSS style feeds'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp3.blogger.com/_f5taJtU-20M/Rzi2F72GHRI/AAAAAAAAACA/yJGhNm0dPVk/s72-c/Screenshot-RESTTest+-+HTTP+Tester.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-4981061164242298354</id><published>2007-10-23T14:12:00.000-05:00</published><updated>2007-10-23T14:25:09.702-05:00</updated><title type='text'>Groovy REST client with Apache httpclient (setting accept request-header value)</title><content type='html'>Been doing quite a bit with REST style services in &lt;a href="http://www.grails.org/"&gt;Grails&lt;/a&gt;.  In particular trying to follow closes REST best practices approaches.  One of these approaches is to inspect the HTTP Accept header values.  (Ref: &lt;a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html"&gt;http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;While creating these services a person really needs a simple client that they can alter the accept request-header field with.  I created one using the Apache httpclient package (&lt;a href="http://jakarta.apache.org/httpcomponents/httpclient-3.x/"&gt;http://jakarta.apache.org/httpcomponents/httpclient-3.x/&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;Simply download and place the commons-httpclient-*.jar file into your groovy lib directory (or somewhere you class loader will find it) and generate a &lt;a href="http://groovy.codehaus.org/"&gt;Groovy&lt;/a&gt; program like:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;import org.apache.commons.httpclient.HttpClient;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;import org.apache.commons.httpclient.UsernamePasswordCredentials;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;import org.apache.commons.httpclient.methods.GetMethod;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;def url = "URL TO SERVICE"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;client = new HttpClient()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;get = new GetMethod(url)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;get.setRequestHeader("Accept", "text/xml")&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;client.executeMethod(get)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;println get.getResponseBodyAsString().toString()&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;It's a simple client and one can alter the ACCEPT header value easily to check and validate REST services response to various settings of accept request-header.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-4981061164242298354?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/4981061164242298354/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=4981061164242298354' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/4981061164242298354'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/4981061164242298354'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2007/10/groovy-rest-client-with-apache.html' title='Groovy REST client with Apache httpclient (setting accept request-header value)'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-4518029958530366089</id><published>2007-09-17T21:42:00.000-05:00</published><updated>2007-09-18T08:49:46.639-05:00</updated><title type='text'>Using CHRONOS Timescale Converter Service Calls</title><content type='html'>The timescale converter web application accessible through the CHRONOS portal (Ref: &lt;a href="http://portal.chronos.org/gridsphere/gridsphere?cid=tools_tsconvert"&gt;http://portal.chronos.org/gridsphere/gridsphere?cid=tools_tsconvert&lt;/a&gt;) uses publicly available web service calls to the timescale service described by the WSDL document located at &lt;a href="http://services.chronos.org:9090/axis/timescales.jws?wsdl"&gt;http://services.chronos.org:9090/axis/timescales.jws?wsdl&lt;/a&gt;.  These services are available for use on any platform.&lt;br /&gt;&lt;br /&gt;Simple clients to these end points can be created in any modern programming language.  Examples using Python and Groovy, two popular dynamic languages, are given below.  Examples using Ruby or C# would be quite similar.&lt;br /&gt;&lt;br /&gt;Example using Python&lt;br /&gt;&lt;br /&gt;&lt;div style="margin-left: 40px;"&gt;   &lt;span style="font-family:Courier New;"&gt;&lt;b&gt;#!/usr/bin/python&lt;/b&gt;&lt;/span&gt;    &lt;span style="font-family:Courier New;"&gt;&lt;b&gt;&lt;br /&gt;#&lt;/b&gt;&lt;/span&gt;   &lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;&lt;b&gt;import re,   string&lt;/b&gt;&lt;/span&gt;   &lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;&lt;b&gt;from SOAPpy import   SOAPProxy&lt;/b&gt;&lt;/span&gt;       &lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;&lt;b&gt;server = SOAPProxy("http://services.chronos.org:9090/axis/timescales.jws")&lt;/b&gt;&lt;/span&gt;        &lt;span style="font-family:Courier New;"&gt;&lt;b&gt;&lt;br /&gt;time =   20.0&lt;/b&gt;&lt;/span&gt;    &lt;span style="font-family:Courier New;"&gt;&lt;b&gt;&lt;br /&gt;while time &amp;lt;   40.0:&lt;/b&gt;&lt;/span&gt;    &lt;span style="font-family:Courier New;"&gt;&lt;b&gt;&lt;br /&gt;  result = server.convertTime("GTS 2004", "Berggren 95",time)&lt;/b&gt;&lt;/span&gt;             &lt;span style="font-family:Courier New;"&gt;&lt;b&gt;         &lt;br /&gt;  print time , result&lt;/b&gt;&lt;/span&gt;    &lt;span style="font-family:Courier New;"&gt;&lt;b&gt;         &lt;br /&gt;  time = time + 0.1&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Example using Groovy&lt;br /&gt;     &lt;br /&gt;&lt;div style="margin-left: 40px;"&gt;&lt;b&gt;import groovy.net.soap.SoapClient&lt;/b&gt;  &lt;b&gt;&lt;br /&gt;&lt;br /&gt;def proxy = new SoapClient("http://services.chronos.org:9090/axis/timescales.jws?wsdl")&lt;/b&gt;  &lt;b&gt;&lt;br /&gt;&lt;br /&gt;def serviceClosure = {&lt;/b&gt;&lt;br /&gt;  &lt;b&gt;time -&amp;gt; return proxy.convertTime("GTS 2004", "Berggren 95", time)&lt;/b&gt;&lt;br /&gt; &lt;b&gt;}&lt;/b&gt; &lt;br /&gt;&lt;br /&gt;&lt;b&gt;for (float f = 20;f&amp;lt; 40.0; f=f+0.1) {&lt;br /&gt;&lt;/b&gt;   &lt;b&gt;     println serviceClosure(f)&lt;br /&gt;}&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;br /&gt;A slightly more advanced example of a real-world application of these services is the implementation of the service in a Java-based web application server.  In this case, a user would use e.g. the Xfire (http://xfire.codehaus.org/Client+and+Server+Stub+Generation+from+WSDL) or Apache Axis (http://ws.apache.org/axis/java/client-side-axis.html) packages to generate a library from the WSDL file.  The resulting library could then be easily called from various locations in the application with only a few lines of code.&lt;br /&gt;&lt;br /&gt;The first step would involve the creation of the stub classes in a WSDL-to-Java process.  We will use the Apache Axis package in this example but the process is similar for Xfire or C# style environments.  The initial stub classes are generated through a call like:&lt;br /&gt;&lt;br /&gt;&lt;div style="margin-left: 40px;"&gt;&lt;b&gt;java -cp axis.jar:commons-logging-1.0.4.jar:commons-discovery-0.2.jar:axis-ant.jar:log4j-1.2.8.jar:wsdl4j-1.5.1.jar:jaxrpc.jar:saaj.jar org.apache.axis.wsdl.WSDL2Java  -o . -d Session -p org.chronos.ws http://services.chronos.org:9090/axis/timescales.jws?wsdl &lt;/b&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;The result of this call is a set of Java source files that would then be compiled:&lt;br /&gt;&lt;br /&gt;&lt;div style="margin-left: 40px;"&gt;&lt;b&gt;javac -classpath axis.jar:commons-logging-1.0.4.jar:commons-discovery-0.2.jar:axis-ant.jar:log4j-1.2.8.jar:wsdl4j-1.5.1.jar:jaxrpc.jar:saaj.jar org/chronos/ws/*.java&lt;/b&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;and the resulting class files collected into a jar file:&lt;br /&gt;&lt;br /&gt;&lt;div style="margin-left: 40px;"&gt;&lt;b&gt;jar -cvf timescale.jar org/chronos/ws/*.class&lt;/b&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;The resulting jar file can then be used to greatly simplify the creation of clients in Java or any other Java byte code compatible language like Jruby, Jpython or Groovy.&lt;br /&gt;&lt;br /&gt;An example of Java client that gets the color scheme for the Geological Time Scale is:&lt;br /&gt;&lt;br /&gt;&lt;div style="margin-left: 40px;"&gt;&lt;b&gt;public class wsClient {&lt;/b&gt; &lt;b&gt;&lt;br /&gt;  public static void main(String [] args) throws Exception {&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;   &lt;b&gt;// Make a service&lt;/b&gt;&lt;br /&gt;   &lt;b&gt;org.chronos.ws.TimescalesService service = new org.chronos.ws.TimescalesServiceLocator();&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;   &lt;b&gt;// Now use the service to get a stub to the service&lt;/b&gt; &lt;b&gt;        org.chronos.ws.Timescales_PortType ts = service.gettimescales();&lt;/b&gt;   &lt;b&gt;&lt;br /&gt;&lt;br /&gt;  // Make the actual call&lt;/b&gt; &lt;b&gt;&lt;br /&gt;  System.out.println("call " + ts.getColorScales());&lt;/b&gt; &lt;b&gt;&lt;br /&gt; }&lt;/b&gt; &lt;b&gt;&lt;br /&gt;}&lt;/b&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;A Groovy client that uses the jar file (here using the batch convert method for time conversion) is:&lt;br /&gt;&lt;div style="margin-left: 40px;"&gt;&lt;b&gt;import java.text.DecimalFormat&lt;/b&gt;  &lt;b&gt;&lt;br /&gt;&lt;br /&gt;// Make a service&lt;/b&gt;&lt;br /&gt;&lt;b&gt;def org.chronos.ws.TimescalesService service = new org.chronos.ws.TimescalesServiceLocator();&lt;/b&gt;  &lt;b&gt;&lt;br /&gt;&lt;br /&gt;// Now use the service to get a stub to the service&lt;/b&gt;&lt;br /&gt;&lt;b&gt;def org.chronos.ws.Timescales_PortType ts = service.gettimescales();&lt;/b&gt;   &lt;b&gt;&lt;br /&gt;&lt;br /&gt;// Make the actual call&lt;/b&gt; &lt;b&gt;&lt;br /&gt;def batchResults = (ts.convertTimeBatch("GTS 2004", "Berggren 95", 0.toDouble(), 60.toDouble(), 1.toDouble()));&lt;/b&gt; &lt;br /&gt;&lt;br /&gt;&lt;b&gt;DecimalFormat df2 = new DecimalFormat( "#,###,###,##0.000" );&lt;/b&gt;  &lt;b&gt;&lt;br /&gt;&lt;br /&gt;//  Closure for 2 place formating&lt;/b&gt; &lt;b&gt;&lt;br /&gt;def decf2 = { &lt;/b&gt; &lt;b&gt;&lt;br /&gt;  value -&amp;gt; return new Double(df2.format(value)).doubleValue();&lt;/b&gt; &lt;b&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/b&gt; &lt;b&gt;for (item in batchResults) {&lt;/b&gt;&lt;br /&gt;   &lt;b&gt;println decf2(item)&lt;/b&gt;&lt;br /&gt;&lt;b&gt;}&lt;/b&gt; &lt;/div&gt;&lt;br /&gt;     &lt;br /&gt;These examples illustrate the process involved in the creation of clients using only the WSDL URL.  Once created, jar libraries like those at the end of the process can be dropped into application server class paths and used in frameworks like Grails (&lt;a href="http://www.gridsphere.org/"&gt;http://www.grails.org&lt;/a&gt;), Seam ( &lt;a href="http://www.jboss.com/products/seam"&gt;http://www.jboss.com/products/seam&lt;/a&gt;) or JSR-168 portal environments like Gridsphere (&lt;a href="http://www.gridsphere.org/"&gt;http://www.gridsphere.org&lt;/a&gt;).  Any application or tool with network access can invoke these services in a similar manner.&lt;br /&gt;&lt;br /&gt;All CHRONOS services a similar pattern and can be utilized in web-based or stand-alone clients that have access to the network.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-4518029958530366089?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/4518029958530366089/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=4518029958530366089' title='13 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/4518029958530366089'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/4518029958530366089'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2007/09/using-chronos-timescale-converter.html' title='Using CHRONOS Timescale Converter Service Calls'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><thr:total>13</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-1865596105786098737</id><published>2007-09-04T13:57:00.000-05:00</published><updated>2007-09-04T14:12:29.257-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='grails'/><category scheme='http://www.blogger.com/atom/ns#' term='groovy'/><title type='text'>Grails SQL date formating lib</title><content type='html'>Been working with Grails more and created a little tag lib I thought I would post up for others.  The date that comes out of the domains is a rather ugly SQL date style so I create a tag lib with the following code:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="font-family:courier new;"&gt; def formatSqlDate = { attrs -&amp;gt; &lt;br /&gt;    def String startdatetime =  "${attrs['targetDate']}"&lt;br /&gt;    def DateFormat odf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.S");&lt;br /&gt;    def DateFormat df = new SimpleDateFormat( "MMM d, ''yy" );&lt;br /&gt;    out &amp;lt;&amp;lt; df.format(odf.parse(startdatetime))     &lt;br /&gt; }&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;Then I can simple reference it with:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;span&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;g:formatsqldate targetdate="${domain.dateObject}"&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;A person can mode the date format string all they want and also could put in various cases or a flag to select a format style if they wished.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-1865596105786098737?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/1865596105786098737/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=1865596105786098737' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/1865596105786098737'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/1865596105786098737'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2007/09/grails-sql-date-formating-lib.html' title='Grails SQL date formating lib'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-7725355444353506109</id><published>2007-07-27T10:06:00.000-05:00</published><updated>2007-07-27T10:51:08.191-05:00</updated><title type='text'>Terminal shell in eclipse</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_f5taJtU-20M/RqoPMEmERiI/AAAAAAAAAAU/8bf_Mhr3lTM/s1600-h/Screenshot-Show+View+-1.png"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer;" src="http://bp0.blogger.com/_f5taJtU-20M/RqoPMEmERiI/AAAAAAAAAAU/8bf_Mhr3lTM/s320/Screenshot-Show+View+-1.png" alt="" id="BLOGGER_PHOTO_ID_5091899028762019362" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;The state of working with Grails in Eclipse is not the best for me.  Using the external tool call has been a pain and I have been using an external terminal shell.  Today I went looking for a terminal shell solution built into Eclipse and found the &lt;a href="http://www.eclipse.org/dsdp/tm/"&gt;Target Management Project&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;You can install the components for this via the Eclipse update manager with the information from: &lt;a href="http://europa-mirror1.eclipse.org/dsdp/tm/updates/"&gt;http://europa-mirror1.eclipse.org/dsdp/tm/updates/&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Once this is done use the menu sequence Window -&gt; Show_View -&gt; Other and select the Remote Systems folder.  From there I added "Remote System Details" (not really needed) and "Remote Shell".  Using the triangle menu for this latter element I selected the default local connection.&lt;br /&gt;&lt;br /&gt;After all this though..   failure..  it exec's each command out to the shell and as such there is no way to re-attach and kill a process easily.  If you run grails run-app it's disconnected to one has to ps its PID and kill it.  (not optimal).&lt;br /&gt;&lt;br /&gt;After some looking I found sshView (&lt;a href="http://www.eclipse-plugins.info/eclipse/plugin_details.jsp?id=1187"&gt;http://www.eclipse-plugins.info/eclipse/plugin_details.jsp?id=1187&lt;/a&gt;).  This installed but gave some very strange behavior and never was able to get it to successfully work.  You can access it in the same sequence as above and look for sshview.&lt;br /&gt;&lt;br /&gt;In the end there is &lt;a href="http://pluginbox.sourceforge.net/plugins.html"&gt;easyShell&lt;/a&gt;.  However, all this does is launch the shell I was using when I started this journey.  Yes, you can configure it to open up in the directory the file is in and you can get to rather easily through the contextual menu.  In the end not really worth the time and effort and still no good built into the IDE view shell solutions that I can find at least.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-7725355444353506109?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/7725355444353506109/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=7725355444353506109' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/7725355444353506109'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/7725355444353506109'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2007/07/terminal-shell-in-eclipse.html' title='Terminal shell in eclipse'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp0.blogger.com/_f5taJtU-20M/RqoPMEmERiI/AAAAAAAAAAU/8bf_Mhr3lTM/s72-c/Screenshot-Show+View+-1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-485603220625433288</id><published>2007-07-19T15:44:00.000-05:00</published><updated>2007-07-19T15:51:52.311-05:00</updated><title type='text'>Using Grails GSP to provide alternating colors in a table</title><content type='html'>Using Grails GSP to provide alternating colors in a table&lt;br /&gt;&lt;br /&gt;I saw something related to this a while ago on the net but was not able to find it again. So I just came up with my own approach.&lt;br /&gt;&lt;br /&gt;I wanted a table that had alternating rows highlighted. There are many ways to approach this. This solution is what I am going to use since it all falls on the view side of things and as such is rather easy to code. It is based on the code examples from &lt;a href="http://grails.org/GSP+Tag+-+set"&gt;http://grails.org/GSP+Tag+-+set&lt;/a&gt;&lt;br /&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;span style="font-family:Arial Narrow;"&gt;  &amp;lt;table width="50%" align="right" border="0" cellpaddinng="0" cellspacing="0"&amp;gt;&lt;/span&gt; &lt;span style="font-family:Arial Narrow;"&gt;           &lt;/span&gt;&lt;span style="font-weight: bold;font-family:Arial Narrow;" &gt;&lt;br /&gt;  &amp;lt;g:def var="counter" value="${1}" /&amp;gt;&lt;/span&gt; &lt;span style="font-family:Arial Narrow;"&gt;&lt;br /&gt;    &amp;lt;g:each in="${lastElement}"&amp;gt;&lt;/span&gt; &lt;span style="font-family:Arial Narrow;"&gt;&lt;br /&gt;               &amp;lt;tr&amp;gt;&lt;/span&gt; &lt;span style="font-family:Arial Narrow;"&gt;&lt;br /&gt;                   &amp;lt;td style="background:&lt;/span&gt;&lt;span style="font-weight: bold;font-family:Arial Narrow;" &gt;${counter % 2 == 0 ? 'white' : 'grey'&lt;/span&gt;&lt;span style="font-family:Arial Narrow;"&gt;"&amp;gt;&lt;/span&gt; &lt;span style="font-family:Arial Narrow;"&gt;&lt;br /&gt;                       &amp;lt;g:showElementResults id='${it.id}'/&amp;gt;&lt;/span&gt; &lt;span style="font-family:Arial Narrow;"&gt;&lt;br /&gt;                   &amp;lt;/td&amp;gt;&lt;/span&gt; &lt;span style="font-family:Arial Narrow;"&gt;&lt;br /&gt;               &amp;lt;/tr&amp;gt;&lt;/span&gt; &lt;span style="font-family:Arial Narrow;"&gt;                &lt;/span&gt;&lt;span style="font-weight: bold;font-family:Arial Narrow;" &gt;&lt;br /&gt;&amp;lt;g:set var="counter" value="${counter + 1}" /&amp;gt;&lt;/span&gt; &lt;span style="font-family:Arial Narrow;"&gt;&lt;br /&gt;          &amp;lt;/g:each&amp;gt;&lt;/span&gt; &lt;span style="font-family:Arial Narrow;"&gt;&lt;br /&gt;   &amp;lt;/table&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;It is the "&lt;span style="font-size:85%;"&gt;${counter % 2 == 0 ? 'white' : 'grey'}&lt;/span&gt;" that does all the work. The only other interesting elements are in bold.  Simply change the two colors to get the banding effect you want. A more advanced version of this could set a style name or some other CSS element to improve the approach. I am sure there are several ways to do this. This seems to work for me. The "&amp;lt;g:showElementResults id='${it.id}'/&amp;gt;" code is not relevant here. It's just a taglib I use to create the formatted text of the cell based on an id and the rest is the just the &amp;lt;g:each&amp;gt; tag boilerplate.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-485603220625433288?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/485603220625433288/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=485603220625433288' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/485603220625433288'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/485603220625433288'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2007/07/using-grails-gsp-to-provide-alternating.html' title='Using Grails GSP to provide alternating colors in a table'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-7439913991975424226</id><published>2007-07-12T10:20:00.000-05:00</published><updated>2007-07-12T10:27:24.787-05:00</updated><title type='text'>Keyboard shortcut for grails external tool in Eclipse</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_f5taJtU-20M/RpZHI7ODvuI/AAAAAAAAAAM/Uwn90oG9uYM/s1600-h/Screenshot-Preferences+.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://bp2.blogger.com/_f5taJtU-20M/RpZHI7ODvuI/AAAAAAAAAAM/Uwn90oG9uYM/s320/Screenshot-Preferences+.png" alt="" id="BLOGGER_PHOTO_ID_5086331047822737122" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Somehow I think this should have been much easier to do.  Since it didn't seem to be I am placing it here.&lt;br /&gt;&lt;br /&gt;Using Grails in Eclipse (&lt;a href="http://grails.codehaus.org/IDE+Integration"&gt;IDE integration information here&lt;/a&gt;), I wanted to make a shortcut for the external tools command which is used so much in this set up.&lt;br /&gt;&lt;br /&gt;To do this you need to go to preferences (under the window menu), and select Keys -&gt; Modify (Tab) -&gt; Run/Debug (Category pull down) -&gt; Run Last Launched External Tool (Name pull down) then assign the key in the key sequence and be sure to click the "Add" button.&lt;br /&gt;&lt;br /&gt;Once all that is done you have a keyboard shortcut for the external tool.&lt;br /&gt;&lt;br /&gt;(Please..  I'd like to see&lt;a href="http://blogs.sun.com/geertjan/entry/grails_in_netbeans_ide"&gt; netbeans and grails integration&lt;/a&gt;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-7439913991975424226?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/7439913991975424226/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=7439913991975424226' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/7439913991975424226'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/7439913991975424226'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2007/07/keyboard-shortcut-for-grails-external.html' title='Keyboard shortcut for grails external tool in Eclipse'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp2.blogger.com/_f5taJtU-20M/RpZHI7ODvuI/AAAAAAAAAAM/Uwn90oG9uYM/s72-c/Screenshot-Preferences+.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-6023514815070690722</id><published>2007-06-26T10:14:00.000-05:00</published><updated>2007-06-26T10:16:59.764-05:00</updated><title type='text'>Perm gen size and Grails</title><content type='html'>I've been continuing to work with the &lt;a href="http://www.grails.org"&gt;Grails&lt;/a&gt; framework and found an interesting issue.  When working with the Tomcat application server I run into several issues related to out of memory errors with Grails applications. &lt;br /&gt;&lt;br /&gt;Attempts to resolve this with -Xmx512m or some other setting  for the memory heap size failed to work.  This seems to be due to the large number of elements (controllers, domains, etc) in my grails app that load classes.  I believe this is related to issues of lots of use of reflection (not sure).  It does appear that this memory is alive during the entire life of the application (not garbage collected).  After installing several plug-ins and increasing the size of the application quite a bit this occurred.  It also seems to be partly related to the creation of an additional "Context Path" for an application in Tomcat.  &lt;br /&gt;&lt;br /&gt;I found some reference to Tomcat 6 having better "perm size" management on the net vs Tomcat 5 series.  Though nothing of a definitive nature.  I saw it seems related since it removing the extra "Context Path" for this grails application seemed to resolve things.  Perhaps it is an issue with grails applications in multiple Context Path's but the perm gen size increase did resolve it cleanly. &lt;br /&gt;&lt;br /&gt;My current options line for catalina.sh:&lt;br /&gt;&lt;span style="font-style: italic;font-size:85%;" &gt;&lt;span style="font-family: courier new;"&gt; JAVA_OPTS='-Xmx512m -XX:MaxPermSize=256m -server -Djava.awt.headless=true'&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-6023514815070690722?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/6023514815070690722/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=6023514815070690722' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/6023514815070690722'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/6023514815070690722'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2007/06/perm-gen-size-and-grails.html' title='Perm gen size and Grails'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-3574325686004989880</id><published>2007-05-18T07:59:00.000-05:00</published><updated>2007-05-31T09:44:24.928-05:00</updated><title type='text'>CBS bought me (well, last.fm)</title><content type='html'>So I didn't want this blog to become abandoned, and in fact I have several items throughout the last weeks that I have felt worthy of blogging about and have not.  I think I just need to discipline myself to post my thoughts when I have them and not "I'll do that later".&lt;br /&gt;&lt;br /&gt;But yesterday when I heard &lt;a href="http://news.com.com/CBS+buys+music+network+Last.fm/2100-1027_3-6187408.html?tag=item"&gt;CBS bought last.fm&lt;/a&gt; (and being a last.fm user) it got me to thinking and motivated to post this thought.  I have just been bought...  along with my data.  Will CBS keep it, take it, toss it out?  Indeed if you look around I have relationships with Google, Amazon, Last.fm, Digg and other sites.  All this data is valuable to me and what might happen to it in a merger, take-over, bankruptcy?&lt;br /&gt;&lt;br /&gt;Do we need a &lt;span style="font-style: italic;"&gt;Federal DATA Insurance Corp&lt;/span&gt;.&lt;br /&gt;I had this thought a few weeks ago when talking to Josh, regarding my use of &lt;a href="http://aws.amazon.com/s3"&gt;Amazon S3&lt;/a&gt; to backup my data.  I was looking at various on-line data backup sites.  There are many and for my small amount several I could get free (add supported).  However, I liked the Amazon S3 due to it's use of services and quite frankly the size and apparent strength of &lt;a href="http://finance.google.com/finance?q=amazon"&gt;Amazon&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;We began talking about the amount of data a person has on the net.  I have data I would call valuable with Google (mail, RSS, this blog and a bit more), Amazon (data via S3) and Yahoo (&lt;a href="http://arstechnica.com/news.ars/post/20051210-5733.html"&gt;they own del.icio.us now&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;However, if any of these were to go away what would happen to my data?  Gone?  It got me to thinking about the &lt;a href="http://en.wikipedia.org/wiki/Federal_Deposit_Insurance_Corporation"&gt;Federal Deposit Insurance Corp&lt;/a&gt;.  Established to provide some assurance that money (or at least some) would be safe.&lt;br /&gt;&lt;br /&gt;Though the analogy is obviously not one to one it does make me wonder if there isn't some general consumer &lt;a href="http://en.wikipedia.org/wiki/Service_Level_Agreement"&gt;SLA&lt;/a&gt; that needs to be established with on-line data "deposit" sites. A Federal DATA Insurance Corp. to provide the public with some level of trust, confidence that data stored on-line in places like Flicker, MySpace, S3, Google, etc are retrievable when/if a company goes south.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-3574325686004989880?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/3574325686004989880'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/3574325686004989880'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2007/05/cbs-bought-me-well-lastfm.html' title='CBS bought me (well, last.fm)'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-7278247891999895206</id><published>2007-03-04T09:08:00.000-06:00</published><updated>2007-03-04T09:26:39.543-06:00</updated><title type='text'>IDE for jRuby</title><content type='html'>I went looking for the current state of IDE's for Ruby and in particular Ruby on Rails.  In fact even more specifically for &lt;a href="http://jruby.sourceforge.net/"&gt;jRuby&lt;/a&gt; since I am not very interested in Ruby or ROR unless it is hosted on the JVM.  &lt;br /&gt;&lt;br /&gt;I found &lt;a href="http://www.radrails.org/"&gt;RadRails&lt;/a&gt; and &lt;a href="http://rubyeclipse.sourceforge.net/"&gt;RDT&lt;/a&gt;.  Both of these are based on the Eclipse IDE platform.  The former apparently based on the later.  I installed and attempted to use both with jRuby.  I had little success in this effort and from what I can gather jRuby support is yet to come for these packages.&lt;br /&gt;&lt;br /&gt;I grabbed one of the &lt;a href="http://wiki.netbeans.org/wiki/view/MilestoneDownloads"&gt;Netbeans 6 nightly builds&lt;/a&gt; and was presently surprised to find jRuby there.  A little more searching reveled &lt;a href="http://tnlessone.wordpress.com/2007/02/28/ruby-rails-ide-comparison-idea-netbeans-radrails/"&gt;this site which has done a far further exhaustive review of various Ruby IDE's&lt;/a&gt; than I have seen so far.  &lt;a href="http://blogs.sun.com/tor/category/Ruby"&gt;Tor Norbye's blog section on Ruby&lt;/a&gt; also provides news straight from the source on this effort.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-7278247891999895206?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/7278247891999895206/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=7278247891999895206' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/7278247891999895206'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/7278247891999895206'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2007/03/ide-for-jruby.html' title='IDE for jRuby'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-3546359804074209738</id><published>2007-03-01T11:59:00.000-06:00</published><updated>2007-03-01T13:18:12.364-06:00</updated><title type='text'>February Errata</title><content type='html'>So it has been some time since I made a post.  Been busy but I hope to manage my time better in future so that I can post my thoughts more often. The main reason I do this is to benefit myself in terms of aligning what I see and experience in the community into a coherent philosophy.&lt;br /&gt;&lt;br /&gt;I wanted to touch on several things in the last few weeks I have been interested in.  Actually sitting down and writing this was sparked by this news item (&lt;a href="http://news.com.com/Adobe+to+take+Photoshop+online/2100-7345_3-6163015.html?tag=nefd.lede"&gt;Adobe to take Photoshop online at  Cnet&lt;/a&gt;) that caught my eye in my RSS feeds.  &lt;br /&gt;&lt;br /&gt;It caught my eye due to a discussion I had with Josh, where we debated a bit this very concept.  Word processing and excell spread sheets aside it seemed unlikely that the on-line application model as exemplified by Google docs would work for something like GIMP or Photoshop.  It is interesting to look at this in light of things like &lt;a href="http://www.joyent.com/"&gt;Joyent&lt;/a&gt; though.  Correl is looking to take a variation of Word Perfect into a model that uses both on-line and off-line elements in collaboration with Joyent.  This mix of on-line and off-line aspects to an application is very interesting to me. It is all part of the development that is taking place where API's like XUL, XAML etc are getting attention in the same context as GTK and QT.  However, how much application API's matter is up to debate.  Is it only the movement and management of information in an open and extensible manner that really is important?&lt;br /&gt;&lt;br /&gt;One element of that did catch my eye was Remix which uses Flex.  This is more interesting to me as it brings up the issue of rich client development.  I have been watching XUL, XAML (Windows Presentation Foundation) and things like FLEX and Laszlo for some time now.  Mix in things like the rich client platforms from Eclipse and Netbeans and you have the making of new "internet aware application API's" forming.  This would be great.  GTK, QT, Cocca etc. aside what is more interesting to me is the ability to make "application" that come to the user over the net.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Grails Update&lt;/span&gt;&lt;br /&gt;Grails has a new major number out and a major shift in the way it deals with incorporating third party features.  A very nice plug in approach.  The jump from .3 to .4 was a bit painful as you have to un-weave the code you have done in the old approach for the new.  I updated an Acegi security based application from .3 to .4.  The biggest pain is removing the controller, domain, and other classes that were required prior to the plugin approach.  Though this was a bit tedious it is well worth it for the nice new plugin based system.  Hopefully such a major effort will not be required in the future.  I suspect the Acegi package is one of the bigger ones to migrate.&lt;br /&gt;&lt;br /&gt;Seems they also changed the way to they do the creation of URL's and several of my relative links got broken.  I should be using more of the Grails link tag (&lt;a href="http://grails.org/Tag+-+link"&gt;http://grails.org/Tag+-+link&lt;/a&gt;) more than using relative URL linking.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;This blog visualization is cool&lt;/span&gt;&lt;br /&gt;This is neat..  &lt;a href="http://twingly.se/ScreenSaver.aspx"&gt;http://twingly.se/ScreenSaver.aspx&lt;/a&gt;  useful?  Not so sure, but for sure neat.  If I ran windows I would likely install it and play with it some. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Yahoo Pipes&lt;/span&gt;&lt;br /&gt;&lt;a href="http://pipes.yahoo.com/"&gt;Yahoo Pipes&lt;/a&gt; came out, this one one of those things I was interested in blogging about. I even retrieved/reactivated my Yahoo account just to play with this.  While I found it very interesting, I can not say I found it highly useful.  This idea implemented as an API I could embed in my app server, that would be far more interesting. &lt;br /&gt;&lt;br /&gt;There are several other packages like this out there too. &lt;a href="http://www.xfruits.com/"&gt;xFruits&lt;/a&gt; and  even &lt;a href="www.yourminis.com"&gt;www.yourminis.com&lt;/a&gt;.  &lt;br /&gt;&lt;br /&gt;Don't get me wrong, the idea behind Pipes is very much along the route I would like to see things going.  Mechanisms to collect, relate and cross reference data generated on the net.  I'd just rather have it as an API for my applications rather than a third party service provide to/for me.  &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Get things done&lt;/span&gt;&lt;br /&gt;I was only tangentially aware of the GTD approach.  &lt;a href="http://www.amazon.com/gp/product/0142000280?ie=UTF8&amp;tag=thehtmlcenter&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0142000280"&gt;The book&lt;/a&gt; has spawned several packages on-line and I reviewed a few of them listed in the &lt;a href="http://www.centernetworks.com/the-getting-things-done-phenomenon-an-update-primer"&gt;post at Center Networks&lt;/a&gt;.  One, &lt;a href="http://www.rousette.org.uk/projects/"&gt;Tracks&lt;/a&gt;, caught my eye and I actually installed and got ruby working (which can be a pain with regard to DB access at times).  (rant) The Ruby on Rails database API and interface is archaic in comparison to Java JDBC let alone persistence aspects (/rant)&lt;br /&gt;&lt;br /&gt;I got it set up and working and played around with it some.  It took a while to &lt;i&gt;get this done&lt;/i&gt; due to the poor, IMHO, ruby database approach.  Anyway, Tracks is interesting, but I think I was more interested in the experience it gave me with Ruby on Rails than anything else.  I may try and play with it some more in the future though and revisit it as a utility and approach to time management.  On a side note the Joyent package mentioned above is a Ruby on Rails application.  The note some interesting news coming from them based on the collaboration with Sun.  One might speculate on them switching to &lt;a href="http://jruby.codehaus.org/"&gt;jRuby&lt;/a&gt; in the near future.  jRuby plus the Java VM could be a very powerful combination for an application like this.  I am still a &lt;a href="http://www.grails.org"&gt;Grails&lt;/a&gt; person until jRuby evolves more.  When it does I will give it a try again.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-3546359804074209738?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/3546359804074209738/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=3546359804074209738' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/3546359804074209738'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/3546359804074209738'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2007/03/february-errata.html' title='February Errata'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-5299374960387028840</id><published>2007-01-27T10:17:00.000-06:00</published><updated>2007-01-29T10:09:24.955-06:00</updated><title type='text'>XML UI's revisted (XAML, XUL and AJAX)</title><content type='html'>Back &lt;a href="http://douglasfils.blogspot.com/2006/10/net-30-attach-on-standards.html"&gt;in October I made a post about WPF&lt;/a&gt; and my concerns around it.   Now the European Committee for Interoperable Systems (ECIS), &lt;a href="http://www.e-c-i-s.org/news/2007_jan26.htm"&gt;has raised similar concerns&lt;/a&gt;.  To be fair some of the points raised by the people at the respectable Ars Technica site are valid on this point.  &lt;a href="http://arstechnica.com/news.ars/post/20070126-8715.html"&gt;Their article on this&lt;/a&gt; development raises  many issues that indicate XAML (WPF) is not quite a full scale attack on standards (not yet anyway).  &lt;a href="http://en.wikipedia.org/wiki/Windows_Presentation_Foundation"&gt;A review of WPF at Wikipedia&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;This was interesting news for me to wake up to since I have been thinking about XML based GUI's lately in relation to the Grails development I have been doing.  Grails recently added &lt;a href="http://www.openlaszlo.org/"&gt;OpenLaszlo&lt;/a&gt; as a build option for interfaces.  (Ref: &lt;a href="http://grails.codehaus.org/OpenLaszlo+plugin"&gt;http://grails.codehaus.org/OpenLaszlo+plugin&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;The combination of XHTML and JavaSript to make user interfaces via AJAX that one can embedd into XHTML is currently all the rage.  One can contrast this with &lt;a href="http://www.mozilla.org/projects/xul/"&gt;XUL&lt;/a&gt; as yet another  plus JavasScriptUI toolset.  The process of embedding XUL UI's into XHTML might not be so clear to me at this time.  Though perhaps XHTML in XUL is more likely anyway.  I need to investigate this and also how &lt;a href="http://www.w3.org/2004/CDF/"&gt;CDF&lt;/a&gt; might play into this.   Blending AJAX and XUL approaches might be an interesting gadonkin.&lt;br /&gt;&lt;br /&gt;In the same manner that the &lt;span style="font-style: italic;"&gt;grails generate-views&lt;/span&gt; command can be used to  make XHTML interfaces the &lt;span style="font-style: italic;"&gt;grails generate-laszlo&lt;/span&gt; is used to scaffold artifacts for Laszlo.  So why not a &lt;span style="font-style: italic;"&gt;grails generate-xul&lt;/span&gt; command?    Indeed, as the Ars article points out it is hard to imagine anything that could compete with the ubiquitous presence of HTML.  However, for web applications the ability to auto generate different UI's (XHTML, XUL, OpenLaszlo, etc) has some appeal.   If this is done automatically from the domain classes with common class extensions to a set of scaffold'ed artifacts then a developer can simply worry about the application and the elements a UI needs and leave the final implementation of the UI up to the user.  If the user wants XUL, then give that, if the user wants OpenLaszlo then give that.   This might have more appeal yet as the web moves toward things like the &lt;a href="http://www.apple.com/iphone"&gt;iPhone&lt;/a&gt;, or the &lt;a href="http://www.openmoko.com/"&gt;OpenMoko&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Also of note in that regard is the development of things like &lt;a href="http://wiki.wazaabi.org/index.php/Main_Page"&gt;Wazaabi&lt;/a&gt; which brings XUL to the Eclipse RPC environment which can be used develop rich client applications.   A friend of mine has used &lt;a href="http://www.adtmag.com/blogs/blog.aspx?a=20058"&gt;Eclipse RPC in his efforts related to work in Antarctica&lt;/a&gt;.  :)&lt;br /&gt;&lt;br /&gt;In conclusion I believe that the generation of richer UI's delivered across the web to browsers or brokered out to supporting apps by browsers is a developing trend.  I'm interested to see how the Grails application framework could be used to generate XUL interfaces that are used from within Mozilla based browsers like Firefox.   Combine this with the Mircoformats based semantics I have written previously about and I start to see a component framework built around Web standards and protocols.  I need to build an example of some of this to truly investigate it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-5299374960387028840?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/5299374960387028840/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=5299374960387028840' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/5299374960387028840'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/5299374960387028840'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2007/01/xml-uis-revisted-xaml-xul-and-ajax.html' title='XML UI&apos;s revisted (XAML, XUL and AJAX)'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-6910887159537104789</id><published>2007-01-14T09:22:00.000-06:00</published><updated>2007-01-14T09:38:23.205-06:00</updated><title type='text'>Microformats</title><content type='html'>I was interested to see some news items that on the surface don't seem related but to me have a lot to say about trends.&lt;br /&gt;&lt;br /&gt;Mozilla has started talking about Firefox 3 (&lt;a href="http://www.readwriteweb.com/archives/mozilla_does_microformats_firefox3.php"&gt;http://www.readwriteweb.com/archives/mozilla_does_microformats_firefox3.php&lt;/a&gt;)  and in particular has mentioned microformats and a broader role for the browser as broker of information and service on the net to other applications.  As a long time UNIX person I believe in the vision of small dedicated programs that do what they are meant to do and do it well tied together via piping.  So the idea of data described by microformats, discovered or retrieved by broker and routed (piped) to other more dedicated applications has appeal to me.&lt;br /&gt;&lt;br /&gt;Also of note was &lt;a href="http://www.songbirdnest.com/node/1165"&gt;Songbird talking about plans for an API &lt;/a&gt;for site developers.  I hope this evolves into a &lt;a href="http://microformats.org"&gt;microformat&lt;/a&gt; or &lt;a href="http://rdfa.info"&gt;RDFa&lt;/a&gt; that allows a music centric site developer to place data directly into their web page that allows browsers like Songbird or even machine searching and indexing of music by the likes of Google or &lt;a href="http://search.singingfish.com/sfw/home.jsp"&gt;Singing Fish&lt;/a&gt; to use structured data from within a page or site.&lt;br /&gt;&lt;br /&gt;This could get very exciting with things like Apple TV and The Venice Project (&lt;a href="http://newteevee.com/2007/01/11/venice-project-mozilla/"&gt;which is also using Mozilla technology&lt;/a&gt;) coming up and extending this possibility into video.  With browsers getting more extensible and smarter about how they can handle structured data site developers will actually be able to see a reason (ie benefit) to doing something (anything) with metadata.  Which to this point has has little to no use or benefit (IMHO).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-6910887159537104789?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/6910887159537104789/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=6910887159537104789' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/6910887159537104789'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/6910887159537104789'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2007/01/microformats.html' title='Microformats'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-3816935683043502355</id><published>2006-12-29T08:19:00.000-06:00</published><updated>2006-12-29T09:18:50.292-06:00</updated><title type='text'>404... your app no longer works</title><content type='html'>How many more buzz words could I get into to the title?  Been a while with Christmas this month, but there is something I have been meaning to think/write about.  Google says it will do no evil.  So why then am I some what concerned when I see things like the news at: &lt;a href="http://code.google.com/apis/soapsearch/"&gt;http://code.google.com/apis/soapsearch/&lt;/a&gt;.    While I might not be surprised to see the SOAP end point go away, replaced by a ReST end point, I am a bit shocked to see an AJAX replacement.&lt;br /&gt;&lt;br /&gt;This Google search box is definitely exactly what I have been working with myself (and many others).  The ability to place a software component directly into a remote DOM.  It is also very analogous to the OpenDoc approach I have been advocating for sometime.&lt;br /&gt;&lt;br /&gt;However, &lt;span style="font-style: italic;"&gt;an AJAX component is not a service&lt;/span&gt;.  It is not something that I can invoke like a SOAP or ReST end point. Obviously (I think) that a dissection of what is occurring with Google Search AJAX component would reveal a ReST based response system, likely returning XML or most likely JSON(P).   However that doesn't mean that the average user will be able to use it or even access that ReST end point (if it is there).&lt;br /&gt;&lt;br /&gt;This whole issue with services is interesting.  A development group might say they are going to create all their service components as open ReST or SOAP end points.  For them to then eat their own dog food is important.  That is they should use what they offer others.  However, this can have issues like performance and scaling factors.  These are issues that might be avoided in a group just used native environment services like (for Java) RMI, Jini, beans, EJB, etc.  The lure of SOAP and ReST is that others can use them regardless of platform.  However, we don't have an environment right now where many service consumers rely on or trust remote data services to build web apps on.  Aggregated RSS/ATOM feeds don't count as a service.&lt;br /&gt;&lt;br /&gt;In fact, most groups create and use their own services to build their final value added result, not for others.  In that case however, the argument for SOAP or ReST is even harder to make.   Indeed that very argument favors the use of components in the primary language(s) of the development group.&lt;br /&gt;&lt;br /&gt;Yes, the argument can be made that in the case of Google, driving or presenting the brand is more important from a business POV than "doing good" by giving out a SOAP (or ReST) end point for people to use with potentially no reference to Google at all.  However, I am not going to dwell on the business model aspect of this action in this post (perhaps tangentially I will).&lt;br /&gt;&lt;br /&gt;No the real wonder I have is since there is no real market for services, will the SOAP and ReST efforts just wither and die for now? Until a need (&lt;span style="font-style: italic;"&gt;a want&lt;/span&gt;) for the ability for sites like Slashdot and Digg, or TV listing sites or Mac rumors sites or whatever to actually work together for the benefit of each other (and as a result the users) we wont see much need for services.  This is unlikely to occur in our current environment where the business model for sites is to get readership and eye balls across adds or to the fewer "pay for premium access" sites.    It may occure in other groups less driven by economics and more by altruistic endeavours like science, social good, etc.  Even then though, how many groups are willing to risk the operations of their web app on the existence and reliability of services provided by completely autonomous groups?&lt;br /&gt;&lt;br /&gt;Had UDDI or any other directory service actually succeeded in gaining use perhaps some of this might have been avoided (perhaps... not likely though).  However, that didn't happen.  I am curious about an approach that involves more server side logic where an "agent" like application downloads logic and data into a local cache.  From there execution of local code can produce results based on the remote logic and data.  This has many issues though since many disciplines have so much data that transferring the all the data is not feasible (or logical).&lt;br /&gt;&lt;br /&gt;Don't get me wrong.  Services are not dead and things like SOAP and ReST may find more affection from things like mobile devices, web aware game consoles (for things like &lt;a href="http://www.engadget.com/2006/12/19/wii-weather-channel-finally-launches/"&gt;Wii weather&lt;/a&gt;) or the recent Google / NASA efforts that might show up in Google Earth than they might from server farm based efforts.&lt;br /&gt;&lt;br /&gt;Additionally, ReST based service end point information embedded into a page perhaps via some &lt;a href="http://www.microformats.org/"&gt;microformat&lt;/a&gt; syntax might be interesting if more value added browsers (rich internet apps (RIA)) like &lt;a href="http://www.songbirdnest.com/"&gt;Songbird&lt;/a&gt; become more popular.  In that example a web site devoted to music might inform a browser like Songbird about its local offering via ReST end points rather than Songbird scrapping the sites content and page DOMs.&lt;br /&gt;&lt;br /&gt;Perhaps services are just waiting for that killer app (RIA or agent) to come along and actually make people want all this.&lt;br /&gt;&lt;br /&gt;Ref:&lt;br /&gt;&lt;a href="http://developers.slashdot.org/developers/06/12/20/0155238.shtml"&gt;http://developers.slashdot.org/developers/06/12/20/0155238.shtml&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-3816935683043502355?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/3816935683043502355/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=3816935683043502355' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/3816935683043502355'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/3816935683043502355'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2006/12/404-your-app-no-longer-works.html' title='404... your app no longer works'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-9039869574602373761</id><published>2006-12-02T08:50:00.000-06:00</published><updated>2006-12-02T13:13:45.686-06:00</updated><title type='text'>A groovy week on grails</title><content type='html'>So the Ruby on Rails people asked the group that started the "Groovy on Rails" effort to stop using the term "on Rails" (whatever).  That is why they have the name &lt;a href="http://grails.codehaus.org/"&gt;Grails&lt;/a&gt; now.  They didn't ask me and I have to say that this week of building a first end to end app for production use with Grails was quite groovy.&lt;br /&gt;&lt;br /&gt;First, I do like the coding by convention approach that allows less code and less configuration to be used.  I also like that what configuration is there is in the form of classes not XML.  We made an app for the ANDRILL effort and it should see the light of day soon (ie be reviewed and deployed).&lt;br /&gt;&lt;br /&gt;During the course of this development I was very impressed with how the various packages in &lt;a href="http://grails.codehaus.org/"&gt;Grails&lt;/a&gt;: Hibernate, Quartz, AJAX (via prototype in my case), Spring (obviously)  and the GORM objection relation mapping all work.   I am very keen to make up a Quartz job and then use the &lt;a href="http://groovy.codehaus.org/Groovy+Jabber-RPC"&gt;jabber resource&lt;/a&gt; to make a job that looks for changes or additions to the database and then IM's me.  That is more for me, the real version would likely report via email.&lt;br /&gt;&lt;br /&gt;We did run into some issues (Grails is only version .3 after all).  An issue with binary uploads in a none scaffolded controller (I assume the generated static code is somehow out of sync with the dynamic scaffold generated code).  Also had an issue with using the remotelink tag for AJAX calls vs using the remoteform tag for the same effect.  We resolved this by just not using them :)  but I need to report this to the Grails people to see if it is a known issue or something I was doing wrong.  Getting used to the scope of certain classes and methods took some getting used to as well, but that is more just my ignorance with how the plumbing was working at the start of this effot.&lt;br /&gt;&lt;br /&gt;Having full access to the all the wonderful Java classes makes Grails a no brain-er for me over Ruby on Rails.  I have to admit I am a bit sad that Sun seems to be in love with Ruby (via jRuby which ironically is also a codehaus effort at http://jruby.codehaus.org) and pays little if any attention to Grails so far (hopefully this will change).  Yes, though jRuby the Ruby syntax gets access to the classes as well.  We will see how this all works out.  I was interested to find that one of the key people in the &lt;a href="http://geronimo.apache.org/"&gt;Apache Geronimo&lt;/a&gt; effort is also one of the key &lt;a href="http://groovy.codehaus.org/"&gt;Groovy&lt;/a&gt; people as well.  Ruby has some very cool aspects to it, but I think the JVM is a better host for it than as a stand alone app directly on top of the OS.&lt;br /&gt;&lt;br /&gt;In a final experiment (ref:&lt;a href="http://www.infoq.com/articles/grails-ejb-tutorial"&gt; InfoQ Grails + EJB&lt;/a&gt; and a &lt;a href="http://graemerocher.blogspot.com/2006/06/grails-ejb3-entity-beans.html"&gt;Graeme Rocher blog entry&lt;/a&gt;) we used entity classes (not entity beans) that we generated via Netbeans for a database and dropped the POJO's into a grails app and were able to get read and write access to the db via the grails app using these entity classes as our domains with simple generated controllers and views.   We had some issues with primary key mappings, but nothing too hard for us to work around. This was interesting to me since I could use the entity classes along with Hibernate to do the data access work and then Grails as an lightweight flexible dev layer on top of that.   Grails lacks sophisticated buses like &lt;a href="http://servicemix.org/site/home.html"&gt;Service mix&lt;/a&gt; and others, but I am not certain I need or want those at this time (or that I can't do what I really want inside the Grails framework anyway).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-9039869574602373761?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/9039869574602373761/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=9039869574602373761' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/9039869574602373761'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/9039869574602373761'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2006/12/groovy-on-grails-week.html' title='A groovy week on grails'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-7595572329539484478</id><published>2006-11-26T13:19:00.000-06:00</published><updated>2006-11-26T13:26:42.469-06:00</updated><title type='text'>coding by convention vs prior convention</title><content type='html'>Been a while since I posted.  I have still be doing some work with Grails and Java &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;EE&lt;/span&gt;5.  I completed out my test for &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;UI's&lt;/span&gt; via AJAX as well but I thought I would put down some thoughts on coding by convention.&lt;br /&gt;&lt;br /&gt;I am new to the Rails approach and I have to say I quite like it. The idea that the file system, file names and such carry meaning and that the framework uses these to look for things that might otherwise be designated in XML configuration files is quite nice.&lt;br /&gt;&lt;br /&gt;&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-corrected" id="SPELLING_ERROR_2"&gt;Until&lt;/span&gt; of course you create a domain image.  I created the domain image in Grails.  This has the effect of telling Grails that any URL with /app/image in it should be processed by the controllers, services and such associated with that domain.  Unfortunately this also means that &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;img&lt;/span&gt; tags with &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;src&lt;/span&gt; attributes that use /app/image in their path don't load images from a directory in that path, but that pass the request on to the domain controller. &lt;br /&gt;&lt;br /&gt;It's a small point perhaps, but it does make me wonder what else I might run into.  Domains with names like image, &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;pdf&lt;/span&gt; or I am sure many other (conventional names)  just might &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-corrected" id="SPELLING_ERROR_6"&gt;interfere&lt;/span&gt; with the convention of the framework.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-7595572329539484478?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/7595572329539484478/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=7595572329539484478' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/7595572329539484478'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/7595572329539484478'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2006/11/coding-by-convention-vs-prior.html' title='coding by convention vs prior convention'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-1902997302406603341</id><published>2006-11-06T09:01:00.000-06:00</published><updated>2006-11-06T11:27:35.544-06:00</updated><title type='text'>Working on contrasting EE5 and Grails (Rails)</title><content type='html'>It has been a while since I did a post.  I have been busy at work on some new architecture designs and intend to make a good entry contrasting &lt;a href="http://grails.codehaus.org/"&gt;Grails&lt;/a&gt; and &lt;a href="http://java.sun.com/developer/technicalArticles/J2EE/intro_ee5/"&gt;Java EE5&lt;/a&gt; efforts soon.  However it has been a while and thought I would post up some errata thoughts I have had.   It has been very interesting to see how the two efforts (Grails and EE5)  deal with similar goals compared and contrasted to each other.  Trying to do the same thing in two different frameworks has definitely made it easier to see how each is addressing needs.  Of particular interest is comparing how &lt;a href="http://grails.codehaus.org/Ajax"&gt;grails deals with call backs from ajax widgets&lt;/a&gt; to server side logic compared to the Java &lt;a href="https://ajax.dev.java.net/"&gt;Jmaki&lt;/a&gt; effort.   I've got a longer post with my lessons from this that I am working on for a later date.&lt;br /&gt;&lt;br /&gt;I must say I have come to really like closures.  A programming concept I have not used much to this point.  &lt;a href="http://groovy.codehaus.org/Closures"&gt;Groovy (which Grails is based on) does closures&lt;/a&gt; and I also found an interesting page on &lt;a href="http://blog.morrisjohns.com/javascript_closures_for_dummies"&gt;closures for Javascript&lt;/a&gt;.  Ruby also obviously does this well.&lt;br /&gt;&lt;br /&gt;I selected Grails over &lt;a href="http://www.rubyonrails.org/"&gt;Ruby on Rails&lt;/a&gt; mostly due to the access I would have to the JVM combined with the Rails approach.   Also since I was wanting to contrast against a pure EE5 approach this made more sense.   By pure EE5 I mean an entity bean approach combined with JSF.  With the hiring of Nutter and Enebo by Sun Microsystems, &lt;a href="http://jruby.codehaus.org/"&gt;Jruby&lt;/a&gt; (another codehaus.org effort) could becoming an interesting option too since then "Ruby" will have access to the Java API's.  It has that access  now I believe, however I don't believe the Ruby and Rails aspect of Ruby is fully over to the JVM yet.   I do like the coding by convention vs. the XML configuration approach however.    I love XML, but think we have done too much with it in places where we could just use the coding language we have available.  I definately will be looking at &lt;a href="http://www.ruby-lang.org/en/"&gt;Ruby&lt;/a&gt; in general and the Ruby on Rails community more. &lt;br /&gt;&lt;br /&gt;A very interesting interview is given by &lt;a href="http://www.infoq.com/interviews/tim_bray_rails_and_more"&gt;Tim Bray on InfoQ&lt;/a&gt;.  It's a great listen for anyone interested in dynamic languages, RAILs concepts, ReST vs WS and some of the issues surrounding them.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-1902997302406603341?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/1902997302406603341/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=1902997302406603341' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/1902997302406603341'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/1902997302406603341'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2006/11/working-on-contrasting-ee5-and-grails.html' title='Working on contrasting EE5 and Grails (Rails)'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-3005095692506912139</id><published>2006-10-24T08:51:00.000-05:00</published><updated>2006-10-24T09:25:01.036-05:00</updated><title type='text'>AJAX and server side scripting</title><content type='html'>I ran across this page at the sun developer site.  It has a very nice run down of various AJAX design strategies. (Ref: &lt;a href="http://java.sun.com/developer/technicalArticles/J2EE/AJAX/DesignStrategies/?feed=JSC"&gt;http://java.sun.com/developer/technicalArticles/J2EE/AJAX/DesignStrategies/?feed=JSC&lt;/a&gt;).  This is a good read not just for Java developers but anyone.  The principles in it apply toward the development of any architecture in any language implementing AJAX.&lt;br /&gt;&lt;br /&gt;In reviewing this document I came across a project again that interested me and spent some time playing with it on our app server (&lt;a href="https://glassfish.dev.java.net/"&gt;glassfish&lt;/a&gt; this time).  This is the Phobos project (Ref: &lt;a href="https://phobos.dev.java.net/"&gt;https://phobos.dev.java.net/&lt;/a&gt;).    It basically allows for the use of javascript (and later other scripting languages like hopefully &lt;a href="http://groovy.codehaus.org/"&gt;Groovy)&lt;/a&gt; to be used on the server side.   JSP and JSF use tags to embed Java code into pages that are rendered server side.  Phobos extends this to javascript with the concept of "ejs" files which embed javascript into the page for server side rendering.   The benefits to an AJAX implementation of javascript on both side are obvious.    I do not know yet how well the server side javascript has access to the Java classes.   Future integration with &lt;a href="https://ajax.dev.java.net/"&gt;JMaki&lt;/a&gt; might also make future use of JMaki widgets in Phobos apps easy.   How might one instance this into a remote domain though?&lt;br /&gt;&lt;br /&gt;I am still curious if one could simply make a GET call to an app server that would render custom javascript in &lt;a href="http://ajaxian.com/archives/jsonp-json-with-padding"&gt;JSONP&lt;/a&gt; manner and return it to a script call of a page.   In truth couldn't this be a servlet.  A servlet responds to a GET call and can return just about anything.  So one would seem to be able to make a servlet that returns JSONP.  If the Phobos server could return JSON or JSONP as well as EJS rendered HTML that might open some interesting possibilities for remote access to widgets.   This may be worth some investigation and comparison to some of our early &lt;a href="http://code.google.com/webtoolkit/"&gt;GWT&lt;/a&gt; application experiments.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-3005095692506912139?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/3005095692506912139/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=3005095692506912139' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/3005095692506912139'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/3005095692506912139'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2006/10/ajax-and-server-side-scripting.html' title='AJAX and server side scripting'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-6671093873876840838</id><published>2006-10-15T08:00:00.000-05:00</published><updated>2006-10-15T09:04:59.097-05:00</updated><title type='text'>Why Portals Must Die</title><content type='html'>A few days back I read a couple articles on some efforts by Google.  These were an article on &lt;a href="http://news.com.com/Google+offers+mini+applications+to+other+sites/2100-1032_3-6122593.html"&gt;&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;Googles&lt;/span&gt; &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;Gadet&lt;/span&gt; effort &lt;/a&gt;and &lt;a href="http://www.thewhir.com//marketwatch/101206_Google_BEA_in_Mash-up_Talks.cfm"&gt;Google /BEA mash up talks&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;While interesting in their own right and likely the kind of thing being done by Yahoo, Microsoft and others it got me to thinking about a mantra I have had going for some time:&lt;br /&gt;&lt;br /&gt;Portals must DIE.&lt;br /&gt;&lt;br /&gt;This is not to say portals themselves in concept are bad things.  Only that they are often used or implemented poorly.  I oversee a &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;JSR&lt;/span&gt;-168 based portal myself and direct development of applications under that.   The intent of portals is obvious.  It provides a development group a unified display and authentication API set, among others, to work with.  This helps to focus development skill and look and feel issues.   A great thing compared to developing against a myriad of &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;API's&lt;/span&gt;.  Of course portal &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;API's&lt;/span&gt; themselves don't talk to each other so little was gained for efforts outside the local enterprise (or enterprise group).   In the Java camp the &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;JSR&lt;/span&gt;-168 helps to focus efforts around a common &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;portlet&lt;/span&gt; spec and that is great.  Web services for remote &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;portlets&lt;/span&gt; (&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;WSRP&lt;/span&gt;)  might have been a wonderful thing had I ever seen one example of it in the wild.&lt;br /&gt;&lt;br /&gt;It is just that portals don't allow for dynamic mixing of content from various sites into my own space.  I can't easily (yet) pull maps from Google, stock tickers from Yahoo, search interfaces from 3rd party databases  sites and simply drop them into my page and have them work with authentication and styles (&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;CSS&lt;/span&gt;) resident there.    I want to be able to do this, so portals must die.&lt;br /&gt;&lt;br /&gt;I believe that the common HTML DOM or a &lt;a href="http://www.w3.org/2004/CDF/"&gt;&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;CDF&lt;/span&gt;&lt;/a&gt; derived instance is the common glue (as I spoke about in my &lt;a href="http://douglasfils.blogspot.com/2006/10/cdf-google-gadgets-opendoc.html"&gt;&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;OpenDoc&lt;/span&gt; posting&lt;/a&gt;).  Combine this with remote AJAX applications that have some capacity for awareness of secure federated identity and we begin to see the a &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;portlet&lt;/span&gt; concept in this environment.  Secure "inter-AJAX &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_13"&gt;portlet&lt;/span&gt;" communication could be done via a messaging &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-corrected" id="SPELLING_ERROR_14"&gt;middle&lt;/span&gt;-ware though I want to explore what Javascript allows in terms of intercommunication between various functions in a web page to see if that is possible.  Look and feel issues could be addressed through systematic &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_15"&gt;CSS&lt;/span&gt; utilization.  In a manner similar to &lt;a href="http://code.google.com/webtoolkit/"&gt;&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_16"&gt;GWT&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;To me the future portal is a simple DOM with portable code that can be pulled across the net to create its &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_17"&gt;UI&lt;/span&gt; through local DOM object manipulation.  Combine this with federated identity and &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_18"&gt;CSS&lt;/span&gt; based styling for logging in and look and feel issues respectively.   Let the whole thing talk to a services oriented architecture for logic execution.  Hopefully the efforts of the &lt;a href="http://www.w3.org/2006/rwc/"&gt;W3C Rich Web Clients&lt;/a&gt; efforts will go well.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-6671093873876840838?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/6671093873876840838/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=6671093873876840838' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/6671093873876840838'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/6671093873876840838'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2006/10/why-portals-must-die.html' title='Why Portals Must Die'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-1567588995115726700</id><published>2006-10-15T07:54:00.000-05:00</published><updated>2006-10-15T08:21:39.666-05:00</updated><title type='text'>.NET 3.0 an attack on standards?</title><content type='html'>So I read my first article on .Net 3.0 this morning over at&lt;a href="http://www.informit.com/articles/article.asp?p=659520&amp;seqNum=1&amp;amp;rl=1"&gt; informit.com&lt;/a&gt;.  I then headed out to the Netfx3 site and did a little reading on the Communication, Presentation, Workflow and Cardspace foundation that are part of .Net 3.0.&lt;br /&gt;&lt;br /&gt;Microsoft has obviously turned their back on standards like Web services, SVG, efforts like SAML, WS-Federation and the Liberty Alliance.   I am sure they have done in this in the name of "user experience".  However, this will be user experience only on Microsoft Windows.&lt;br /&gt;&lt;br /&gt;Do I trust that things like WPF/E (the "Everywhere" cross platform version of WPF) will be coded to, made easy to code to, be used at all by many developers?  Of course not, Microsoft has no interest in doing that.    As a company they have fostered a culture based around ignoring standards and ignoring where the network is going.  Even as powerful as they are, I have no doubt they will fail, but they have the potential to cause huge amounts of damage to peoples data along the way.&lt;br /&gt;&lt;br /&gt;The core interconnecting standards of the net are under attack.  Microsoft will use its influence, FUD and any other tactics to encourage this.  Then they will wrap themselves in the flag of "competition is the cornerstone of capitalism" implying that they are the moral high ground holders.&lt;br /&gt;&lt;br /&gt;It is obvious that Vista and .NET 3.0 will bring the most concerted effort yet by Microsoft to undermine Internet standards and cross platform environments.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-1567588995115726700?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/1567588995115726700/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=1567588995115726700' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/1567588995115726700'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/1567588995115726700'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2006/10/net-30-attach-on-standards.html' title='.NET 3.0 an attack on standards?'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-7261962067805407206</id><published>2006-10-06T08:53:00.000-05:00</published><updated>2006-10-06T09:22:53.728-05:00</updated><title type='text'>CDF + Google gadgets = OpenDoc ?</title><content type='html'>So recently Google was noted for putting out "gadgets" that could be syndicated across the network (ref: &lt;a href="http://news.com.com/Googles+Universal+Gadgets+woos+developers/2100-1032_3-6122593.html"&gt;Cnet&lt;/a&gt;  ).  The direct link to this being at: &lt;a href="http://www.google.com/ig/directory?synd=open/"&gt;http://www.google.com/ig/directory?synd=open/.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This is basically javascript that you can instance in your own web page.  There is nothing spectacular about this.  However, Google has done a nice job of making it easy (easier) to do this.  I am a big supporter of this syndication concept even though there are likely several issues still with this idea especially around security. (&lt;a href="http://weblogs.java.net/blog/gmurray71/archive/2006/08/restricting_acc.html"&gt;One Ref at Greg Murrays Blog&lt;/a&gt;) &lt;br /&gt;&lt;br /&gt;Now combine this with something like the &lt;a href="http://www.w3.org/2004/CDF/"&gt;W3C CDF efforts&lt;/a&gt;.  CDF allows a developer to place multiple XML formats into a common document. &lt;br /&gt;&lt;br /&gt;The collision of all this reminds me of something from Apple from way back.  Those that know me know I still haven't gotten over &lt;a href="http://en.wikipedia.org/wiki/Opendoc"&gt;OpenDoc.&lt;/a&gt; systems could begin to   However, CDF + remote web apps like AJAX Esqdevelop the kind of application that currently is still restricted to the true rich client applications.  I don't know where web based applications will stop in terms of being reasonable approaches.  Email, RSS aggregation, content management and many other types of communication based efforts have done very well on the browser platform.    Lately word processing, spreadsheets and other attempts have started to crop up.  I doubt we will see an AJAX based GIMP (or ever want one).    For the most part, if I am working on data or creating data local like in a GIMP image there is no need to send that over a network.  However, Writely has shown that even word processing can benefit from network aware ability, in its case in the form of real time collaborative editing of documents.  (&lt;a href="http://en.wikipedia.org/wiki/Knowledge_Navigator"&gt;Apple Knowledge Navigator&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;Imagine though a document with a SVG canvas being written to by an embedded ajax application communicating over XmlHttpProxy and then locally updating the SVG canvas through inter DOM communication.  How about an OpenGL canvas?  (Java 3d and applets is perhaps a bit of a digression for this posting, but not much). &lt;br /&gt;&lt;br /&gt;I am encouraged and interested by where an open format, open standards based approach will go that mixes interactive applications with the DOM and graphics languages like SVG and perhaps even OpenGL.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-7261962067805407206?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/7261962067805407206/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=7261962067805407206' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/7261962067805407206'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/7261962067805407206'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2006/10/cdf-google-gadgets-opendoc.html' title='CDF + Google gadgets = OpenDoc ?'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-5167854438327394286</id><published>2006-09-26T10:59:00.000-05:00</published><updated>2006-09-26T11:11:59.017-05:00</updated><title type='text'>It's about the data</title><content type='html'>I have been trying to figure out what would make me happy.  I don't like the net as it is today, it feels to ethereal.  Like anything I make, a blog post, a OPML file anything is just going to end up like some old 9 track tape I find some day and can't read or use.&lt;br /&gt;&lt;br /&gt;Yea, I could download this stuff and store it somewhere (I do) but must I?  Should I?  I find that while I have my dug articles from Digg, how many of these links will be there in a year?  I'd rather just cut and past them into a personal store.  Like the &lt;a href="http://amb.vis.ne.jp/mozilla/scrapbook/index.php?lang=en"&gt;scrapbook firefox extension&lt;/a&gt; which I love.&lt;br /&gt;&lt;br /&gt;I some ways I would like to see it combined with something like the &lt;a href="http://simile.mit.edu/piggy-bank/"&gt;Simile Piggy / Semantic bank&lt;/a&gt; efforts.  Perhaps those are what I like and I am just not using them enough yet.  At least they are using standards I philosophically agree with like RDF and XHTML and such.&lt;br /&gt;&lt;br /&gt;Lately I have been listening about &lt;a href="http://www.jini.org/wiki/Main_Page"&gt;Jini&lt;/a&gt; on the &lt;a href="http://javaposse.com/"&gt;Javapossee&lt;/a&gt; podcasts and been wondering about how it could be used in data grids vs. the compute grids it seems focused on now.&lt;br /&gt;&lt;br /&gt;Now if I could just figure out a portal/dashboard approach I like I would be set.  Wonder if KDE's plasma effort will have an easily extensible UI apsect to it ala kramaba (sp) that will make it the wonder desktop.  I like the concept of the containers I see so far in it.  What I need is a tag based files systems (who needs folders?) and a tagged based UI to go with it.  :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-5167854438327394286?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/5167854438327394286/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=5167854438327394286' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/5167854438327394286'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/5167854438327394286'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2006/09/its-about-data.html' title='It&apos;s about the data'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-1371394934523228580</id><published>2006-09-21T11:11:00.000-05:00</published><updated>2006-09-21T11:21:29.876-05:00</updated><title type='text'>Firefox Application Framework</title><content type='html'>For some time I have watched the XUL effort at Mozilla.  It is interesting as more and more people talk about the creation of "rich apps" (network centric apps.. whatever) to watch various approaches rise to the top.  The strong efforts by the eclipse and netbeans camps to form their solutions about their respective architectures is great.  There is also the efforts by M$ and their XAML goals eventually.  I don't really think XAML is all that "Internet" when you have to run it on a windows machine though.&lt;br /&gt;&lt;br /&gt;However, I have been interested to see that XUL, which I felt was only going to be a solution for Mozilla's own apps like firefox, thunderbird and sunbird, gain some traction in the community.  The Songbird (&lt;a href="http://www.songbird.org"&gt;http://www.songbird.org&lt;/a&gt;) effort is likely the one with the highest visibility, but Democracy TV (&lt;a href="http://www.getdemocracy.com/"&gt;http://www.getdemocracy.com/&lt;/a&gt;) is also popular.   I recently saw on a on-line episide of Command N where they talked about Cletx (&lt;a href="http://www.celtx.com"&gt;http://www.celtx.com&lt;/a&gt;) which I guess is also based on XUL.  They say it's a firefox app, but I assume the meant XUL. &lt;br /&gt;&lt;br /&gt;It would be nice if we had a true XML UI language (yes, perhaps XML is a bad method to represent UI's ... that is another topic) that was a standard.  Not that M$ would bother to support it but XUL can't claim to be a standard yet for anything but Mozilla apps. &lt;br /&gt;&lt;br /&gt;There are tons of XML UI languages for the Java VM true, but I am not sure they leverage well of the developer community till they get some kinda of buy in from Sun itself.   Perhaps with AJAX there is no need.  Javascript + DOM + XHTML and go from there, but you loose some of the spiffyness of a true UI (widgets and all).  I haven't seen SVG care much for doing it and I refuse to go the flash route. &lt;br /&gt;&lt;br /&gt;So I don't know..  if you want to make a true Internet application I guess there is not set of standards to work with other than AJAX approaches.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-1371394934523228580?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/1371394934523228580/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=1371394934523228580' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/1371394934523228580'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/1371394934523228580'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2006/09/firefox-application-framework.html' title='Firefox Application Framework'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-8352208829891639132</id><published>2006-09-19T11:57:00.000-05:00</published><updated>2006-09-19T12:09:53.784-05:00</updated><title type='text'>Web 2.0 semita (footprint)</title><content type='html'>So I am trying to figure out what my "Web 2.0" footprint looks like and how this compares to my personal computer footprint.  The core elements of my web  footprint are: (beyond this blog):&lt;br /&gt;Del.icio.us (&lt;a href="http://del.icio.us/fils"&gt;http://del.icio.us/fils&lt;/a&gt;), Odeo (&lt;a href="http://odeo.com/profile/Fils"&gt;http://odeo.com/profile/Fils&lt;/a&gt;), Tag cloud and Blog lines (don't much care for Blog lines for RSS reading)&lt;br /&gt;&lt;br /&gt;I have found I don't care for any on-line RSS tools.  Prefering instead my Liferea on Linux, though obviously it is my OPML file that is the most important to me.&lt;br /&gt;&lt;br /&gt;For news I see I use: Slashdot, Digg, Newsvine, Last.fm for music and Boxxet (the later more interesting in concept than useful in execution) .  For all I have accounts and I should resolve out the URL's for them and get them posted here. &lt;br /&gt;&lt;br /&gt;I find tools like Writely and box.net to be rather nice and I have started to use them some.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-8352208829891639132?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/8352208829891639132/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=8352208829891639132' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/8352208829891639132'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/8352208829891639132'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2006/09/web-20-semita-footprint.html' title='Web 2.0 semita (footprint)'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651912408580529938.post-5572584032267266145</id><published>2006-09-01T11:49:00.000-05:00</published><updated>2006-09-01T11:50:49.374-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='root'/><title type='text'>Why do this</title><content type='html'>So I am not sure why I just did this.  I am not really much of a blogger (at least I don't think I am).  However, I have started to try and figure out what it is about web 2.0 that bugs me...  so I have to do it to resolve why.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651912408580529938-5572584032267266145?l=douglasfils.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglasfils.blogspot.com/feeds/5572584032267266145/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651912408580529938&amp;postID=5572584032267266145' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/5572584032267266145'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651912408580529938/posts/default/5572584032267266145'/><link rel='alternate' type='text/html' href='http://douglasfils.blogspot.com/2006/09/why-do-this.html' title='Why do this'/><author><name>fils</name><uri>http://www.blogger.com/profile/04578829160811273052</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://1.bp.blogspot.com/_f5taJtU-20M/TGMO3P9Pq1I/AAAAAAAAGEQ/qr6gQUI4Bx8/S220/filssmallsquare.png'/></author><thr:total>1</thr:total></entry></feed>
