<?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>2Paths &#187; Under the hood</title>
	<atom:link href="http://www.2paths.com/category/blog/tech/technology-under-the-hood/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.2paths.com</link>
	<description>Custom Software Technical Architecture, Design and Development in Vancouver, BC, Canada</description>
	<lastBuildDate>Mon, 27 Sep 2010 01:15:46 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Grails 1.1 Testing &#8211; Unit, Integration &amp; Functional</title>
		<link>http://www.2paths.com/2009/07/20/grails-11-testing-unit-integration-functional/</link>
		<comments>http://www.2paths.com/2009/07/20/grails-11-testing-unit-integration-functional/#comments</comments>
		<pubDate>Mon, 20 Jul 2009 21:50:28 +0000</pubDate>
		<dc:creator>dkoo</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Under the hood]]></category>
		<category><![CDATA[antbuilder]]></category>
		<category><![CDATA[controllerunittestcase]]></category>
		<category><![CDATA[functional test]]></category>
		<category><![CDATA[functional testing]]></category>
		<category><![CDATA[Grails]]></category>
		<category><![CDATA[grails 1.1]]></category>
		<category><![CDATA[grails testing]]></category>
		<category><![CDATA[grailsunittestcase]]></category>
		<category><![CDATA[groovy]]></category>
		<category><![CDATA[groovytestcase]]></category>
		<category><![CDATA[htmlunit]]></category>
		<category><![CDATA[integration test]]></category>
		<category><![CDATA[integration testing]]></category>
		<category><![CDATA[mockdomain]]></category>
		<category><![CDATA[unit test]]></category>
		<category><![CDATA[unit testing]]></category>

		<guid isPermaLink="false">http://www.2paths.com/?p=1138</guid>
		<description><![CDATA[Last Friday I gave a presentation to the team here at 2Paths on the testing capabilities in Grails 1.1.
As you Grails die-hards know, Grails 1.1 introduced the new GrailsUnitTestCase class which is a very useful extension of GroovyTestCase with support for mocking the dynamic properties and methods that Grails injects into various types of classes [...]]]></description>
			<content:encoded><![CDATA[<p>Last Friday I gave a <a href="http://www.slideshare.net/dkoo761/grails-11-testing-unit-integration-functional">presentation</a> to the team here at 2Paths on the testing capabilities in Grails 1.1.</p>
<p>As you Grails die-hards know, Grails 1.1 introduced the new <a href="http://grails.org/doc/1.1.1/guide/9.%20Testing.html#9.1%20Unit%20Testing">GrailsUnitTestCase</a> class which is a very useful extension of <a href="http://groovy.codehaus.org/Unit+Testing">GroovyTestCase</a> with support for mocking the dynamic properties and methods that Grails injects into various types of classes (domain, controller &amp; taglibs). Getting the team up to speed on this change was the original purpose of the presentation, but I decided to expand it to cover the full spectrum of testing capabilities in Grails 1.1 for those who might not have much exposure to it previously (including me!)</p>
<p>The presentation covered:</p>
<p>- the benefits &amp; drawbacks of each type of testing: <a href="http://en.wikipedia.org/wiki/Unit_testing">unit testing</a>, <a href="http://en.wikipedia.org/wiki/Integration_testing">integration testing</a>, <a href="http://en.wikipedia.org/wiki/Functional_testing">functional testing</a>.</p>
<p>- details on the new GrailsUnitTestCase and it&#8217;s extensions (ControllerUnitTestCase and TagLibUnitTestCase)</p>
<p>- a few &#8220;gotchas&#8221; &#8211; such as using mockDomain with inheritance hierarchies</p>
<p>- WebTest goodness &#8211; test organization &amp; re-use, Groovy step, passing params between Groovy &amp; WebTest contexts, a little dive into using HtmlUnit to test AJAX</p>
<p>- general recommendations for what types of tests to create for each artifact (domain classes, controllers, services, etc)</p>
<p>Here&#8217;s a link to the presentation on SlideShare.net (where you can view it online or download it):</p>
<div style="width: 425px; text-align: left;"><a title="Grails 1.1 Testing - Unit, Integration &amp; Functional" href="http://www.slideshare.net/dkoo761/grails-11-testing-unit-integration-functional">Grails 1.1 Testing &#8211; Unit, Integration &amp; Functional</a>  </p>
<div style="font-size: 11px; font-family: tahoma,arial; height: 26px; padding-top: 2px;">View more <a href="http://www.slideshare.net/">presentations</a> from <a href="http://www.slideshare.net/dkoo761">Dave Koo</a>.</div>
</div>
<p>Happy testing!<br />
Dave</p>
]]></content:encoded>
			<wfw:commentRss>http://www.2paths.com/2009/07/20/grails-11-testing-unit-integration-functional/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>memcached and Grails</title>
		<link>http://www.2paths.com/2009/07/16/memcached-and-grails/</link>
		<comments>http://www.2paths.com/2009/07/16/memcached-and-grails/#comments</comments>
		<pubDate>Fri, 17 Jul 2009 01:16:30 +0000</pubDate>
		<dc:creator>Tim</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Under the hood]]></category>
		<category><![CDATA[Utilities]]></category>
		<category><![CDATA[continuous integration]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[Grails]]></category>
		<category><![CDATA[memcached]]></category>
		<category><![CDATA[scalability]]></category>

		<guid isPermaLink="false">http://www.2paths.com/?p=1122</guid>
		<description><![CDATA[I put together a Grails app to try out memcached. Like a lot of things in Grails, it was quite simple to integrate memcached once I found the right magic words. hibernate-memcached works nicely and has clear setup instructions.
Install memcached, which is simple if you use a Mac and have MacPorts installed.
$ sudo port install [...]]]></description>
			<content:encoded><![CDATA[<p>I put together a <a href="http://www.grails.org/">Grails</a> app to try out <a href="http://www.danga.com/memcached/">memcached</a>. Like a lot of things in Grails, it was quite simple to integrate memcached once I found the right magic words. <a href="http://code.google.com/p/hibernate-memcached/">hibernate-memcached</a> works nicely and has clear setup instructions.</p>
<p>Install memcached, which is simple if you use a Mac and have <a href="http://www.macports.org/">MacPorts</a> installed.</p>
<pre>$ sudo port install memcached</pre>
<p>Get the <a href="http://spymemcached.googlecode.com/files/memcached-2.3.1.jar">memcached jar</a> , the <a href="http://code.google.com/p/hibernate-memcached/downloads/list">hibernate-memcached jar</a> and the <a href="http://jdbc.postgresql.org/">PostgreSQL JDBC driver jar</a>, then  add them to the project.</p>
<pre>$ cp memcached-2.3.1.jar hibernate-memcached-1.2.jar postgresql-8.4-701.jdbc3.jar &lt;project_dir&gt;/lib/</pre>
<p>Configure memcached as the second-level cache by adding something like this to your DataSource.groovy.</p>
<pre><span class="pln">hibernate </span><span class="pun">{</span><span class="pln">
    cache</span><span class="pun">.</span><span class="pln">use_second_level_cache </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pln">
    cache</span><span class="pun">.</span><span class="pln">use_query_cache </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pln">
    cache</span><span class="pun">.</span><span class="pln">provider_class </span><span class="pun">=</span><span class="pln"> </span><span class="str">'com.googlecode.hibernate.memcached.MemcachedCacheProvider'</span><span class="pln">
    memcached </span><span class="pun">{</span><span class="pln">
        servers </span><span class="pun">=</span><span class="pln"> </span><span class="str">"localhost:11211"</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>
<p>I wrote a simple test to generate a whole bunch of domain objects and shove them in the database, then go back and fetch them all again. I set the test to run the insert/load loops in batches of 1, 10, 100, 1,000, 2,000, 4,000, 7,000, and 10,000 objects. I expected that inserting the objects would take a little longer because of the memcached overhead but that loading the objects would be faster because they could be loaded from memcached instead of going out to the database.</p>
<p>I tested three persistence backend configurations.</p>
<ul>
<li><a href="http://en.wikipedia.org/wiki/HSQLDB">HSQLDB</a>, the default for new Grails projects and when running unit/integration tests. This is an in-memory database only, so data aren&#8217;t persisted permanently.</li>
<li><a href="http://en.wikipedia.org/wiki/PostgreSQL"> PostgreSQL</a> for a full-blown RDBMS setup. I set dbCreate to &#8220;create-drop&#8221; in <a href="http://docs.codehaus.org/display/GRAILS/Quick+Start">DataSource.groovy</a> so that each test started with an empty database.</li>
<li>PostgreSQL with memcached enabled. I should point out that in this test I had both PostgreSQL and memcached running on the same machine (my laptop) as the application, so it&#8217;s really not taking advantage of memcached&#8217;s parallelism strengths.</li>
</ul>
<p>My expectations held true for the inserts. The memcached case is a little slower but not that much.</p>
<div id="attachment_1123" class="wp-caption alignnone" style="width: 806px"><img class="size-full wp-image-1123 " title="db-compare-inserts" src="http://www.2paths.com/wp-content/uploads/2009/07/db-compare-inserts.png" alt="db-compare-inserts" width="796" height="516" /><p class="wp-caption-text">Comparison of object insert times using HSQL, PostgreSQL, and memcached+PostgreSQL for persistence backend</p></div>
<p>When I tested the load times, I was surprised. It looked like memcached wasn&#8217;t speeding things up at all. I was also surprised to see that it took less time to load 10,000 objects from the data store than 7,000 objects. I ran the test a few times to rule out the possibility of a load spike from something else running at the same time, but I got similar results every time.</p>
<div id="attachment_1124" class="wp-caption alignnone" style="width: 806px"><img class="size-full wp-image-1124 " title="db-compare-loads" src="http://www.2paths.com/wp-content/uploads/2009/07/db-compare-loads.png" alt="Comparison object load times using HSQL, PostgreSQL, and memcached+PostgreSQL for persistence backend" width="796" height="516" /><p class="wp-caption-text">Comparison of object load times using HSQL, PostgreSQL, and memcached+PostgreSQL for persistence backend</p></div>
<p>I then tried to improve my test setup by running memcached on a second machine (my desktop, connected by gigabit ethernet to the laptop). Using the PostgreSQL + memcached configuration for each test this time, I looked at three more scenarios.</p>
<ul>
<li>PostgreSQL running locally on the laptop, memcached running locally on the laptop.</li>
<li>PostgreSQL running locally on the laptop, memcached running remotely on the desktop.</li>
<li>PostgreSQL running locally on the laptop, memcached running on both the laptop and the desktop.</li>
</ul>
<p>There&#8217;s some overhead in going out to the network to retrieve data instead of fetching it from a process running locally, so I expected the memcached local instance to be faster than the memcached remote instance. I expected the third test, with two instances of memcached running in parallel, to be fastest because it splits the load between the two instances and frees up some CPU time on the laptop. Things didn&#8217;t play out that way, though.</p>
<div id="attachment_1125" class="wp-caption alignnone" style="width: 806px"><img class="size-full wp-image-1125" title="local-remote-inserts" src="http://www.2paths.com/wp-content/uploads/2009/07/local-remote-inserts.png" alt="Comparison of object insert times for various memcache setups" width="796" height="516" /><p class="wp-caption-text">Comparison of object insert times for various memcache setups</p></div>
<div id="attachment_1126" class="wp-caption alignnone" style="width: 806px"><img class="size-full wp-image-1126" title="local-remote-loads" src="http://www.2paths.com/wp-content/uploads/2009/07/local-remote-loads.png" alt="Comparison of object load times for various memcache setups" width="796" height="516" /><p class="wp-caption-text">Comparison of object load times for various memcache setups</p></div>
<p>I have to be honest that these were not great tests. For one, I should really have run those insert/load loops in parallel instead of sequentially. I&#8217;m guessing that the test spent a lot of time stalled waiting for data when it could have been sending out more requests. I would also like to test with a large group of memcached servers and a remote database, perhaps even a cluster of app servers with a load balancer to try the full meal deal. The <a href="http://code.google.com/p/memcached/wiki/FAQ#Memcached_is_not_faster_than_my_database._Why?">memcached FAQ</a> explains that running everything on one machine will not show off memcached&#8217;s scalability.</p>
<p>However, this gave me the opportunity to get my hands dirty with memcached and learn a few things.</p>
<ul>
<li>Integrating memcached is so simple and the performance penalty of just running it locally during development is so small that there&#8217;s no reason not to enable it.</li>
<li>It&#8217;s dead simple to install and set up. We could , for example, easily  install it on a bunch of test servers and run multiple instances on different ports &#8211; one for each developer (to prevent us from clobbering each other&#8217;s data).</li>
<li>Measuring performance and scalability realistically is tricky. It&#8217;s one thing to hand wave and say that running multiple instances of a database or a cache will speed things up, but it takes some work to set up a realistic simulation of high traffic application performance.</li>
<li>Adding memcached doesn&#8217;t automatically turn performance up to <a href="http://www.youtube.com/watch?v=EbVKWCpNFhY">11</a>. I need to learn more about what&#8217;s going on under the hood with my domain objects and how they&#8217;re being persisted through memcached.</li>
</ul>
<p>I look forward to using memcached more in the future and learning how to really take advantage of it.</p>
<p><strong>Update (2009-07-24)</strong>: Ray pointed out in the <a href="#comment-8792">comments</a> that I should have enabled <a href="http://www.grails.org/GORM+-+Mapping+DSL">caching</a> in my domain objects under test. I added &#8220;static mapping = { cache true }&#8221; to my domain class definition and re-ran the tests to compare the effect under 4 scenarios.</p>
<ul>
<li>no domain object caching (as before)</li>
<li>domain object caching with memcached running locally</li>
<li>domain object caching with memcached running remotely</li>
<li>domain object caching with memcached running both locally and remotely</li>
</ul>
<p>Not much difference with the inserts.</p>
<div id="attachment_1145" class="wp-caption alignnone" style="width: 806px"><img class="size-full wp-image-1145" title="cache-true-inserts" src="http://www.2paths.com/wp-content/uploads/2009/07/cache-true-inserts.png" alt="Comparison of object insert times with domain object caching enabled and disabled" width="796" height="516" /><p class="wp-caption-text">Comparison of object insert times with domain object caching enabled and disabled</p></div>
<p>However, the load times are slightly better with memcached enabled during heavy activity! The advantage disappears when I add the overhead of traversing the network, but it&#8217;s a start. Thanks for the pointer, Ray!</p>
<div id="attachment_1146" class="wp-caption alignnone" style="width: 806px"><img class="size-full wp-image-1146" title="cache-true-loads" src="http://www.2paths.com/wp-content/uploads/2009/07/cache-true-loads.png" alt="Comparison of object load times with domain object caching enabled and disabled" width="796" height="516" /><p class="wp-caption-text">Comparison of object load times with domain object caching enabled and disabled</p></div>
]]></content:encoded>
			<wfw:commentRss>http://www.2paths.com/2009/07/16/memcached-and-grails/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>C# features &#8211; LINQ primer</title>
		<link>http://www.2paths.com/2009/04/30/c-features-linq-primer/</link>
		<comments>http://www.2paths.com/2009/04/30/c-features-linq-primer/#comments</comments>
		<pubDate>Thu, 30 Apr 2009 19:04:32 +0000</pubDate>
		<dc:creator>Geoff</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Under the hood]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[dotnet]]></category>
		<category><![CDATA[newbies]]></category>

		<guid isPermaLink="false">http://www.2paths.com/?p=939</guid>
		<description><![CDATA[Language INtegrated Query (LINQ) adds extensions to the .NET framework which provide a domain specific language for querying and transforming collections right within C# (or VB for that matter). It provides syntax similar to other 4GL querying languages such as SQL, HQL or even OQL.
Below is a simple test case showing how to do LINQ [...]]]></description>
			<content:encoded><![CDATA[<p>Language INtegrated Query (<a href="http://msdn.microsoft.com/en-ca/library/bb308959.aspx">LINQ</a>) adds extensions to the .NET framework which provide a domain specific language for querying and transforming collections right within C# (or VB for that matter). It provides syntax similar to other 4GL querying languages such as SQL, HQL or even OQL.</p>
<p>Below is a simple test case showing how to do LINQ operations on a simple array:</p>
<pre class="brush: csharp">
        public void LinqArrayTest()
        {
            String[] names = { &quot;Burke&quot;, &quot;Connor&quot;, &quot;Frank&quot;,
                   &quot;Everett&quot;, &quot;Albert&quot;, &quot;George&quot;,
                   &quot;Harris&quot;, &quot;David&quot; };

            IEnumerable&lt;string&gt; query = from s in names
                               where s.Length == 5
                               orderby s
                               select s;

            List&lt;String&gt; results = query.ToList();

            Assert.AreEqual(3, results.Count);
            String[] expected = new String[] {&quot;Burke&quot;, &quot;David&quot;, &quot;Frank&quot;};
            for (int i = 0; i &lt; results.Count; i++)
            {
                Assert.AreEqual(expected[i], results.ElementAt(i));
            }
        }
</pre>
<p>It is also possible to create runtime LINQ queries using lambda expressions to qualify conditional logic:</p>
<pre class="brush: csharp">
        [TestMethod()]
        public void LinqLambdaTest()
        {
            String[] items = { &quot;cabbage&quot;, &quot;broccoli&quot;, &quot;carrot&quot;, &quot;parsnip&quot;, &quot;cauliflower&quot; };

            IEnumerable&lt;String&gt; query = items;

            // additive query generation using lambda expressions
            query = query.Where(item =&gt; item.StartsWith(&quot;c&quot;));
            query = query.Where(item =&gt; item.Length &lt; 8);
            query = query.OrderByDescending(item =&gt; item.ToLower());

            List&lt;String&gt; results = query.ToList();

            Assert.AreEqual(2, results.Count);
            String[] expected = { &quot;carrot&quot;, &quot;cabbage&quot; };
            for (int i = 0; i &lt; results.Count; i++)
            {
                Assert.AreEqual(expected[i], results.ElementAt(i));
            }
        }
</pre>
<p>LINQ provides a simple, generalised query framework for operating on data collections within the .NET stack. There are framework plugins to support LINQ backed by various datastore technologies, these include: <a href="http://msdn.microsoft.com/en-us/library/bb425822.aspx">LINQ to SQL</a>, <a href="http://msdn.microsoft.com/en-us/library/bb387098.aspx">LINQ to XML</a> and <a href="http://msdn.microsoft.com/en-us/library/bb386964.aspx">LINQ to Entities</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.2paths.com/2009/04/30/c-features-linq-primer/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>C# features &#8211; question mark syntax</title>
		<link>http://www.2paths.com/2009/04/28/c-features-question-mark-syntax/</link>
		<comments>http://www.2paths.com/2009/04/28/c-features-question-mark-syntax/#comments</comments>
		<pubDate>Tue, 28 Apr 2009 18:27:34 +0000</pubDate>
		<dc:creator>Geoff</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Under the hood]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[dotnet]]></category>
		<category><![CDATA[newbies]]></category>

		<guid isPermaLink="false">http://www.2paths.com/?p=919</guid>
		<description><![CDATA[Some recent project work in C# unearthed a few grains of syntactic sugar which I thought deserved a quick post. Not necessarily because they are ground breaking discoveries, but more because I found it difficult to find information via the usual channels (google) and wanted to share. I think the poor information discovery is a [...]]]></description>
			<content:encoded><![CDATA[<p>Some recent project work in C# unearthed a few grains of syntactic sugar which I thought deserved a quick post. Not necessarily because they are ground breaking discoveries, but more because I found it difficult to find information via the usual channels (google) and wanted to share. I think the poor information discovery is a result of said features being based on the question mark which is not an easy symbol to use for searches online.</p>
<h3>Single Question Mark &#8211; nullable types</h3>
<p>The single question mark syntax is somewhat obscure. Essentially it is short hand syntax for marking primitives as nullable. <code>System.Nullable</code> is a generic struct that is essentially a <a href="http://msdn.microsoft.com/en-us/library/1t3y8s4s(VS.80).aspx">wrapper to signify nullability</a>. This can be used as shown below:</p>
<pre class="brush: java">
// a nullable type for int
int? thing = 12;

// is syntactically equivalent to
System.Nullable&lt;int&gt; otherThing = 12;

// can be any valid int value OR null
thing = -12;
thing = null;

// usage
//y is set to zero
int y = thing.GetValueOrDefault();
// but this will throw an exception as thing.HasValue == false
y = thing.Value;
</pre>
<h3>Double Question Mark &#8211; non null assignment precedence</h3>
<p>This one is a little obscure but can be quite handy, it is very similar to certain assignment constructs in Perl as it allows one to use precedence to assign a variable from other potential variables and is a nice way to deal with default values.</p>
<pre class="brush: java">
String thing = null;
String defaultThing = &quot;nothing&quot;;

// standard trinary syntax
String otherThing = (thing != null) ? thing : defaultThing;

// syntactic sugar for the above
String sugaredThing = thing ?? defaultThing;

// can also chain things
otherThing = null;

// the first non-null value is the result of the assignment
String anotherThing = thing ?? otherThing ?? defaultThing;

// if all potentials are null, then the assignement is null)
anotherThing = thing ?? otherThing;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.2paths.com/2009/04/28/c-features-question-mark-syntax/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Scalability &#8211; proxying heavyweight webapps</title>
		<link>http://www.2paths.com/2009/02/23/scalability-proxying-heavyweight-webapps/</link>
		<comments>http://www.2paths.com/2009/02/23/scalability-proxying-heavyweight-webapps/#comments</comments>
		<pubDate>Mon, 23 Feb 2009 21:51:40 +0000</pubDate>
		<dc:creator>Geoff</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Under the hood]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[proxy]]></category>
		<category><![CDATA[scalability]]></category>

		<guid isPermaLink="false">http://www.2paths.com/?p=301</guid>
		<description><![CDATA[
We recently had a tech talk about scalability as it pertains to developing web applications. Many best practises were discussed including load balancing, clustering, highly-available databases, eventually consistent application designs.
In most web applications, the proportion of dynamic requests (application logic) to static requests (images, javascript, css, html, flash) is usually quite low. As a result, [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.2paths.com/wp-content/uploads/2009/02/2009-02-23_traffic.png"><img src="http://www.2paths.com/wp-content/uploads/2009/02/2009-02-23_traffic.png" alt="" title="2009-02-23_traffic" width="401" height="234" class="alignright size-full wp-image-788" /></a><br />
We recently had a tech talk about scalability as it pertains to developing web applications. Many best practises were discussed including load balancing, clustering, highly-available databases, eventually consistent application designs.</p>
<p>In most web applications, the proportion of dynamic requests (application logic) to static requests (images, javascript, css, html, flash) is usually quite low. As a result, it can be quite taxing on your application server if most of its time is spent serving static content to users.</p>
<p>Looking at some real statistics over two months from one of the systems we developed shows that out of 2,522,507 total requests, only 395,742 were for dynamic application data. That is 15% of all requests were dynamic, the remainder being requests for images, stylesheets or flash components.</p>
<p><a href="http://www.2paths.com/wp-content/uploads/2009/02/2009-02-23_proxy_arch.png"><img src="http://www.2paths.com/wp-content/uploads/2009/02/2009-02-23_proxy_arch.png" alt="" title="web system architecture" width="338" height="297" class="alignleft size-full wp-image-784" /></a><br />
<strong>System architecture</strong><br />
A common technique in web systems is to have a lightweight web server reside between your backend web application (usually a heavyweight beast) and the world at large. This allows the lightweight web server to take load off the heavyweight backend web application leaving it to focus on generating all the fun dynamic content for your application. The application server threads do not get tied up serving static content this improving system utilisation.</p>
<p>A lightweight proxy server (e.g. Apache HTTPD with mod_proxy) can be configured to improve performance by serving up static content fast and ensure correct headers are set such that upstream content proxies and end user browser software will cache the static content appropriately, further improving performance for repeat visitors.</p>
<p><br clear="all" /><br />
<strong>Example Implementation</strong><br />
We setup a system with Apache HTTPD as the lightweight proxy server which sits in front of our application servers. The two are connected via <code>mod_proxy</code>. This Apache module provides a bridge between the two servers so that they may seamlessly interact to provide different components for a single starting web request. Essentially, all dynamic content is generated by the app server, this may reference images and other static content which will be served by the proxy server.</p>
<p>An example configuration is provided below:</p>
<pre class="brush: xml">
# create an alias for static content to be served
Alias /static/ &quot;/location/of/content&quot;

RewriteEngine on

# static content should not be proxied to tomcat - just serve it up directly
# we re-write the URL and rely on the ALIAS defined above for &#039;/static/&#039;
# Essentially, we rewrite all requests for static content to use the
# hard wired alias which should point to content on disk
RewriteCond %{REQUEST_URI}  .*\.(jpg|png|gif|swf|flv|css|js|html)$
RewriteRule ^/(.+) /static/$1 [PT,L]

# assume our Java app is deployed to the &#039;app&#039; context
RewriteRule ^/app/(.+) ajp://localhost:8009/app/$1 [P]

ProxyPass /app/ ajp://java-server:8009/app/ timeout=300
ProxyPassReverse /app/ ajp://java-server:8009/app/

&lt;Proxy *&gt;
AddDefaultCharset off
Order deny,allow
Allow from all
&lt;/Proxy&gt;
</pre>
<p>This particular example uses <code>mod_proxy_ajp</code> to connect Apache HTTPD to a Java application server. However, this technique can be used to front many different backends using the Apache <code>mod_proxy</code> module including applications developed targeting <code>Perl/mod_perl</code>, IIS/ASP.NET or even ColdFusion.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.2paths.com/2009/02/23/scalability-proxying-heavyweight-webapps/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Locale aware caching</title>
		<link>http://www.2paths.com/2009/01/29/locale-aware-caching/</link>
		<comments>http://www.2paths.com/2009/01/29/locale-aware-caching/#comments</comments>
		<pubDate>Fri, 30 Jan 2009 01:09:10 +0000</pubDate>
		<dc:creator>Geoff</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Under the hood]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[locale]]></category>
		<category><![CDATA[spring]]></category>

		<guid isPermaLink="false">http://www.2paths.com/?p=492</guid>
		<description><![CDATA[To help boost the performance of our webapps we like to implement caching. One nice feature of the Spring Framework is its support for AOP features within applications. We utilise this to implement AOP method caching within our Spring enabled web applications. This allows us to write code without needing to worry too much about [...]]]></description>
			<content:encoded><![CDATA[<p>To help boost the performance of our webapps we like to implement caching. One nice feature of the Spring Framework is its support for <a href="http://www.springframework.org/docs/reference/aop.html">AOP features</a> within applications. We utilise this to implement AOP method caching within our Spring enabled web applications. This allows us to write code without needing to worry too much about direct caching as we can easily enable it at the method invocation level with some simple Spring config chicanery.</p>
<p>The <a href="https://springmodules.dev.java.net/docs/reference/0.8/html/cache.html">SpringModules cache</a> extension provides the legwork for implementing this and Spring AOP the glue. One limitation of this implementation out of the box is that it is not Locale aware. Spring nicely provides a <a href="http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/context/i18n/LocaleContextHolder.html">LocaleContextHolder</a> to enable disparate components within the app stack to be locale aware so we needed to leverage this in order to ensure our method caching was able to not only cache method invocations with the same argument signature, but also within the same Locale (not something passed as arguments) .</p>
<p>Below is the meat of our simple solution, a LocaleAwareCacheKeyGenerator:</p>
<pre class="brush: java">
    public final Serializable generateKey(MethodInvocation methodInvocation) {

        Method method = methodInvocation.getMethod();

        HashCodeCalculator hashCodeCalculator = new HashCodeCalculator();
        hashCodeCalculator.append(method.hashCode());

        // now suck in the locale
        Locale locale = LocaleContextHolder.getLocale();

        // and use the bit we care about for hashcode generation
        if (considerLanguageOnly) {
            hashCodeCalculator.append(locale.getLanguage().hashCode());
        } else {
            hashCodeCalculator.append(locale.hashCode());
        }

        // now try and sort out things for the method args
        Object[] methodArguments = methodInvocation.getArguments();

        if (methodArguments != null) {
            int methodArgumentCount = methodArguments.length;

            for (int i = 0; i &lt; methodArgumentCount; i++) {
                Object methodArgument = methodArguments[i];
                int hash = 0;

                if (generateArgumentHashCode) {
                    hash = Reflections.reflectionHashCode(methodArgument);
                } else {
                    hash = Objects.nullSafeHashCode(methodArgument);
                }

                hashCodeCalculator.append(hash);
            }
        }

        return new HashCodeCacheKey(hashCodeCalculator.getCheckSum(), hashCodeCalculator.getHashCode());
    }
</pre>
<p>This class simply adds the Locale to the code used in the HashCodeChacheKeyGenerator supplied with Spring. So now we can easily enable locale aware AOP configured method invocation caching transparently to our application code.</p>
<p>Nice!</p>
<p>P.S. An eclipse project with code/test samples is <a href="http://www.2paths.com/static/blog/LocaleCacheKey.zip">available</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.2paths.com/2009/01/29/locale-aware-caching/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Building GRAILS app on Debian using Maven GRAILS Plugin</title>
		<link>http://www.2paths.com/2008/12/23/building-grails-app-on-debian-using-maven-grails-plugin/</link>
		<comments>http://www.2paths.com/2008/12/23/building-grails-app-on-debian-using-maven-grails-plugin/#comments</comments>
		<pubDate>Tue, 23 Dec 2008 23:07:54 +0000</pubDate>
		<dc:creator>Lorill</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Under the hood]]></category>
		<category><![CDATA[Utilities]]></category>
		<category><![CDATA[debian]]></category>
		<category><![CDATA[Grails]]></category>
		<category><![CDATA[Grails ended with a non null return code]]></category>
		<category><![CDATA[grails maven plugin]]></category>
		<category><![CDATA[hudson]]></category>

		<guid isPermaLink="false">http://www.2paths.com/?p=432</guid>
		<description><![CDATA[We&#8217;re now using GRAILS in one of our Maven-ized projects, and have it building using the Maven GRAILS plugin. We needed to roll this integration out to Husdon, our CI server which is running on a Debian box. We ran into a couple of snags.  
We had downloaded and installed the debian package grails_1.0.4-1_all.deb [...]]]></description>
			<content:encoded><![CDATA[<p>We&#8217;re now using GRAILS in one of our Maven-ized projects, and have it building using the <a href="http://forge.octo.com/maven/sites/mtg/grails-maven-plugin/">Maven GRAILS plugin</a>. We needed to roll this integration out to Husdon, our CI server which is running on a Debian box. We ran into a couple of snags.  </p>
<p>We had downloaded and installed the debian package <code>grails_1.0.4-1_all.deb</code> from the <a href="http://grails.org/Download">GRAILS site</a>, configured the GRAILS_HOME environment variable for our build target, and attempted to  build it. We got this error:<br />
<code>Grails ended with a non null return code: 127</code><br />
After some digging, it turns out that the debian package installs GRAILS but puts the actual executable in /usr/bin instead of just a symlink from the GRAILS_HOME.  The Maven GRAILS plugin appears to be calling grails using the GRAILS_HOME path. Making a symlink to the grails executable in the bin dir of the GRAILS_HOME fixed this problem (although the symlink really more correctly belongs in the /usr/bin dir).</p>
<p>Trying to build again we came across a different problem, where the GRAILS version was showing up as null, causing build errors. After some googling I found <a href="http://code.google.com/p/ant-deb-task/issues/detail?id=19#c1">this useful post</a>, and re-installed GRAILS with the updated <a href="http://code.google.com/p/ant-deb-task/downloads/detail?name=grails_1.0.4-2_all.deb&amp;can=2&amp;q=">grails_1.0.4-2_all.deb</a> package, repeating the steps for the GRAILS executable.  Now we&#8217;re all up and running in Hudson!  I hope this might alleviate some pain for anyone trying to troubleshoot this problem.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.2paths.com/2008/12/23/building-grails-app-on-debian-using-maven-grails-plugin/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>LiquiBase-ifying your Grails Application</title>
		<link>http://www.2paths.com/2008/12/23/liquibase-ifying-your-grails-application/</link>
		<comments>http://www.2paths.com/2008/12/23/liquibase-ifying-your-grails-application/#comments</comments>
		<pubDate>Tue, 23 Dec 2008 21:46:27 +0000</pubDate>
		<dc:creator>Lorill</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Under the hood]]></category>
		<category><![CDATA[Utilities]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[Grails]]></category>
		<category><![CDATA[LiquiBase]]></category>

		<guid isPermaLink="false">http://www.2paths.com/?p=401</guid>
		<description><![CDATA[At 2Paths we&#8217;ve got some pretty good processes in place: we practice agile software development and scrum, have all our projects set up in Continuous Integration. We try to do test-driven development where at all possible. One area that has slipped through the cracks though is database change management. What company hasn&#8217;t run into the [...]]]></description>
			<content:encoded><![CDATA[<p>At 2Paths we&#8217;ve got some pretty good processes in place: we practice agile software development and scrum, have all our projects set up in Continuous Integration. We try to do test-driven development where at all possible. One area that has slipped through the cracks though is database change management. What company hasn&#8217;t run into the problem of ensuring all database environments in a project (dev, staging, production, test) are in sync and in source control? Without this, it becomes an onerous if not impossible task to rollback a set of databases to a known state, or to recreate one from scratch to a known state.</p>
<p>Enter <a href="http://liquibase.org">LiquiBase</a>, an open source database-agnostic tool for tracking, managing and applying database changes. We recently worked on a small Grails project and decided to give this tool a try and I was duly impressed.</p>
<p>LiquiBase functionality is built around a main changelog.xml file containing changesets representing incremental database changes to be applied to a database. LiquiBase manages which changesets have been run through a DATABASECHANGELOG table it creates in each database. </p>
<p>We used the <a href="http://www.liquibase.org/manual/grails">grails plugin</a> which gave us most of the full LiquiBase functionality, albeit a little less than mature.  There were a couple of gotchas and bugs with the plugin, but nothing we couldn&#8217;t work around.</p>
<p>LiquiBase buys us the ability to store database change in source control, easily sync databases in multi-environments in an automated and controlled fashion, tag database states upon iteration-end releases, auto-generate rollback sql to tagged states, diff databases, and much more.</p>
<h2>LiquiBase-ifying Your Application</h2>
<p>With your database in a known state, you can use the grails plugin to create your changelog.xml. First you need to install the grails LiquiBase plugin:<br />
<code>grails install-plugin liquibase</code><br />
Once installed simply run this from the root of your grails app:<br />
<code>grails generate-changelog grails-app/changelog.xml</code></p>
<p>This will generate the changelog.xml from your development database (specified in DataSource.groovy) and write it to the path specified in the command.  <code>grails-app/changelog.xml</code> is the default path where the grails plugin will be expecting the changelog to be. If you need to read from a different database environment like staging for example, just add the -Dgrails.env=staging option to the command.</p>
<p>To propagate this changelog to other databases (say, test), run<br />
<code>grails -Dgrails.env=test migrate</code>. This runs all the sql necessary to upate the database to match the changelog. Any new changes from here on will be appended as new changesets, and can be migrated with the same command as above.  You can also use the migrate-sql command instead if want to generate the sql and run it yourself.  Most LiquiBase commands come in tuples: one to generate the sql for you and one to just run the sql directly against your database.</p>
<p>If you&#8217;re integrating LiquiBase mid-project and already have all your databases set up, you&#8217;ll need to run sql against them to update the LiquiBase DATABASECHANGELOG table to show all the changes as run.  First, make sure that the databases are all in sync. To do this, you can use the handy LiquiBase diff tool. Unfortunately, the grails plugin for this diff tool is not very robust and will only diff your development database against your test database &#8211; the plugin has those two environments hard-coded. You can either mess with your DataSource.groovy db environments to do the diff setting the two dbs in question to dev and test temporarily, or <a href="http://www.liquibase.org/download">install LiquiBase</a> itself and run the <a href="http://www.liquibase.org/manual/diff">diff</a> passing the db parameters to the diff command. Using the grails plugin you would run:<br />
<code>grails db-diff</code> which will spit to the screen any differences as changesets to be applied. Strangely, there is no documentation for this command in the <a href="http://www.liquibase.org/manual/grails">LiquiBase Grails plugin page</a>.</p>
<p>Once your database are in sync, run<br />
<code>grails changelog-sync-sql</code> with the appropriate <code>-Dgrails.env</code> switch to generate the sql to update the DATABASECHANGELOG table, then run the sql in your database.</p>
<h2>LiquiBase and Continuous Integration</h2>
<p>We use Hudson at 2Paths for our CI, and have added the simple <code>grails -Dgrails.env=test migrate</code> command as part of our build process to migrate the test database upon every checkin. This ensures that the test db is always the most up-to-date.</p>
<h2>Rolling LiquiBase into our Dev Process</h2>
<p>We&#8217;ve adopted on a trial basis the following process for database change management as part of our agile software development, taking into consideration Grails development (which uses hibernate) which can auto-generates schemas based on domain objects:</p>
<ol>
<li>Generate changelog from initial schema and commit to svn</li>
<li>Rollout schema to other databases by migrating from changelog</li>
<ol>
<li>if the schema already exists and it needs &#8220;LiquiBase-ifying&#8221;, generate changelog-sync-sql and run it</li>
</ol>
<li>Add every schema change via new changeset from hereon in by generating changelogs via grails <a href="http://www.liquibase.org/manual/diff">db-diff</a></li>
<ol>
<li>add / change domain objects in project</li>
<li>set hiberante ddl mode to update</li>
<li>start app and grails will automatically update the db</li>
<li>generate new changelogs using db-diff (against the test db)</li>
<li>append changelogs to changelog.xml</li>
<li>run <code>grails changelog-sync-sql</code> to generate the sql that will mark all these new changes as ran on your db, then run the sql</li>
<li>checkin changes. this will be applied to test</li>
</ol>
<li>provide explicit rollback sql for any custom sql</li>
<li>tag each iteration end with a &#8220;tagDatabase&#8221; changelog in the changelog.xml</li>
</ol>
<h2>Gotchas</h2>
<p>We ran into some gotchas with LiquiBase. One of the first things we started doing before fully understanding how LiquiBase worked was to update existing changesets when changing the schema. LiquiBase generates checksums for each changeset to ensure they don&#8217;t change, and altering existing changelogs will cause future migrations to fail. Even though LiquiBase gives you some tools to get around this, it&#8217;s generally a better practice to just add a new changeset for every database change. There is a good blog on the LiquiBase site explaining  <a href="http://blog.liquibase.org/2008/10/dealing-with-changing-changesets.html">how to deal with changing changesets</a>.</p>
<p>Another gotcha is that the rollback-sql command won&#8217;t magically generate rollback scripts for hand-coded sql (obviously!) You must to generate your own rollback sql for these custom sql tags, otherwise not only will you not get rollback sql for those particular changesets, but the rollback functionality won&#8217;t spit out sql for any other changeset either until you do.</p>
<p>Tagging was a little fussy as well. The command line <code>grails tag</code> can only tag a given state once &#8211; future tags will overwrite the earlier ones unless you&#8217;re at a different changeset. I found it better to add a tag changeset explicitly in the changelog.xml. The Grails plugin for tagging also seems to be problematic with spaces in the tag name. We decided to just use underscores as a convention.</p>
<p>We also ran across some broken functionality:</p>
<ul>
<li>The <code>grails generate-changelog</code> command generates some extraneous information that breaks sql for data type numeric(19,0) if that type has auto-increment on.  It generates this in the changelog:<br />
&lt;column autoIncrement=&#8221;true&#8221; name=&#8221;id&#8221; type=&#8221;numeric()(19,0)&#8221;&gt; (notice the extra empty brackets).  We needed to manually remove these to get it to work.</li>
<li>The <code>grails rollback-to-date-sql</code> command writes to a file with the datestamp instead of to console like the other rollbacks do, even though the docs say it writes to STDOUT (<code>rollback-count-sql</code> also has issues, but <code>rollback-sql</code> for tags works just fine). The code for these plugin commands doesn&#8217;t seem to do the right thing with the args. Time permitting, we may provide a patch for this.</li>
<li>db-doc generation doesn&#8217;t work with large amount of columns in a table because it uses the table description including column names for the html file name.  Too many db columns make the file names too long.</li>
</ul>
<h2>Moving Forward</h2>
<p>Although there&#8217;s a bit of grumbling amongst the developers here that using LiquiBase with the above process is a little onerous, it buys us a lot more certainty for knowing what state our databases are in, making sure changes are in source control, and knowing what updates have or haven&#8217;t been run. It&#8217;s a whole lot easier than hand-coding a bunch of sql, and easily accommodates the possibility of migrating to other DBMS&#8217;s in the future without having to re-write DBMS-specific sql. There&#8217;s even talk of trying to go a step or two further to automate even more of the process so a developer doesn&#8217;t have to think about generating changesets upon changing of a grails domain model. We&#8217;ll see how that goes.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.2paths.com/2008/12/23/liquibase-ifying-your-grails-application/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Tequila Rendering Made Easier</title>
		<link>http://www.2paths.com/2008/12/12/tequila-rendering-made-easier/</link>
		<comments>http://www.2paths.com/2008/12/12/tequila-rendering-made-easier/#comments</comments>
		<pubDate>Fri, 12 Dec 2008 20:01:52 +0000</pubDate>
		<dc:creator>Garrett</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Under the hood]]></category>
		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://www.2paths.com/?p=322</guid>
		<description><![CDATA[Recently I&#8217;ve been working on our in-house open source project, Tequila. It is a RESTful web service framework, and was lacking some familiar rendering capabilities out of the box. (See http://tequilaframework.org/ for project details). The formats that we thought may be useful were XML, JSON, and RDF, and so I set out to provide these [...]]]></description>
			<content:encoded><![CDATA[<p><strong>R</strong>ecently I&#8217;ve been working on our in-house open source project, Tequila. It is a RESTful web service framework, and was lacking some familiar rendering capabilities out of the box. (See http://tequilaframework.org/ for project details). The formats that we thought may be useful were <a href="http://en.wikipedia.org/wiki/Xml" target="_blank">XML</a>, <a href="http://en.wikipedia.org/wiki/Json" target="_blank">JSON</a>, and <a href="http://en.wikipedia.org/wiki/Resource_Description_Framework" target="_blank">RDF</a>, and so I set out to provide these basic abilities.</p>
<p><strong>O</strong>ur XML and JSON rendering functionality leverages the <a href="http://xstream.codehaus.org" target="_blank">XStream project</a>, and provides an easy mechanism for pairing aliases and their respective Java objects.<br />
The <a href="http://www.springframework.org/" target="_blank">Spring Framework</a> configuration in the webapp project sets the rendering information for each response type. Response types are used when specifying <em>routes</em>, which are the Tequila representation for URL request patterns.</p>
<p><strong>JSON example:</strong></p>
<pre class="brush: xml">
&lt;bean id=&quot;dataPointJsonRenderer&quot; class=&quot;org.tequilaframework.core.renderer.JsonRenderer&quot;&gt;
&lt;property name=&quot;responseType&quot; value=&quot;datapoint/json&quot;/&gt;
&lt;property name=&quot;contentType&quot; value=&quot;text/plain&quot;/&gt;
&lt;property name=&quot;aliases&quot;&gt;
&lt;map value-type=&quot;java.lang.Class&quot;&gt;
&lt;entry&gt;
&lt;key&gt;&lt;value&gt;dataPoints&lt;/value&gt;&lt;/key&gt;
&lt;value&gt;java.util.List&lt;/value&gt;
&lt;/entry&gt;
&lt;entry&gt;
&lt;key&gt;&lt;value&gt;dataPoint&lt;/value&gt;&lt;/key&gt;
&lt;value&gt;com.twopaths.example.domain.DataPoint&lt;/value&gt;
&lt;/entry&gt;
&lt;entry&gt;
&lt;key&gt;&lt;value&gt;time&lt;/value&gt;&lt;/key&gt;
&lt;value&gt;com.twopaths.example.domain.TimeDimension&lt;/value&gt;
&lt;/entry&gt;
&lt;entry&gt;
&lt;key&gt;&lt;value&gt;spatial&lt;/value&gt;&lt;/key&gt;
&lt;value&gt;com.twopaths.example.domain.SpatialDimension&lt;/value&gt;
&lt;/entry&gt;
&lt;/map&gt;
&lt;/property&gt;
&lt;!-- Example omission --&gt;
&lt;!-- to omit a field, you must declare the parent class as the class value, and the key is the would-be rendered value --&gt;
&lt;!-- &lt;property name=&quot;omissions&quot;&gt;
&lt;map value-type=&quot;java.lang.Class&quot;&gt;
&lt;entry&gt;
&lt;key&gt;&lt;value&gt;spatial&lt;/value&gt;&lt;/key&gt;
&lt;value&gt;com.twopaths.example.domain.DataPoint&lt;/value&gt;
&lt;/entry&gt;
&lt;/map&gt;
&lt;/property&gt;
--&gt;
&lt;/bean&gt;
</pre>
<p><strong>XML example:</strong></p>
<pre class="brush: xml">
&lt;bean id=&quot;dataPointXmlRenderer&quot; class=&quot;org.tequilaframework.core.renderer.XmlRenderer&quot;&gt;
&lt;property name=&quot;responseType&quot; value=&quot;datapoint/xml&quot;/&gt;
&lt;property name=&quot;contentType&quot; value=&quot;text/plain&quot;/&gt;
&lt;property name=&quot;aliases&quot;&gt;
&lt;map value-type=&quot;java.lang.Class&quot;&gt;
&lt;entry&gt;
&lt;key&gt;&lt;value&gt;dataPoints&lt;/value&gt;&lt;/key&gt;
&lt;value&gt;java.util.List&lt;/value&gt;
&lt;/entry&gt;
&lt;entry&gt;
&lt;key&gt;&lt;value&gt;dataPoint&lt;/value&gt;&lt;/key&gt;
&lt;value&gt;com.twopaths.example.domain.DataPoint&lt;/value&gt;
&lt;/entry&gt;
&lt;entry&gt;
&lt;key&gt;&lt;value&gt;time&lt;/value&gt;&lt;/key&gt;
&lt;value&gt;com.twopaths.example.domain.TimeDimension&lt;/value&gt;
&lt;/entry&gt;
&lt;entry&gt;
&lt;key&gt;&lt;value&gt;spatial&lt;/value&gt;&lt;/key&gt;
&lt;value&gt;com.twopaths.example.domain.SpatialDimension&lt;/value&gt;
&lt;/entry&gt;
&lt;/map&gt;
&lt;/property&gt;
&lt;!-- Example omission --&gt;
&lt;!-- to omit a field, you must declare the parent class as the class value, and the key is the would-be rendered value --&gt;
&lt;!-- &lt;property name=&quot;omissions&quot;&gt;
&lt;map value-type=&quot;java.lang.Class&quot;&gt;
&lt;entry&gt;
&lt;key&gt;&lt;value&gt;spatial&lt;/value&gt;&lt;/key&gt;
&lt;value&gt;com.twopaths.example.domain.DataPoint&lt;/value&gt;
&lt;/entry&gt;
&lt;/map&gt;
&lt;/property&gt;
--&gt;
&lt;/bean&gt;
</pre>
<p><strong>T</strong>he RDF renderer leverages the <a href="http://jena.sourceforge.net" target="_blank">Jena project</a> and <a href="http://code.google.com/p/jenabean/" target="_blank">Jenabean project</a>. Jena supported RDF formats include<em> RDF/XML, RDF/XML-ABBREV, N-TRIPLE, TURTLE, N3, N3-PP, N3-PLAIN, and N3-TRIPLE</em>. Because of Jena, the Tequila RDF renderer gets these formats for free. The only trick with RDF in Tequila is that you will need to use annotations in the Java classes you wish to have RDF support in. If you&#8217;re using <a href="http://www.hibernate.org/" target="_blank">Hibernate</a>, then you&#8217;ll likely already have RDF rendering configured. If no rdfType is specified, the default is RDF/XML.</p>
<p><strong>RDF example:</strong></p>
<pre class="brush: xml">
&lt;bean id=&quot;dataDescriptionRdfRenderer&quot; class=&quot;org.tequilaframework.core.renderer.RdfRenderer&quot;&gt;
&lt;property name=&quot;responseType&quot; value=&quot;application/rdf&quot;/&gt;
&lt;property name=&quot;contentType&quot; value=&quot;text/plain&quot;/&gt;
&lt;property name=&quot;domain&quot; value=&quot;http://www.2paths.com/example&quot;/&gt;
&lt;property name=&quot;rdfType&quot; value=&quot;TURTLE&quot;/&gt;
&lt;/bean&gt;
</pre>
<p><strong>W</strong>ith multiple rendering capabilities, the GET request to the webapp can alter the rendering output by including the <em>flavor</em> RPC verb descriptor to modify the return format. For example, the URL of</p>
<p>http://localhost:8080/example/app/data/example?flavor=application/rdf</p>
<p>would return an RDF rendered output, and the original response format may have been JSON, or another response format laid out in the configuration file.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.2paths.com/2008/12/12/tequila-rendering-made-easier/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using Spring themes to override resource bundle messages</title>
		<link>http://www.2paths.com/2008/10/17/spring-themes-and-resource-bundles/</link>
		<comments>http://www.2paths.com/2008/10/17/spring-themes-and-resource-bundles/#comments</comments>
		<pubDate>Fri, 17 Oct 2008 19:00:33 +0000</pubDate>
		<dc:creator>Geoff</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Under the hood]]></category>
		<category><![CDATA[bundle]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[spring]]></category>
		<category><![CDATA[theme]]></category>

		<guid isPermaLink="false">http://blog.2paths.com/?p=94</guid>
		<description><![CDATA[We use Spring quite a bit. In one project we use Spring MVC (I won&#8217;t get into a rant about whether that&#8217;s a good thing or not) and rightly or wrongly we use Spring themes within our UI. Yes I know JSP based UIs are so last century but sometimes if the shoe fits &#8230;
One [...]]]></description>
			<content:encoded><![CDATA[<p>We use Spring quite a bit. In one project we use Spring MVC (I won&#8217;t get into a rant about whether that&#8217;s a good thing or not) and rightly or wrongly we use Spring themes within our UI. Yes I know JSP based UIs are so last century but sometimes if the shoe fits &#8230;</p>
<p>One thing that we wanted to do was have themes which override certain resource bundle variables defined in an application wide, internationalized properties file. For example, our login greeting is &#8220;Welcome&#8221; with an appropriate i18n version for various locales. We also have certain themes based on types of user accounts. Some themes require their own customized login greeting and others will rely on using messages from the default MessageSource.</p>
<p>Our Spring application utilizes two classes for accessing resource bundles:</p>
<ul>
<li><code>org.springframework.context.support.ResourceBundleMessageSource</code></li>
<li><code>org.springframework.ui.context.support.ResourceBundleThemeSource</code></li>
</ul>
<p>Both these classes provide access to specific resource bundles but do not necessarily know about each other which means the operate in isolation. Ideally we wanted to have a hierarchy of resource bundles such that a resource message defined in the bundle accessed by <code>ResourceBundleMessageSource</code> could be overridden by a message defined in resource bundles accessed by <code>ResourceBundleThemeSource</code>. Whilst the <code>ResourceBundleMessageSource</code> class has a <code>setParentResourceBundle()</code>, there is no way to inject that to the <code>ResourceBundleThemeSource</code> via configuration.</p>
<p>As the resourceful (no pun intended) java developers that we are, we decided to create our own wrapper class for theme bundle resolution. This class will use the application&#8217;s <code>ResourceBundleMessageSource</code> definition as a parent for its own resource message source so that we can ensure that if a message cannot be resolved by key in the theme bundle, it will then defer to the parent resource bundle (which is the application level MessageSource) and try and look up the key there. This simple class is outlined below:</p>
<pre class="brush: java">
public class CustomResourceBundleThemeSource
        extends ResourceBundleThemeSource {

    private MessageSource parent;

    public void setParentMessageSource(MessageSource messageSource) {
        parent = messageSource;
    }

    @Override
    protected MessageSource createMessageSource(String basename) {
        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
        messageSource.setBasename(basename);
        messageSource.setUseCodeAsDefaultMessage(true);
        messageSource.setParentMessageSource(parent);
        return messageSource;
    }
}
</pre>
<p>With this class, we just need the following in our Spring config class:</p>
<pre class="brush: xml">

    &lt;bean id=&quot;messageSource&quot;
          class=&quot;org.springframework.context.support.ResourceBundleMessageSource&quot;&gt;
        &lt;property name=&quot;basenames&quot;&gt;
            &lt;list&gt;
                &lt;value&gt;bundles/messages&lt;/value&gt;
            &lt;/list&gt;
        &lt;/property&gt;
    &lt;/bean&gt;
    &lt;bean id=&quot;themeSource&quot;
          class=&quot;CustomResourceBundleThemeSource&quot;&gt;
        &lt;property name=&quot;basenamePrefix&quot; value=&quot;/themes/&quot; /&gt;
        &lt;property name=&quot;parentMessageSource&quot; ref=&quot;messageSource&quot; /&gt;
    &lt;/bean&gt;
</pre>
<p>Now whenever we need to resolve resource messages, we use the Spring specific theme tags:</p>
<pre class="brush: xml">
    &lt;spring:theme code=&quot;login.greeting&quot; /&gt;
</pre>
<p>And if we have a definition in our theme resource bundle we see that else we see the default definition as specified in the underlying MessageSource.</p>
<p>This allows us to override resource bundle messages for various themes as required and removed quite a bit of ugly JSP/JSTL logic for resolving messages conditionally.</p>
<p>Job done.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.2paths.com/2008/10/17/spring-themes-and-resource-bundles/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

