<?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-3675576906879941038</id><updated>2012-01-06T01:47:26.869-08:00</updated><category term='groovy grails exception'/><category term='grails taglib ajax'/><category term='grails'/><category term='amazon aws virtualhosts https ec2 elb'/><category term='ubuntu'/><category term='maven java'/><category term='https ssl apache virtualhosts aws'/><category term='git'/><category term='dns'/><category term='groovy'/><category term='java mail grails mail plugin'/><title type='text'>Programming 34m0</title><subtitle type='html'>In my daily life as a programmer I come across problems. This blog, is where I record them (and more importantly their solutions) so that I can dig them out in the future. I hope it might save others some problem solving time too.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://programming34m0.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://programming34m0.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Eamonn O'Connell</name><uri>http://www.blogger.com/profile/17064544953690759392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://2.bp.blogspot.com/_vC3SkHYsTQs/TBHf_uhM1_I/AAAAAAAAAn4/YLzceffi1_c/S220/profilePic.JPG'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>34</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3675576906879941038.post-3963840568040666164</id><published>2011-12-07T06:28:00.001-08:00</published><updated>2012-01-06T01:47:26.886-08:00</updated><title type='text'>Installing and configuring Cband for Apache2 on Ubuntu</title><content type='html'>If you need to manage bandwidth usage on Apache web server (particularly on a per virtualhost basis) CBand could be that hero you were hoping for. Below are the steps I followed to get up and running with a basic CBand setup. &lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-oyqAB0ouaKA/Tt-RBzn_HwI/AAAAAAAABQo/JFLCO7FwUvY/s1600/Screen%2BShot%2B2011-12-07%2Bat%2B17.14.20.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 129px;" src="http://4.bp.blogspot.com/-oyqAB0ouaKA/Tt-RBzn_HwI/AAAAAAAABQo/JFLCO7FwUvY/s320/Screen%2BShot%2B2011-12-07%2Bat%2B17.14.20.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5683420714988674818" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Installation&lt;/h4&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;Install additional apache libraries. Only one of these two maybe required. &lt;br /&gt;         &lt;i&gt;apt-get install apache2-prefork-dev&lt;/i&gt;&lt;br /&gt;         &lt;i&gt;apt-get install apache2-threaded-dev&lt;/i&gt;&lt;br /&gt;  &lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Download the module&lt;br /&gt;        &lt;i&gt;wget http://dembol.org/downloads/cband/mod-cband-0.9.7.5.tgz&lt;/i&gt;&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Untar the file&lt;br /&gt;         &lt;i&gt;tar -xzf mod-cband-0.9.7.5.tgz&lt;/i&gt;&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Enter newly created directory&lt;br /&gt;         &lt;i&gt;cd mod-cband-0.9.7.5&lt;/i&gt;&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Add -lm to the APXS OPTS in Makefile.in like so: &lt;br /&gt;         &lt;i&gt;APXS_OPTS=-lm -Wc,-Wall -Wc,-DDST_CLASS=@DST_CLASS@&lt;/i&gt;&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Configure and install&lt;br /&gt;         &lt;i&gt;./configure&lt;/i&gt;&lt;br /&gt;         &lt;i&gt;make&lt;/i&gt;&lt;br /&gt;         &lt;i&gt;make install&lt;/i&gt;&lt;br /&gt;  &lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Restart Apache&lt;br /&gt;         &lt;i&gt;/etc/apache2/restart&lt;/i&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Hopefully you should now have successfully installed Cband on your Ubuntu server. &lt;br /&gt;Now let's configure it. &lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Configuration&lt;/h4&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;In order to improve performance of Cband, add the following to &lt;i&gt;/etc/apache2/mods-available/cband.conf&lt;/i&gt;&lt;br /&gt;   &lt;i&gt;CBandScoreFlushPeriod 1&lt;br /&gt;         CBandRandomPulse On&lt;/i&gt;&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Add sym link in mods-enabled folder&lt;br /&gt;        &lt;i&gt;ln -s ../mods-available/cband.conf cband.conf&lt;/i&gt;&lt;br /&gt;  &lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Make directory to store the accumulated data&lt;br /&gt;         &lt;i&gt;mkdir /var/www/scoreboard&lt;/i&gt;&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Change ownership of directory to the apache user&lt;br /&gt;        &lt;i&gt;chown www-data:www-data /var/www/scoreboard/&lt;/i&gt;&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Configure access to cband-status. Cband provides a status page, which you must activate via the apache configuration. It is likely you should restrict access to this page by some means. For unrestricted access to this page add the following to cband.conf&lt;br /&gt;         &lt;i&gt;&amp;lt;Location /cband-status&amp;gt;&lt;br /&gt;               SetHandler cband-status&lt;br /&gt;               &amp;lt;/Location&amp;gt;&lt;br /&gt;              &amp;lt;Location /cband-status-me&amp;gt;&lt;br /&gt;               SetHandler cband-status-me&lt;br /&gt;               &amp;lt;/Location&amp;gt;&lt;br /&gt;         &lt;/i&gt;&lt;/li&gt;&lt;br /&gt; &lt;li&gt;In your browser, navigate to http://server/cband-status and observe your new cband status page&lt;/li&gt;&lt;br /&gt; &lt;li&gt;Now add cband configuration for one or more virtual hosts, restart apache, and refresh your cband status page&lt;br /&gt;       &lt;i&gt;&amp;lt;IfModule mod_cband.c&amp;gt;&lt;br /&gt;             CBandLimit 6G&lt;br /&gt;             CBandPeriod 4W &lt;br /&gt;             CBandPeriodSlice 1W&lt;br /&gt;             CBandSpeed 500kbps 10 30&lt;br /&gt;             CBandExceededSpeed 128kbps 5 15&lt;br /&gt;             CBandScoreboard /var/www/scoreboard/domain.com.scoreboard&lt;br /&gt;             &amp;lt;/IfModule&amp;gt;&lt;/i&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;If you would like to do something more with all the data Cband is collecting you can retrieve an XML representation by using a url of the form:&lt;br /&gt;       http://server/cband-status?xml&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Security&lt;/h4&gt;&lt;br /&gt;You don't want to let just anyone find intimate details about a site your hosting. You need to password-protect that data!&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;One of the simplest ways to password-protect is using the http auth module of apache. To get started on this path, reopen the file &lt;i&gt;/etc/apache2/mods-available/cband.conf&lt;/i&gt;&lt;br /&gt;  &lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Add the following lines to both of your Location elements replacing knownSystemUser appropriately:&lt;br /&gt;        AuthType Basic&lt;br /&gt;        AuthName "Restricted"&lt;br /&gt;        AuthUserFile /usr/local/apache/passwd/passwords&lt;br /&gt;        Require user knownSystemUser&lt;br /&gt;  &lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Now create a password for the specified user in the specified file&lt;br /&gt;         &lt;i&gt;mkdir -p /usr/local/apache/passwd/passwords&lt;/i&gt;&lt;br /&gt;         &lt;i&gt;htpasswd -c /usr/local/apache/passwd/passwords knownSystemUser&lt;/i&gt;&lt;br /&gt;  &lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Credits&lt;/h4&gt;&lt;br /&gt;&lt;a href="http://blog.lael.be/290"&gt;http://blog.lael.be/290&lt;/a&gt;&lt;br /&gt;&lt;a href="http://dembol.org/mod_cband"&gt;http://dembol.org/mod_cband&lt;/a&gt;&lt;br /&gt;&lt;a href="http://pessetto.com/question2answer/index.php?qa=3&amp;qa_1=why-does-mod_cband-have-a-truncf-symbol-undefined"&gt;http://pessetto.com/question2answer/index.php?qa=3&amp;qa_1=why-does-mod_cband-have-a-truncf-symbol-undefined&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.howtoforge.com/mod_cband_apache2_bandwidth_quota_throttling"&gt;http://www.howtoforge.com/mod_cband_apache2_bandwidth_quota_throttling&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.uno-code.com/?q=node/64"&gt;http://www.uno-code.com/?q=node/64&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.sourcefiles.org/Internet/WebServers/Modules/Bandwidth/mod-cband-0.9.7.2.tgz.shtml"&gt;http://www.sourcefiles.org/Internet/WebServers/Modules/Bandwidth/mod-cband-0.9.7.2.tgz.shtml&lt;/a&gt;&lt;br /&gt;&lt;a href="http://httpd.apache.org/docs/2.0/howto/auth.html"&gt;http://httpd.apache.org/docs/2.0/howto/auth.html&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3675576906879941038-3963840568040666164?l=programming34m0.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programming34m0.blogspot.com/feeds/3963840568040666164/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://programming34m0.blogspot.com/2011/12/installing-and-configuring-cband-for.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/3963840568040666164'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/3963840568040666164'/><link rel='alternate' type='text/html' href='http://programming34m0.blogspot.com/2011/12/installing-and-configuring-cband-for.html' title='Installing and configuring Cband for Apache2 on Ubuntu'/><author><name>Eamonn O'Connell</name><uri>http://www.blogger.com/profile/17064544953690759392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://2.bp.blogspot.com/_vC3SkHYsTQs/TBHf_uhM1_I/AAAAAAAAAn4/YLzceffi1_c/S220/profilePic.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-oyqAB0ouaKA/Tt-RBzn_HwI/AAAAAAAABQo/JFLCO7FwUvY/s72-c/Screen%2BShot%2B2011-12-07%2Bat%2B17.14.20.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3675576906879941038.post-1130370925610128407</id><published>2011-12-05T07:17:00.001-08:00</published><updated>2011-12-05T07:49:44.294-08:00</updated><title type='text'>Groovy safe navigation gotcha</title><content type='html'>I just came across this Groovy gotcha today while accessing a list within a chain of attributes. I had a statement like this in a gsp:&lt;br /&gt;&lt;pre&gt;${invoice?.invoiceItems[0]?.name}&lt;/pre&gt;&lt;br /&gt;This is the (erroneous) &lt;a href="http://grails.org/doc/latest/guide/6.%20The%20Web%20Layer.html#6.1.6 Data Binding"&gt;recommended style when data binding many ended associations in Grails&lt;/a&gt;, but it could easily arise in other scenarios. If I try this "safe" statement where &lt;i&gt;invoiceItems&lt;/i&gt; is null, I'll see a null pointer exception. In fact I'll even see it when &lt;i&gt;invoice&lt;/i&gt; is null. The reason for the exception is a combination of how lists and the safe navigation work in Groovy.&lt;br /&gt;&lt;br /&gt;Lists are much more elegant in Groovy than Java, as they share the square brackets that primitive arrays use. Creating a list is as easy as writing:&lt;br /&gt;&lt;pre&gt;def x = [1,2,3]&lt;/pre&gt;&lt;br /&gt;Just like an array you can access the first element of this list like so:&lt;br /&gt;&lt;pre&gt;println x[0]&lt;/pre&gt;&lt;br /&gt;However, unlike a primitive array the [] operator on a list is mapped (by some Groovy magic) behind the scenes to the getAt method of the particular List object. We can expand our example as follows:&lt;br /&gt;&lt;pre&gt;${invoice?.invoiceItems.getAt(0).name}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Safe navigation is a beautiful, and elegant means of protecting your code for scenarios where a variable could be null. It doesn't work as you might expect though. In my example above if invoice is null you might expect that after discovering invoice to be null execution would move to the next statement. Instead what happens is that each part of the chain is executed in turn, and the ? is equivalent to a try/catch block, where if a null pointer exception is caught, the exception will be swallowed, and null returned.&lt;br /&gt;&lt;br /&gt;The end result of these two Groovy behaviors is that in my example (and indeed the examples in the grails documentation) we will see the attempted execution of &lt;pre&gt;null.getAt(0)&lt;/pre&gt;The solution is to avoid using the [] operator when accessing lists and to place a ? before every full stop in your statement chain. &lt;pre&gt;${invoice?.invoiceItems?.getAt(0)?.name}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Credits&lt;/h4&gt;&lt;br /&gt;&lt;a href="http://grails.org/doc/latest/guide/6.%20The%20Web%20Layer.html#6.1.6 Data Binding"&gt;http://grails.org/doc/latest/guide/6.%20The%20Web%20Layer.html#6.1.6 Data Binding&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3675576906879941038-1130370925610128407?l=programming34m0.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programming34m0.blogspot.com/feeds/1130370925610128407/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://programming34m0.blogspot.com/2011/12/groovy-safe-navigation-gotcha.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/1130370925610128407'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/1130370925610128407'/><link rel='alternate' type='text/html' href='http://programming34m0.blogspot.com/2011/12/groovy-safe-navigation-gotcha.html' title='Groovy safe navigation gotcha'/><author><name>Eamonn O'Connell</name><uri>http://www.blogger.com/profile/17064544953690759392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://2.bp.blogspot.com/_vC3SkHYsTQs/TBHf_uhM1_I/AAAAAAAAAn4/YLzceffi1_c/S220/profilePic.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3675576906879941038.post-270599259893649167</id><published>2011-11-02T01:38:00.000-07:00</published><updated>2011-11-02T01:55:08.479-07:00</updated><title type='text'>Mass find and replace on Mac OSX with SED</title><content type='html'>Lets say you are doing some grand refactoring, and you want to change a class name from Dog to Pooch in multiple files. &lt;br /&gt;There are a couple of ways you can do it with the &lt;b&gt;sed&lt;/b&gt; command. One uses the &lt;i&gt;-exec&lt;/i&gt; argument and the other uses the xargs program. Though I'm not sure why, I favor the xargs strategy. In Linux to do a mass find and replace for our Dog to Pooch example you could do something like:&lt;br /&gt;&lt;i&gt;&lt;b&gt;find . -name "*.php" -print | xargs sed -i 's/Dog/Pooch/g'&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;But if you try this same command In Mac OSX you will see an error like this: &lt;br /&gt;&lt;i&gt;&lt;b&gt; extra characters at the end of g command &lt;/b&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;The reason for this is the command in Mac OSX the command doesn't trust you. I wonder if &lt;i&gt;rm -rf /&lt;/i&gt; works in Mac OSX? Well I'm not going to find out ;-) Mac OSX will create a backup file in case you mess up your find and replace, and it requires an extension for this file. With that in mind, the following command will work in Mac OSx:&lt;br /&gt;&lt;i&gt;&lt;b&gt;find . -name "*.php" -print | xargs sed -i.bak 's/Dog/Pooch/g'&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;I recommend you choose a unique backup extension so that you can easily delete all the backup files. Once your happy with your change of course you can run something like: &lt;i&gt;&lt;b&gt;find . -name '*.bak' | xargs rm &lt;/b&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Credits&lt;/h4&gt;&lt;br /&gt;&lt;a href="http://rushi.wordpress.com/2008/08/05/find-replace-across-multiple-files-in-linux/"&gt;http://rushi.wordpress.com/2008/08/05/find-replace-across-multiple-files-in-linux/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.unix.com/emergency-unix-linux-support-help-me/137864-sed-mac-os-versus-linux.html"&gt;http://www.unix.com/emergency-unix-linux-support-help-me/137864-sed-mac-os-versus-linux.html&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3675576906879941038-270599259893649167?l=programming34m0.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programming34m0.blogspot.com/feeds/270599259893649167/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://programming34m0.blogspot.com/2011/11/mass-find-and-replace-on-mac-osx-with.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/270599259893649167'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/270599259893649167'/><link rel='alternate' type='text/html' href='http://programming34m0.blogspot.com/2011/11/mass-find-and-replace-on-mac-osx-with.html' title='Mass find and replace on Mac OSX with SED'/><author><name>Eamonn O'Connell</name><uri>http://www.blogger.com/profile/17064544953690759392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://2.bp.blogspot.com/_vC3SkHYsTQs/TBHf_uhM1_I/AAAAAAAAAn4/YLzceffi1_c/S220/profilePic.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3675576906879941038.post-6214329006565569976</id><published>2011-11-01T07:51:00.001-07:00</published><updated>2011-11-01T08:08:33.323-07:00</updated><title type='text'>Debugging dependencies in Grails</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-1JuZuSz3k6M/TrAKIAPwwMI/AAAAAAAABNE/oOy0HLprq_I/s1600/Screen%2Bshot%2B2011-11-01%2Bat%2B16.02.01.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 207px;" src="http://3.bp.blogspot.com/-1JuZuSz3k6M/TrAKIAPwwMI/AAAAAAAABNE/oOy0HLprq_I/s320/Screen%2Bshot%2B2011-11-01%2Bat%2B16.02.01.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5670043063480795330" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;In Grails, and indeed large Java projects generally, dependency resolution can become quite a headache. Tools like Maven and Ivy are a huge help of course, but even they can't prevent tedious days trying to fix that conflict where two classes of the same name are loaded by the same class loader. Grails provides a feature that helps navigate through the complex web of depencies that your web application will no doubt accrue. &lt;br /&gt;&lt;br /&gt;Issue the command: &lt;i&gt;&lt;b&gt;grails dependency-report&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;or if your using the maven-grails plugin: &lt;i&gt;&lt;b&gt;mvn grails:exec -Dcommand="dependency-report"&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;This will generate a number of reports in the /target/dependency-reports folder for you. The html reports can of course be opened in the browser of your choice. The graph reports (in graphml format) however need a special and - to me at least - uncommon tool. The tool that seems most popular is &lt;a href="http://www.yworks.com/en/products_yed_about.html"&gt;yEd&lt;/a&gt;. Fortunately yEd is available for Linux, Mac, and Windows.&lt;br /&gt;&lt;br /&gt;After you have download and installed yEd, open one of the generated graphml files. The graph won't look like much to start, but after you tweak the view it becomes a very useful resource of information. The Ivy site provides a &lt;a href="http://ant.apache.org/ivy/history/latest-milestone/yed.html"&gt;quick how-to on how to make the graph digestible&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Credits&lt;/h4&gt;&lt;br /&gt;&lt;a href="http://burtbeckwith.com/blog/?p=624"&gt;http://burtbeckwith.com/blog/?p=624&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3675576906879941038-6214329006565569976?l=programming34m0.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programming34m0.blogspot.com/feeds/6214329006565569976/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://programming34m0.blogspot.com/2011/11/debugging-dependencies-in-grails.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/6214329006565569976'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/6214329006565569976'/><link rel='alternate' type='text/html' href='http://programming34m0.blogspot.com/2011/11/debugging-dependencies-in-grails.html' title='Debugging dependencies in Grails'/><author><name>Eamonn O'Connell</name><uri>http://www.blogger.com/profile/17064544953690759392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://2.bp.blogspot.com/_vC3SkHYsTQs/TBHf_uhM1_I/AAAAAAAAAn4/YLzceffi1_c/S220/profilePic.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-1JuZuSz3k6M/TrAKIAPwwMI/AAAAAAAABNE/oOy0HLprq_I/s72-c/Screen%2Bshot%2B2011-11-01%2Bat%2B16.02.01.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3675576906879941038.post-5976391410633765192</id><published>2011-10-22T07:55:00.000-07:00</published><updated>2011-10-30T01:32:13.832-07:00</updated><title type='text'>Groovy XML Parser Gotcha - it's not a Map your parsing!</title><content type='html'>When I first looked at examples of using &lt;a href="http://groovy.codehaus.org/api/groovy/util/XmlParser.html"&gt;the Groovy XmlParser&lt;/a&gt; it appeared that the parser took some nice raw XML and turned it into a map for easy traversing. I could take the following source:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;person&amp;gt;&lt;br /&gt;    &amp;lt;face&amp;gt;&lt;br /&gt;         &amp;lt;eyes&amp;gt;&lt;br /&gt;             blue&lt;br /&gt;         &amp;lt;/eyes&amp;gt;&lt;br /&gt;    &amp;lt;/face&amp;gt;&lt;br /&gt;&amp;lt/person&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And parse it find the eye color like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; def xml = new XmlParser().parseText(xmlSrc)&lt;br /&gt; assert xml.person.face.eyes.text() == 'blue'&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Confident in my understanding, I thought it would be trivial to handle the following XML source I was receiving from a domain registrar:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?xml version="1.0"?&amp;gt;&lt;br /&gt;&amp;lt;interface-response&amp;gt;                       &lt;br /&gt;     &amp;lt;ErrCount&amp;gt; 1&amp;lt;/ErrCount &amp;gt;&lt;br /&gt;     &amp;lt;errors&amp;gt;&lt;br /&gt;         &amp;ly;Err1&amp;gt; Do main name not available &amp;lt;/Err1&amp;gt;&lt;br /&gt;      &amp;lt;/errors&amp;gt;                        &lt;br /&gt;&amp;lt;/interface-response&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I parsed the source in order to extract the errors from the response as follows:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    def xml = new XmlParser().parseText(xmlSrc)&lt;br /&gt;    def errMsg = "Errors:"&lt;br /&gt;    xml.errors.each { err -&gt;&lt;br /&gt;        errMsg += "\n ${err.text()}"&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This made perfect sense to me,  but I wasn't getting the expected output in my error message. The problem was my "understanding". I had not grasped just what the &lt;br /&gt;"xml.person.face.eyes" groovy magic was actually being done behind the scenes. If the parser had created a Map representation of my xml, my logic would have been right, but it wasn't. While being able to write &lt;i&gt;xml.errors&lt;/i&gt; or &lt;i&gt;xml.person.face.eyes&lt;/i&gt; might give the impression you can bring the ubiquitous map paradigm here it is a "Faux Amis" (a false friend as we say here in France). The associative dot notation is actually translated into XPath, and then this XPath query is run against your XML. So while sometimes the XPath can be equivalent to retrieving data from a Map often times it is not. Now here is code that follows the XPath paradigm (and it works!):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    def xml = new XmlParser().parseText(xmlSrc)&lt;br /&gt;    def errMsg = "Errors:"&lt;br /&gt;    xml.errors.'*'.each { err -&gt;&lt;br /&gt;        errMsg += "\n ${err.text()}"&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3675576906879941038-5976391410633765192?l=programming34m0.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programming34m0.blogspot.com/feeds/5976391410633765192/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://programming34m0.blogspot.com/2011/10/groovy-xml-parser-its-not-map-your.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/5976391410633765192'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/5976391410633765192'/><link rel='alternate' type='text/html' href='http://programming34m0.blogspot.com/2011/10/groovy-xml-parser-its-not-map-your.html' title='Groovy XML Parser Gotcha - it&apos;s not a Map your parsing!'/><author><name>Eamonn O'Connell</name><uri>http://www.blogger.com/profile/17064544953690759392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://2.bp.blogspot.com/_vC3SkHYsTQs/TBHf_uhM1_I/AAAAAAAAAn4/YLzceffi1_c/S220/profilePic.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3675576906879941038.post-5042525753939023045</id><published>2011-09-28T23:50:00.000-07:00</published><updated>2011-09-29T00:40:12.186-07:00</updated><title type='text'>Configuring Logging of Bind DNS in Ubuntu</title><content type='html'>After installing the Bind9 DNS server in Ubuntu, you might find the need to play with the logging settings. Logging is essential when your trying to figure out why the hell DNS setup is not working as expected. Without any explicit logging configuration (from you or your colleagues) Bind will log messages of the category "default" to "/var/log/syslog". In order to customize the configuration to your own needs try the following steps.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Step 1: Create a new file to write your logs to&lt;/b&gt;&lt;br /&gt;The location of this file is up to you, but due to AppArmor restrictions in Ubuntu the easiest strategy is to place it in "/var/log/named". If you need to place it somewhere else you might need to alter your AppArmor configuration.&lt;br /&gt;&lt;pre&gt;mkdir /var/log/named&lt;br /&gt;touch /var/log/named/debug.log&lt;br /&gt;touch /var/log/named/query.log&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;Step 2: Define the configuration&lt;/b&gt;&lt;br /&gt;You can place your logging configuration in either "/etc/bind/named.conf" or "/etc/bind/named.conf.local". If there is a best practice on where to place it I couldn't find it - do let me know if you have any insights! Which ever file you choose, the content to add would be something like the following:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;logging {&lt;br /&gt;&lt;br /&gt;    channel debug_log {&lt;br /&gt;         file "/var/log/named/debug.log";&lt;br /&gt;        severity debug 3;&lt;br /&gt;        print-category yes;&lt;br /&gt;        print-severity yes;&lt;br /&gt;        print-time yes;&lt;br /&gt;    };&lt;br /&gt;&lt;br /&gt;    channel query_log {&lt;br /&gt;        file "/var/log/named/query.log";&lt;br /&gt;        severity dynamic;&lt;br /&gt;        print-category yes;&lt;br /&gt;        print-severity yes;&lt;br /&gt;        print-time yes;&lt;br /&gt;    };&lt;br /&gt;&lt;br /&gt;    category resolver { debug_log; };&lt;br /&gt;    category security { debug_log; }; &lt;br /&gt;    category queries { query_log; };&lt;br /&gt;   &lt;br /&gt;};&lt;/pre&gt;&lt;br /&gt;The severity option is the logging level. The possible levels are critical, error, warning, notice, info, debug [ level ] , and dynamic. In the example above you can see I'm using both debug and dynamic. Note that debug is subdivided into levels 1, 2, and 3. &lt;br /&gt;&lt;br /&gt;Logs in Bind are divided into categories. In our example we are printing logs from from 3 of the categories. For a complete list of the categories available see  &lt;a href="http://www.bind9.net/manual/bind/9.3.2/Bv9ARM.ch06.html#id2553006"&gt;the Bind reference &lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Logs are output to channels. In our example we have two channels, each corresponding to a file. Note from the example how it is possible to send the logs of multiple categories to the one channel.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Step:3 Restart Bind&lt;/b&gt;&lt;br /&gt;Don't forget to restart Bind for your changes to take effect.&lt;br /&gt;&lt;pre&gt;sudo /etc/init.d/bind9 restart&lt;/pre&gt;&lt;br /&gt;&lt;h4&gt;Credits:&lt;/h4&gt;&lt;br /&gt;&lt;a href="https://help.ubuntu.com/community/BIND9ServerHowto"&gt;https://help.ubuntu.com/community/BIND9ServerHowto&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.bind9.net/manual/bind/9.3.2/Bv9ARM.ch06.html#id2552867"&gt;http://www.bind9.net/manual/bind/9.3.2/Bv9ARM.ch06.html#id2552867&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3675576906879941038-5042525753939023045?l=programming34m0.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programming34m0.blogspot.com/feeds/5042525753939023045/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://programming34m0.blogspot.com/2011/09/configuring-logging-of-bind-dns-in.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/5042525753939023045'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/5042525753939023045'/><link rel='alternate' type='text/html' href='http://programming34m0.blogspot.com/2011/09/configuring-logging-of-bind-dns-in.html' title='Configuring Logging of Bind DNS in Ubuntu'/><author><name>Eamonn O'Connell</name><uri>http://www.blogger.com/profile/17064544953690759392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://2.bp.blogspot.com/_vC3SkHYsTQs/TBHf_uhM1_I/AAAAAAAAAn4/YLzceffi1_c/S220/profilePic.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3675576906879941038.post-4004590353166467986</id><published>2011-05-18T05:07:00.000-07:00</published><updated>2011-05-19T04:33:57.689-07:00</updated><title type='text'>A Custom Dialog Box in JQuery Tutorial</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-gKO1d-sJQLM/TdPANRRYJfI/AAAAAAAAArU/43QMr-woDUw/s1600/jquery_ui_dialog_box.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 152px;" src="http://3.bp.blogspot.com/-gKO1d-sJQLM/TdPANRRYJfI/AAAAAAAAArU/43QMr-woDUw/s320/jquery_ui_dialog_box.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5608037295213520370" /&gt;&lt;/a&gt;&lt;br /&gt;In the Jquery world, constructing a basic custom dialog box can be quite trivial. Using &lt;a href="http://jqueryui.com"&gt;Jquery UI&lt;/a&gt;, creating a dialog box like the above can be done with this little snippet of code:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;div id=&amp;quot;dialog&amp;quot; title=&amp;quot;Basic dialog&amp;quot;&amp;gt;&lt;br /&gt; &amp;lt;p&amp;gt;This is the default dialog which is useful for displaying information. The dialog window can be moved, resized and closed with the 'x' icon.&amp;lt;/p&amp;gt;&lt;br /&gt;&amp;lt;/div&amp;gt;&lt;br /&gt;&amp;lt;script&amp;gt;&lt;br /&gt;$( &amp;quot;#dialog&amp;quot; ).dialog();&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Web development is easy right? Well in a perfect world yes, but as any developer will tell you there are two worlds: the ideal world, and the real world. JQuery UI is a fine toolkit when one is looking for a standard off the shelf styled widget, but not when something more custom is desired - even with help from the excellent &lt;a href="http://jqueryui.com/themeroller/"&gt;Themeroller&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-DQgLKASoECI/TdO8iC93r8I/AAAAAAAAArM/druic1fMdvo/s1600/twitter_dialog_box.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 196px;" src="http://1.bp.blogspot.com/-DQgLKASoECI/TdO8iC93r8I/AAAAAAAAArM/druic1fMdvo/s400/twitter_dialog_box.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5608033254104346562" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The recent Twitter UI redesign does everything it can to ensure users will use their browser's back button less. Many of the actions possible do not change the principle view for the user, but merely extend it.  One such measure was the compose a tweet dialog box. The JQuery UI dialog widget won't give you a Twitter inspired dialog box - you have to create your own.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;font-size:1.2em"&gt;Analysis&lt;/span&gt; of the Twitter dialog box reveals the following:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Non modal -  actions possible on the originating view&lt;/li&gt;&lt;li&gt;Fixed position - dialog box is fixed in center of window even as window scrolls&lt;/li&gt;&lt;li&gt;Dialog box has a simple structure, but the nature of opaque inheritance could cause some problems.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-jpqtnwgTHQ0/TdPYFC3UU5I/AAAAAAAAArc/e79EgqSs_Fo/s1600/dialogBox.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/-jpqtnwgTHQ0/TdPYFC3UU5I/AAAAAAAAArc/e79EgqSs_Fo/s320/dialogBox.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5608063542186234770" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The dialog box really has a very simple structure, and the HTML required reflects this.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;div class=&amp;quot;dialog&amp;quot;&amp;gt;&lt;br /&gt;&amp;lt;div class=&amp;quot;dialog-frame&amp;quot;&amp;gt;&lt;br /&gt;  &amp;lt;header&amp;gt;&lt;br /&gt;    &amp;lt;h1&amp;gt;Our first Dialog&amp;lt;/h1&amp;gt;&lt;br /&gt;  &amp;lt;/header&amp;gt;&lt;br /&gt;&amp;lt;/div&amp;gt;&lt;br /&gt;&amp;lt;div class=&amp;quot;dialog-content&amp;quot;&amp;gt;&lt;br /&gt;   &amp;lt;p&amp;gt;A pleasure to open our first dialog with you&amp;lt;/p&amp;gt;&lt;br /&gt;&amp;lt;/div&amp;gt;&lt;br /&gt;&amp;lt;/dialog&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p style="border:1px solid black;width:90%"&gt;&lt;b&gt;Note:&lt;/b&gt;&lt;br /&gt;The dialog-frame div is a sibling of the dialog-content div rather than being its parent. The reason for this is to accommodate a &lt;br /&gt;semi-transparent dialog frame. Once you reduce the opacity of an element, its children will automatically inherit this opacity. You cannot increase the opacity of  an element from the value it has inherited.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;b&gt;Most of the work is in the javascript:&lt;/b&gt;  you don't know the size of the user's browser window when writing your css, so you need to set dimensions and coordinates of the dialog box dynamically. &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    var dialog = $('.dialog') // cache the dialog element&lt;br /&gt;&lt;br /&gt;   // Initial dialog setup&lt;br /&gt;    var dialogFrameWidth = '10px'&lt;br /&gt;    dialog.css({position: 'fixed', padding:dialogFrameWidth})&lt;br /&gt;&lt;br /&gt;    // Set dialog coordinates &lt;br /&gt;    dialogHeight = dialog.outerHeight()&lt;br /&gt;    dialogWidth = dialog.outerWidth()&lt;br /&gt;    dialogTop = ($(window).height() - dialogHeight)/2&lt;br /&gt;    dialogLeft = ($(window).width() - dialogWidth)/2&lt;br /&gt;    dialogFrameWidth = "10px"&lt;br /&gt;    dialog.css({top: dialogTop, left: dialogLeft, position: fixed,  padding:dialogFrameWidth}})&lt;br /&gt;&lt;br /&gt;    // Set coordinates and dimensions of dialog frame&lt;br /&gt;    dialogFrame = dialog.find('.dialog-frame')&lt;br /&gt;    dialogFrame.css({height: dialogHeight, width: dialogWidth, position: 'absolute', top: 0, left: 0, opacity: 0.8, z-index:1000}})&lt;br /&gt;&lt;br /&gt;   // Set coordinates and dimensions of dialog content&lt;br /&gt;    dialogFrameHeaderHeight = dialogFrame.find('header').outerHeight(true)&lt;br /&gt;    dialogContent = dialog.find('.dialog-content')&lt;br /&gt;    dialogContent.css({'margin-top': dialogFrameHeaderHeight, position: 'relative', top: 0, left: 0, z-index: 3000})&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Add some style like background colors, fonts, etc. and your in business!&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Credits:&lt;/h4&gt;&lt;br /&gt;&lt;a href="http://twitter.com"&gt;http://twitter.com&lt;/a&gt;&lt;br /&gt;&lt;a href="http://jqueryui.com/demos/dialog/"&gt;http://jqueryui.com/demos/dialog/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3675576906879941038-4004590353166467986?l=programming34m0.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programming34m0.blogspot.com/feeds/4004590353166467986/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://programming34m0.blogspot.com/2011/05/custom-dialog-box-jquery.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/4004590353166467986'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/4004590353166467986'/><link rel='alternate' type='text/html' href='http://programming34m0.blogspot.com/2011/05/custom-dialog-box-jquery.html' title='A Custom Dialog Box in JQuery Tutorial'/><author><name>Eamonn O'Connell</name><uri>http://www.blogger.com/profile/17064544953690759392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://2.bp.blogspot.com/_vC3SkHYsTQs/TBHf_uhM1_I/AAAAAAAAAn4/YLzceffi1_c/S220/profilePic.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-gKO1d-sJQLM/TdPANRRYJfI/AAAAAAAAArU/43QMr-woDUw/s72-c/jquery_ui_dialog_box.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3675576906879941038.post-6072099502507319471</id><published>2011-05-16T02:33:00.000-07:00</published><updated>2011-05-19T00:02:41.705-07:00</updated><title type='text'>Simplifying a javascript jump menu</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-ctKW2wTt7tc/TdDx3Zll6aI/AAAAAAAAAq0/34Aykn6RliA/s1600/twitter_click_on_click_off.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 360px; height: 185px;" src="http://1.bp.blogspot.com/-ctKW2wTt7tc/TdDx3Zll6aI/AAAAAAAAAq0/34Aykn6RliA/s320/twitter_click_on_click_off.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5607247470139926946" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The jump menu is a reasonably common UI design pattern on the web. It is used by big guns such as Facebook and Twitter, and has been &lt;a href="http://davidwalsh.name/twitter-dropdown-jquery"&gt;dissected and reproduced&lt;/a&gt; many times over. &lt;br /&gt;&lt;br /&gt;When I set about implementing my own jump menu I found opening and closing the menu when it is clicked on was rather trivial. &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$('.jump-menu').click(function(e){&lt;br /&gt;   toggleMenu();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The difficulty came in closing the menu when there is a click outside the jump menu. Googling for answers, I found the scenario of closing a menu on clicking outside it to be a well trodden path. Stackoverflow had plenty of examples and possible solutions such as &lt;a href="http://stackoverflow.com/questions/2868582/click-outside-menu-to-close-in-jquery"&gt;here&lt;/a&gt; and &lt;a href="http://stackoverflow.com/questions/152975/how-to-detect-a-click-outside-an-element"&gt;here&lt;/a&gt;. I even found a plugin created by Ben Alman that extended Jquery to provide a &lt;a href="http://benalman.com/projects/jquery-outside-events-plugin/"&gt;custom clickoutside event.&lt;/a&gt; Many of the proposed &lt;a href="http://stackoverflow.com/questions/152975/how-to-detect-a-click-outside-an-element/6051126#6051126"&gt;solutions were fragile&lt;/a&gt;, and I was slow to add a new plugin to my web application - as good and all as the implementation appeared. I really wanted to understand the problem before opting to take a proposed solution off the shelf.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-Z8WzF6zQqeo/TdD4DE160LI/AAAAAAAAAq8/F5EwPEqIqS4/s1600/click_on_off_menu_states.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 450px; height: 310px;" src="http://1.bp.blogspot.com/-Z8WzF6zQqeo/TdD4DE160LI/AAAAAAAAAq8/F5EwPEqIqS4/s320/click_on_off_menu_states.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5607254267799457970" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The state diagram above illustrates the four possible actions for the two menu states of open and closed. We can see that one of the four actions results in no change of state, while another two result in the same change of state. Clearly this diagram could be simplified, and along with it my perception of the problem. &lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;"Make things as simple as possible, but not simpler" - Albert Einstein&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-m7TkXFf86Ng/TdD6mQ5uUFI/AAAAAAAAArE/788CatmcGT4/s1600/click_on_click_off_states_2.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 450px; height: 220px;" src="http://2.bp.blogspot.com/-m7TkXFf86Ng/TdD6mQ5uUFI/AAAAAAAAArE/788CatmcGT4/s320/click_on_click_off_states_2.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5607257071355318354" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Given this simplified state transition diagram, there was no need for an event register, a global array, comparing with event.target, a handler that would be called for each and every document click, or the jquery plugin. All that I needed was something like the following:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    isMenuOpen = function(menu) {&lt;br /&gt;      return menu.hasClass('ui-active-state');&lt;br /&gt;    };&lt;br /&gt;    openMenu = function(event) {&lt;br /&gt;      var documentClicks, menu, self;&lt;br /&gt;      menu = $(event.target).parents('.jump-menu');&lt;br /&gt;      if (isMenuOpen(menu)) {&lt;br /&gt;        menu.removeClass('ui-default-state');&lt;br /&gt;        menu.addClass('ui-active-state');&lt;br /&gt;        self = this;&lt;br /&gt;        documentClicks = 0;&lt;br /&gt;        $(document).bind("click", __bind(function(e) {&lt;br /&gt;          documentClicks++;&lt;br /&gt;          if (documentClicks === 2) {&lt;br /&gt;            $(this).unbind(e);&lt;br /&gt;            this.closeMenu(menu);&lt;br /&gt;          }&lt;br /&gt;          return this;&lt;br /&gt;        }, this));&lt;br /&gt;      }&lt;br /&gt;      return this;&lt;br /&gt;    };&lt;br /&gt;    closeMenu = function(menu) {&lt;br /&gt;      menu = $(this.el).find('.jump-menu');&lt;br /&gt;      menu.removeClass('ui-active-state');&lt;br /&gt;      menu.addClass('ui-default-state');&lt;br /&gt;    };&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;There is always another way to look at a problem.&lt;br /&gt;Happy Coding!&lt;br /&gt;&lt;br /&gt;Credits:&lt;br /&gt;&lt;a href="http://davidwalsh.name/twitter-dropdown-jquery"&gt;http://davidwalsh.name/twitter-dropdown-jquery&lt;/a&gt;&lt;br /&gt;&lt;a href="http://stackoverflow.com/questions/152975/how-to-detect-a-click-outside-an-element"&gt;http://stackoverflow.com/questions/152975/how-to-detect-a-click-outside-an-element&lt;/a&gt;&lt;br /&gt;&lt;a href="http://stackoverflow.com/questions/2868582/click-outside-menu-to-close-in-jquery"&gt;http://stackoverflow.com/questions/2868582/click-outside-menu-to-close-in-jquery&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.filamentgroup.com/lab/developer_your_own_jquery_themeroller_ready_components/"&gt;http://www.filamentgroup.com/lab/developer_your_own_jquery_themeroller_ready_components/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3675576906879941038-6072099502507319471?l=programming34m0.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programming34m0.blogspot.com/feeds/6072099502507319471/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://programming34m0.blogspot.com/2011/05/simplifying-javascript-jump-menu.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/6072099502507319471'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/6072099502507319471'/><link rel='alternate' type='text/html' href='http://programming34m0.blogspot.com/2011/05/simplifying-javascript-jump-menu.html' title='Simplifying a javascript jump menu'/><author><name>Eamonn O'Connell</name><uri>http://www.blogger.com/profile/17064544953690759392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://2.bp.blogspot.com/_vC3SkHYsTQs/TBHf_uhM1_I/AAAAAAAAAn4/YLzceffi1_c/S220/profilePic.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-ctKW2wTt7tc/TdDx3Zll6aI/AAAAAAAAAq0/34Aykn6RliA/s72-c/twitter_click_on_click_off.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3675576906879941038.post-6945108168124090191</id><published>2011-04-21T02:17:00.000-07:00</published><updated>2011-05-11T01:20:28.342-07:00</updated><title type='text'>Compiling brunch from source</title><content type='html'>&lt;h3&gt;Background:&lt;/h3&gt;&lt;a href="http://brunchwithcoffee.com"&gt;Brunch&lt;/a&gt; is a client side web app framework built using a number of open source tools and libs from the world of javascript and node.js: &lt;a href="http://jashkenas.github.com/coffee-script"&gt;CoffeeScript&lt;/a&gt;, &lt;a href="http://documentcloud.github.com/backbone/"&gt;Backbone&lt;/a&gt;, Eco templates, and &lt;a href="http://search.npmjs.org/#/brunch"&gt;more&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The steps&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;Pull source from Github &lt;br /&gt;      git pull https://github.com/brunch/brunch&lt;br /&gt;  &lt;/li&gt;&lt;li&gt;check if you have all the brunch dependencies: &lt;br /&gt;      ./bin/brunch --version&lt;br /&gt;  &lt;/li&gt;&lt;li&gt;Building from source means you don't get the dependency management of npm as easily. &lt;br /&gt;     You must have node installed, and the &lt;a href="http://search.npmjs.org/#/brunch"&gt;required packages&lt;/a&gt;:&lt;br /&gt;     Note: at time of writing Stitch was not defined in npm dependencies but required &lt;br /&gt;     npm install stitch&lt;br /&gt;  &lt;/li&gt;&lt;li&gt;Compile brunch with Cake: &lt;br /&gt;    cake watch&lt;br /&gt;  &lt;/li&gt;&lt;li&gt;To create a project: &lt;br /&gt;    ./bin/brunch new --output $locationOfNewProject&lt;br /&gt;  &lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3675576906879941038-6945108168124090191?l=programming34m0.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programming34m0.blogspot.com/feeds/6945108168124090191/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://programming34m0.blogspot.com/2011/04/compiling-brunch-from-source.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/6945108168124090191'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/6945108168124090191'/><link rel='alternate' type='text/html' href='http://programming34m0.blogspot.com/2011/04/compiling-brunch-from-source.html' title='Compiling brunch from source'/><author><name>Eamonn O'Connell</name><uri>http://www.blogger.com/profile/17064544953690759392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://2.bp.blogspot.com/_vC3SkHYsTQs/TBHf_uhM1_I/AAAAAAAAAn4/YLzceffi1_c/S220/profilePic.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3675576906879941038.post-4516857895537806710</id><published>2011-04-15T00:34:00.000-07:00</published><updated>2011-11-15T12:54:59.124-08:00</updated><title type='text'>Nerd Tree: A File Explorer with Mac Vim</title><content type='html'>The one thing missing from the great text editor that is &lt;a href="https://github.com/b4winckler/macvim"&gt;Mac Vim&lt;/a&gt; is a project / file explorer side bar. Competing text editors such as Sublime and Text Mate have one, so why not MacVim? It doesn't seem like it would require too much additional work of the developers. Reading through &lt;a href="http://groups.google.com/group/vim_mac/browse_thread/thread/34a3e23bcc9ee977"&gt;debates the community has had on the issue&lt;/a&gt;, the reason appears to be the elitist and idealistic nature of the Mac Vim community. Please don't read that last sentence pejoratively; these guys are purists, and very good at what they do. There were quite a few in the community who believed &lt;a href="http://www.vim.org/scripts/script.php?script_id=1658"&gt;NERDTree&lt;/a&gt; was more than enough for any code jocky's needs, so I decided to checkout what all the fuss was about.&lt;br /&gt;&lt;br /&gt;I use &lt;a href="http://www.vim.org/scripts/script.php?script_id=2332"&gt;pathogen&lt;/a&gt; to manage vim plugins, and it is especially useful in conjunction with a public source control system like github. Once you have pathogen installed simply pull the NerdTree Github project to your vim plugins directory. &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;cd ~/.vim/bundle&lt;br /&gt;git clone git://github.com/scrooloose/nerdtree.git&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Next add a shortcut to make opening your NERDTree more convenient by adding the following to your vim config file (~/.vimrc)&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;" Give a shortcut key to NERD Tree&lt;br /&gt;map &amp;lt;F2&amp;gt; :NERDTreeToggle&amp;lt;CR&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now fire up your MacVim, open a window, and press (fn+F2).&lt;br /&gt;With NerdTree now started,  the following commands should get you going:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;Use the natural vim navigation keys hjkl to navigate the files, or just the arrow keys&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Press o to open the file in a new buffer or open/close directory.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Press t to open the file in a new tab.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Press i to open the file in a new horizontal split.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Press s to open the file in a new vertical split.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Press p to go to parent directory.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Press r to refresh the current directory.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;p style="border:1px solid black;width:90%"&gt;&lt;b&gt;Tip:&lt;/b&gt;&lt;br /&gt;Open a project with mvim + nerdtree from the command line like this:&lt;br /&gt;mvim ~/Dev/path/to/project&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;Happy Coding!&lt;br /&gt;&lt;br /&gt;References:&lt;br /&gt;&lt;a href="http://www.catonmat.net/blog/vim-plugins-nerdtree-vim"&gt;http://www.catonmat.net/blog/vim-plugins-nerdtree-vim&lt;/a&gt;&lt;br /&gt;&lt;a href="http://tammersaleh.com/posts/the-modern-vim-config-with-pathogen"&gt;http://tammersaleh.com/posts/the-modern-vim-config-with-pathogen&lt;/a&gt;&lt;br /&gt;&lt;a href="http://tammersaleh.com/posts/the-modern-vim-config-with-pathogen"&gt;http://wiredupandfiredup.blogspot.com/2008/09/pimp-your-macvim.html&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3675576906879941038-4516857895537806710?l=programming34m0.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programming34m0.blogspot.com/feeds/4516857895537806710/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://programming34m0.blogspot.com/2011/04/nerd-tree-file-explorer-with-mac-vim.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/4516857895537806710'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/4516857895537806710'/><link rel='alternate' type='text/html' href='http://programming34m0.blogspot.com/2011/04/nerd-tree-file-explorer-with-mac-vim.html' title='Nerd Tree: A File Explorer with Mac Vim'/><author><name>Eamonn O'Connell</name><uri>http://www.blogger.com/profile/17064544953690759392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://2.bp.blogspot.com/_vC3SkHYsTQs/TBHf_uhM1_I/AAAAAAAAAn4/YLzceffi1_c/S220/profilePic.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3675576906879941038.post-4267751988144191124</id><published>2010-07-28T08:37:00.000-07:00</published><updated>2010-07-28T08:42:27.251-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='grails'/><title type='text'>Accessing appName property from controller in Grails</title><content type='html'>It is trivial to access the appName property from within the config.groovy file, and it is a common practice to do so. Here is an example of specifying an external config file based on the name of the grails application:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;grails.config.locations = ["file:$userHome/.osaas/$appName.groovy"&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I could find no where obvious that described how to access this appName property from a constructor. You would expect the following to work but it does not:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;grailsApplication.config.appName&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The following does work however&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;grailsApplication.metadata['app.name']&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3675576906879941038-4267751988144191124?l=programming34m0.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programming34m0.blogspot.com/feeds/4267751988144191124/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://programming34m0.blogspot.com/2010/07/accessing-appname-property-from.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/4267751988144191124'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/4267751988144191124'/><link rel='alternate' type='text/html' href='http://programming34m0.blogspot.com/2010/07/accessing-appname-property-from.html' title='Accessing appName property from controller in Grails'/><author><name>Eamonn O'Connell</name><uri>http://www.blogger.com/profile/17064544953690759392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://2.bp.blogspot.com/_vC3SkHYsTQs/TBHf_uhM1_I/AAAAAAAAAn4/YLzceffi1_c/S220/profilePic.JPG'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3675576906879941038.post-4331844516119899545</id><published>2010-07-05T02:49:00.001-07:00</published><updated>2010-07-05T03:32:53.044-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dns'/><title type='text'>Tracing DNS resolution</title><content type='html'>When you need to trace how dns is resolving your server here is a way to do it.&lt;br /&gt;First run this nslookup query:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;nslookup -q=ns example.com a.root-servers.net&lt;br /&gt;Authoritative answers can be found from:&lt;br /&gt;com nameserver = h.gtld-servers.net.&lt;br /&gt;com nameserver = d.gtld-servers.net.&lt;br /&gt;com nameserver = k.gtld-servers.net.&lt;br /&gt;com nameserver = g.gtld-servers.net.&lt;br /&gt;com nameserver = c.gtld-servers.net.&lt;br /&gt;com nameserver = f.gtld-servers.net.&lt;br /&gt;com nameserver = j.gtld-servers.net.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now choose one of the results and run the query again like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;nslookup -q=ns example.com a.gtld-servers.net&lt;br /&gt;Authoritative answers can be found from:&lt;br /&gt;example.com nameserver = ns1.example.com.&lt;br /&gt;example.com nameserver = ns2.example.com.&lt;br /&gt;example.com nameserver = ns3.example.com.&lt;br /&gt;ns1.example.com internet address = 10.12.12.12&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;You can repeat the above if you still haven't reached your destination&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3675576906879941038-4331844516119899545?l=programming34m0.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programming34m0.blogspot.com/feeds/4331844516119899545/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://programming34m0.blogspot.com/2010/07/tracing-dns-resolution.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/4331844516119899545'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/4331844516119899545'/><link rel='alternate' type='text/html' href='http://programming34m0.blogspot.com/2010/07/tracing-dns-resolution.html' title='Tracing DNS resolution'/><author><name>Eamonn O'Connell</name><uri>http://www.blogger.com/profile/17064544953690759392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://2.bp.blogspot.com/_vC3SkHYsTQs/TBHf_uhM1_I/AAAAAAAAAn4/YLzceffi1_c/S220/profilePic.JPG'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3675576906879941038.post-4363549582809999919</id><published>2010-06-07T15:13:00.000-07:00</published><updated>2010-06-08T02:57:42.625-07:00</updated><title type='text'>A Javascript best practice: one special semicolon</title><content type='html'>It is becoming common practice to concatenate javascript files. Such concatenation means that only one HTTP request is required to download the necessary javascript rather than several. This reduction in HTTP overhead reduces the time taken to download the particular web application. This concatenation can introduce an unforeseen problem: if, in one file, some code is not properly finished (i.e. with a  semicolon), and the proceeding file begins with a closure&lt;br /&gt;being opened, the interpreter will break.&lt;br /&gt;&lt;br /&gt;Jquery plugins often begin with closures and so are susceptible to this problem. Beginning the file with a semicolon will prevent this kind of problem. Where a file begins with a closure, best practice should dictate that it begins with a semicolon. An example of this practice in action is &lt;a href="http://github.com/malsup/form/raw/master/jquery.form.js?v2.43"&gt;source code&lt;/a&gt; of the &lt;a href="http://jquery.malsup.com/form/"&gt;jquery form plugin&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;References:&lt;/u&gt;&lt;br /&gt;http://groups.google.com/group/jquery-dev/browse_thread/thread/2ce10bc1bcf6a8d1?pli=1&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3675576906879941038-4363549582809999919?l=programming34m0.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programming34m0.blogspot.com/feeds/4363549582809999919/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://programming34m0.blogspot.com/2010/06/javascript-best-practice-one-special.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/4363549582809999919'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/4363549582809999919'/><link rel='alternate' type='text/html' href='http://programming34m0.blogspot.com/2010/06/javascript-best-practice-one-special.html' title='A Javascript best practice: one special semicolon'/><author><name>Eamonn O'Connell</name><uri>http://www.blogger.com/profile/17064544953690759392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://2.bp.blogspot.com/_vC3SkHYsTQs/TBHf_uhM1_I/AAAAAAAAAn4/YLzceffi1_c/S220/profilePic.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3675576906879941038.post-189919710870043992</id><published>2010-05-28T02:32:00.000-07:00</published><updated>2010-06-01T08:35:34.047-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='amazon aws virtualhosts https ec2 elb'/><title type='text'>Overcomming the virtual hosts/HTTPs conflict on Amazon AWS</title><content type='html'>&lt;style type="text/css"&gt;&lt;br /&gt;textarea{&lt;br /&gt;   width:100%;&lt;br /&gt;}&lt;br /&gt;&lt;/style&gt;&lt;br /&gt;Previously I've described the &lt;a href="http://programming34m0.blogspot.com/2010/05/multiple-http-websites-on-one-webserver.html"&gt;conflict between virtual hosts and HTTPs&lt;/a&gt;. For those that use Amazon's EC2 cloud, the below describes an elegant remedy for that conflict . &lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Assumed Basic Setup&lt;/h2&gt;&lt;br /&gt;For the purposes of this example, I'll assume you have an EC2 instance of Ubuntu Lucid with an apache server serving two websites: example.com and eazybusiness.com. Both have their own virtual host definitions, each containing it's corresponding site's specific configuration. If you need more information on how to configure your virtual hosts I direct you to apache's &lt;a href="http://httpd.apache.org/docs/2.2/vhosts/"&gt;comprehensive documentation on the subject&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The virtual host definitions would look something like:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;VirtualHost *:80&amp;gt;&lt;br /&gt;        ServerName www.eazybusiness.com&lt;br /&gt;       &lt;br /&gt;        ServerAdmin admin@eazybusiness.com&lt;br /&gt;        DocumentRoot /var/sites/eazybusiness.com/&lt;br /&gt;&amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;&amp;lt;VirtualHost *:80&amp;gt;&lt;br /&gt;        ServerName www.example.com&lt;br /&gt;       &lt;br /&gt;        ServerAdmin admin@example.com&lt;br /&gt;        DocumentRoot /var/sites/example.com/&lt;br /&gt;&amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The above definitions allow insequre, plain HTTP connections to both sites. The hostname provided by the browser client is matched against the servername's in the virtual hosts and the correct configuration is used accordingly.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Configure Amazon's Elastic Load Balancer&lt;/h2&gt;&lt;br /&gt;In order to secure our two websites, we'll first create the necessary proxy via Amazon's load balancer facility. &lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;First configure your ec2 image to use the Amazon command line tools. Ubuntu this images make this easier thanks to the power of apt-get.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;br /&gt;Seperate command line tools are required for ELB. &lt;a href="http://developer.amazonwebservices.com/connect/entry.jspa?externalID=2536&amp;categoryID=88"&gt;Download the tools from Amazon&lt;/a&gt;, and unzip to somewhere on your image.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Set an environment variable AWS_ELB_HOME to point to where you unzipped the tools.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Now, let's create our first loadbalancer:&lt;br /&gt;&lt;textarea style="width:100%"&gt;&lt;br /&gt;elb-create-lb eazybusiness --headers --listener "lb-port=443,instance-port=8445,protocol=TCP" --listener "lb-port=80,instance-port=80,protocol=http" --availability-zones us-west-1a --region us-west-1&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;Here we configured loadbalacer to listen on port 443 and port 80. All requests to port 80, are to be forwarded to port 80, and requests to 443 are to be forwarded to 8445 &lt;br /&gt;&lt;i&gt;Note: amazon's api tools default to the region us-east-1. If you wish to use any other region, you must provide the --region parameter&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Create a second loadbalancer for example.com:&lt;br /&gt;&lt;textarea style="width:100%"&gt;&lt;br /&gt;elb-create-lb example --headers --listener "lb-port=443,instance-port=8443,protocol=TCP" --listener "lb-port=80,instance-port=80,protocol=http" --availability-zones us-west-1a --region us-west-1&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;i&gt;Note: the example.com loadbalancer will forward requests to port 443 to a different port than the eazybusiness.com loadbalancer&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Next, register our instance with both load balancers:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;elb-register-instances-with-lb eazybusiness --region us-west-1 --instances $instanceId&lt;br /&gt;elb-register-instances-with-lb example --region us-west-1 --instances $instanceId&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Configure Apache&lt;/h2&gt;&lt;br /&gt;Apache must start to list on the ports that the load balancers will forward to. To this, edit /etc/apache2/ports.conf and add the lines:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Listen 8443 https&lt;br /&gt;Listen 8445 https&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;To confirm the ports are being listened on try the following commands:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;netstat -na | more&lt;br /&gt;nmap -sT -O localhost&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Ensure mod_headers is enabled&lt;br /&gt;&lt;pre&gt;sudo a2enmod headers&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Configure Virtual Hosts&lt;/h2&gt;&lt;br /&gt;The virtual hosts need to be configured for SSL, and reflect the ports defined for the loadbalancers. In our example, the virtual hosts become:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;VirtualHost *:80&amp;gt;&lt;br /&gt;        ServerName www.eazybusiness.com&lt;br /&gt;       &lt;br /&gt;        ServerAdmin admin@eazybusiness.com&lt;br /&gt;        DocumentRoot /var/sites/eazybusiness.com/&lt;br /&gt;        SSLEngine On&lt;br /&gt;        SSLCertificateFile /etc/ssl/eazybusiness.com.crt&lt;br /&gt;        SSLCertificateKeyFile /etc/ssl/eazybusiness.com.key&lt;br /&gt;        RequestHeader set X_FORWARDED_PROTO 'https'&lt;br /&gt;&amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;&amp;lt;VirtualHost *:80&amp;gt;&lt;br /&gt;        ServerName www.example.com&lt;br /&gt;       &lt;br /&gt;        ServerAdmin admin@example.com&lt;br /&gt;        DocumentRoot /var/sites/example.com/&lt;br /&gt;        SSLEngine On&lt;br /&gt;        SSLCertificateFile /etc/ssl/example.com.crt&lt;br /&gt;        SSLCertificateKeyFile /etc/ssl/example.com.key&lt;br /&gt;        RequestHeader set X_FORWARDED_PROTO 'https'&lt;br /&gt;&amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;i&gt;Note: the RequestHeader directive requires that you enable mod_headers for Apache.&lt;/i&gt;&lt;br /&gt;&lt;pre&gt;sudo a2enmod headers&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Configure DNS&lt;/h2&gt;&lt;br /&gt;The AWS console displays a list of load balancers. From this list, glean the relevant DNS names, and make the relevant alterations to the dns server like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;eazybusiness.com. IN CNAME eazybusiness-2028819496.us-west-1.elb.amazonaws.com.&lt;br /&gt;example.com. IN CNAME example-2028229496.us-west-1.elb.amazonaws.com.&lt;br /&gt;&lt;/pre&gt; &lt;br /&gt;&lt;i&gt;Note: don't forget the proceeding dot when using full domains.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Configure Amazon Firewall&lt;/h2&gt;&lt;br /&gt;Ensure the specified ports open, which in our example are 8445 and 8443. &lt;br /&gt;&lt;br /&gt;To confirm the port is open with Telnet try:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;telnet $public_dns_of_image 8445&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;After completing all of the steps above you should now be able to support multiple secure websites sharing the same webserver.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;References&lt;/h2&gt;&lt;br /&gt;Major credit goes to &lt;a href="http://elwoodicious.com/2009/12/23/using-elb-to-serve-multiple-domains-over-ssl-on-ec2-for-giggles/"&gt;this post&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3675576906879941038-189919710870043992?l=programming34m0.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programming34m0.blogspot.com/feeds/189919710870043992/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://programming34m0.blogspot.com/2010/05/overcomming-virtual-hostshttps-conflict.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/189919710870043992'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/189919710870043992'/><link rel='alternate' type='text/html' href='http://programming34m0.blogspot.com/2010/05/overcomming-virtual-hostshttps-conflict.html' title='Overcomming the virtual hosts/HTTPs conflict on Amazon AWS'/><author><name>Eamonn O'Connell</name><uri>http://www.blogger.com/profile/17064544953690759392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://2.bp.blogspot.com/_vC3SkHYsTQs/TBHf_uhM1_I/AAAAAAAAAn4/YLzceffi1_c/S220/profilePic.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3675576906879941038.post-7386493074353198381</id><published>2010-05-27T08:40:00.001-07:00</published><updated>2010-05-31T09:12:27.441-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='https ssl apache virtualhosts aws'/><title type='text'>Multiple HTTPs websites on one webserver</title><content type='html'>A long time ago, servers were very slow and a web server could only handle one web site.  In time, increased computing power and virtual hosts technology allowed one webserver to handle multiple web sites. At the same time as websites started to share the one webserver, HTTPS was coming to the fore as the defato means of securing web communication from fraudsters, snoopers, and other nefarious trades. Unfortunately, due to the nature of the technologies HTTPS and virtual hosts were not fully compatible.&lt;br /&gt;&lt;br /&gt;Virtual hosts work based on host/server names. Examples of hostnames are example.com, eazybusiness.com, and blogger.com. The hostname provided by the client browser determined what one of its web sites the webserver servered to that client.&lt;br /&gt;&lt;br /&gt;In order for a website to be able to offer the security of HTTPS, it must provide its own unique SSL certificate. This SSL cert is proof of the site's authenticity, and forms part of the protocol used to secure the communication between a user's browser client and the webserver.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The conflict between virtual hosts and HTTPs&lt;/b&gt; lies in the fact that the SSL protocol (the 's' in HTTPs) does not include the need for the client to pass the hostname to the server during initiation. This missing information means that if a webserver hosts multiple websites, each with their own SSL certificate, it does not know which SSL certificate to use. &lt;br /&gt;&lt;br /&gt;Recently browsers and websites have starting supporting a technology called &lt;b&gt;SNI&lt;/b&gt;. SNI enables the hostname to be included part of the SSL protocol. SNI works, and solves the conflict perfectly, but unfortunately the prevelance of older browsers makes using it impractical.&lt;br /&gt;&lt;br /&gt;An alternative solution is to use &lt;b&gt;multi-domain certificates&lt;/b&gt;. Using multi-domain certs means that all the web sites sharing a webserver can also share the one certificate. The webserver then only has the one certificate to use, and so does not need to know information about the hostname when establishing an SSL connection. This solution works, but these certificates can be expensive and come with a number of limitations:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;There is generally a limit to the number of websites a multi-domain cert can accomodate (usually around 100)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Multi-domain certificates do not accomodate wild-card certificates&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;An third possible solution to this problem is to use a &lt;b&gt;proxy&lt;/b&gt;, and have each website operate on a different port. My next post will contain a &lt;a href="http://programming34m0.blogspot.com/2010/05/overcomming-virtual-hostshttps-conflict.html"&gt;solution to the multiple https websites on Amazon's AWS&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3675576906879941038-7386493074353198381?l=programming34m0.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programming34m0.blogspot.com/feeds/7386493074353198381/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://programming34m0.blogspot.com/2010/05/multiple-http-websites-on-one-webserver.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/7386493074353198381'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/7386493074353198381'/><link rel='alternate' type='text/html' href='http://programming34m0.blogspot.com/2010/05/multiple-http-websites-on-one-webserver.html' title='Multiple HTTPs websites on one webserver'/><author><name>Eamonn O'Connell</name><uri>http://www.blogger.com/profile/17064544953690759392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://2.bp.blogspot.com/_vC3SkHYsTQs/TBHf_uhM1_I/AAAAAAAAAn4/YLzceffi1_c/S220/profilePic.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3675576906879941038.post-5839975689130190049</id><published>2010-05-25T23:53:00.001-07:00</published><updated>2010-05-26T00:01:58.626-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java mail grails mail plugin'/><title type='text'>Error sending Mail: 501 Syntax: HELO hostname</title><content type='html'>The exact error I found was:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;javax.mail.MessagingException: 501 Syntax: HELO hostname&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;To fix it I had to set the hostname of the server&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;hostname $hostname.tld&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3675576906879941038-5839975689130190049?l=programming34m0.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programming34m0.blogspot.com/feeds/5839975689130190049/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://programming34m0.blogspot.com/2010/05/error-sending-mail-501.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/5839975689130190049'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/5839975689130190049'/><link rel='alternate' type='text/html' href='http://programming34m0.blogspot.com/2010/05/error-sending-mail-501.html' title='Error sending Mail: 501 Syntax: HELO hostname'/><author><name>Eamonn O'Connell</name><uri>http://www.blogger.com/profile/17064544953690759392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://2.bp.blogspot.com/_vC3SkHYsTQs/TBHf_uhM1_I/AAAAAAAAAn4/YLzceffi1_c/S220/profilePic.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3675576906879941038.post-3074533203296144599</id><published>2010-05-25T04:47:00.000-07:00</published><updated>2010-05-25T23:59:39.009-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='groovy grails exception'/><title type='text'>Grails/Groovy deleting an element in a collection while iterating over it</title><content type='html'>I ran into a recent problem whereby I wanted to delete a sub-set of the elements in a list after processing all elements in the list. The general gist of the logic was:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;apples.each { apple -&gt;&lt;br /&gt;   if(apple.red) apple.delete()   &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;which resulted in a java.util.ConcurrentModificationException exception.&lt;br /&gt;&lt;br /&gt;The solution is to remove the element from the interator before deleting it.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Iterator itr = apples.iterator()&lt;br /&gt;while(itr.hasNext()){&lt;br /&gt;    def apple = itr.next() &lt;br /&gt;    itr.remove()&lt;br /&gt;    apple.delete()&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;For more a little more detail see this &lt;a href="http://markmail.org/thread/f4yorjloegamztyi"&gt;thread&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3675576906879941038-3074533203296144599?l=programming34m0.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programming34m0.blogspot.com/feeds/3074533203296144599/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://programming34m0.blogspot.com/2010/05/grailsgroovy-deleting-element-in.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/3074533203296144599'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/3074533203296144599'/><link rel='alternate' type='text/html' href='http://programming34m0.blogspot.com/2010/05/grailsgroovy-deleting-element-in.html' title='Grails/Groovy deleting an element in a collection while iterating over it'/><author><name>Eamonn O'Connell</name><uri>http://www.blogger.com/profile/17064544953690759392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://2.bp.blogspot.com/_vC3SkHYsTQs/TBHf_uhM1_I/AAAAAAAAAn4/YLzceffi1_c/S220/profilePic.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3675576906879941038.post-4815522125528888473</id><published>2010-04-20T06:42:00.001-07:00</published><updated>2010-04-20T06:48:14.574-07:00</updated><title type='text'>Dynamic methods with javascript</title><content type='html'>I recently had an implementation requirement to be able to call a method given a string with the name of the method.&lt;br /&gt;&lt;br /&gt;I came across two strategies for achieving this:&lt;br /&gt;&lt;br /&gt;1. Eval&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;function a(){&lt;br /&gt;alert('a called');&lt;br /&gt;}&lt;br /&gt;eval('a');&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;2. Map&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;function a(){&lt;br /&gt;alert('a called');&lt;br /&gt;}&lt;br /&gt;window['a']();&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3675576906879941038-4815522125528888473?l=programming34m0.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programming34m0.blogspot.com/feeds/4815522125528888473/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://programming34m0.blogspot.com/2010/04/dynamic-methods-with-javascript.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/4815522125528888473'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/4815522125528888473'/><link rel='alternate' type='text/html' href='http://programming34m0.blogspot.com/2010/04/dynamic-methods-with-javascript.html' title='Dynamic methods with javascript'/><author><name>Eamonn O'Connell</name><uri>http://www.blogger.com/profile/17064544953690759392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://2.bp.blogspot.com/_vC3SkHYsTQs/TBHf_uhM1_I/AAAAAAAAAn4/YLzceffi1_c/S220/profilePic.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3675576906879941038.post-8188046077151081121</id><published>2010-03-30T08:35:00.000-07:00</published><updated>2010-03-30T08:40:09.358-07:00</updated><title type='text'>Daylight Saving Time for Ubunu Linux</title><content type='html'>If you find the time of your Ubuntu machine out by an hour due to DST, then the following steps might sort it out for you:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt; &lt;li&gt;locate the name of the timezone that is suitable for you&lt;br /&gt;    &lt;pre&gt;&lt;br /&gt;         ls /usr/share/zoneinfo&lt;br /&gt;    &lt;/pre&gt;&lt;br /&gt; &lt;/li&gt;&lt;br /&gt; &lt;li&gt;Use zic to set the zone correctly for your localtime&lt;br /&gt;     &lt;pre&gt;&lt;br /&gt;         zic -l $zoneName&lt;br /&gt;     &lt;/pre&gt;&lt;br /&gt; &lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3675576906879941038-8188046077151081121?l=programming34m0.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programming34m0.blogspot.com/feeds/8188046077151081121/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://programming34m0.blogspot.com/2010/03/daylight-saving-time-for-ubunu-linux.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/8188046077151081121'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/8188046077151081121'/><link rel='alternate' type='text/html' href='http://programming34m0.blogspot.com/2010/03/daylight-saving-time-for-ubunu-linux.html' title='Daylight Saving Time for Ubunu Linux'/><author><name>Eamonn O'Connell</name><uri>http://www.blogger.com/profile/17064544953690759392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://2.bp.blogspot.com/_vC3SkHYsTQs/TBHf_uhM1_I/AAAAAAAAAn4/YLzceffi1_c/S220/profilePic.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3675576906879941038.post-5544812237034255675</id><published>2010-03-04T05:58:00.001-08:00</published><updated>2010-03-04T08:23:28.691-08:00</updated><title type='text'>Copying EC2 Instances Between Regions</title><content type='html'>&lt;p&gt;On Amazon AWS EC2, there are different regions. Presently there are three regions. EU-West, US-West, and US-East. To move/copy instances between regions is not trivial, and is not possible using the GUI (either elasticfox or amazon console).&lt;br /&gt;&lt;br /&gt;The following is what has worked for me to copy from EU-WEST to US-WEST:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h4&gt;Determine the name of the bucket your current instance is stored at&lt;/h4&gt;&lt;br /&gt;&lt;p&gt;The bucket name is usually part of the manifest url and is something of the form:&lt;br /&gt;$bucket_name/$manifest_name.xml&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Determine suitable kernel and ramdisk ids in the target region&lt;/h4&gt;&lt;br /&gt;&lt;p&gt;Each AMI image requires references to suitable kernels and ramdisks. This references differ from region to region, so suitable ids need to be researched for your target region. For best results, select akis and aris that are as close as possible to those in the original region&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;ec2-describe-images -o amazon --region $target_region | grep $kernel_description&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Using the &lt;a href="http://developer.amazonwebservices.com/connect/entry.jspa?externalID=351"&gt;API tools provided by Amazon&lt;/a&gt;, run the following Command&lt;/h4&gt;&lt;br /&gt;&lt;pre style=":bash"&gt;&lt;br /&gt;./ec2-migrate-image -o $Access_Key -w $Access_Password --region eu-west-1 --bucket $name_of_existing_bucket --destination-bucket $new_bucket_in_us --manifest $manifest_name.manifest.xml --location us-west-1 --kernel=$suitable_kernel_id --ramdisk=$suitable_ram_disk_id&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Note: Transferring ECB blocks currently needs to be done out of band. This involves using rsync, dd, or equivalent.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Resources&lt;/h4&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://docs.amazonwebservices.com/AWSEC2/latest/CommandLineReference/"&gt;Amazon API Tools Reference&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.dotanmazor.com/index.php?option=com_content&amp;view=article&amp;id=96:ec2-ami-move&amp;catid=16:2008-11-14-08-43-34&amp;Itemid=48"&gt;Migration Tutorial&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1345"&gt;Running an instance with a different kernel&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3675576906879941038-5544812237034255675?l=programming34m0.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programming34m0.blogspot.com/feeds/5544812237034255675/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://programming34m0.blogspot.com/2010/03/copying-instances-between-ec2-regions.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/5544812237034255675'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/5544812237034255675'/><link rel='alternate' type='text/html' href='http://programming34m0.blogspot.com/2010/03/copying-instances-between-ec2-regions.html' title='Copying EC2 Instances Between Regions'/><author><name>Eamonn O'Connell</name><uri>http://www.blogger.com/profile/17064544953690759392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://2.bp.blogspot.com/_vC3SkHYsTQs/TBHf_uhM1_I/AAAAAAAAAn4/YLzceffi1_c/S220/profilePic.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3675576906879941038.post-1879995006444587508</id><published>2010-02-05T08:46:00.000-08:00</published><updated>2011-11-01T09:44:12.529-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='maven java'/><title type='text'>Jar Scanning</title><content type='html'>Sometimes it can be helpful to track down where exactly a class is within a library of jars. &lt;br /&gt;&lt;br /&gt;One means of doing it is to run something like the following from the command line:&lt;br /&gt;&lt;pre class="brush: bash"&gt;&lt;br /&gt;find . -name \*jar -print -exec jar -tvf {} \; | nawk '/YOURSEARCHSTRING/ || /jar/ {print} '&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Another means is to use a java based &lt;a href="http://www.inetfeedback.com/jarscan/"&gt;jarscan tool&lt;/a&gt;.&lt;br /&gt;The tool comes with a .bat file, which is not exactly ideal for linux development. &lt;br /&gt;I created an equivalent .sh file with the following contents:&lt;br /&gt;&lt;pre class="brush: bash"&gt;&lt;br /&gt;java -jar $JARSCAN_HOME/jarscan.jar $1 $2&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;and added an alias to my ~/.bashrc file of the form:&lt;br /&gt;&lt;pre class="brush: bash"&gt;&lt;br /&gt;alias jarscan='~/dev/apps/jarscan/jarscan.sh'&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now you have a command line jarscanner. Navigate to any directory, and to run a recursive jar search enter a short command like the following:&lt;br /&gt;&lt;pre class="brush: bash"&gt;&lt;br /&gt;jarscan MBeanServer&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3675576906879941038-1879995006444587508?l=programming34m0.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programming34m0.blogspot.com/feeds/1879995006444587508/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://programming34m0.blogspot.com/2010/02/jar-scanning.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/1879995006444587508'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/1879995006444587508'/><link rel='alternate' type='text/html' href='http://programming34m0.blogspot.com/2010/02/jar-scanning.html' title='Jar Scanning'/><author><name>Eamonn O'Connell</name><uri>http://www.blogger.com/profile/17064544953690759392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://2.bp.blogspot.com/_vC3SkHYsTQs/TBHf_uhM1_I/AAAAAAAAAn4/YLzceffi1_c/S220/profilePic.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3675576906879941038.post-2114162352097251683</id><published>2010-02-05T05:30:00.001-08:00</published><updated>2010-03-10T09:08:24.731-08:00</updated><title type='text'>Maven Tricks</title><content type='html'>see all the libs that end up on the classpath of your maven project:&lt;br /&gt;&lt;br /&gt;mvn dependency:build-classpath | sed 's/:/\n/g' &gt; cp.txt&lt;br /&gt;&lt;br /&gt;Jar search:&lt;br /&gt;find . -name \*jar -print -exec jar -tvf {} \; | nawk '/YOURSEARCHSTRING/ || /jar/ {print} '&lt;br /&gt;&lt;br /&gt;or use &lt;a href="https://jarscan.dev.java.net/"&gt;jarscan tool&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;bash script:&lt;br /&gt;java -jar $JARSCAN_HOME/jarscan.jar $1 $2&lt;br /&gt;&lt;br /&gt;alias added to .bashrc:&lt;br /&gt;alias jarscan='~/dev/apps/jarscan/jarscan.sh'&lt;br /&gt;&lt;br /&gt;and your good to go. Now you can run a recursive search of jars in any directory with a command like:&lt;br /&gt;jarscan MBean&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3675576906879941038-2114162352097251683?l=programming34m0.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programming34m0.blogspot.com/feeds/2114162352097251683/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://programming34m0.blogspot.com/2010/02/maven-tricks.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/2114162352097251683'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/2114162352097251683'/><link rel='alternate' type='text/html' href='http://programming34m0.blogspot.com/2010/02/maven-tricks.html' title='Maven Tricks'/><author><name>Eamonn O'Connell</name><uri>http://www.blogger.com/profile/17064544953690759392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://2.bp.blogspot.com/_vC3SkHYsTQs/TBHf_uhM1_I/AAAAAAAAAn4/YLzceffi1_c/S220/profilePic.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3675576906879941038.post-7578350255207428723</id><published>2010-02-05T05:09:00.000-08:00</published><updated>2010-10-05T04:24:30.261-07:00</updated><title type='text'>The Wonder of GIT</title><content type='html'>Setup your identity:&lt;br /&gt;&lt;pre class="brush: bash"&gt;&lt;br /&gt;git config --global user.name "FirstName LastName"&lt;br /&gt;git config --global user.email "user@example.com"&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Make git a little prettier:&lt;br /&gt;&lt;pre class="brush: bash"&gt;&lt;br /&gt;git config --global color.ui "auto"&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The basic format of the push operation is:&lt;br /&gt;&lt;pre class="brush: bash"&gt;&lt;br /&gt;git push $repository-location $source-branch:$dest-branch&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Publish a local branch, remotely:&lt;br /&gt;&lt;pre class="brush: bash"&gt;&lt;br /&gt;git push origin $local-branch:$remote-branch&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Delete a remote branch:&lt;br /&gt;&lt;pre class="brush: bash"&gt;&lt;br /&gt;git push origin :$remote-ref&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Once a remote branch is deleted, other team members must delete references to the deleted branches by running:&lt;br /&gt;&lt;pre class="brush: bash"&gt;&lt;br /&gt;git remote prune origin&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Create a local branch to track a remote branch:&lt;br /&gt;&lt;pre class="brush: bash"&gt;&lt;br /&gt;git branch --track local-branch-2 origin/remote-branch-2&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Work on a remote branch other than master&lt;br /&gt;&lt;pre class="brush: bash"&gt;&lt;br /&gt;git fetch // to ensure git local knows about remote branch&lt;br /&gt;git checkout --track -b $local-branch origin/$remote-branch&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;To find some code you previously had in a file&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;// Find the relevant commit&lt;br /&gt;git log /path/to/file&lt;br /&gt;// Now view the changes in that file since that particular commit&lt;br /&gt;git diff $commitHash /path/to/file&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;strong&gt;To revert just one file to a previous commit&lt;/strong&gt;&lt;br /&gt;git checkout $commitHASH /path/to/file&lt;br /&gt;&lt;br /&gt;To see who is responsible for the current state of a particular file:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;git blame $fileName&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Sources:&lt;/h4&gt;&lt;br /&gt;&lt;a target="_blank" href="http://www.sourcemage.org/Git_Guide"&gt;http://www.sourcemage.org/Git_Guide&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3675576906879941038-7578350255207428723?l=programming34m0.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programming34m0.blogspot.com/feeds/7578350255207428723/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://programming34m0.blogspot.com/2010/02/wonder-of-git.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/7578350255207428723'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/7578350255207428723'/><link rel='alternate' type='text/html' href='http://programming34m0.blogspot.com/2010/02/wonder-of-git.html' title='The Wonder of GIT'/><author><name>Eamonn O'Connell</name><uri>http://www.blogger.com/profile/17064544953690759392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://2.bp.blogspot.com/_vC3SkHYsTQs/TBHf_uhM1_I/AAAAAAAAAn4/YLzceffi1_c/S220/profilePic.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3675576906879941038.post-891654069208200680</id><published>2009-12-14T02:09:00.000-08:00</published><updated>2009-12-14T12:34:34.034-08:00</updated><title type='text'>Working With HTML's Underrated UL and LI  Tags</title><content type='html'>I think it is important to note that the HTML tag ul is short for unordered list. Many novice html coders think ul and li (and indeed ol) tags are for bullet points, but the main purpose of these tags is to define lists. A list can run verticaly, or horizontally, and elements can be separated by any manner of means - the default rendering of a list just happens to be that of a series of bullet points. &lt;br /&gt;&lt;br /&gt;Tutorials illustrating how to use css to turn a list into a top navigation bar for a website abound on the web, so I'm no need to go there. Instead, I'm going to illustrate how to use the ul and li tags to get a nice bottom navigation, that would typically include a privacy policy, and a copyright declaration.&lt;br /&gt;&lt;br /&gt;First lets define the list of elements to go in our bottom navigation in HTML:&lt;br /&gt;&lt;pre class="brush: html"&gt;&lt;br /&gt;&lt;ul id="footer-nav"&gt;&lt;br /&gt;    &lt;li&gt;&amp;copy; Copyright 2009 &lt;br /&gt;        &lt;a href="http://www.eazybusiness.com"&gt;EazyBusiness&lt;/a&gt;&lt;br /&gt;    &lt;/li&gt;&lt;br /&gt;    &lt;li&gt;&lt;a href="/about-us"&gt;Company&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;    &lt;li&gt;&lt;a href="/support"&gt;Support&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;    &lt;li&gt;&lt;a href="http://www.eazybusiness.com/privacy"&gt;Privacy Policy&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;    &lt;li&gt;&lt;a href="http://www.eazybusiness.com/terms"&gt;Terms of Service&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;    &lt;li&gt;&lt;a href="/affiliates"&gt;Affiliates&lt;/a&gt;&lt;/li&gt;   &lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now that we have defined the content in a structured way, we have to turn our attentions to the style.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: css"&gt;&lt;br /&gt;#footer-nav li{float:left;list-style:none;}&lt;br /&gt;#footer-nav li:before{content:"\2014\a0";}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The above css removes the default list style of the HTML elements, and instead adds a dash before each element. Combining the style, and the data structure, we get the following list:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.mydatanest.com/files/34m0/38036_1zznb/bottom_nav_1.png" /&gt;&lt;br /&gt;&lt;br /&gt;Now we have our navigation list running horizontally, separated by dashes, and all that is needed is for us to tidy it up a little bit. In doing that our HTML became:&lt;br /&gt;&lt;pre class="brush: html"&gt;&lt;br /&gt;&lt;div id="footer"&gt;&lt;br /&gt;&lt;ul id="footer-nav"&gt;&lt;br /&gt;    &lt;li class="first"&gt;&amp;copy; Copyright 2009 &lt;br /&gt;        &lt;a href="http://www.eazybusiness.com"&gt;EazyBusiness&lt;/a&gt;&lt;br /&gt;    &lt;/li&gt;&lt;br /&gt;    &lt;li&gt;&lt;a href="/about-us"&gt;Company&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;    &lt;li&gt;&lt;a href="/support"&gt;Support&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;    &lt;li&gt;&lt;a href="http://www.eazybusiness.com/privacy"&gt;Privacy Policy&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;    &lt;li&gt;&lt;a href="http://www.eazybusiness.com/terms"&gt;Terms of Service&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;    &lt;li&gt;&lt;a href="/affiliates"&gt;Affiliates&lt;/a&gt;&lt;/li&gt;   &lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And our CSS became:&lt;br /&gt;&lt;pre class="brush: css"&gt;&lt;br /&gt;#footer-nav li{float:left;list-style:none;font-size:10pt;color:#fff;}&lt;br /&gt;#footer-nav li:before{content:"\2014\a0";color:#fff;margin-left:2px;}&lt;br /&gt;#footer-nav li.first:before{ content:"";margin-left:0px;}&lt;br /&gt;#footer-nav a:link, #footer-nav a:hover, #footer-nav a:visited{color:#fff;text-decoration:none;}&lt;br /&gt;#footer {float:left;padding:10px;background-color:#039;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And our menu became:&lt;br /&gt;&lt;img src="http://www.mydatanest.com/files/34m0/38040_edh0d/bottom_nav_2.png" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3675576906879941038-891654069208200680?l=programming34m0.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programming34m0.blogspot.com/feeds/891654069208200680/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://programming34m0.blogspot.com/2009/12/working-with-htmls-li-tag.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/891654069208200680'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/891654069208200680'/><link rel='alternate' type='text/html' href='http://programming34m0.blogspot.com/2009/12/working-with-htmls-li-tag.html' title='Working With HTML&apos;s Underrated UL and LI  Tags'/><author><name>Eamonn O'Connell</name><uri>http://www.blogger.com/profile/17064544953690759392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://2.bp.blogspot.com/_vC3SkHYsTQs/TBHf_uhM1_I/AAAAAAAAAn4/YLzceffi1_c/S220/profilePic.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3675576906879941038.post-2963072694413194733</id><published>2009-12-09T07:03:00.001-08:00</published><updated>2010-03-11T03:35:25.810-08:00</updated><title type='text'>Using Groovy Scripting To Remove Unwanted MySQL Databases</title><content type='html'>Doing some Autumn cleaning on a server, I wanted to delete a lot of redundant &lt;a href="http://www.mysql.com/"&gt;mysql databases&lt;/a&gt;. There were over 900 databases, of which about 90% could be deleted or archived.&lt;br /&gt;&lt;br /&gt;To create a list of databases from a terminal window first create a file show_db.sql&lt;br /&gt;:&lt;br /&gt;&lt;pre class="brush: bash"&gt;&lt;br /&gt;echo "show databases" &gt; show_db.sql&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Then use this file to generate a text file containing a list of your databases&lt;br /&gt;&lt;pre class="brush: bash"&gt;&lt;br /&gt;mysql -p &lt; show_db.sql &gt; dblist.txt&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The resulting text file had unwanted characters and spaces. Fortunately file manipulation is easy in groovy. &lt;br /&gt;&lt;pre class="brush: groovy"&gt;&lt;br /&gt;def file = '/tmp/dblistOriginal.txt'&lt;br /&gt;def targetFile = new File('/tmp/dblistClean.txt')&lt;br /&gt;if (targetFile.exists()) targetFile.write("")&lt;br /&gt;new File(file).text.eachLine { line -&gt;&lt;br /&gt;    targetFile.append( line.replace('|', '').trim() )&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I reasoned it was better to keep the archieve and deletion tasks separate incase something went wrong in the process. So, firstly I created an archieve script to dump all the databases, and &lt;a href="http://en.wikipedia.org/wiki/Tar_(file_format)"&gt;tar them&lt;/a&gt; into one file.&lt;br /&gt;&lt;pre class="brush: groovy"&gt;&lt;br /&gt;def dbsToPreserve = new File('/tmp/dbsToSave.txt') // list of databases to exclude&lt;br /&gt;def dbsList = new File('/tmp/dblistClean.txt')&lt;br /&gt;def archiveScript = new File('/tmp/archiveAndDeleteDBs.sh')&lt;br /&gt;def password = 'pwd12345'&lt;br /&gt;def scriptBackupFolder = 'archived_dbs'&lt;br /&gt;&lt;br /&gt;dbsToPreserveList = []&lt;br /&gt;dbsToPreserve.text.eachLine { line -&gt;&lt;br /&gt;    dbsToPreserveList &lt;&lt; line.trim()    &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Archive Script&lt;br /&gt;if (archiveScript.exists()) archiveScript.write("")&lt;br /&gt;archiveScript.append('#!/bin/sh \n')&lt;br /&gt;dbsList.eachLine { line -&gt;&lt;br /&gt;    if(!dbsToPreserveList.contains(line)){&lt;br /&gt;        def dbName = line.trim()&lt;br /&gt;        archiveScript.append("mysqldump -p$password $dbName &gt; /tmp/$scriptBackupFolder/${dbName}.sql \n")&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;archiveScript.append('cd /tmp \n')&lt;br /&gt;archiveScript.append("tar -czf dbArchives${(new Date()).getTime()}.tgz $scriptBackupFolder \n")&lt;br /&gt;&lt;/pre&gt; &lt;br /&gt;&lt;br /&gt;Next, I created the sql to delete all the relevant databases&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:groovy"&gt;&lt;br /&gt;// SQL Script&lt;br /&gt;if (sqlScript.exists()) sqlScript.write("")&lt;br /&gt;dbsList.eachLine { line -&gt;&lt;br /&gt;    if(!dbsToPreserveList.contains(line) &amp;&amp; !line.contains('-')){&lt;br /&gt;        def dbName = line.trim()        &lt;br /&gt;        sqlScript.append("DROP DATABASE IF EXISTS $dbName;\n")&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Using my newly created files, has saved me so much time, and kept me from doing oh so tedious work. Thanks again &lt;a href="http://groovy.codehaus.org/"&gt;Groovy&lt;/a&gt;!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3675576906879941038-2963072694413194733?l=programming34m0.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programming34m0.blogspot.com/feeds/2963072694413194733/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://programming34m0.blogspot.com/2009/12/using-groovy-scripting-to-remove.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/2963072694413194733'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/2963072694413194733'/><link rel='alternate' type='text/html' href='http://programming34m0.blogspot.com/2009/12/using-groovy-scripting-to-remove.html' title='Using Groovy Scripting To Remove Unwanted MySQL Databases'/><author><name>Eamonn O'Connell</name><uri>http://www.blogger.com/profile/17064544953690759392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://2.bp.blogspot.com/_vC3SkHYsTQs/TBHf_uhM1_I/AAAAAAAAAn4/YLzceffi1_c/S220/profilePic.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3675576906879941038.post-3434854974490071053</id><published>2009-12-08T07:41:00.001-08:00</published><updated>2009-12-08T08:07:23.923-08:00</updated><title type='text'>Overriding Domain Class Getters and Setters in Grails</title><content type='html'>One might assume that it is possible to override getters and setters in the following manner:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: groovy"&gt;&lt;br /&gt;def setName(String name){&lt;br /&gt;//do stuff&lt;br /&gt;}&lt;br /&gt;def getName(){&lt;br /&gt;//do stuff&lt;br /&gt;return name&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;but infact static typing is required&lt;br /&gt;&lt;pre class="brush: groovy"&gt;&lt;br /&gt;public void setName(String name){&lt;br /&gt;//do stuff&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public String getName(){&lt;br /&gt;//do stuff&lt;br /&gt;return name&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3675576906879941038-3434854974490071053?l=programming34m0.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programming34m0.blogspot.com/feeds/3434854974490071053/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://programming34m0.blogspot.com/2009/12/overriding-domain-class-getters-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/3434854974490071053'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/3434854974490071053'/><link rel='alternate' type='text/html' href='http://programming34m0.blogspot.com/2009/12/overriding-domain-class-getters-and.html' title='Overriding Domain Class Getters and Setters in Grails'/><author><name>Eamonn O'Connell</name><uri>http://www.blogger.com/profile/17064544953690759392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://2.bp.blogspot.com/_vC3SkHYsTQs/TBHf_uhM1_I/AAAAAAAAAn4/YLzceffi1_c/S220/profilePic.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3675576906879941038.post-1402468408114781027</id><published>2009-12-05T11:02:00.000-08:00</published><updated>2009-12-06T06:23:54.738-08:00</updated><title type='text'>My Data Nest Registration Error</title><content type='html'>&lt;a href="http://www.mydatanest.com"&gt;mydatanest&lt;/a&gt; can't handle us Irish, or at least our names.&lt;br /&gt;This error appeared to me, on my first attempt at registration:&lt;br /&gt;&lt;pre class="brush: sql"&gt;&lt;br /&gt;MySQL Error: You have an error in your SQL syntax;&lt;br /&gt; check the manual that corresponds to your MySQL server version &lt;br /&gt;for the right syntax to use near 'Connell',`address`='Dublin',`refferal_id`=NULL,`phone`='',&lt;br /&gt;`max_messages`='20000'' at line 1 on line 244 &lt;br /&gt;in /home/datan3st/public_html/account.php&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3675576906879941038-1402468408114781027?l=programming34m0.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programming34m0.blogspot.com/feeds/1402468408114781027/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://programming34m0.blogspot.com/2009/12/data-nest.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/1402468408114781027'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/1402468408114781027'/><link rel='alternate' type='text/html' href='http://programming34m0.blogspot.com/2009/12/data-nest.html' title='My Data Nest Registration Error'/><author><name>Eamonn O'Connell</name><uri>http://www.blogger.com/profile/17064544953690759392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://2.bp.blogspot.com/_vC3SkHYsTQs/TBHf_uhM1_I/AAAAAAAAAn4/YLzceffi1_c/S220/profilePic.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3675576906879941038.post-5327367854413124893</id><published>2009-12-04T01:19:00.000-08:00</published><updated>2009-12-06T06:10:37.202-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='grails'/><title type='text'>Grails doesn't handle gstrings in controllers</title><content type='html'>You would expect Groovy gstrings and plain strings to be interchangable in Grails, but today I discovered that it is not so. In a Grails controller calling the redirect operation like this works:&lt;br /&gt;&lt;pre class="brush: groovy"&gt;&lt;br /&gt;redirect(action:'step1') // redirects to step1&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;but like this does not, and it redirects to the default index action&lt;br /&gt;&lt;pre class="brush: groovy"&gt;&lt;br /&gt;redirect(action:"step${getNextStep()}") //redirects to next step if it worked&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;the temporary solution to achieve dynamic actions is to convert the gstring into a string like so:&lt;br /&gt;&lt;pre class="brush: groovy"&gt;&lt;br /&gt;redirect(action:"step${getNextStep()}".toString())&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3675576906879941038-5327367854413124893?l=programming34m0.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programming34m0.blogspot.com/feeds/5327367854413124893/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://programming34m0.blogspot.com/2009/12/grails-doesnt-handle-gstrings-in.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/5327367854413124893'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/5327367854413124893'/><link rel='alternate' type='text/html' href='http://programming34m0.blogspot.com/2009/12/grails-doesnt-handle-gstrings-in.html' title='Grails doesn&apos;t handle gstrings in controllers'/><author><name>Eamonn O'Connell</name><uri>http://www.blogger.com/profile/17064544953690759392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://2.bp.blogspot.com/_vC3SkHYsTQs/TBHf_uhM1_I/AAAAAAAAAn4/YLzceffi1_c/S220/profilePic.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3675576906879941038.post-8346328218518087311</id><published>2009-12-03T07:00:00.000-08:00</published><updated>2009-12-06T06:10:29.274-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='groovy'/><title type='text'>Kris Kindle / Secret Santa the Groovy Way</title><content type='html'>In efforts to explain to folks in the office how secret santa works I directed them to take a look at this &lt;a href="http://en.wikipedia.org/wiki/Secret_Santa"&gt;secret santa definition&lt;/a&gt; or alternatively to examine the following groovy code:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: groovy"&gt;&lt;br /&gt;def ezbPeeps  = User.findByCompanyName('eazybusiness')&lt;br /&gt;def hatOfNames = ezbPeeps.collect{it.name}&lt;br /&gt;ezbPeeps.each { peep -&gt;&lt;br /&gt;&lt;br /&gt;        def goodPick = null&lt;br /&gt;        while(!goodPick){&lt;br /&gt;                def randomInteger = RandomInteger.getGenerate()&lt;br /&gt;                assert randomInteger &gt; 0&lt;br /&gt;                def index = randomInteger%hatOfNames.size()&lt;br /&gt;                switch( hatOfNames[index] ){&lt;br /&gt;                        case peep.name:&lt;br /&gt;                                goodPick = false&lt;br /&gt;                                break&lt;br /&gt;                        default:&lt;br /&gt;                                goodPick = true&lt;br /&gt;                                print "${peep.name} gets ${hatOfNames[index]}"&lt;br /&gt;                                hatOfNames.remove(index)&lt;br /&gt;                                break                        &lt;br /&gt;                }&lt;br /&gt;        }       &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;        &lt;br /&gt;mistakes on a postcard to Eamonn O'Connell, Saasplex, 3015 Lake View&lt;br /&gt;Drive, Citywest, Dublin, Ireland&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3675576906879941038-8346328218518087311?l=programming34m0.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programming34m0.blogspot.com/feeds/8346328218518087311/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://programming34m0.blogspot.com/2009/12/kris-kindle-secret-santa-groovy-way.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/8346328218518087311'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/8346328218518087311'/><link rel='alternate' type='text/html' href='http://programming34m0.blogspot.com/2009/12/kris-kindle-secret-santa-groovy-way.html' title='Kris Kindle / Secret Santa the Groovy Way'/><author><name>Eamonn O'Connell</name><uri>http://www.blogger.com/profile/17064544953690759392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://2.bp.blogspot.com/_vC3SkHYsTQs/TBHf_uhM1_I/AAAAAAAAAn4/YLzceffi1_c/S220/profilePic.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3675576906879941038.post-2105784462975528197</id><published>2009-12-03T04:22:00.000-08:00</published><updated>2009-12-06T06:10:16.222-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><title type='text'>Ubuntu adds did you mean to command line</title><content type='html'>Just miss spell a command in the the terminal window to see what I mean.&lt;br /&gt;&lt;br /&gt;I mistyped pico as pioc and recieved the following response:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: bash"&gt;&lt;br /&gt;pioc&lt;br /&gt;No command 'pioc' found, did you mean:&lt;br /&gt; Command 'pico' from package 'nano' (main)&lt;br /&gt; Command 'pico' from package 'alpine-pico' (universe)&lt;br /&gt; Command 'pic' from package 'groff-base' (main)&lt;br /&gt;pioc: command not found&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This appears to be one of the added benefits of the Karmic release. Pretty cool!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3675576906879941038-2105784462975528197?l=programming34m0.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programming34m0.blogspot.com/feeds/2105784462975528197/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://programming34m0.blogspot.com/2009/12/ubuntu-adds-did-you-mean-to-command.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/2105784462975528197'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/2105784462975528197'/><link rel='alternate' type='text/html' href='http://programming34m0.blogspot.com/2009/12/ubuntu-adds-did-you-mean-to-command.html' title='Ubuntu adds did you mean to command line'/><author><name>Eamonn O'Connell</name><uri>http://www.blogger.com/profile/17064544953690759392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://2.bp.blogspot.com/_vC3SkHYsTQs/TBHf_uhM1_I/AAAAAAAAAn4/YLzceffi1_c/S220/profilePic.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3675576906879941038.post-8293286692257206140</id><published>2009-11-30T07:30:00.000-08:00</published><updated>2009-12-06T06:21:52.229-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='git'/><title type='text'>Git Pack Error</title><content type='html'>I believe this error occurred when a pack operation was interupted during a push operation:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: bash"&gt;&lt;br /&gt;Counting objects: 338, done.&lt;br /&gt;warning: suboptimal pack - out of memory&lt;br /&gt;fatal: Out of memory, malloc failed   &lt;br /&gt;error: pack-objects died with strange error&lt;br /&gt;error: failed to push some refs to 'ssh://build@192.168.0.17/~build/dev/git-public/platform/billing/billing'&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The solution that worked for me:&lt;br /&gt;&lt;pre class="brush: bash"&gt;&lt;br /&gt;git repack -adf --window-memory=100M&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3675576906879941038-8293286692257206140?l=programming34m0.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programming34m0.blogspot.com/feeds/8293286692257206140/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://programming34m0.blogspot.com/2009/11/git-error.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/8293286692257206140'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/8293286692257206140'/><link rel='alternate' type='text/html' href='http://programming34m0.blogspot.com/2009/11/git-error.html' title='Git Pack Error'/><author><name>Eamonn O'Connell</name><uri>http://www.blogger.com/profile/17064544953690759392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://2.bp.blogspot.com/_vC3SkHYsTQs/TBHf_uhM1_I/AAAAAAAAAn4/YLzceffi1_c/S220/profilePic.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3675576906879941038.post-4827610353389440623</id><published>2009-11-30T05:29:00.000-08:00</published><updated>2009-12-06T06:18:31.419-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='grails'/><title type='text'>Hibernate Exception in Grails when dealing with exceptions</title><content type='html'>HibernateException: Found shared references to a collection&lt;br /&gt;&lt;br /&gt;Like me, you may have have caused this error by having something like the following &lt;br /&gt;&lt;pre class="brush: groovy"&gt;&lt;br /&gt;sale2.discounts = sale1.discounts&lt;br /&gt;sale2.save()&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The solution in my case was to do the following:&lt;br /&gt;&lt;pre class="brush: groovy"&gt;&lt;br /&gt;sale1.discounts.each { d-&gt;&lt;br /&gt;    sale2.discounts &lt;&lt; d&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3675576906879941038-4827610353389440623?l=programming34m0.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programming34m0.blogspot.com/feeds/4827610353389440623/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://programming34m0.blogspot.com/2009/11/hibernate-exception-in-grails-when.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/4827610353389440623'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/4827610353389440623'/><link rel='alternate' type='text/html' href='http://programming34m0.blogspot.com/2009/11/hibernate-exception-in-grails-when.html' title='Hibernate Exception in Grails when dealing with exceptions'/><author><name>Eamonn O'Connell</name><uri>http://www.blogger.com/profile/17064544953690759392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://2.bp.blogspot.com/_vC3SkHYsTQs/TBHf_uhM1_I/AAAAAAAAAn4/YLzceffi1_c/S220/profilePic.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3675576906879941038.post-3581421628221605033</id><published>2009-11-30T04:35:00.000-08:00</published><updated>2009-12-06T06:16:53.011-08:00</updated><title type='text'>Quick Solution to Godaddy Certs not working in Java</title><content type='html'>If your experiencing problems with godaddy certs (generally an SSLHandshakes error) when using Java (perhaps with HttpClient), the following may solve your problem quickly.&lt;br /&gt;&lt;br /&gt;Note: this was done on Ubuntu, so you may need to adjust it to your OS.&lt;br /&gt;&lt;pre class="brush: bash"&gt;&lt;br /&gt;wget 'http://blogs.sun.com/andreas/resource/InstallCert.java'&lt;br /&gt;&lt;br /&gt;javac InstallCert.java&lt;br /&gt;&lt;br /&gt;java InstallCert $mydomainname &lt;br /&gt;#respond to prompt with return&lt;br /&gt;&lt;br /&gt;sudo cp jssecacerts $JAVA_HOME/jre/lib/security&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3675576906879941038-3581421628221605033?l=programming34m0.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programming34m0.blogspot.com/feeds/3581421628221605033/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://programming34m0.blogspot.com/2009/11/quick-solution-to-godaddy-certs-not.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/3581421628221605033'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/3581421628221605033'/><link rel='alternate' type='text/html' href='http://programming34m0.blogspot.com/2009/11/quick-solution-to-godaddy-certs-not.html' title='Quick Solution to Godaddy Certs not working in Java'/><author><name>Eamonn O'Connell</name><uri>http://www.blogger.com/profile/17064544953690759392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://2.bp.blogspot.com/_vC3SkHYsTQs/TBHf_uhM1_I/AAAAAAAAAn4/YLzceffi1_c/S220/profilePic.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3675576906879941038.post-4002290464787188738</id><published>2009-11-13T04:56:00.000-08:00</published><updated>2009-12-06T06:03:42.762-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='grails taglib ajax'/><title type='text'>grails remotefunction limitation</title><content type='html'>I stumbled apon a limitation of the grails remote function today. I have two drop down lists Products and Prices, with the Prices dependent on the particular Product selected, and also the customer in question. In order to achieve this, I needed to pass two params to the remote method. &lt;br /&gt;&lt;br /&gt;There are two ways of using the params attribute of the &lt;a href="http://docs.codehaus.org/display/GRAILS/Tag+-+remoteFunction"&gt;remotefunction&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;Option 1:&lt;br /&gt;&lt;br /&gt;You can pass a string &lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: xml"&gt;&lt;br /&gt;&amp;lt;select onchange="${remoteFunction(action:'getRightPriceForProduct',update:'price', params:'\'productId=\' + this.value\'' )}"&gt;&lt;br /&gt;&lt;option&gt;product1&lt;/option&gt;&lt;br /&gt;    &lt;option&gt;product2&lt;/option&gt;&lt;br /&gt;&amp;lt;/select&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Option 2:&lt;br /&gt;&lt;br /&gt;you can pass a map&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: xml"&gt;&lt;br /&gt;&amp;lt;select onchange="${remoteFunction(action:'getRightPriceForProduct',update:'price', params:[customerId:customer.id])}"&gt;&lt;br /&gt;    &lt;option&gt;product1&lt;/option&gt;&lt;br /&gt;    &lt;option&gt;product2&lt;/option&gt;&lt;br /&gt;&amp;lt;/select&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Option 1 allows me to use 'this' in javascript to send the product selected, and option 2 allows me to pass the customer's id at the page rendering time, but neither option allows me to do both at the same time.&lt;br /&gt;&lt;br /&gt;One solution to choose option 1, and use document.getElementById to retrieve the value of the customer id&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: xml"&gt;&lt;br /&gt;&amp;lt;select onchange="${remoteFunction(action:'getRightPriceForProduct',update:'price', params:'\'productId + \'&amp;document.getElementById(\'customerId\')'&lt;br /&gt;params:'\'customerI=\'document.getElementById(\'customerid\').value\'&amp;productId= \' + this.value\')}"&gt;&lt;br /&gt;&lt;option&gt;product1&lt;/option&gt;&lt;br /&gt;&lt;option&gt;product2&lt;/option&gt;&lt;br /&gt;&amp;lt;/select&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A better solution is to implement your own taglib funtion like this&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: groovy"&gt;&lt;br /&gt;def ezbRemoteFuction= { attrs, body -&gt;&lt;br /&gt;    def params = attrs['params']?:null&lt;br /&gt;    if(params){&lt;br /&gt;    String pString = "\'"&lt;br /&gt;    params.each { key, value -&gt;&lt;br /&gt;    pString += "${key}=${value}&amp;"&lt;br /&gt;    }&lt;br /&gt;    pString += "\'"&lt;br /&gt;    attrs['params'] = pString;&lt;br /&gt;    }&lt;br /&gt;    out &lt;&lt; g.remoteFunction(attrs, body)&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3675576906879941038-4002290464787188738?l=programming34m0.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://programming34m0.blogspot.com/feeds/4002290464787188738/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://programming34m0.blogspot.com/2009/11/grails-remotefunction-limitation.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/4002290464787188738'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3675576906879941038/posts/default/4002290464787188738'/><link rel='alternate' type='text/html' href='http://programming34m0.blogspot.com/2009/11/grails-remotefunction-limitation.html' title='grails remotefunction limitation'/><author><name>Eamonn O'Connell</name><uri>http://www.blogger.com/profile/17064544953690759392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://2.bp.blogspot.com/_vC3SkHYsTQs/TBHf_uhM1_I/AAAAAAAAAn4/YLzceffi1_c/S220/profilePic.JPG'/></author><thr:total>0</thr:total></entry></feed>
