<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>puredanger.com Blog</title>
	<atom:link href="http://puredanger.com/kablooie/index.php/feed/" rel="self" type="application/rss+xml" />
	<link>http://puredanger.com/kablooie</link>
	<description>Scott Bale's technical blog</description>
	<lastBuildDate>Tue, 23 Jun 2009 15:19:57 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Things Afoot</title>
		<link>http://puredanger.com/kablooie/2009/06/11/things-afoot/</link>
		<comments>http://puredanger.com/kablooie/2009/06/11/things-afoot/#comments</comments>
		<pubDate>Fri, 12 Jun 2009 00:47:33 +0000</pubDate>
		<dc:creator>Scott</dc:creator>
				<category><![CDATA[Emerging Solutions]]></category>
		<category><![CDATA[Lambda Lounge]]></category>
		<category><![CDATA[St. Louis IT]]></category>

		<guid isPermaLink="false">http://puredanger.com/kablooie/2009/06/11/things-afoot/</guid>
		<description><![CDATA[Here&#8217;s what I&#8217;m up to these days:
I now work for the Emerging Solutions group of BJC HealthCare.  So far I&#8217;m loving it.  I&#8217;ve been reunited with a couple of colleagues: Pat, who I worked with at MetaMatrix, and Paul who I worked with at Monsanto.  My timing was fortunate: my first real [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s what I&#8217;m up to these days:</p>
<p>I now work for the Emerging Solutions group of <a href="http://www.bjc.org/">BJC HealthCare</a>.  So far I&#8217;m loving it.  I&#8217;ve been reunited with a couple of colleagues: <a href="http://blog.muddyhorse.com/">Pat</a>, who I worked with at <a href="http://www.metamatrix.com/">MetaMatrix</a>, and <a href="http://paul.caffeinatedbliss.com/">Paul</a> who I worked with at Monsanto.  My timing was fortunate: my first real work is to be on a team that is kicking off a new, large web portal.  Technology includes Spring (MVC, Web Flow, Security), Hibernate, Velocity, Maven, CVS, web services.  Development tools are Eclipse, the Atlassian tools (Bamboo, FishEye, Crucible, Jira, Confluence), GreenHopper (a Jira plugin giving a Scrum-centric view).  We do scrum and even have two certified ScrumMasters.</p>
<p>Another colleague, <a href="http://www.objectcommando.com/blog/">Ryan Senior,</a> has started within ES a shadowy secret cabal known as the Dead Coders Society.  The group meets informally for an hour every few weeks and discusses some technology, book, or whatnot.  We met this week, it was my second meeting; the group has just finished up <a href="www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882">Bob Martin&#8217;s Clean Code</a> and then we voted on what to do next.  We ultimately decided to read Guy Steele&#8217;s two <a href="http://library.readscheme.org/page1.html">Lambda Papers</a> in preparation for tackling <a href="http://www.realworldhaskell.org/">Real World Haskell</a>.</p>
<p>Which segues nicely into the <a href="http://lambdalounge.org/">Lambda Lounge</a>.  This local functional and dynamic languages interest group has given me, and many others, the language itch.  I believe Ryan (another regular) got the idea from λL to propose both the lambda papers and Real World Haskell.  There has already been <a href="http://codetojoy.blogspot.com/2009/04/monads-102-using-haskell-online-or.html">one Haskell presentation</a>, and there are two more <a href="http://lambdalounge.org/schedule/">scheduled</a>.  I&#8217;ll be presenting on the <a href="http://fandev.org/">Fan</a> programming language in July.  Fan is considerably less mind-bending for a Java programmer than something like Haskell, but nonetheless it is an enjoyable learning experience and I&#8217;m looking forward to presenting.  I also implemented a <a href="http://github.com/scottbale/vendingmachine-fan/tree">Fan vending machine</a> for the <a href="http://lambdalounge.org/2009/05/05/may-meeting/">language shootout</a> last month.</p>
<p>In other news, earlier this year I released a new version of my church&#8217;s <a href="http://www.kirkwoodcoc.org/">website</a> which I built using WordPress.  It&#8217;s central feature is essentially a podcast of the audio of each sermon.  I&#8217;d like to blog more about this in great deal, I learned quite a bit in the process.  While I&#8217;m happy with the result &#8211; it is a quantum leap beyond the old site &#8211; I&#8217;ve already got a long mental list of improvements.  First up &#8211; refactor away a lot of hardcoded behavior and, if possible, find or make WordPress plugins instead.</p>
<p>By the way, as I publish this I am sitting in the audience of the <a href="http://www.ociweb.com/javasig/">St. Louis Java User&#8217;s Group</a>, watching <a href="http://weblog.dangertree.net/">Matt Taylor</a> present about <a href="http://groovy.codehaus.org/">Groovy</a> and Test Driven Development.  He is writing an application from scratch live on stage using Groovy and TDD.</p>
]]></content:encoded>
			<wfw:commentRss>http://puredanger.com/kablooie/2009/06/11/things-afoot/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Google Chrome + remapped keys = True Love</title>
		<link>http://puredanger.com/kablooie/2009/04/11/google-chrome-remapped-keys-true-love/</link>
		<comments>http://puredanger.com/kablooie/2009/04/11/google-chrome-remapped-keys-true-love/#comments</comments>
		<pubDate>Sun, 12 Apr 2009 02:53:56 +0000</pubDate>
		<dc:creator>Scott</dc:creator>
				<category><![CDATA[Chrome]]></category>

		<guid isPermaLink="false">http://puredanger.com/kablooie/2009/04/11/google-chrome-remapped-keys-true-love/</guid>
		<description><![CDATA[I know I&#8217;m a little late to this party, but I have fallen in love with Google Chrome.  I have made it my main browser at work and now at home.  Once it&#8217;s available for Mac, there&#8217;s a good chance I&#8217;ll make the transition there, too.
The thing about Chrome is, 90% of the [...]]]></description>
			<content:encoded><![CDATA[<p>I know I&#8217;m a little late to this party, but I have fallen in love with <a href="http://www.google.com/chrome">Google Chrome</a>.  I have made it my main browser at work and now at home.  Once it&#8217;s available for Mac, there&#8217;s a good chance I&#8217;ll make the transition there, too.</p>
<p>The thing about Chrome is, 90% of the time what I want to do with the browser is google for something.  With Chrome this is so optimized, it&#8217;s the closest thing on Windows that&#8217;s felt like <a href="http://www.blacktree.com/">QuickSilver</a>.  This is what I find myself doing multiple times per hour at work:</p>
<ol>
<li><code>alt-tab</code> to Chrome</li>
<li><code>ctrl-t</code> opens a new tab and automatically places the cursor in the multi-purpose address/search bar</li>
<li>type search text, hit enter, done</li>
</ol>
<p>Only then, when the search results are up, do I have to reach for my mouse and select one.  And in fact, often when typing the search criteria Chrome will display the top search results as I type, allowing me to select one with the arrow keys and bring up a search result without ever touching the mouse.</p>
<p><img id="image52" src="http://puredanger.com/kablooie/wp-content/uploads/2009/04/chrome.png" alt="Chrome" /></p>
<p>On a related note, and I&#8217;m definitely late to this party &#8211; I can&#8217;t believe I&#8217;ve lived this long without remapping my <code>Caps Lock</code> and left <code>Ctrl</code> keys!  I&#8217;ve done this at work and now at home, and it feels like typing on silk!</p>
<p>The one twist is that I share this home XP box with my wife, so the registry key I edited was:</p>
<p><code>HKEY_CURRENT_USER\Keyboard Layout</code></p>
<p>Instead of the local machine.  This seems to work.</p>
<p>A couple nice quick Chrome key-combos (many of these are not specific to Chrome, of course):</p>
<ul>
<li><code>ctrl-t</code> &#8211; new tab</li>
<li><code>ctrl-shift-t</code> &#8211; reopen most-recently-closed tab</li>
<li><code>ctrl-w</code> &#8211; close current tab</li>
<li><code>ctrl-tab</code> &#8211; next tab</li>
<li><code>ctrl-shift-tab</code> &#8211; previous tab</li>
<li><code>ctrl-h</code> &#8211; history</li>
<li><code>ctrl-j</code> &#8211; downloads</li>
<li><code>ctrl-d</code> &#8211; bookmark current page</li>
<li><code>ctrl-b</code> &#8211; show/hide bookmarks bar</li>
<li><code>ctrl-shift-b</code> &#8211; bookmark manager</li>
<li><code>shift-Esc</code> &#8211; Google Chrome Task Manager (shows mem/CPU/network for each Chrome process (each tab is a separate process))</li>
</ul>
<p>I still like Firefox, especially when I&#8217;m using the <a href="http://getfirebug.com/">Firebug</a> plugin.  But there&#8217;s just something about Chrome, so slick, so clean&#8230;</p>
<p>Update: a coworker just suggested I search for <code>about:internets</code> in Chrome:</p>
<p><img id="image53" src="http://puredanger.com/kablooie/wp-content/uploads/2009/04/internets.png" alt="about:internets" /></p>
]]></content:encoded>
			<wfw:commentRss>http://puredanger.com/kablooie/2009/04/11/google-chrome-remapped-keys-true-love/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Got my Geek Fix at the Lambda Lounge</title>
		<link>http://puredanger.com/kablooie/2009/04/02/got-my-geek-fix-at-the-lambda-lounge/</link>
		<comments>http://puredanger.com/kablooie/2009/04/02/got-my-geek-fix-at-the-lambda-lounge/#comments</comments>
		<pubDate>Fri, 03 Apr 2009 03:38:54 +0000</pubDate>
		<dc:creator>Scott</dc:creator>
				<category><![CDATA[St. Louis IT]]></category>

		<guid isPermaLink="false">http://puredanger.com/kablooie/2009/04/02/got-my-geek-fix-at-the-lambda-lounge/</guid>
		<description><![CDATA[Once again, the Lambda Lounge did not disappoint.
This month&#8217;s mind-bending topics included Factor, presented by Kyle Cordes, and Perl 6/Parrot, presented by Charles Sharp.  Both of these guys are great speakers, I make it a point not to miss their talks.
Appistry again very generously hosted the λ Lounge and supplied Fortel&#8217;s pizza and beverages.
Jim [...]]]></description>
			<content:encoded><![CDATA[<p>Once again, the <a href="http://lambdalounge.org/">Lambda Lounge</a> did not disappoint.</p>
<p>This month&#8217;s mind-bending topics included <a href="http://factorcode.org/">Factor</a>, presented by <a href="http://kylecordes.com/">Kyle Cordes</a>, and <a href="http://dev.perl.org/perl6/">Perl 6</a>/<a href="http://www.parrot.org/">Parrot</a>, presented by Charles Sharp.  Both of these guys are great speakers, I make it a point not to miss their talks.</p>
<p><a href="http://www.appistry.com">Appistry</a> again very generously hosted the λ Lounge and supplied Fortel&#8217;s pizza and beverages.</p>
<p>Jim Brasunas took a few minutes to talk about <a href="http://www.innovatestl.org/ITEN.html">ITEN</a>, a non-profit group which helps support ventures and startups.  I think everyone was surprised to hear that there are nearly 100 technology-related startups in the St. Louis area.</p>
<p>We&#8217;ve been really spoiled by some great presentations and great speakers, so I don&#8217;t know what I was thinking when I volunteered to speak about the <a href="http://www.fandev.com/">Fan</a> programming language in <a href="http://lambdalounge.org/schedule/">July</a>.  Tonight I took notes during both talks, and I think I&#8217;ve spotted a few patterns that help to make any programming language presentation better.</p>
<ol>
<li>Go ahead and do a Hello World program, but&#8230;</li>
<li>&#8230;a fibonacci sequence program has emerged as a must-have.  It&#8217;s like the new Hello World.</li>
<li>Keep things moving along.  The slides/software can always be made available later or even made into handouts, as Kyle did.</li>
<li>I like to hear just enough background to get an appreciation of where the language is coming from.  What persons are involved?  What are they trying to accomplish?  What (if any) languages preceeded this language?  Kyle and Charles both struck just the right note here, imho.</li>
<li>How concise is the language? How productive does it make you?</li>
<li>What real-world projects/accomplishments are associated with this language?</li>
<li>What idioms are unique/advantageous in this language?</li>
</ol>
<p>I&#8217;m very much looking forward to the <a href="http://lambdalounge.org/schedule/">language shootout</a> next month, as I believe everyone is.</p>
]]></content:encoded>
			<wfw:commentRss>http://puredanger.com/kablooie/2009/04/02/got-my-geek-fix-at-the-lambda-lounge/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Revamping Church Website</title>
		<link>http://puredanger.com/kablooie/2008/12/27/revamping-church-website/</link>
		<comments>http://puredanger.com/kablooie/2008/12/27/revamping-church-website/#comments</comments>
		<pubDate>Sat, 27 Dec 2008 06:51:34 +0000</pubDate>
		<dc:creator>Scott</dc:creator>
				<category><![CDATA[church website]]></category>

		<guid isPermaLink="false">http://puredanger.com/kablooie/2008/12/27/revamping-church-website/</guid>
		<description><![CDATA[I attend church services at the Kirkwood Church of Christ, and have for almost my whole life.  In around 2005 I helped create the church website and have maintained it ever since.  It is extremely basic, made entirely of static file content.  It uses frames.  Boilerplate HTML (the header for example) [...]]]></description>
			<content:encoded><![CDATA[<p>I attend church services at the <a href="http://www.kirkwoodcoc.org/">Kirkwood Church of Christ</a>, and have for almost my whole life.  In around 2005 I helped create the church website and have maintained it ever since.  It is extremely basic, made entirely of static file content.  It uses frames.  Boilerplate HTML (the header for example) is copied into almost every HTML file.  This is a website that would have been unimpressive back in 1997.  It is extremely mundane and time-consuming to make almost any changes or addition to the content, and I have very little time to spare.</p>
<p>So I am redoing it from scratch, in the hope that some much-needed work this month will make future changes much easier.  The main catalyst is that we want to be able to post the audio from every sermon, basically a podcast.  A slightly less high priority would be to set up a blog for the preacher (L.A. Stauffer) and fold the existing &#8220;bulletin articles&#8221; into that.  While I&#8217;m at it, I&#8217;d like to do a proper CSS layer, and if time permits I&#8217;d definitely like to add some <a href="http://jquery.com/">jQuery</a> goodness.</p>
<p>I decided it would be a good idea to blog my progress, for my own information if nothing else.  So here goes.</p>
<h2>Settling on a stack</h2>
<p>(I stole that phrase from <a href="http://tech.puredanger.com/2008/07/29/settling-on-a-stack/">Alex&#8217;s</a> blog entry, about the <a href="http://www.terracotta.org/web/display/orgsite/Web+App+Reference+Implementation">reference web app</a> we implemented for <a href="http://www.terracotta.org/">Terracotta</a>.)</p>
<p><a href="en.wikipedia.org/wiki/LAMP_(software_bundle)">LAMP</a> will be the stack, basically.  We are using <a href="http://www.ipower.com/">ipower for web hosting</a>.  The server environment they have us hosted on, in a nutshell, is Debian, MySQL 5.0.45, Perl 5.8.8, PHP 4.4.7.  Which is great, because I was thinking I wanted to use <a href="http://wordpress.org/">Wordpress</a> for the sermon podcast.  I decided I would do the work on my work MacBook Pro, I would use <a href="http://git.or.cz/">git</a> for version control, and I would try to set everything up to run locally on the MBP before promoting to production.</p>
<p>By the way, I&#8217;ve never programmed in PHP before.</p>
<h2>Day One</h2>
<p>I spent about eight hours on Tuesday the 23rd getting started.  By the end of the night I had installed <a href="http://httpd.apache.org/>apache</a> server, <a href="http://www.php.net/">PHP</a> and Wordpress on my MBP, set it up with <a href="http://www.mysql.com/">mysql</a>, and had a running empty Wordpress blog running on my localhost.  Here&#8217;re are some notes.</p>
<p>Apache 2.2.11 wouldn&#8217;t build on my box for some reason, so I reverted back to 2.0.63.  (The whole make process for that project is amazing, how it auto-detects various things about the environment it&#8217;s being built with.)  I decided I wanted to keep my project in a directory separate from the web server install, so I had to edit the httpd.conf file and add an <a href="http://httpd.apache.org/docs/2.0/mod/mod_alias.html">Alias</a> for that directory.</p>
<p>Wordpress has a nice <a href="http://codex.wordpress.org/Installing_WordPress#Famous_5-Minute_Install">famouse 5 minute install</a> that walked me through creating the mysql user/password and database, then editing the wp-config.php file to use it.  During this installation I realized I hadn&#8217;t installed PHP yet, so I <a href="http://us3.php.net/manual/en/install.unix.apache2.php">did that</a> (required more edits to httpd.conf).  Then the next <a href="http://wordpress.org/support/topic/160033">gotcha</a> &#8211; apparently the way mysql hashes passwords is incompatible with PHP 4.4.x (or something), so the password has to be created in mysql like this:</p>
<p><code>mysql> SET PASSWORD FOR 'username'@'localhost' = OLD_PASSWORD('supersecretpassword');</code></p>
<h2>Day Two</h2>
<p>Tonight was my second night of working on things.  My two accomplishments were to install <a href="http://git.or.cz/">git</a> and get the initial project structure into version control, and to install the <a href="http://www.eclipse.org/pdt/">Eclipse PDT</a> plugin for PHP development, and create an initial project out of the directory I&#8217;m working in.  I have yet to open a single PHP file or program a line of code, but it feels good getting this much of my development environment squared away.</p>
<p>I got some help from <a href="http://kylecordes.com/2008/04/30/git-windows-go/">Kyle Cordes&#8217; blog</a> about git, as well as the handout I kept from his talk at the <a href="http://www.ociweb.com/javasig/knowledgebase/2008-10/index.html">St. Louis Java User&#8217;s Group</a>.</p>
<p>Still a lot of unanswered questions.  In particular, I&#8217;m not sure if Wordpress will be a good enough fit for what I want to do.  I like the way Wordpress can do both blogs and static pages, so I&#8217;m hoping I can use a single installation of Wordpress to handle the main web site and also the podcasts, and I&#8217;m wondering if it&#8217;s possible (and easy enough) to modify Wordpress to be able to handle a separate blog (the preacher&#8217;s articles).  So, two (or more) blogs but just one site, one theme, one mysql database.  I&#8217;m guessing all the php can be modified to do this but I don&#8217;t really know.</p>
]]></content:encoded>
			<wfw:commentRss>http://puredanger.com/kablooie/2008/12/27/revamping-church-website/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Kyle Cordes presentation on Git tomorrow at St. Louis JUG</title>
		<link>http://puredanger.com/kablooie/2008/10/08/kyle-cordes-presentation-on-git-tomorrow-at-st-louis-jug/</link>
		<comments>http://puredanger.com/kablooie/2008/10/08/kyle-cordes-presentation-on-git-tomorrow-at-st-louis-jug/#comments</comments>
		<pubDate>Wed, 08 Oct 2008 18:22:52 +0000</pubDate>
		<dc:creator>Scott</dc:creator>
				<category><![CDATA[Git]]></category>
		<category><![CDATA[St. Louis IT]]></category>

		<guid isPermaLink="false">http://puredanger.com/kablooie/2008/10/08/kyle-cordes-presentation-on-git-tomorrow-at-st-louis-jug/</guid>
		<description><![CDATA[Just a quick post &#8211; tomorrow evening at the St. Louis Java User&#8217;s Group, Kyle Cordes will be giving a presentation on Git.  I&#8217;m looking forward to this both because Kyle is a very good and accomplished speaker on technical topics, and also because I&#8217;m eager to learn more about this distributed source control [...]]]></description>
			<content:encoded><![CDATA[<p>Just a quick post &#8211; tomorrow evening at the <a href="http://www.ociweb.com/javasig/">St. Louis Java User&#8217;s Group</a>, <a href="http://kylecordes.com/">Kyle Cordes</a> will be giving a presentation on <a href="http://git.or.cz/">Git</a>.  I&#8217;m looking forward to this both because Kyle is a very good and accomplished speaker on technical topics, and also because I&#8217;m eager to learn more about this distributed source control tool.  Hope to see you there!</p>
]]></content:encoded>
			<wfw:commentRss>http://puredanger.com/kablooie/2008/10/08/kyle-cordes-presentation-on-git-tomorrow-at-st-louis-jug/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Caching the Hot Stuff with Terracotta</title>
		<link>http://puredanger.com/kablooie/2008/10/06/caching-the-hot-stuff-with-terracotta/</link>
		<comments>http://puredanger.com/kablooie/2008/10/06/caching-the-hot-stuff-with-terracotta/#comments</comments>
		<pubDate>Mon, 06 Oct 2008 15:03:49 +0000</pubDate>
		<dc:creator>Scott</dc:creator>
				<category><![CDATA[Ehcache]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Terracotta]]></category>
		<category><![CDATA[Terracotta developer]]></category>

		<guid isPermaLink="false">http://puredanger.com/kablooie/2008/10/06/caching-the-hot-stuff-with-terracotta/</guid>
		<description><![CDATA[As I&#8217;ve been blogging about recently, we have been developing an exam-taking web application at Terracotta to demonstrate the Session Clustering capabilities of Terracotta.  Since one of the requirements of this web app is that we support 40,000 concurrent users, we thought we&#8217;d better cache the hottest exams (using Ehcache) rather than fetch them [...]]]></description>
			<content:encoded><![CDATA[<p>As I&#8217;ve been <a href="/kablooie/2008/10/06/hibernate-orm-can-lead-to-inflexibility-terracotta-can-help/">blogging about recently</a>, we have been developing an exam-taking web application at Terracotta to demonstrate the <a href="http://tech.puredanger.com/2008/07/08/narrowing-the-focus/">Session Clustering</a> capabilities of Terracotta.  Since one of the requirements of this web app is that we support 40,000 concurrent users, we thought we&#8217;d better cache the hottest exams (using <a href="http://ehcache.sourceforge.net/">Ehcache</a>) rather than fetch them from <a href="http://www.hibernate.org/">Hibernate</a> each time.  Since modifying an exam should occur far, far less frequently than taking an Exam, and since <a href="http://www.terracotta.org/confluence/display/howto/EHCache+Quick+Start">Terracotta already supports Ehcache</a>, this was a no-brainer.</p>
<p>There is an <code>ExamService</code> service, configured as a Spring bean, with <code>DaoExamService</code> being the default implementation:</p>
<textarea name="code" class="java:nocontrols:nogutter" cols="60" rows="10">
public interface ExamService extends BootstrapService {
  public Exam findById(Long id);
  public Exam createExam(Exam newExam);
  public Exam updateExam(Exam exam);
  …
}
</textarea>
<p>The <code>findById</code> method is expected to be the most frequently-invoked method. The other two methods shown are administrative functionality, not expected to be used frequently. We want to cache the results of all three methods in a single, clustered Exam cache.</p>
<p>My approach was to write a new service, <code>CachingWrapperExamService</code>, a proxy which owned the cache and which delegated to another <code>ExamService</code> instance:</p>
<textarea name="code" class="java:nocontrols:nogutter" cols="60" rows="10">
public class CachingWrapperExamService implements ExamService {
  private final ExamService examService;
  private final Ehcache cache;
   /* clustered by Terracotta */
  private final CacheManager cacheManager = CacheManager.getInstance();

  /* dependency injection via Spring */ 
  public CachingWrapperExamService(ExamService examService){ … }

  /* cache results when desired, delegate to examService */
  …
}
</textarea>
<p>The following were straightforward changes:</p>
<ul>
<li>Once again, our use of interfaces have reaped dividends: Introducing this new Caching <code>ExamService</code> was as easy as tweaking the Spring XML file &#8211; the change was completely transparent to all users of the <code>ExamService</code> bean. It also made unit testing easy, as I could create a mock <code>ExamService</code> to test caching with.</li>
<li>The Maven <code>pom.xml</code> had to be changed to note that Ehcache is now a compile-time dependency, not just a runtime dependency.</li>
<li>The Terracotta <a href="http://www.terracotta.org/confluence/display/docs1/Configuration+Guide+and+Reference">config file</a> <code>tc-config.xml</code> did not have to be modified, as we were already using the <a href="http://forge.terracotta.org/releases/projects/tim-ehcache/">Ehcache TIM</a>, and so our CacheManager was automatically clustered.</li>
</ul>
<p>And just like that, we have a clustered cache of the hottest exams being used.</p>
]]></content:encoded>
			<wfw:commentRss>http://puredanger.com/kablooie/2008/10/06/caching-the-hot-stuff-with-terracotta/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>ORM can lead to inflexibility; Terracotta can help</title>
		<link>http://puredanger.com/kablooie/2008/10/06/hibernate-orm-can-lead-to-inflexibility-terracotta-can-help/</link>
		<comments>http://puredanger.com/kablooie/2008/10/06/hibernate-orm-can-lead-to-inflexibility-terracotta-can-help/#comments</comments>
		<pubDate>Mon, 06 Oct 2008 14:26:10 +0000</pubDate>
		<dc:creator>Scott</dc:creator>
				<category><![CDATA[Hibernate]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Terracotta]]></category>
		<category><![CDATA[Terracotta developer]]></category>

		<guid isPermaLink="false">http://puredanger.com/kablooie/2008/10/06/hibernate-orm-can-lead-to-inflexibility-terracotta-can-help/</guid>
		<description><![CDATA[Okay, granted, I&#8217;m biased, I work for Terracotta.  Be that as it may, I&#8217;d like to share some experiences my teammates and I have had using Hibernate recently while developing a web app.
First, some brief background.  We are developing a &#8220;reference&#8221; web app at Terracotta to use to promote and explore the Sessions [...]]]></description>
			<content:encoded><![CDATA[<p>Okay, granted, I&#8217;m biased, I work for <a href="http://www.terracotta.org">Terracotta</a>.  Be that as it may, I&#8217;d like to share some experiences my teammates and I have had using <a href="http://www.hibernate.org/">Hibernate</a> recently while developing a web app.</p>
<p>First, some brief background.  We are developing a &#8220;reference&#8221; web app at Terracotta to use to promote and explore the <a href="http://tech.puredanger.com/2008/07/08/narrowing-the-focus/">Sessions Clustering Use Case</a> which we are working to nail.  The app is an online exam-taking application, with the goal of supporting 40,000 concurrent users.  I&#8217;ve <a href="/kablooie/2008/08/03/weekly-summary-web-app/">blogged</a> about this before, and you can read about the <a href="http://tech.puredanger.com/2008/07/29/settling-on-a-stack/">technology stack</a> we settled on.  Development has been done primarily by myself and my teammates <a href="http://rifers.org/blogs">Geert Bevin</a>, <a href="http://www.abhisanoujam.blogspot.com/">Abhishek Sanoujam</a>, and our supervisor <a href="http://tech.puredanger.com/">Alex Miller</a>.</p>
<p>Hibernate is wonderful, and it is an integral part of our web app.  It feels to me like we got moving pretty quickly using Hibernate for persistence of our domain objects.  For <a href="http://en.wikipedia.org/wiki/Object-relational_mapping">ORM</a>, it&#8217;s unbeatable.</p>
<p>But the thing I noticed is, there&#8217;s just no avoiding the fact that whatever your domain POJO&#8217;s are that need to be persisted, chances are good that the use of ORM will impose some constraints on how you must write those POJO&#8217;s.  I have two examples of this to share.</p>
<h3>Example One &#8211; Generics</h3>
<p>First, we have an exam Section class which, conceptually, is a container for either multiple sub sections, or Questions, but not both. The ideal solution would be to define Section as this (JPA annotations omitted):</p>
<textarea name="code" class="java:nocontrols:nogutter" cols="60" rows="10">
public class Section<E extends TestContent> {
  …
  public List<E> getContents(){...}
}
</textarea>
<p>where TestContent is an interface implemented by both Section and Question. Thus, an instance of Section could be declared as having type of either Section<Section> or Section<Question>, which satisfies our constraint.</p>
<p>However, at runtime (when starting Tomcat), Hibernate (the JPA provider) threw an exception pointing out that Section had an unbounded type (or something like that). After a little digging around on the internet, I found a <a href="http://forums.sun.com/thread.jspa?messageID=10125058">forum</a> where someone explained that an Entity cannot have a generic type, because it&#8217;s not known until instantiation time what the linked Entity will be.</p>
<p>Therefore I had to compromise. I modified Section, removing it&#8217;s generic type and adding two explicit collections, one for Questions, one for Sections. </p>
<textarea name="code" class="java:nocontrols:nogutter" cols="60" rows="10">
public class Section{
  ..
  public List<Section> getSections(){...}
  public List<Question> getQuestions(){...}
}
</textarea>
<p>This is less than ideal because the Section API itself doesn&#8217;t naturally prevent a single Section instance from having both sub-sections and questions, even though we don&#8217;t want to allow this.</p>
<h3>Example Two &#8211; complex object tree</h3>
<p>Similarly, for my other example, one of the constraints is that a Question must have exactly one correct choice (from among it&#8217;s two or more choices). So our first inclination was to structure the Question class thusly:</p>
<textarea name="code" class="java:nocontrols:nogutter" cols="60" rows="10">
@Entity
@Table(name = "QUESTION")
public class Question implements … {

@OneToOne private Choice correctChoice;

@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) 
private List<Choice> choices;
}
</textarea>
<p>But this caused problems when saving an edited Exam which had had a Question added to it. I no longer have the stack trace handy, but the gist of the Hibernate exception was that a transient (unsaved) object was detected in the object graph being merged (updated).</p>
<p>Alex and I dug in and finally examined the generated database schema. What we saw was that the QUESTION table had a CORRECT_CHOICE column which was a foreign key into another table, QUESTION_CHOICE I think it was. Alex and I theorized that there was a possible ordering problem in updating an Exam with a new Question and Choices &#8211; what if Hibernate attempted to set the CORRECT_CHOICE foreign key before inserting the new choices for the question?</p>
<p>I&#8217;m not 100% positive that&#8217;s the correct explanation, but in any case Alex made the executive decision to simplify our domain model and not spend any more time debugging. We added a boolean &#8220;isCorrect&#8221; property to Choice, and removed the &#8220;correctChoice&#8221; reference from Question:</p>
<textarea name="code" class="java:nocontrols:nogutter" cols="60" rows="10">
@Entity
@Table(name = "QUESTION")
public class Question implements … {

@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) 
private List<Choice> choices;

}
</textarea>
<textarea name="code" class="java:nocontrols:nogutter" cols="60" rows="10">
@Entity
@Table(name = "CHOICE")
public class Choice implements … {

@Column(name = "IS_CORRECT") @Type(type = "yes_no") 
private boolean isCorrectChoice; }
</textarea>
<p>Problem solved &#8211; we no longer got the Hibernate exception. But, as Abhishek pointed out, our domain objects no longer enforced the constraint that a question could have only one correct choice. With the updated classes, nothing would prevent instantiating a question with multiple choices marked as correct. This put the burden on additional validation code to enforce this constraint, and overall is just less than ideal.</p>
<h3>How Terracotta Can Help</h3>
<p>The point I am agonizingly slowly building to is, I think it&#8217;s acceptable to have these constraints on our persistent domain objects, but <i>only on the ones that should be persisted</i>.  An anti-pattern that we at Terracotta have seen again and again is the misuse of the database and ORM to persist state that really does not belong in the <a href="http://en.wikipedia.org/wiki/System_of_record">System of Record</a>, but rather is transient state that must be persisted only to scale applications by keeping the applications stateless.  One of the Terracotta co-founders, <a href="http://orionl.blogspot.com/">Orion</a>, coined the term &#8220;State Monster&#8221; to describe this abuse of the db, and recently Wille Faler wrote a <a href="http://faler.wordpress.com/2008/10/04/killing-the-state-monster-challenging-your-implicit-assumptions/">very good blog</a> describing this.</p>
<p>Terracotta can help by providing an alternative to making apps stateless for scalability purposes.  With Terracotta, go ahead and write your application in the most natural way, including shared state that is only transient.  Consider this helpful graph about <a href="http://tech.puredanger.com/2008/08/01/thinking-about-data-lifetimes/">data lifetimes</a> when deciding what state belongs in the SOR and what state is merely transient or pending.  Then, use Terracotta to both cluster and <a href="http://orionl.blogspot.com/2008/03/terracotta-is-not-object-cache.html">persist</a> the POJOs that don&#8217;t belong in the SOR.  The advantage is that Terracotta does not impose any constraints on the API of the sorts I have written about here &#8211; generics are fine, arbitrarily complex object graphs are no problem.  Terracotta clustered objects don&#8217;t even have to implement Serializable.</p>
]]></content:encoded>
			<wfw:commentRss>http://puredanger.com/kablooie/2008/10/06/hibernate-orm-can-lead-to-inflexibility-terracotta-can-help/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Me Meme</title>
		<link>http://puredanger.com/kablooie/2008/10/05/me-meme/</link>
		<comments>http://puredanger.com/kablooie/2008/10/05/me-meme/#comments</comments>
		<pubDate>Mon, 06 Oct 2008 04:09:02 +0000</pubDate>
		<dc:creator>Scott</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://puredanger.com/kablooie/2008/10/05/me-meme/</guid>
		<description><![CDATA[
Via Mario

 Take a picture of yourself right now.
Don’t change your clothes, don’t fix your hair…just take a picture.
Post that picture with NO editing.
Post these instructions with your picture.

]]></description>
			<content:encoded><![CDATA[<p><a class="imagelink" href="http://puredanger.com/kablooie/wp-content/uploads/2008/10/Photo%2061.jpg" title="couch potato"><img id="image44" src="http://puredanger.com/kablooie/wp-content/uploads/2008/10/Photo%2061.thumbnail.jpg" alt="unflattering" /></a></p>
<p>Via <a href="http://marioaquino.blogspot.com/2008/10/me-meme.html">Mario</a></p>
<ol>
<li> Take a picture of yourself right now.</li>
<li>Don’t change your clothes, don’t fix your hair…just take a picture.</li>
<li>Post that picture with NO editing.</li>
<li>Post these instructions with your picture.</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://puredanger.com/kablooie/2008/10/05/me-meme/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Weekly Summary &#8211; web app</title>
		<link>http://puredanger.com/kablooie/2008/08/03/weekly-summary-web-app/</link>
		<comments>http://puredanger.com/kablooie/2008/08/03/weekly-summary-web-app/#comments</comments>
		<pubDate>Mon, 04 Aug 2008 04:15:44 +0000</pubDate>
		<dc:creator>Scott</dc:creator>
				<category><![CDATA[Terracotta developer]]></category>

		<guid isPermaLink="false">http://puredanger.com/kablooie/2008/08/03/weekly-summary-web-app/</guid>
		<description><![CDATA[It was a better week.  As I said last week I was looking to cut down on distractions and improve my focus.  I stuck to a morning routine this week: every day I got up around six, took a 30 minute walk on the beach while listening to Stackoverflow podcasts, then got showered [...]]]></description>
			<content:encoded><![CDATA[<p>It was a better week.  As I said <a href="kablooie/2008/07/27/weekly-summary-6/">last week</a> I was looking to cut down on distractions and improve my focus.  I stuck to a morning routine this week: every day I got up around six, took a 30 minute walk on the beach while listening to <a href="http://blog.stackoverflow.com/">Stackoverflow</a> podcasts, then got showered and online by 7 to 7:15.  I usually got over an hour of work done before anybody else even woke up.  I kept twittering, e-mail and such to a minimum.  </p>
<p>I&#8217;ve definitely enjoyed <a href="kablooie/2008/07/28/my-office-this-week/">working at our condo</a> here in Destin, FL.  It was quite a novelty to work on a balcony overlooking the Gulf of Mexico, and I made sure to rub my teammates&#8217; faces in it.  But honestly by the end of the week I couldn&#8217;t stand to work out there with all the noise and glare.  I spent most of my remaining time on the north balcony which overlooks a golf course and lake, and is much quieter.</p>
<p>This week I got started on the reference web app that we are working on as part of Terracotta&#8217;s strategy to really nail the clustered &#8220;user session&#8221; use case.  Alex has blogged in detail about that <a href="http://tech.puredanger.com/2008/07/08/narrowing-the-focus/">strategy</a>, and more recently on the <a href="http://tech.puredanger.com/2008/07/29/settling-on-a-stack/">technology stack</a> we settled on for the web app.  <a href="http://rifers.org/blogs">Geert Bevin</a>, who is himself the author of the <a href="http://rifers.org/">Rife</a> web framework, had already spent a week or two learning <a href="http://www.springframework.org/about">Spring MVC</a> and laying down some architectural groundwork.  By the time I got started on Monday he was up and running and had stubbed out some basic pages.</p>
<p>My week was divided into two parts.  Part one was two and a half painful days of just setting up my workspace.  This involved upgrading to <a href="http://www.eclipse.org/ganymede/">Eclipse 3.4 Ganymede</a>, which includes the <a href="http://www.eclipse.org/webtools/">WTP</a> that Geert was already using to launch the app in Tomcat.  Then upgrading all of the plugins I needed.  Then endlessly debugging because I got exception after exception when I tried to do seemingly anything.</p>
<p>When I was interviewing for Terracotta, one phrase I heard was &#8220;just in time learning&#8221;, and that was certainly true this week.  Here is a probably-not-complete list of technologies that I&#8217;ve had to learn at least some of (or some more of) this week, quickly: <a href="http://maven.apache.org/">Maven</a> and it&#8217;s Eclipse plugin, Subversion and Subclipse plugin, WTP, Spring MVC, <a href="http://java.sun.com/javaee/technologies/persistence.jsp">JPA annotations</a> with <a href="http://hibernate.org/">Hibernate</a> as ORM provider, <a href="http://tomcat.apache.org/>Tomcat</a>, Java 5 generics, <a href="http://sojo.sourceforge.net/">SOJO</a> (for <a href="http://www.json.org/js.html">JSON</a> parsing in Java), <a href="http://www.thefrontside.net/crosscheck">Crosscheck</a> (being evaluated for JavaScript unit testing in Java vm), <a href="http://jquery.com/">jQuery</a>, <a href="http://mysql.com/">MySql</a>, and probably some other stuff I&#8217;m forgetting.</p>
<p>During the second half of the week, everything started clicking and I was finally committing changes.  I began working on the exam-creation page.  Geert recommended that we approach the page by using JavaScript to allow the user to build up an entire exam and submit it as a single request, passing JSON to the Controller.  I&#8217;m really excited about this because I&#8217;ve grown to like coding JavaScript.  I&#8217;m almost disappointed that I&#8217;ll be on vacation this week.  By week&#8217;s end I had the controller basically working, accepting and parsing JSON.  But I did not get any JavaScript in place yet, although I spent a good bit of time reading up on jQuery and Crosscheck.</p>
]]></content:encoded>
			<wfw:commentRss>http://puredanger.com/kablooie/2008/08/03/weekly-summary-web-app/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>My Office This Week</title>
		<link>http://puredanger.com/kablooie/2008/07/28/my-office-this-week/</link>
		<comments>http://puredanger.com/kablooie/2008/07/28/my-office-this-week/#comments</comments>
		<pubDate>Mon, 28 Jul 2008 16:04:00 +0000</pubDate>
		<dc:creator>Scott</dc:creator>
				<category><![CDATA[Terracotta developer]]></category>

		<guid isPermaLink="false">http://puredanger.com/kablooie/2008/07/28/my-office-this-week/</guid>
		<description><![CDATA[I&#8217;m working remotely this week in Destin, FL.  It&#8217;s rough, but that&#8217;s life working for Terracotta.
 
]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m working remotely this week in Destin, FL.  It&#8217;s rough, but that&#8217;s life working for <a href="http://www.terracotta.org/">Terracotta</a>.</p>
<p><a class="imagelink" href="http://puredanger.com/kablooie/wp-content/uploads/2008/07/destin.jpg" title="destin.jpg"><img id="image40" src="http://puredanger.com/kablooie/wp-content/uploads/2008/07/destin.thumbnail.jpg" alt="destin.jpg" /></a> <a class="imagelink" href="http://puredanger.com/kablooie/wp-content/uploads/2008/07/s100_1479.JPG" title="s100_1479.JPG"><img id="image42" src="http://puredanger.com/kablooie/wp-content/uploads/2008/07/s100_1479.thumbnail.JPG" alt="s100_1479.JPG" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://puredanger.com/kablooie/2008/07/28/my-office-this-week/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic Page Served (once) in 0.614 seconds -->

