<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>PrettyPrint.me</title>
	
	<link>http://prettyprint.me</link>
	<description>by Ran Tavory</description>
	<lastBuildDate>Wed, 03 Mar 2010 06:34:20 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/PrettyPrintMe" /><feedburner:info uri="prettyprintme" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><creativeCommons:license>http://creativecommons.org/licenses/by-nd/2.0/</creativeCommons:license><image><link>http://creativecommons.org/licenses/by-nd/2.0/</link><url>http://creativecommons.org/images/public/somerights20.gif</url><title>Some Rights Reserved</title></image><item>
		<title>Load balancing and improved failover in Hector</title>
		<link>http://feedproxy.google.com/~r/PrettyPrintMe/~3/BRscjMHD6Ak/</link>
		<comments>http://prettyprint.me/2010/03/03/load-balancing-and-improved-failover-in-hector/#comments</comments>
		<pubDate>Wed, 03 Mar 2010 06:34:20 +0000</pubDate>
		<dc:creator>Ran Tavory</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://prettyprint.me/?p=278</guid>
		<description><![CDATA[
I&#8217;ve added a very simple load balancing feature, as well as improved failover behavior to Hector. Hector is a Java Cassandra client, to read more about it please see my previous post Hector – a Java Cassandra client.
In version 0.5.0-6 I added poor-man&#8217;s load balancing as well as improved failover behavior.
The interface CassandraClientPool used to have this [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fprettyprint.me%2F2010%2F03%2F03%2Fload-balancing-and-improved-failover-in-hector%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fprettyprint.me%2F2010%2F03%2F03%2Fload-balancing-and-improved-failover-in-hector%2F" height="61" width="51" /></a></div><p><img class="size-thumbnail wp-image-279 alignleft" title="Balance the load" src="http://prettyprint.me/wp-content/uploads/2010/03/load_balance-150x150.jpg" alt="Balance the load, woman!" width="150" height="150" /></p>
<p>I&#8217;ve added a very simple load balancing feature, as well as improved failover behavior to <a href="http://github.com/rantav/hector">Hector</a>. Hector is a Java Cassandra client, to read more about it please see my previous post <a href="http://prettyprint.me/2010/02/23/hector-a-java-cassandra-client/comment-page-1/">Hector – a Java Cassandra client</a>.</p>
<p>In <a href="http://github.com/downloads/rantav/hector/hector-0.5.0-6.jar">version 0.5.0-6</a> I added poor-man&#8217;s load balancing as well as improved failover behavior.</p>
<p>The interface <a href="http://github.com/rantav/hector/blob/master/src/main/java/me/prettyprint/cassandra/service/CassandraClientPool.java">CassandraClientPool</a> used to have this method for obtaining clients:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #008000; font-style: italic; font-weight: bold;">/**
 * Borrows a client from the pool defined by url:port
 * @param url
 * @param port
 * @return
 */</span>
CassandraClient borrowClient<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> url, <span style="color: #000066; font-weight: bold;">int</span> port<span style="color: #009900;">&#41;</span>
    <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">IllegalStateException</span>, PoolExhaustedException, <span style="color: #003399;">Exception</span><span style="color: #339933;">;</span></pre></div></div>

<p>Now with the added LB and failover it has:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #008000; font-style: italic; font-weight: bold;">/**
 * Borrow a load-balanced client, a random client from the array of given client addresses.
 *
 * This method is typically used to allow load balancing b/w the list of given client URLs. The
 * method will return a random client from the array of the given url:port pairs.
 * The method will try connecting each host in the list and will only stop when there's one
 * successful connection, so in that sense it's also useful for failover.
 *
 * @param clientUrls An array of &quot;url:port&quot; cassandra client addresses.
 *
 * @return A randomly chosen client from the array of clientUrls.
 * @throws Exception
 */</span>
CassandraClient borrowClient<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> clientUrls<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">Exception</span><span style="color: #339933;">;</span></pre></div></div>

<p>And usage looks like that:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// Get a connection to any of the hosts cas1, ca2 or cas3</span>
CassandraClient client <span style="color: #339933;">=</span> pool.<span style="color: #006633;">borrowClient</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">String</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#123;</span><span style="color: #0000ff;">&quot;cas1:9160&quot;</span>, <span style="color: #0000ff;">&quot;cas2:9160&quot;</span>, <span style="color: #0000ff;">&quot;cas3:9160&quot;</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>So, when calling borrowClient(String[]) the method randomly chooses any of the clients in the array and connects to it. That&#8217;s what I call poor man&#8217;s load balancing, just plain dumb random, not real load balancing. By all means, true load balancing which takes into account performance measurements such as response time and throughput is infinitely better than the plain random selection I&#8217;m employing here and in my opinion should be left out for your ops folks to deal with and not to the program, however, if you only need a very simplistic approach of random selection, then this method may suite your needs.</p>
<p>A nice side effect of using this method is <strong>improved failover</strong>. In previous versions hector implemented failover, but in order to find out about the ring structure it had to connect to at least one host in the ring first and query it to learn about the rest. The result was that if a new connection is made and it&#8217;s so unfortunate that this new connections is made to unavailable host, then this new client cannot connect to the host to learn about other live hosts so it fails right away. With this new method which sends an array of hosts the client keeps connecting to hosts in the list in random order until it finds one that&#8217;s up. In the example above the client may choose to connect to cas2 first; if cas2 is down it&#8217;ll try to connect to (say) cas3 and if cas3 is also down it&#8217;ll try to connect to cas1; only if all three hosts are down will it give up and return an error. Failing to connect to hosts is considered an error, but a recoverable error, so it&#8217;s transparent to the client of hector but is reported to JMX and has its own special counter (RecoverableLoadBalancedConnectErrors).</p>
<img src="http://feeds.feedburner.com/~r/PrettyPrintMe/~4/BRscjMHD6Ak" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://prettyprint.me/2010/03/03/load-balancing-and-improved-failover-in-hector/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://prettyprint.me/2010/03/03/load-balancing-and-improved-failover-in-hector/</feedburner:origLink></item>
		<item>
		<title>Hector – a Java Cassandra client</title>
		<link>http://feedproxy.google.com/~r/PrettyPrintMe/~3/l9ry9NFrcao/</link>
		<comments>http://prettyprint.me/2010/02/23/hector-a-java-cassandra-client/#comments</comments>
		<pubDate>Tue, 23 Feb 2010 14:04:09 +0000</pubDate>
		<dc:creator>Ran Tavory</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://prettyprint.me/?p=263</guid>
		<description><![CDATA[UPDATE: I added a downloads section, so you may simply download the jar and sources if you&#8217;re not into git or maven.
UPDATE 2: I added license clarification; the license it MIT, which is the most permissive license I know of and basically lets you do anything with the software: use it commercially or uncommercially, copy it, [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fprettyprint.me%2F2010%2F02%2F23%2Fhector-a-java-cassandra-client%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fprettyprint.me%2F2010%2F02%2F23%2Fhector-a-java-cassandra-client%2F" height="61" width="51" /></a></div><p>UPDATE: I added a <a href="http://github.com/rantav/hector/downloads">downloads</a> section, so you may simply download the jar and sources if you&#8217;re not into git or maven.</p>
<p>UPDATE 2: I added license clarification; the license it <a href="http://www.opensource.org/licenses/mit-license.php">MIT</a>, which is the most permissive license I know of and basically lets you do anything with the software: use it commercially or uncommercially, copy it, fork it (but I&#8217;ll be happy to accept patches and committers) and whatnot. I added a <a href="http://github.com/rantav/hector/blob/master/LICENSE">LICENSE file</a> and over time I&#8217;ll add that block of comment to every file.</p>
<p>In the <a href="http://en.wikipedia.org/wiki/Greek_mythology">Greek Mythology</a>, <a href="http://en.wikipedia.org/wiki/Hector">Hector</a> was the builder of <a href="http://en.wikipedia.org/wiki/Troy">Troy</a>, the greatest warrior ever and brother of <a href="http://en.wikipedia.org/wiki/Cassandra">Cassandra</a>.</p>
<p><a href="http://prettyprint.me/wp-content/uploads/2010/02/Ajax_and_Hector_exchange_gifts1.jpg"><img class="size-medium wp-image-268 alignnone" title="Ajax_and_Hector_exchange_gifts" src="http://prettyprint.me/wp-content/uploads/2010/02/Ajax_and_Hector_exchange_gifts1-300x286.jpg" alt="" width="240" height="229" /></a></p>
<p><a href="http://prettyprint.me/wp-content/uploads/2010/02/Ajax_and_Hector_exchange_gifts1.jpg"></a>Nowdays, <a href="http://incubator.apache.org/cassandra/">Cassandra</a> is a high scale database and <a href="http://github.com/rantav/hector">Hector</a> is the Java client I&#8217;ve written for it.</p>
<p>Over the last couple of days I got the the conclusion that the java client I&#8217;ve been using so far to speak to cassanrda wasn&#8217;t satisfactory. I used the one simply called <a href="http://code.google.com/p/cassandra-java-client/">cassandra-java-client</a>, which is a good start but had some shortcomings I could just not live with (no support for Cassandra v0.5, no JMX and no failover). So I&#8217;ve written my own.</p>
<p>For anyone not familiar with cassanra, it&#8217;s client API is just a simple <a href="http://incubator.apache.org/thrift/">thrift</a> client. This means that, unlike other datastore clients such as jdbc etc, the client provided has somewhat limiter functionality; It can sent messages to cassanra, write values and read values of course, but other client goodies required for large scale applications are not provided, features such as monitoring, connection pooling etc. The client I initially used provides connection pooling, which is a very nice start, but I decided it was missing too much so I&#8217;d write my own.</p>
<p>As a good open-source citizen, I initially contacted the authors of cassandra-java-client asking their permission to contribute and make the suggested improvements, but after weeks without reply I realized I&#8217;ll need to go solo. I started with the concepts captured by the folks who had built the java-client, but pretty soon the code has morphed to be something completely different.</p>
<p>Here&#8217;s how code that uses Hector looks like. This is an implementation of a simple distributed hashtable over cassandra. By the virtue of cassandra, this hashtable can grow pretty large:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">  <span style="color: #008000; font-style: italic; font-weight: bold;">/**
   * Insert a new value keyed by key
   * @param key Key for the value
   * @param value the String value to insert
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> insert<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">String</span> key, <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">String</span> value<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">Exception</span> <span style="color: #009900;">&#123;</span>
    execute<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> Command<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
      <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">Void</span> execute<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">final</span> Keyspace ks<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">Exception</span> <span style="color: #009900;">&#123;</span>
        ks.<span style="color: #006633;">insert</span><span style="color: #009900;">&#40;</span>key, createColumnPath<span style="color: #009900;">&#40;</span>COLUMN_NAME<span style="color: #009900;">&#41;</span>, bytes<span style="color: #009900;">&#40;</span>value<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #008000; font-style: italic; font-weight: bold;">/**
   * Get a string value.
   * @return The string value; null if no value exists for the given key.
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">String</span> get<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">String</span> key<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">Exception</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">return</span> execute<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> Command<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
      <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">String</span> execute<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">final</span> Keyspace ks<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">Exception</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">try</span> <span style="color: #009900;">&#123;</span>
          <span style="color: #000000; font-weight: bold;">return</span> string<span style="color: #009900;">&#40;</span>ks.<span style="color: #006633;">getColumn</span><span style="color: #009900;">&#40;</span>key, createColumnPath<span style="color: #009900;">&#40;</span>COLUMN_NAME<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">getValue</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">catch</span> <span style="color: #009900;">&#40;</span>NotFoundException e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
          <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #008000; font-style: italic; font-weight: bold;">/**
   * Delete a key from cassandra
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> delete<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">String</span> key<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">Exception</span> <span style="color: #009900;">&#123;</span>
    execute<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> Command<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
      <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">Void</span> execute<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">final</span> Keyspace ks<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">Exception</span> <span style="color: #009900;">&#123;</span>
        ks.<span style="color: #006633;">remove</span><span style="color: #009900;">&#40;</span>key, createColumnPath<span style="color: #009900;">&#40;</span>COLUMN_NAME<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span></pre></div></div>

<p>Out of the box Cassanra provides a raw <a href="http://incubator.apache.org/thrift/">thrift</a> client, which is OK, but lacks many features essential to real world clients. I&#8217;ve built Hector to fill this gap.</p>
<p>Here are the high level features of <a href="http://github.com/rantav/hector">Hector</a>, currently hosted at github.</p>
<ul>
<li>A high-level object oriented interface to cassandra. As noted before, Cassandra&#8217;s out of the box client is a thrift client, which isn&#8217;t always that nice and clean to work with. I wanted to provide higher level and cleaner API. This part was mainly inspired by the mentioned cassandra-java-client. The API is defined in the <a href="http://github.com/rantav/hector/blob/master/src/main/java/me/prettyprint/cassandra/service/Keyspace.java">Keyspace</a> interface. See for example methods such as Keyspace.insert() and keyspace.getColumn()</li>
<li>Failover support. Cassandra is a distributed data store and it may handle very well one or several hosts going down. However, out of the box thrift provides no support for failing clients. What it the client is configured to connect a cassandra host that just happened to be down right now? In hector, if a client is connected to one host in the ring and this host goes down, the client will automatically and transparently search for other available hosts to perform its operation before giving up  and returning an error to its user. There are currently 3 ways to configure the failover policy: FAIL_FAST (no retry, just fail if there are errors, nothing smart), ON_FAIL_TRY_ONE_NEXT_AVAILABLE (try one more host before giving up) and ON_FAIL_TRY_ALL_AVAILABLE (try all available hosts before giving up). See <a href="http://github.com/rantav/hector/blob/master/src/main/java/me/prettyprint/cassandra/service/CassandraClient.java">CassandraClient.FailoverPolicy</a>.</li>
<li>Connection pooling. This is a real necessity for high scale applications. The usual pattern for DAOs (Data Access Objects) is large number of small reads/writes. Clients cannot afford to open a new connection with each and every request, not only because of the overhead in the tcp handshake (thrift uses tcp), but also because of the fact that sockets remain in <a href="http://www.developerweb.net/forum/showthread.php?t=2941">TIME_WAIT</a> so a client may easily run out of available sockets if it operates fast enough. This part was also inspired by cassandra-java-client but was improved in my version. Hector provides connection pooling and a nice framework that manages all its gory details.</li>
<li>JMX support. It&#8217;s a widely known fact that applications have a life of their own. You built it to do X but it does Y b/c you didn&#8217;t expect Z to happen. Running an application without the ability to monitor it is like walking blindfolded on a dark highway; sooner or later you&#8217;ll get hit by something. Hector exposes JMX for many important runtime metrics, such as number of available connections, idle connections, error statistics and more.</li>
<li>Support for the Command design pattern to allow clients to concentrate on their business logic and let hector take care of the required plumbing. This is demonstrated in the code above.</li>
</ul>
<p>I&#8217;ve been using hector internally, at outbrain and so far so good. I&#8217;d be happy to get the comminuty feedback &#8211; API, implementation, features and so on and hope you can find it useful.</p>
<img src="http://feeds.feedburner.com/~r/PrettyPrintMe/~4/l9ry9NFrcao" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://prettyprint.me/2010/02/23/hector-a-java-cassandra-client/feed/</wfw:commentRss>
		<slash:comments>27</slash:comments>
		<feedburner:origLink>http://prettyprint.me/2010/02/23/hector-a-java-cassandra-client/</feedburner:origLink></item>
		<item>
		<title>Running Cassandra as an embedded service</title>
		<link>http://feedproxy.google.com/~r/PrettyPrintMe/~3/o8mE_Zqwh-A/</link>
		<comments>http://prettyprint.me/2010/02/14/running-cassandra-as-an-embedded-service/#comments</comments>
		<pubDate>Sun, 14 Feb 2010 06:08:45 +0000</pubDate>
		<dc:creator>Ran Tavory</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://prettyprint.me/?p=255</guid>
		<description><![CDATA[While developing an application at outbrain, using Cassandra I was looking for a good way to test my app. The application consists of a Cassandra Client package, some Data Access Objects (DAOs) and some bean object that represent the data entities in cassandra. I wanted to test them all.
As unit test tradition goes, my requirement [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fprettyprint.me%2F2010%2F02%2F14%2Frunning-cassandra-as-an-embedded-service%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fprettyprint.me%2F2010%2F02%2F14%2Frunning-cassandra-as-an-embedded-service%2F" height="61" width="51" /></a></div><p><a href="http://prettyprint.me/wp-content/uploads/2010/02/cassandra3125.jpg"><img class="size-medium wp-image-257 alignleft" title="cassandra embedded" src="http://prettyprint.me/wp-content/uploads/2010/02/cassandra3125-220x300.jpg" alt="" width="220" height="300" /></a>While developing an application at outbrain, using <a href="http://incubator.apache.org/cassandra/">Cassandra</a> I was looking for a good way to test my app. The application consists of a Cassandra Client package, some Data Access Objects (DAOs) and some bean object that represent the data entities in cassandra. I wanted to test them all.</p>
<p>As unit test tradition goes, my requirement was zero-configuration, zero preparation, no external dependencies, full isolation, fully reproducible results and fast. Database testing has always been a challenge in this perspective, for example when testing SQL clients in java often <a href="http://hsqldb.org/">HSQLDB</a> is used to to mock the database. Cassandra, however, did not have something ready just yet so I had to build it.</p>
<p>One way to go was to setup a cassandra instance just for unit testing. There are many downsides to this approach, such as it&#8217;s not zero-configuration, tests need to cleanup before they execute, if two tests are run at the same time by two developers they can collide and change the results in unexpected way, it&#8217;s slow&#8230; out of the question, not good.</p>
<p>Enter the embedded cassandra server.</p>
<p>With the help of the community I&#8217;ve built an embedded cassandra service ideal for unit testing and perhaps other uses. I&#8217;ve also built a cleanup utility that helps wipe out all data before the service starts running so the combination of both provides isolation etc. Now each test process runs an in-process, embedded instance of cassandra.</p>
<p>Below is the source code, already committed to cassandra SCM on trunk. If you want to use it for the current stable release(0.5.0) only a small package rename is required (in trunk some classes moved a bit), and it&#8217;s presented at the end of the post.</p>
<p>The embedded service:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">package</span> <span style="color: #006699;">org.apache.cassandra.service</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.io.File</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.io.FileOutputStream</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.io.IOException</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.io.InputStream</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.io.OutputStream</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.cassandra.config.DatabaseDescriptor</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.cassandra.io.util.FileUtils</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.cassandra.thrift.CassandraDaemon</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.thrift.transport.TTransportException</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.slf4j.Logger</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.slf4j.LoggerFactory</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #008000; font-style: italic; font-weight: bold;">/**
 * An embedded, in-memory cassandra storage service that listens
 * on the thrift interface as configured in storage-conf.xml
 * This kind of service is useful when running unit tests of
 * services using cassandra for example.
 *
&nbsp;
 * This is the implementation of https://issues.apache.org/jira/browse/CASSANDRA-740
 *
&nbsp;
 * How to use:
 * In the client code create a new thread and spawn it with its {@link Thread#start()} method.
 * Example:
 *
 *      // Tell cassandra where the configuration files are.
        System.setProperty(&quot;storage-config&quot;, &quot;conf&quot;);
&nbsp;
        cassandra = new EmbeddedCassandraService();
        cassandra.init();
&nbsp;
        // spawn cassandra in a new thread
        Thread t = new Thread(cassandra);
        t.setDaemon(true);
        t.start();
&nbsp;
 *
 * @author Ran Tavory (rantav@gmail.com)
 *
 */</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> EmbeddedCassandraService <span style="color: #000000; font-weight: bold;">implements</span> <span style="color: #003399;">Runnable</span>
<span style="color: #009900;">&#123;</span>
&nbsp;
    CassandraDaemon cassandraDaemon<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> init<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> TTransportException, <span style="color: #003399;">IOException</span>
    <span style="color: #009900;">&#123;</span>
        cassandraDaemon <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> CassandraDaemon<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        cassandraDaemon.<span style="color: #006633;">init</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> run<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        cassandraDaemon.<span style="color: #006633;">start</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>The data cleaner:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">package</span> <span style="color: #006699;">org.apache.cassandra.contrib.utils.service</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.io.File</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.io.IOException</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.util.HashSet</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.util.Set</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.cassandra.config.DatabaseDescriptor</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.cassandra.io.util.FileUtils</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #008000; font-style: italic; font-weight: bold;">/**
 * A cleanup utility that wipes the cassandra data directories.
 *
 * @author Ran Tavory (rantav@gmail.com)
 *
 */</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> CassandraServiceDataCleaner <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #008000; font-style: italic; font-weight: bold;">/**
     * Creates all data dir if they don't exist and cleans them
     * @throws IOException
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> prepare<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">IOException</span> <span style="color: #009900;">&#123;</span>
        makeDirsIfNotExist<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        cleanupDataDirectories<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #008000; font-style: italic; font-weight: bold;">/**
     * Deletes all data from cassandra data directories, including the commit log.
     * @throws IOException in case of permissions error etc.
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> cleanupDataDirectories<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">IOException</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> s<span style="color: #339933;">:</span> getDataDirs<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            cleanDir<span style="color: #009900;">&#40;</span>s<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #008000; font-style: italic; font-weight: bold;">/**
     * Creates the data diurectories, if they didn't exist.
     * @throws IOException if directories cannot be created (permissions etc).
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> makeDirsIfNotExist<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">IOException</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> s<span style="color: #339933;">:</span> getDataDirs<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            mkdir<span style="color: #009900;">&#40;</span>s<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #008000; font-style: italic; font-weight: bold;">/**
     * Collects all data dirs and returns a set of String paths on the file system.
     *
     * @return
     */</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">Set</span> getDataDirs<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #003399;">Set</span> dirs <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">HashSet</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> s <span style="color: #339933;">:</span> DatabaseDescriptor.<span style="color: #006633;">getAllDataFileLocations</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            dirs.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span>s<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        dirs.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span>DatabaseDescriptor.<span style="color: #006633;">getLogFileLocation</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">return</span> dirs<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #008000; font-style: italic; font-weight: bold;">/**
     * Creates a directory
     *
     * @param dir
     * @throws IOException
     */</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">void</span> mkdir<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> dir<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">IOException</span> <span style="color: #009900;">&#123;</span>
        FileUtils.<span style="color: #006633;">createDirectory</span><span style="color: #009900;">&#40;</span>dir<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #008000; font-style: italic; font-weight: bold;">/**
     * Removes all directory content from file the system
     *
     * @param dir
     * @throws IOException
     */</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">void</span> cleanDir<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> dir<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">IOException</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #003399;">File</span> dirFile <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">File</span><span style="color: #009900;">&#40;</span>dir<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>dirFile.<span style="color: #006633;">exists</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;</span>amp<span style="color: #339933;">;&amp;</span>amp<span style="color: #339933;">;</span> dirFile.<span style="color: #006633;">isDirectory</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            FileUtils.<span style="color: #006633;">delete</span><span style="color: #009900;">&#40;</span>dirFile.<span style="color: #006633;">listFiles</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>And an example test that uses both:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">package</span> <span style="color: #006699;">org.apache.cassandra.contrib.utils.service</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">static</span> org.<span style="color: #006633;">junit</span>.<span style="color: #000000; font-weight: bold;">Assert</span>.<span style="color: #006633;">assertEquals</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">static</span> org.<span style="color: #006633;">junit</span>.<span style="color: #000000; font-weight: bold;">Assert</span>.<span style="color: #006633;">assertNotNull</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.io.IOException</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.io.UnsupportedEncodingException</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.cassandra.service.EmbeddedCassandraService</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.cassandra.thrift.Cassandra</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.cassandra.thrift.ColumnOrSuperColumn</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.cassandra.thrift.ColumnPath</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.cassandra.thrift.ConsistencyLevel</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.cassandra.thrift.InvalidRequestException</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.cassandra.thrift.NotFoundException</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.cassandra.thrift.TimedOutException</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.cassandra.thrift.UnavailableException</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.thrift.TException</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.thrift.protocol.TBinaryProtocol</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.thrift.protocol.TProtocol</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.thrift.transport.TSocket</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.thrift.transport.TTransport</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.thrift.transport.TTransportException</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.junit.BeforeClass</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.junit.Test</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #008000; font-style: italic; font-weight: bold;">/**
 * Example how to use an embedded and a data cleaner.
 *
 * @author Ran Tavory (rantav@gmail.com)
 *
 */</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> CassandraServiceTest <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> EmbeddedCassandraService cassandra<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #008000; font-style: italic; font-weight: bold;">/**
     * Set embedded cassandra up and spawn it in a new thread.
     *
     * @throws TTransportException
     * @throws IOException
     * @throws InterruptedException
     */</span>
    @BeforeClass
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000066; font-weight: bold;">void</span> setup<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> TTransportException, <span style="color: #003399;">IOException</span>,
            <span style="color: #003399;">InterruptedException</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// Tell cassandra where the configuration files are.</span>
        <span style="color: #666666; font-style: italic;">// Use the test configuration file.</span>
        <span style="color: #003399;">System</span>.<span style="color: #006633;">setProperty</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;storage-config&quot;</span>, <span style="color: #0000ff;">&quot;../../test/conf&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        CassandraServiceDataCleaner cleaner <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> CassandraServiceDataCleaner<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        cleaner.<span style="color: #006633;">prepare</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        cassandra <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> EmbeddedCassandraService<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        cassandra.<span style="color: #006633;">init</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #003399;">Thread</span> t <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">Thread</span><span style="color: #009900;">&#40;</span>cassandra<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        t.<span style="color: #006633;">setDaemon</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        t.<span style="color: #006633;">start</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>   
&nbsp;
    @Test
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> testInProcessCassandraServer<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
            <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">UnsupportedEncodingException</span>, InvalidRequestException,
            UnavailableException, TimedOutException, TException,
            NotFoundException <span style="color: #009900;">&#123;</span>
        Cassandra.<span style="color: #006633;">Client</span> client <span style="color: #339933;">=</span> getClient<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #003399;">String</span> key_user_id <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;1&quot;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000066; font-weight: bold;">long</span> timestamp <span style="color: #339933;">=</span> <span style="color: #003399;">System</span>.<span style="color: #006633;">currentTimeMillis</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        ColumnPath cp <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ColumnPath<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Standard1&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        cp.<span style="color: #006633;">setColumn</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;name&quot;</span>.<span style="color: #006633;">getBytes</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;utf-8&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// insert</span>
        client.<span style="color: #006633;">insert</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Keyspace1&quot;</span>, key_user_id, cp, <span style="color: #0000ff;">&quot;Ran&quot;</span>.<span style="color: #006633;">getBytes</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;UTF-8&quot;</span><span style="color: #009900;">&#41;</span>,
                timestamp, ConsistencyLevel.<span style="color: #006633;">ONE</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// read</span>
        ColumnOrSuperColumn got <span style="color: #339933;">=</span> client.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Keyspace1&quot;</span>, key_user_id, cp,
                ConsistencyLevel.<span style="color: #006633;">ONE</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// assert</span>
        assertNotNull<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Got a null ColumnOrSuperColumn&quot;</span>, got<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        assertEquals<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Ran&quot;</span>, <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">String</span><span style="color: #009900;">&#40;</span>got.<span style="color: #006633;">getColumn</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">getValue</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>, <span style="color: #0000ff;">&quot;utf-8&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #008000; font-style: italic; font-weight: bold;">/**
     * Gets a connection to the localhost client
     *
     * @return
     * @throws TTransportException
     */</span>
    <span style="color: #000000; font-weight: bold;">private</span> Cassandra.<span style="color: #006633;">Client</span> getClient<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> TTransportException <span style="color: #009900;">&#123;</span>
        TTransport tr <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> TSocket<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;localhost&quot;</span>, <span style="color: #cc66cc;">9170</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        TProtocol proto <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> TBinaryProtocol<span style="color: #009900;">&#40;</span>tr<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        Cassandra.<span style="color: #006633;">Client</span> client <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Cassandra.<span style="color: #006633;">Client</span><span style="color: #009900;">&#40;</span>proto<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        tr.<span style="color: #006633;">open</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">return</span> client<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>To use this source code in v0.5.0 a small package rename is required:<br />
org.apache.cassandra.io.util.FileUtils =&gt; org.apache.cassandra.utils.FileUtils<br />
org.apache.thrift.transport.TTransportException =&gt; org.apache.transport.TTransportException<br />
org.apache.cassandra.thrift.CassandraDaemon =&gt; org.apache.cassandra.CassandraDaemon</p>
<p>One nifty detail: When running multiple tests serially, make sure to spawn each test in a separate JVM (fork mode) since cassandra doesn&#8217;t shut down all threads immediately. Running each in separate jvm ensures the previous test dies before the next one begins.</p>
<img src="http://feeds.feedburner.com/~r/PrettyPrintMe/~4/o8mE_Zqwh-A" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://prettyprint.me/2010/02/14/running-cassandra-as-an-embedded-service/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://prettyprint.me/2010/02/14/running-cassandra-as-an-embedded-service/</feedburner:origLink></item>
		<item>
		<title>Introduction to NOSQL and cassandra, part 2</title>
		<link>http://feedproxy.google.com/~r/PrettyPrintMe/~3/ycWVpLZvggU/</link>
		<comments>http://prettyprint.me/2010/01/20/introduction-to-nosql-and-cassandra-part-2/#comments</comments>
		<pubDate>Wed, 20 Jan 2010 08:52:40 +0000</pubDate>
		<dc:creator>Ran Tavory</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://prettyprint.me/?p=241</guid>
		<description><![CDATA[In part 1 of this talk I presented few of the theoretical  concepts behind nosql and cassandra.
In this talk we deep dive into the Cassandra API and implementation. The video is again in Hebrew, but the slides are multilingual ;-)



Started with a short recap of some of RDBMS and SQL properties, such as ADIC, why SQL [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fprettyprint.me%2F2010%2F01%2F20%2Fintroduction-to-nosql-and-cassandra-part-2%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fprettyprint.me%2F2010%2F01%2F20%2Fintroduction-to-nosql-and-cassandra-part-2%2F" height="61" width="51" /></a></div><p>In <a href="http://prettyprint.me/2010/01/09/introduction-to-nosql-and-cassandra-part-1/">part 1</a> of this talk I presented few of the theoretical  concepts behind nosql and cassandra.</p>
<p>In this talk we deep dive into the Cassandra API and implementation. The video is again in Hebrew, but the slides are multilingual ;-)<br />
<object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/8P_wAe6Xpxw&#038;hl=en_US&#038;fs=1&#038;"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/8P_wAe6Xpxw&#038;hl=en_US&#038;fs=1&#038;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></object><br />
<iframe src="http://docs.google.com/present/embed?id=ahbp3bktzpkc_145c5gmf2gz" frameborder="0" width="410" height="342"></iframe></p>
<ul>
<li>Started with a short recap of some of RDBMS and SQL properties, such as <a href="http://databases.about.com/od/specificproducts/a/acid.htm">ADIC</a>, why SQL if very programmer friendly, but is also limited in its support for large scale systems.</li>
<li><a href="http://databases.about.com/od/specificproducts/a/acid.htm"></a>Short recap of the <a href="http://www.julianbrowne.com/article/viewer/brewers-cap-theorem">CAP theorem</a></li>
<li><a href="http://www.julianbrowne.com/article/viewer/brewers-cap-theorem"></a>Short recap of what N/R/W are</li>
<li>Cassandra Data Model: Cassandra is a column oriented DB which follows a similar data model to <a href="http://labs.google.com/papers/bigtable.html">Google&#8217;s BigTable</a></li>
<li>Do you know SQL? So you better start forgetting it, Cassandra is a different game.</li>
<li>Vocabulary:
<ul>
<li>Keyspace &#8211; a logical buffer for application data. For example &#8211; Billing keyspace, or statistics keyspace, appX keyspace etc</li>
<li>ColumnFamily &#8211; similar to SQL tables. Aggregates columns and rows</li>
<li>Keys (or Rows). Each set of columns is identified by a key. A key is unique per Column Family</li>
<li>Columns &#8211; the actual values. Columns are represented by triplets &#8211; (name, value, timestamp)</li>
<li>Super-Columns &#8211; Facebook&#8217;s addition to the BigTable model SuperColumns are columns who&#8217;s values is a list of Columns. (but this is not recursive, you can only have one level of super-columns)</li>
</ul>
</li>
<li><a href="http://labs.google.com/papers/bigtable.html"></a>One way to think of cassandra is as a key-value store, but with extra functionality:
<ul>
<li>Each key has multiple values. In Cassandra jargon those are Columns</li>
<li>When reading or writing data it&#8217;s possible to read/write a set of columns for one specific key (row) atomically. This set of columns may either be a specified by the list column names, or by a slice predicate, assuming the columns are sorted in some way (that&#8217;s a configuration parameter)</li>
<li>In a addition, a multi-get operation is supported and a row-range-read operation is supported as well.</li>
<li>Row-range-read operations are supported only of a partitioner is defined which supports that (configuration parameter)</li>
</ul>
</li>
<li><strong>Key concept</strong>: In SQL you add your data first and then retrieve it in ad-hoc manner using select queries and where clauses; In Cassandra you can&#8217;t do that. Data can only be retrieved by it&#8217;s row key, so you have to think about how you&#8217;re going to be reading your data before you insert it. This is a conceptual diff b/w SQL and Cassandra.</li>
<li>I covered the Cassandra API methods:
<ul>
<li>get</li>
<li>get_slice</li>
<li>multiget</li>
<li>multiget_slice</li>
<li>get_count</li>
<li>get_range_slice</li>
<li>insert</li>
<li>batch_insert</li>
<li>delete</li>
<li>(these are the 0.4 api method. In 0.5 it&#8217;s a little different)</li>
</ul>
</li>
<li>Between N/R/W, N is set per keyspace; R is defined per each read operation (get/multiget/etc) and W is defined per write operation (insert/batch_insert/delete)</li>
<li>Applications play with their R/W values to get different effects, for example they use QUORUM to get high consistency levels, or DC_QUORUM for a balance of high consistency and performance, W=0 to have async writes with reduced consistency.</li>
<li>Cassandra defines different sorting orders on it&#8217;s columns. Sort order may be defined at the ColumnFamily level and is used to get a slice of columns, for example, read all columns that start with a&#8230; and end with z&#8230;</li>
<li>There are several out of the box sort types, such as ascii, utf, numeric and date; Applications may also add their own sorters; This is as far as I recall the only place where Cassandra allows external code to be hooked in.</li>
<li>Thrift is a protocol and a library for cross-process communication and is used by Cassandra. You define a thrift interface and then compile it to the language of your choosing &#8211; C++, Java, Python, PHP etc. This makes it very easy for cross-language processes to talk to each other.</li>
<li>Thrift is also very efficient serializing and  deserializing objects and is also space-efficient (much more than Java serialization is).</li>
<li>I did not have enough time to cover the <a href="http://en.wikipedia.org/wiki/Gossip_protocol">Gossip protocol</a> used by Cassandra internally to learn about the health of its hosts.</li>
<li>I also did not have enough time to cover the Repair-on-reads algorithm used by Cassandra to repair data inconsistencies lazily.</li>
<li>I did not have time to talk about <a href="http://en.wikipedia.org/wiki/Consistent_hashing">consistent hashing</a>, which is what cassandra implements internally to reduce overhead of joined or dropped hosts occurrences.</li>
</ul>
<p>So, as you can see, this was an overloaded, 1h+ talk with a lot to grasp. Wish me luck implementing Cassandra into outbrain!</p>
<img src="http://feeds.feedburner.com/~r/PrettyPrintMe/~4/ycWVpLZvggU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://prettyprint.me/2010/01/20/introduction-to-nosql-and-cassandra-part-2/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://prettyprint.me/2010/01/20/introduction-to-nosql-and-cassandra-part-2/</feedburner:origLink></item>
		<item>
		<title>Maven Code Quality Dashboard and TeamCity</title>
		<link>http://feedproxy.google.com/~r/PrettyPrintMe/~3/DMlg7EKjPA4/</link>
		<comments>http://prettyprint.me/2010/01/14/maven-code-quality-dashboard-and-teamcity/#comments</comments>
		<pubDate>Thu, 14 Jan 2010 19:38:13 +0000</pubDate>
		<dc:creator>Ran Tavory</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://prettyprint.me/?p=227</guid>
		<description><![CDATA[I&#8217;ve recently implemented a code-quality dashboard at outbrain for maven java projects and hooked it into the our TeamCity continuous integration server. I was very pleased with the result, but the process had a few hickups, so I thought I&#8217;d mention them here for future generations.
A code quality dashboard includes the following components:

Tests status &#8211; [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fprettyprint.me%2F2010%2F01%2F14%2Fmaven-code-quality-dashboard-and-teamcity%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fprettyprint.me%2F2010%2F01%2F14%2Fmaven-code-quality-dashboard-and-teamcity%2F" height="61" width="51" /></a></div><p>I&#8217;ve recently implemented a code-quality dashboard at <a href="http://outbrain.com">outbrain</a> for <a href="http://maven.apache.org/">maven</a> java projects and hooked it into the our <a href="http://www.jetbrains.com/teamcity/index.html">TeamCity</a> continuous integration server. I was very pleased with the result, but the process had a few hickups, so I thought I&#8217;d mention them here for future generations.</p>
<p>A code quality dashboard includes the following components:</p>
<ul>
<li>Tests status &#8211; failed, passed and  skipped count <strong>along with good looking graphs</strong></li>
<li><strong>Code coverage</strong> report detailing all covered and uncovered lines and branches, including nice coverage graphs</li>
<li><strong> Copy-Paste detection</strong> by <a href="http://pmd.sourceforge.net/cpd.html">CPD</a></li>
<li><a href="http://findbugs.sourceforge.net/">FindBugs</a> report</li>
<li><a href="http://clarkware.com/software/JDepend.html">jDepend</a> report</li>
</ul>
<p>The process had two phases: phase one is where I add the dashboard report to maven&#8217;s site goal in my pom.xml and phase two is where I make this report available at TeamCity, which is a bit of a manual work bot not too bad.</p>
<p>To add those nice reports, edit your pom.xml to add:</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;">  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;reporting<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;plugins<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.codehaus.mojo<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>cobertura-maven-plugin<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.apache.maven.plugins<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>maven-pmd-plugin<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>2.3<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
          <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;linkXref<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>true<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/linkXref<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
          <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;targetJdk<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1.5<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/targetJdk<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.apache.maven.plugins<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>maven-surefire-report-plugin<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>2.4.2<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.codehaus.mojo<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>jdepend-maven-plugin<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.codehaus.mojo<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>findbugs-maven-plugin<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>2.0.1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
          <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;xmlOutput<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>true<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/xmlOutput<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
          <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;effort<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Max<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/effort<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.codehaus.mojo<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>dashboard-maven-plugin<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/plugins<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/reporting<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>Now, in theory, that would have been all. All you have to do is run <em><strong>mvn site</strong></em> and bang &#8211; you have the reports under target/site. That&#8217;s why maven is nice.</p>
<p>However, if you&#8217;re running a multi-module project then mvn-site is buggy&#8230; all links to the subproject are broken links. But no despair, here&#8217;s the solution &#8211; configure the site plugin to place its generated content where the site plugin expects it to be&#8230; yeah, I know it sounds confusing, the thing is that the site plugin has a bug so it&#8217;s links to the submodule projects are broken, but here&#8217;s an easy fix that worked for me (as long as the projects are only one directory deep under the parent pom.xml). In the parent pom.xml add:</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;">      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.apache.maven.plugins<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>maven-site-plugin<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
          <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;outputDirectory<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>../target/site/${project.name}<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/outputDirectory<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>Now the reports are fixed.</p>
<p>Next step is to add them into TeamCity.</p>
<p>Step one: Tell teamcity to collect the site artifacts (html, css, js&#8230;). Go to the build configuration and under Artifacts Paths add <strong>**/target/site/**/*</strong></p>
<p><a href="http://prettyprint.me/wp-content/uploads/2010/01/Trunk-Code-Quality-Configuration-TeamCity.png"><img class="size-full wp-image-234 alignnone" title="Trunk Code Quality Configuration -- TeamCity" src="http://prettyprint.me/wp-content/uploads/2010/01/Trunk-Code-Quality-Configuration-TeamCity.png" alt="" width="590" height="161" /></a></p>
<p>Step two: Add a Code Quality tab to the build results. You do that by ssh-ing to the teamc host and editing</p>
<pre>vi /teamc/TeamCity/.BuildServer/config/main-config.xml</pre>
<p>to add</p>
<pre>&lt;report-tab title="Code Quality" basePath="target/site/" startPage="dashboard-report-details.html" /&gt;</pre>
<p>Here&#8217;s the result:</p>
<p><img class="alignnone size-full wp-image-233" title="Code Quality Tab" src="http://prettyprint.me/wp-content/uploads/2010/01/Trunk-__-Trunk-Code-Quality-8-13-Jan-10-20_43-Overview-TeamCity.png" alt="" width="632" height="83" /></p>
<p>That&#8217;s it! Now run your build with mvn site and get those gorgeous looking reports right in your teamcity build results page.<br />
<a href="http://prettyprint.me/wp-content/uploads/2010/01/Global-DashBoard-Report.png"><img class="size-full wp-image-228 alignnone" title="Global DashBoard Report" src="http://prettyprint.me/wp-content/uploads/2010/01/Global-DashBoard-Report.png" alt="" width="715" height="677" /></a></p>
<p><img class="size-full wp-image-230 alignnone" title="Outrain Root Project - DashBoard Report" src="http://prettyprint.me/wp-content/uploads/2010/01/Outrain-Root-Project-DashBoard-Report-2.png" alt="" width="590" height="359" /></p>
<p><a href="http://prettyprint.me/wp-content/uploads/2010/01/Outrain-Root-Project-DashBoard-Report-1-1.png"><img class="size-full wp-image-229 alignnone" title="Outrain Root Project - DashBoard Report" src="http://prettyprint.me/wp-content/uploads/2010/01/Outrain-Root-Project-DashBoard-Report-1-1.png" alt="" width="441" height="274" /></a></p>
<p><a href="http://prettyprint.me/wp-content/uploads/2010/01/Coverage-Report.png"><img class="alignnone size-full wp-image-236" title="Coverage Report" src="http://prettyprint.me/wp-content/uploads/2010/01/Coverage-Report.png" alt="" width="703" height="536" /></a></p>
<p><a href="http://prettyprint.me/wp-content/uploads/2010/01/Coverage-Report-1.png"><img class="alignnone size-full wp-image-235" title="Coverage Report" src="http://prettyprint.me/wp-content/uploads/2010/01/Coverage-Report-1.png" alt="" width="460" height="378" /></a><img class="alignnone size-full wp-image-237" title="FindBugs piechart" src="http://prettyprint.me/wp-content/uploads/2010/01/ImageFetcher-DashBoard-Report.png" alt="" width="825" height="426" /></p>
<img src="http://feeds.feedburner.com/~r/PrettyPrintMe/~4/DMlg7EKjPA4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://prettyprint.me/2010/01/14/maven-code-quality-dashboard-and-teamcity/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://prettyprint.me/2010/01/14/maven-code-quality-dashboard-and-teamcity/</feedburner:origLink></item>
		<item>
		<title>Moved hosting away from #godaddy #sucks</title>
		<link>http://feedproxy.google.com/~r/PrettyPrintMe/~3/egGDH4_kYyA/</link>
		<comments>http://prettyprint.me/2010/01/11/moved-hosting-away-from-godaddy-sucks/#comments</comments>
		<pubDate>Mon, 11 Jan 2010 18:34:12 +0000</pubDate>
		<dc:creator>Ran Tavory</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://prettyprint.me/?p=223</guid>
		<description><![CDATA[
This blog has moved away from GoDaddy hosting to bluehost. I don&#8217;t know how good bluehost is (so far it&#8217;s been OK) but I know for sure that GoDaddy is pretty darn awful.

Awful as in


So slow that it&#8217;s a nightmare to be editing posts online. I had to do them offline and then copy-paste (and [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fprettyprint.me%2F2010%2F01%2F11%2Fmoved-hosting-away-from-godaddy-sucks%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fprettyprint.me%2F2010%2F01%2F11%2Fmoved-hosting-away-from-godaddy-sucks%2F" height="61" width="51" /></a></div><p><a href="http://prettyprint.me/wp-content/uploads/2010/01/go_daddy_sucks.png"><img class="alignleft size-full wp-image-224" title="go_daddy_sucks" src="http://prettyprint.me/wp-content/uploads/2010/01/go_daddy_sucks.png" alt="" width="270" height="103" /></a><br />
This blog has moved away from <a href="http://www.godaddy.com/">GoDaddy</a> hosting to <a href="https://www.bluehost.com/">bluehost</a>. I don&#8217;t know how good bluehost is (so far it&#8217;s been OK) but I know for sure that GoDaddy is pretty darn awful.</p>
<div style="clear: both;"></div>
<div style="clear: both;">Awful as in</div>
<div style="clear: both;">
<ul>
<li>So slow that it&#8217;s a nightmare to be editing posts online. I had to do them offline and then copy-paste (and reformat), what a waste of time.</li>
<li>So fragile that my <a href="http://www.pingdom.com/">pingdom</a> monitor reports it unavailable for more than 5 minutes at least twice a day.</li>
<li>So unresponsive that I&#8217;m sometimes ashamed to share permalinks to my blog in fear it would be offline. Why did I even pay them?</li>
</ul>
<p>I didn&#8217;t wait for the one year I paid up front to end, just packed my stuff and moved over to bluehost. I don&#8217;t know how good bluehost is, but at least it&#8217;s fun again to be editing online and my pingdom monitor hasn&#8217;t told me anything bad yet, so knock on wood, looking good so far.</p>
</div>
<img src="http://feeds.feedburner.com/~r/PrettyPrintMe/~4/egGDH4_kYyA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://prettyprint.me/2010/01/11/moved-hosting-away-from-godaddy-sucks/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://prettyprint.me/2010/01/11/moved-hosting-away-from-godaddy-sucks/</feedburner:origLink></item>
		<item>
		<title>Introduction to NOSQL and cassandra, part 1</title>
		<link>http://feedproxy.google.com/~r/PrettyPrintMe/~3/a-xwAmpPq_A/</link>
		<comments>http://prettyprint.me/2010/01/09/introduction-to-nosql-and-cassandra-part-1/#comments</comments>
		<pubDate>Sat, 09 Jan 2010 14:16:50 +0000</pubDate>
		<dc:creator>Ran Tavory</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://prettyprint.me/?p=220</guid>
		<description><![CDATA[I recently gave a talk at outbrain, where I work, about an introduction to no-sql and Cassandra as we&#8217;re looking for alternatives of scaling out our database solution to match our incredible growth rate.
NOSQL is a general name for many non relational databases and Cassandra is one of them.
This was the first session of two [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fprettyprint.me%2F2010%2F01%2F09%2Fintroduction-to-nosql-and-cassandra-part-1%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fprettyprint.me%2F2010%2F01%2F09%2Fintroduction-to-nosql-and-cassandra-part-1%2F" height="61" width="51" /></a></div><p>I recently gave a talk at <a href="http://outbrain.com">outbrain</a>, where I work, about an introduction to no-sql and Cassandra as we&#8217;re looking for alternatives of scaling out our database solution to match our incredible growth rate.</p>
<p><a href="http://en.wikipedia.org/wiki/NoSQL">NOSQL</a> is a general name for many non relational databases and <a href="http://incubator.apache.org/cassandra/">Cassandra</a> is one of them.</p>
<p>This was the first session of two in which I introduced the theoretical background and explained few of the important concepts of nosql. In the second session, due next week, I&#8217;ll talk more specifically about Cassandra.</p>
<p>The talk is on youtube, video below, but it&#8217;s in Hebrew so I&#8217;ll share it&#8217;s outline in English here. Slides are enclosed as well.</p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="425" height="344" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="src" value="http://www.youtube.com/v/fWkEeyT3e2Y&amp;hl=en_US&amp;fs=1&amp;rel=0" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="425" height="344" src="http://www.youtube.com/v/fWkEeyT3e2Y&amp;hl=en_US&amp;fs=1&amp;rel=0" allowfullscreen="true"></embed></object><br />
<iframe src="http://docs.google.com/present/embed?id=ahbp3bktzpkc_145c5gmf2gz" frameborder="0" width="410" height="342"></iframe></p>
<ul>
<li>SQL and relational DBs in general offer is a very good general purpose solution for many  applications such as blogs, banking, my cat&#8217;s site etc.</li>
<li>RDBMS provide <a href="http://databases.about.com/od/specificproducts/a/acid.htm">ACID</a>: Atomicity, Consistency, Isolation and Durability</li>
<li>RDBMS + SQL (the query language) + ACID provide a very nice and clean programming interface, suitable for banks, online merchants and many other applications, but not all applications really actually do require full ACID and one has to realize that ACID and SQL features are not without costs when systems need to scale out. Cost is not only in $$, it&#8217;s also in application performance and features.</li>
<li>The new generation of internet scale applications put very high demands on DB systems when it comes to scale and speed of operation but they don&#8217;t necessariry require all the good that&#8217;s in RDBMS, such as Full Consistency or Atomicity.</li>
<li>So, a new brand of DB systems has grown over the past 5 or so years &#8211; nosql, which either stands for No-SQL or Not-Only-SQL.</li>
<li>Leading actors in the nosql arena are Google with its BigTable, Amazon with Dynamo, Facebook with Cassandra and there&#8217;s more.</li>
<li>I presented intermediate solutions before going no-sql, namely RDBMS <a href="http://en.wikipedia.org/wiki/Shard_(database_architecture)">sharding</a> which is very common and <a href="http://bret.appspot.com/entry/how-friendfeed-uses-mysql">FriendFeed&#8217;s particularly interesting solution</a> of application level indexing for using mysql with a schema-less data model.</li>
<li>CAP Theorem: At large scale systems you may only choose 2 out of the 3 desired attributes: Consistency, Availability and Partition-Tolerance. All three may not go hand in hand and application designers need to realize that.</li>
<li>A Consistent and Available system with no Partition-tolerance is a RDBMS system that comes to a halt if one of it&#8217;s hosts is down. That&#8217;s a very commonly used solution and perfect for small systems. This blog, for example, which uses Wordpress, also uses a single mysql server which, if happens to be down, will also take the blog down. However, for internet scale systems where at almost any point in time there&#8217;s a good chance that one of the nodes is either down, or there are network disruptions, the No-Partition-Tolerance approach just isn&#8217;t going to cut it and they will have to choose a different approach for providing their SLAs.</li>
<li>Systems that are Available at all times and are capable of handling Partitions must sacrifice their consistency. As it turns out, though, this isn&#8217;t bad as it seems, as there are pretty good alternatives for lower levels of consistently, one such solution is <a href="http://en.wikipedia.org/wiki/Eventual_consistency">Eventual Consistency</a>, which actually works pretty nicely for &#8220;social applications&#8221; such as Google&#8217;s Facebook&#8217;s and Outbrain&#8217;s</li>
<li>I introduced the concept of NRW &#8211; N is the number of database replicas data is copied to one must replicate data in order to withstand partitions. W is the number of replicas a write operation would block on until it returns to it&#8217;s caller and is &#8220;successful&#8221; and R is the number of replicas a read operation would block on before returning to its caller.</li>
<li>N, R and W are crucial when dealing with Eventual Consistency as their values usually determine the level of consistency you&#8217;re going to have. For example, when N=R=W you have a full consistency (which isn&#8217;t tolerant to partitions or course). When W=0 you have async writes, which is the lowest level of consistency (you never know when the write operation actually finishes)</li>
<li>I introduced the concept of <a href="http://en.wikipedia.org/wiki/Atomicity_(database_systems)">Quorum</a>, which means R=W=ceil((N+1)/2)</li>
<li>Introduced a (very partial) list of currently available nosql solutions, such as Cassandra, BigTable, HBase, Dynamo, Voldemort, Riak, CouchDB, MongoDB and more.</li>
</ul>
<p>Overall this was a very interesting talk, a lot of (fun and interesting) theory. The next part is going to be specific about Cassandra &#8211; how all this theory fits into Cassandra and how does one use Cassandra&#8217;s API, so stay tuned.</p>
<img src="http://feeds.feedburner.com/~r/PrettyPrintMe/~4/a-xwAmpPq_A" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://prettyprint.me/2010/01/09/introduction-to-nosql-and-cassandra-part-1/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://prettyprint.me/2010/01/09/introduction-to-nosql-and-cassandra-part-1/</feedburner:origLink></item>
		<item>
		<title>StringTemplate – a step forward to a better web MVC</title>
		<link>http://feedproxy.google.com/~r/PrettyPrintMe/~3/c_vvTzhY9JQ/</link>
		<comments>http://prettyprint.me/2009/11/13/stringtemplate-a-step-forward-to-a-better-web-mvc/#comments</comments>
		<pubDate>Fri, 13 Nov 2009 07:15:24 +0000</pubDate>
		<dc:creator>Ran Tavory</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://prettyprint.me/?p=206</guid>
		<description><![CDATA[MVC, Model View Controller is a well known design patten from the field of UI frameworks. It advocates the separation of a Model, an application specific data and business logic, Controller, which takes user input, consults the model and determines the correct view to present a user based on its result and a View, the [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fprettyprint.me%2F2009%2F11%2F13%2Fstringtemplate-a-step-forward-to-a-better-web-mvc%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fprettyprint.me%2F2009%2F11%2F13%2Fstringtemplate-a-step-forward-to-a-better-web-mvc%2F" height="61" width="51" /></a></div><p><img class="alignleft size-thumbnail wp-image-208" title="MVC" src="http://prettyprint.me/wp-content/uploads/2009/11/MVC8x6_209DEC49-150x150.png" alt="MVC" width="150" height="150" /><a href="http://en.wikipedia.org/wiki/Model–view–controller">MVC</a>, Model View Controller is a well known design patten from the field of UI frameworks. It advocates the separation of a Model, an application specific data and business logic, Controller, which takes user input, consults the model and determines the correct view to present a user based on its result and a View, the actual UI component the user interacts with.</p>
<p>In the context of web applications it&#8217;s common to consider a Database along with the application business logic as the Model, a web framework, such as <a href="http://struts.apache.org/">Struts</a>, as the Controller and the rendering engine, such as <a href="http://java.sun.com/products/jsp/">JSP</a> as the View. MVC are widely used in both web development as well as in desktop application development.</p>
<p><a href="http://www.stringtemplate.org/">StringTemplate</a> is a rendering engine, a View, I&#8217;ve recently became familiar with and immediately fell in love with. StringTemplate is a step forward true MVC implementation, but before presenting the solution, let&#8217;s see what the problem is.</p>
<p>The MVC design pattern states that in a UI framework there should be 3 components &#8211; the Model, the View and the Controller. It also states that the Controller should have direct access to the Model and the View, the View have direct access to the Model when presenting the data as seen in the diagram below.</p>
<p><img class="alignnone size-full wp-image-209" title="MVC diagram" src="http://prettyprint.me/wp-content/uploads/2009/11/350px-ModelViewControllerDiagram.svg.png" alt="MVC diagram" width="350" height="165" /></p>
<p>There are many MVC implementations in many languages. In Java only, there are more than 17 mentioned on the <a href="http://en.wikipedia.org/wiki/Model–view–controller#Java">Wiki page</a>. Many of the frameworks use JSP as their rendering engine and add their specific features to it, so for example <a href="http://struts.apache.org/2.x/">struts2</a> implements a very nice controller and as a rendering engine uses JSP with either struts2 tags or another tag library. The problem lies within JSP.</p>
<p>JSP, similar to PHP, ASP and many other simple and fast-start rendering engines, compromise the MVC model; they allows too much in their View component.</p>
<p>JSP allows code to be executed within the context of the page (using the &lt;% %&gt; notation), which is very nice when you want to hack something fast but is extremely dangerous from code maintenance perspective and is a clear violation of the MVC agreement. If code can be executed within a page, that code can easily alter the model or take actions a controller should have taken. A View should be able to READ the model, but not ALTER it. Even the most disciplined programmers who adhere to clean JSP code by not allowing actual Java code inside their pages (using the &lt;% %&gt;) actually suffer from the same problem without even knowing it&#8230; The alternative to the &lt;%  and the &lt;%= constructs are tags, such as JSTL tags, struts2 tags etc. These tags commonly access the model by invoking its getters, but the real problem with them is that the order in which they execute is very important &#8211; read it again &#8211; the order in which they are displayed on the page is crucial to the correctness of the values returned by their backing model. More about this <a href="http://www.artima.com/lejava/articles/stringtemplate.html">here</a>. So with JSP, when using tags, the View implementor has to understand how a Model works in order to succeed. That&#8217;s both inconsistent with the pure MVC model and inconvenient to the UI designer. Lastly are side effect, which cannot be ignored. Views can create side effects by calling methods (even getters can have side effects!) , which I think there&#8217;s no need to mention, is very bad.</p>
<p>StringTemplate comes to the rescue. As a matter of fact, when I programmed django MVC in python, as well as Cheetah in python, I have to say that both MVCs were much stricter than JSP and were therefore a lot more programmer-friendly. But in Java we had Velocity, which is strict, but also less powerful and now we have StringTemplate which is both strict and powerful. (and no &#8211; freemarker isn&#8217;t any better than just plain JSP, sorry).</p>
<p>At outbrain we use struts2 as our MVC driver and so to be able to use StringTemplate as the View engine I&#8217;ve implemented a struts2 View Renderer. Full code and details below. This code is &#8220;unstable&#8221; which means it&#8217;s been developed and tested, so far no bugs or missing features, but hasn&#8217;t gone to production yet.</p>
<p><strong>struts.xml:</strong></p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;struts<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;include</span> <span style="color: #000066;">file</span>=<span style="color: #ff0000;">&quot;webwork-default.xml&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;package</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;regular&quot;</span> <span style="color: #000066;">namespace</span>=<span style="color: #ff0000;">&quot;/&quot;</span> <span style="color: #000066;">extends</span>=<span style="color: #ff0000;">&quot;struts-default&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;result-types<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;result-type</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;stringtemplate&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;org.apache.struts2.dispatcher.StringTemplateResult&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/result-types<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;action</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;st&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;com.mysite.StringTemplateTestAction&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;result</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;success&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;stringtemplate&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>/WEB-INF/st/page.st<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/result<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/action<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/package<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/struts<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<div><strong>Java source code:</strong></div>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">package</span> <span style="color: #006699;">org.apache.struts2.dispatcher</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.io.IOException</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.io.InputStream</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.io.Writer</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.util.Enumeration</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.util.HashMap</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.util.Locale</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.util.Map</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.util.Properties</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.servlet.ServletContext</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.servlet.http.HttpServletRequest</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.servlet.http.HttpServletResponse</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.servlet.http.HttpSession</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.antlr.stringtemplate.NoIndentWriter</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.antlr.stringtemplate.StringTemplate</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.antlr.stringtemplate.StringTemplateGroup</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.antlr.stringtemplate.StringTemplateWriter</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.commons.logging.Log</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.commons.logging.LogFactory</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.struts2.ServletActionContext</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.struts2.StrutsConstants</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.struts2.views.util.ContextUtil</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.struts2.views.util.ResourceUtil</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">com.opensymphony.xwork2.ActionInvocation</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">com.opensymphony.xwork2.LocaleProvider</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">com.opensymphony.xwork2.inject.Inject</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">com.opensymphony.xwork2.util.ValueStack</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">freemarker.template.Configuration</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">freemarker.template.TemplateException</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #008000; font-style: italic; font-weight: bold;">/**
 * Defines the StringTemplate result type for struts2.
 *
 * To use this result type add the following configuration to your struts.xml:
 *
 * &lt;code&gt;
 * &amp;lt;result-types&amp;gt;
 *   &amp;lt;result-type name=&quot;stringtemplate&quot;
 *       class=&quot;org.apache.struts2.dispatcher.StringTemplateResult&quot;/&amp;gt;
 * &amp;lt;/result-types&amp;gt;
 *&lt;/code&gt;
 *
 * Template files should be located relative to /WEB-INF/st/, so for example a common layout
 * would be:
 *
&lt;ul&gt;
 *
	&lt;li&gt;/WEB-INF/st/pages/page1.st&lt;/li&gt;
*
	&lt;li&gt;/WEB-INF/st/layouts/layout1.st&lt;/li&gt;
*
	&lt;li&gt;/WEB-INF/st/snippets/header.st&lt;/li&gt;
*
	&lt;li&gt;/WEB-INF/st/snippets/footer.st&lt;/li&gt;
*&lt;/ul&gt;
*
 * So page1.st would look like:
 * &lt;code&gt;
 * $layouts/layout1(header=snippets/header(), footer=snippets/footer())$
 * &lt;/code&gt;
 *
 * And the associated struts action would be:
 *
 * &lt;code&gt;
 * &amp;lt;action name=&quot;page1&quot;
 *      class=&quot;com.mycompany.Page1Action&quot;&amp;gt;
 *        &amp;lt;result name=&quot;success&quot;
 *          type=&quot;stringtemplate&quot;&amp;gt;/WEB-INF/st/pages/page1.st&amp;lt;/result&amp;gt;
 * &amp;lt;/action&amp;gt;
 * &lt;/code&gt;
 *
 * Localization:
 * All string property files should be packed into the classpath (in one of the jars) at
 * /lang/.
 * For example:
 *
&lt;ul&gt;
 *
	&lt;li&gt;/lang/en_US.properties&lt;/li&gt;
*
	&lt;li&gt;/lang/fr_FR.properties&lt;/li&gt;
*&lt;/ul&gt;
*
 * @author Ran Tavory (ran@outbrain.com)
 *
 */</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> StringTemplateResult <span style="color: #000000; font-weight: bold;">extends</span> StrutsResultSupport <span style="color: #009900;">&#123;</span>
&nbsp;
  <span style="color: #008000; font-style: italic; font-weight: bold;">/**
   * Base path of StringTemplate template files.
   * This is usually something like /WEB-INF/ or /WEB-INF/st/.
   * Must end with /.
   * All templates should reside in subdirectories of this base path and when referencing
   * each other the reference point should be relative to this path.
   * For example, if you have /WEB-INF/pages/page1.st and /WEB-INF/layouts/layout1.st, and assuming
   * the base path is at /WEB-INF then page1 is pages/page1 and layout1 is layouts/layout1.
   * To reference layout1 from page1: $layouts/layout1()$
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">String</span> TEMPLATES_BASE <span style="color: #339933;">=</span>
      <span style="color: #0000ff;">&quot;/WEB-INF/st/&quot;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #008000; font-style: italic; font-weight: bold;">/**
   * Path to the language resource files within the classpath.
   *
   * Resource should be packed inside a jar under /lang/.
   * For example: /lang/en_US.properties
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">String</span> LANG_RESOURCE_BASE <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;/lang/&quot;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #008000; font-style: italic; font-weight: bold;">/**
   * If there was an exception during execution it's accessible via $exception$
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">String</span> KEY_EXCEPTION <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;exception&quot;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #008000; font-style: italic; font-weight: bold;">/**
   * Session values are accessible via $session.key$
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">String</span> KEY_SESSION <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;session&quot;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #008000; font-style: italic; font-weight: bold;">/**
   * All localized strings are accessible via $strings.string_key$
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">String</span> KEY_STRINGS <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;strings&quot;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #008000; font-style: italic; font-weight: bold;">/**
   * Request parameters are accessible via $params.key$
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">String</span> KEY_REQUEST_PARAMETERS <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;params&quot;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #008000; font-style: italic; font-weight: bold;">/**
   * Request attributes are accessible via $request.attribute$
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">String</span> KEY_REQUEST <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;request&quot;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000000; font-weight: bold;">final</span> Log log <span style="color: #339933;">=</span> LogFactory.<span style="color: #006633;">getLog</span><span style="color: #009900;">&#40;</span>StringTemplateResult.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #000066; font-weight: bold;">long</span> serialVersionUID <span style="color: #339933;">=</span> <span style="color: #339933;">-</span>2390940981629097944L<span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">Locale</span> DEFAULT_LOCALE <span style="color: #339933;">=</span> <span style="color: #003399;">Locale</span>.<span style="color: #006633;">US</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">/*
   * Struts results are constructed for each result execution
   *
   * the current context is available to subclasses via these protected fields
   */</span>
  <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">String</span> contentType <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;text/html&quot;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">String</span> defaultEncoding<span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> StringTemplateResult<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">super</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> StringTemplateResult<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> location<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">super</span><span style="color: #009900;">&#40;</span>location<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> setContentType<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> aContentType<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    contentType <span style="color: #339933;">=</span> aContentType<span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #008000; font-style: italic; font-weight: bold;">/**
   * allow parameterization of the contentType the default being text/html
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">String</span> getContentType<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">return</span> contentType<span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  @Inject<span style="color: #009900;">&#40;</span>StrutsConstants.<span style="color: #006633;">STRUTS_I18N_ENCODING</span><span style="color: #009900;">&#41;</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> setDefaultEncoding<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> val<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    defaultEncoding <span style="color: #339933;">=</span> val<span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #008000; font-style: italic; font-weight: bold;">/**
   * Execute this result, using the specified template location.
   *
&nbsp;
   * The template location has already been interpolated for any variable
   * substitutions.
   *
   * NOTE: The current implementation is still under development and has several restrictions.
   *
&lt;ul&gt;
   *
	&lt;li&gt;All template files must end with .st&lt;/li&gt;
*&lt;/ul&gt;
*/</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> doExecute<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> location, ActionInvocation invocation<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">IOException</span>,
      TemplateException <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">final</span> HttpServletRequest request <span style="color: #339933;">=</span> ServletActionContext.<span style="color: #006633;">getRequest</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">final</span> HttpServletResponse response <span style="color: #339933;">=</span> ServletActionContext.<span style="color: #006633;">getResponse</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>location.<span style="color: #006633;">startsWith</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;/&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #666666; font-style: italic;">// Create a fully qualified resource name.</span>
      <span style="color: #666666; font-style: italic;">// final ActionContext ctx = invocation.getInvocationContext();</span>
      <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">String</span> base <span style="color: #339933;">=</span> ResourceUtil.<span style="color: #006633;">getResourceBase</span><span style="color: #009900;">&#40;</span>request<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      location <span style="color: #339933;">=</span> base <span style="color: #339933;">+</span> <span style="color: #0000ff;">&quot;/&quot;</span> <span style="color: #339933;">+</span> location<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">String</span> encoding <span style="color: #339933;">=</span> getEncoding<span style="color: #009900;">&#40;</span>location<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #003399;">String</span> contentType <span style="color: #339933;">=</span> getContentType<span style="color: #009900;">&#40;</span>location<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>encoding <span style="color: #339933;">!=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      contentType <span style="color: #339933;">=</span> contentType <span style="color: #339933;">+</span> <span style="color: #0000ff;">&quot;;charset=&quot;</span> <span style="color: #339933;">+</span> encoding<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    response.<span style="color: #006633;">setContentType</span><span style="color: #009900;">&#40;</span>contentType<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">String</span> basePath <span style="color: #339933;">=</span> ServletActionContext.<span style="color: #006633;">getServletContext</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">getRealPath</span><span style="color: #009900;">&#40;</span>TEMPLATES_BASE<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">final</span> StringTemplateGroup group <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> StringTemplateGroup<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;webpages&quot;</span>, basePath<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #003399;">String</span> fileName <span style="color: #339933;">=</span> location<span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>fileName.<span style="color: #006633;">endsWith</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;.st&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #666666; font-style: italic;">// If filename ends with .st, remove it.</span>
      fileName <span style="color: #339933;">=</span> fileName.<span style="color: #006633;">substring</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span>, fileName.<span style="color: #006633;">length</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">-</span> <span style="color: #0000ff;">&quot;.st&quot;</span>.<span style="color: #006633;">length</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>fileName.<span style="color: #006633;">startsWith</span><span style="color: #009900;">&#40;</span>TEMPLATES_BASE<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #666666; font-style: italic;">// If filename includes the base dir then remove it.</span>
      fileName <span style="color: #339933;">=</span> fileName.<span style="color: #006633;">substring</span><span style="color: #009900;">&#40;</span>TEMPLATES_BASE.<span style="color: #006633;">length</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #000000; font-weight: bold;">final</span> StringTemplate template <span style="color: #339933;">=</span> group.<span style="color: #006633;">getInstanceOf</span><span style="color: #009900;">&#40;</span>fileName<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">Map</span> model <span style="color: #339933;">=</span> createModel<span style="color: #009900;">&#40;</span>invocation<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    template.<span style="color: #006633;">setAttributes</span><span style="color: #009900;">&#40;</span>model<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// Output to client</span>
    <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">Writer</span> responseWriter <span style="color: #339933;">=</span> response.<span style="color: #006633;">getWriter</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">final</span> StringTemplateWriter templateWriter <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> NoIndentWriter<span style="color: #009900;">&#40;</span>responseWriter<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    template.<span style="color: #006633;">write</span><span style="color: #009900;">&#40;</span>templateWriter<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #666666; font-style: italic;">// Flush'n'close</span>
    responseWriter.<span style="color: #006633;">flush</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    responseWriter.<span style="color: #006633;">close</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #008000; font-style: italic; font-weight: bold;">/**
   * Retrieve the encoding for this template.
   *
   * People can override this method if they want to provide specific encodings
   * for specific templates.
   *
   * @return The encoding associated with this template (defaults to the value
   *         of 'struts.i18n.encoding' property)
   */</span>
  <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #003399;">String</span> getEncoding<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> templateLocation<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #003399;">String</span> encoding <span style="color: #339933;">=</span> defaultEncoding<span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>encoding <span style="color: #339933;">==</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      encoding <span style="color: #339933;">=</span> <span style="color: #003399;">System</span>.<span style="color: #006633;">getProperty</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;file.encoding&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>encoding <span style="color: #339933;">==</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      encoding <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;UTF-8&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #000000; font-weight: bold;">return</span> encoding<span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #008000; font-style: italic; font-weight: bold;">/**
   * Retrieve the content type for this template.
   *
   * People can override this method if they want to provide specific content
   * types for specific templates (eg text/xml).
   *
   * @return The content type associated with this template (default
   *         &quot;text/html&quot;)
   */</span>
  <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #003399;">String</span> getContentType<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> templateLocation<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #0000ff;">&quot;text/html&quot;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #008000; font-style: italic; font-weight: bold;">/**
   * Build the instance of the ScopesHashModel, including JspTagLib support
   *
   * Objects added to the model are
   *
   *
&lt;ul&gt;
   *
	&lt;li&gt;Application - servlet context attributes hash model&lt;/li&gt;
*
	&lt;li&gt;JspTaglibs - jsp tag lib factory model&lt;/li&gt;
*
	&lt;li&gt;Request - request attributes hash model&lt;/li&gt;
*
	&lt;li&gt;Session - session attributes hash model&lt;/li&gt;
*
	&lt;li&gt;request - the HttpServletRequst object for direct access&lt;/li&gt;
*
	&lt;li&gt;response - the HttpServletResponse object for direct access&lt;/li&gt;
*
	&lt;li&gt;stack - the OgnLValueStack instance for direct access&lt;/li&gt;
*
	&lt;li&gt;ognl - the instance of the OgnlTool&lt;/li&gt;
*
	&lt;li&gt;action - the action itself&lt;/li&gt;
*
	&lt;li&gt;exception - optional : the JSP or Servlet exception as per the servlet
   * spec (for JSP Exception pages)
   *&lt;/li&gt;
*
	&lt;li&gt;struts - instance of the StrutsUtil class
   *&lt;/li&gt;
*&lt;/ul&gt;
*/</span>
  <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #003399;">Map</span> createModel<span style="color: #009900;">&#40;</span>ActionInvocation invocation<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
    ServletContext servletContext <span style="color: #339933;">=</span> ServletActionContext.<span style="color: #006633;">getServletContext</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    HttpServletRequest request <span style="color: #339933;">=</span> ServletActionContext.<span style="color: #006633;">getRequest</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    HttpServletResponse response <span style="color: #339933;">=</span> ServletActionContext.<span style="color: #006633;">getResponse</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    ValueStack stack <span style="color: #339933;">=</span> ServletActionContext.<span style="color: #006633;">getContext</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">getValueStack</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #003399;">Object</span> action <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>invocation <span style="color: #339933;">!=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      action <span style="color: #339933;">=</span> invocation.<span style="color: #006633;">getAction</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #000000; font-weight: bold;">return</span> buildTemplateModel<span style="color: #009900;">&#40;</span>stack, action, servletContext, request, response, invocation<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">Map</span> buildTemplateModel<span style="color: #009900;">&#40;</span>ValueStack stack, <span style="color: #003399;">Object</span> action,
                                                 ServletContext servletContext,
                                                 HttpServletRequest request,
                                                 HttpServletResponse response,
                                                 ActionInvocation invocation<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #003399;">Map</span> model <span style="color: #339933;">=</span> buildScopesHashModel<span style="color: #009900;">&#40;</span>servletContext, request, response, stack<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    populateContext<span style="color: #009900;">&#40;</span>model, stack, action, request, response<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    populateStrings<span style="color: #009900;">&#40;</span>model, deduceLocale<span style="color: #009900;">&#40;</span>invocation<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">return</span> model<span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #008000; font-style: italic; font-weight: bold;">/**
   * Populates the &lt;code&gt;strings&lt;/code&gt; attribute of the model according to the current locale
   * value.
   * @param model
   * @param local
   */</span>
  <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">void</span> populateStrings<span style="color: #009900;">&#40;</span><span style="color: #003399;">Map</span> model, <span style="color: #003399;">Locale</span> locale<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    log.<span style="color: #006633;">debug</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Local: &quot;</span> <span style="color: #339933;">+</span> locale<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #003399;">Properties</span> p<span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">try</span> <span style="color: #009900;">&#123;</span>
      p <span style="color: #339933;">=</span> getLanguageProperties<span style="color: #009900;">&#40;</span>locale<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      model.<span style="color: #006633;">put</span><span style="color: #009900;">&#40;</span>KEY_STRINGS, p<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #000000; font-weight: bold;">return</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">catch</span> <span style="color: #009900;">&#40;</span><span style="color: #003399;">IOException</span> e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>locale.<span style="color: #006633;">equals</span><span style="color: #009900;">&#40;</span>DEFAULT_LOCALE<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        log.<span style="color: #006633;">error</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Unable to load language file for the default locale &quot;</span> <span style="color: #339933;">+</span> locale<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">return</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
        log.<span style="color: #006633;">warn</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Unable to load language file for &quot;</span> <span style="color: #339933;">+</span> locale <span style="color: #339933;">+</span> <span style="color: #0000ff;">&quot;. Will try to load for the &quot;</span> <span style="color: #339933;">+</span>
            <span style="color: #0000ff;">&quot;default locale&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// Try once again with the default locale.</span>
    populateStrings<span style="color: #009900;">&#40;</span>model, DEFAULT_LOCALE<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #008000; font-style: italic; font-weight: bold;">/**
   * Tries to load language properties for the given locale.
   *
   * The file is loaded from /LANG_RESOURCE_BASE/locale.properties in the classpath, so for example
   * that may be /lang/en_US.properties
   *
   * @param locale
   * @return
   * @throws IOException When the language file isn't found or can't read it.
   */</span>
  <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">Properties</span> getLanguageProperties<span style="color: #009900;">&#40;</span><span style="color: #003399;">Locale</span> locale<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">IOException</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">InputStream</span> in <span style="color: #339933;">=</span>
      getClass<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">getClassLoader</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">getResourceAsStream</span><span style="color: #009900;">&#40;</span>LANG_RESOURCE_BASE <span style="color: #339933;">+</span> locale <span style="color: #339933;">+</span> <span style="color: #0000ff;">&quot;.properties&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">Properties</span> prop <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">Properties</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    prop.<span style="color: #006633;">load</span><span style="color: #009900;">&#40;</span>in<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">return</span> prop<span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #003399;">Map</span> buildScopesHashModel<span style="color: #009900;">&#40;</span>ServletContext servletContext,
                                                     HttpServletRequest request,
                                                     HttpServletResponse response,
                                                     ValueStack stack<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #003399;">Map</span> model <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">HashMap</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// Add session information</span>
    HttpSession session <span style="color: #339933;">=</span> request.<span style="color: #006633;">getSession</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>session <span style="color: #339933;">!=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      model.<span style="color: #006633;">put</span><span style="color: #009900;">&#40;</span>KEY_SESSION, generateAttributeMapForSession<span style="color: #009900;">&#40;</span>session<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// Add requests attributes</span>
    model.<span style="color: #006633;">put</span><span style="color: #009900;">&#40;</span>KEY_REQUEST, generateAttributeMapFromRequest<span style="color: #009900;">&#40;</span>request<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// Add request parameters.</span>
    model.<span style="color: #006633;">put</span><span style="color: #009900;">&#40;</span>KEY_REQUEST_PARAMETERS, request.<span style="color: #006633;">getParameterMap</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">return</span> model<span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  @SuppressWarnings<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;unchecked&quot;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">Map</span> generateAttributeMapForSession<span style="color: #009900;">&#40;</span>HttpSession session<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #003399;">Map</span> attributes <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">HashMap</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003399;">Enumeration</span> e <span style="color: #339933;">=</span> session.<span style="color: #006633;">getAttributeNames</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> e.<span style="color: #006633;">hasMoreElements</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #003399;">String</span> name <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span><span style="color: #009900;">&#41;</span> e.<span style="color: #006633;">nextElement</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      attributes.<span style="color: #006633;">put</span><span style="color: #009900;">&#40;</span>name, session.<span style="color: #006633;">getAttribute</span><span style="color: #009900;">&#40;</span>name<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #000000; font-weight: bold;">return</span> attributes<span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  @SuppressWarnings<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;unchecked&quot;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">Map</span> generateAttributeMapFromRequest<span style="color: #009900;">&#40;</span>HttpServletRequest request<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #003399;">Map</span> attributes <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">HashMap</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003399;">Enumeration</span> e <span style="color: #339933;">=</span> request.<span style="color: #006633;">getAttributeNames</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> e.<span style="color: #006633;">hasMoreElements</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #003399;">String</span> name <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span><span style="color: #009900;">&#41;</span> e.<span style="color: #006633;">nextElement</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      attributes.<span style="color: #006633;">put</span><span style="color: #009900;">&#40;</span>name, request.<span style="color: #006633;">getAttribute</span><span style="color: #009900;">&#40;</span>name<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #000000; font-weight: bold;">return</span> attributes<span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  @SuppressWarnings<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;unchecked&quot;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000066; font-weight: bold;">void</span> populateContext<span style="color: #009900;">&#40;</span><span style="color: #003399;">Map</span> model, ValueStack stack, <span style="color: #003399;">Object</span> action,
                                 HttpServletRequest request, HttpServletResponse response<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// put the same objects into the context that the velocity result uses</span>
    <span style="color: #003399;">Map</span> standard <span style="color: #339933;">=</span> ContextUtil.<span style="color: #006633;">getStandardContext</span><span style="color: #009900;">&#40;</span>stack, request, response<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    model.<span style="color: #006633;">putAll</span><span style="color: #009900;">&#40;</span>standard<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// Support for JSP exception pages, exposing the servlet or JSP exception</span>
    <span style="color: #003399;">Throwable</span> exception <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #003399;">Throwable</span><span style="color: #009900;">&#41;</span> request.<span style="color: #006633;">getAttribute</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;javax.servlet.error.exception&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>exception <span style="color: #339933;">==</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      exception <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #003399;">Throwable</span><span style="color: #009900;">&#41;</span> request.<span style="color: #006633;">getAttribute</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;javax.servlet.error.JspException&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>exception <span style="color: #339933;">!=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      model.<span style="color: #006633;">put</span><span style="color: #009900;">&#40;</span>KEY_EXCEPTION, exception<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// Add action model.</span>
    <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>action <span style="color: #000000; font-weight: bold;">instanceof</span> StringTemplateAction<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      StringTemplateAction stAction <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>StringTemplateAction<span style="color: #009900;">&#41;</span> action<span style="color: #339933;">;</span>
      model.<span style="color: #006633;">putAll</span><span style="color: #009900;">&#40;</span>stAction.<span style="color: #006633;">getModel</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #008000; font-style: italic; font-weight: bold;">/**
   * Returns the locale used for the
   * {@link Configuration#getTemplate(String, Locale)} call. The base
   * implementation simply returns the locale setting of the action (assuming
   * the action implements {@link LocaleProvider}) or, if the action does not
   * the {@link #DEFAULT_LOCALE}
   */</span>
  <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #003399;">Locale</span> deduceLocale<span style="color: #009900;">&#40;</span>ActionInvocation invocation<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>invocation.<span style="color: #006633;">getAction</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">instanceof</span> LocaleProvider<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>LocaleProvider<span style="color: #009900;">&#41;</span> invocation.<span style="color: #006633;">getAction</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">getLocale</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000000; font-weight: bold;">return</span> DEFAULT_LOCALE<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">package</span> <span style="color: #006699;">org.apache.struts2.dispatcher</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.util.Map</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #008000; font-style: italic; font-weight: bold;">/**
 * Interface defining the required behavior from a StringTemplate result type.
 *
 * The result should prepare the model for the page to display.
 * The model is a map of attributes -&amp;gt; Objects where each object may either be a simple string, int,
 * etc or another map.
 * So. for example $username$ is accessible from the template of the model contains a String under
 * the value &quot;username&quot; and $strings.hello$ is accessible if the model contains a map under the key
 * &quot;strings&quot; and this map contains an attribute under the key &quot;hello&quot;
 *
 * @author Ran Tavory (ran@outbrain.com)
 *
 */</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">interface</span> StringTemplateAction <span style="color: #009900;">&#123;</span>
&nbsp;
  <span style="color: #008000; font-style: italic; font-weight: bold;">/**
   * Get the root of the display model.
   *
   * The display model is a map of attributes interpolated by StringTemplate at runtime by
   * substituting the $values$ in the template source.
   * For example to replace $user$ with Ran add
   * &lt;code&gt;map.put(&quot;user&quot;, &quot;Ran&quot;);&lt;/code&gt;
   * @return A map of attributes used by StringTemplate to replace in the template.
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">Map</span> getModel<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<img src="http://feeds.feedburner.com/~r/PrettyPrintMe/~4/c_vvTzhY9JQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://prettyprint.me/2009/11/13/stringtemplate-a-step-forward-to-a-better-web-mvc/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://prettyprint.me/2009/11/13/stringtemplate-a-step-forward-to-a-better-web-mvc/</feedburner:origLink></item>
		<item>
		<title>The joy of deleting code</title>
		<link>http://feedproxy.google.com/~r/PrettyPrintMe/~3/IK1WIEc_U-s/</link>
		<comments>http://prettyprint.me/2009/10/02/the-joy-of-deleting-code/#comments</comments>
		<pubDate>Fri, 02 Oct 2009 19:35:28 +0000</pubDate>
		<dc:creator>Ran Tavory</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://prettyprint.me/?p=182</guid>
		<description><![CDATA[What could be more fun than writing a new shiny super-functional, super-tested piece of code? Deleting it!
When deleting code you know that

You have not introduced new bugs. Perhaps you deleted some potential bugs from the old code but chances are you did not introduce new ones.
You don&#8217;t have to maintain it. It&#8217;s deleted.
Code was probably [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fprettyprint.me%2F2009%2F10%2F02%2Fthe-joy-of-deleting-code%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fprettyprint.me%2F2009%2F10%2F02%2Fthe-joy-of-deleting-code%2F" height="61" width="51" /></a></div><p>What could be more fun than writing a new shiny super-functional, super-tested piece of code? <strong>Deleting it!</strong><br />
When deleting code you know that</p>
<ul>
<li>You have not introduced new bugs. Perhaps you deleted some potential bugs from the old code but chances are you did not introduce new ones.</li>
<li>You don&#8217;t have to maintain it. It&#8217;s deleted.</li>
<li>Code was probably poorly written. Good code is never deleted. In many cases there&#8217;s poorly written code that you just don&#8217;t have the guts to delete it. Now you did, that&#8217;s great.</li>
<li>You&#8217;ve probably found a good way to reuse another piece of code, that&#8217;s why you&#8217;re deleting this piece of code. Code reuse is good.</li>
<li>Or that you&#8217;ve taken off a feature from your product. Taking off features is good, is very good. <a href="http://www.quotationspage.com/quote/26979.html">Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away</a></li>
<li>Or that you&#8217;ve found a more compact and elegant way to do what you want to do.</li>
</ul>
<p>Bottom line: Deleting code makes me happy. How about you?</p>
<p><img class="alignnone size-full wp-image-202" title="Delete" src="http://prettyprint.me/wp-content/uploads/2009/10/img_4207.jpg-1600×1200-pixels.png" alt="Delete" width="459" height="323" /></p>
<img src="http://feeds.feedburner.com/~r/PrettyPrintMe/~4/IK1WIEc_U-s" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://prettyprint.me/2009/10/02/the-joy-of-deleting-code/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://prettyprint.me/2009/10/02/the-joy-of-deleting-code/</feedburner:origLink></item>
		<item>
		<title>Mavenizing our code base</title>
		<link>http://feedproxy.google.com/~r/PrettyPrintMe/~3/Wmif6qd_d3I/</link>
		<comments>http://prettyprint.me/2009/09/20/mavenizing-our-code-base/#comments</comments>
		<pubDate>Sat, 19 Sep 2009 21:18:08 +0000</pubDate>
		<dc:creator>Ran Tavory</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://prettyprint.me/?p=168</guid>
		<description><![CDATA[Maven is a build tool for Java. It&#8217;s more than that actually, but let&#8217;s just call it a build tool.

In outbrain we decided we want to replace good old ant with maven.
Changing the company wide used build tool is not a decision taken lightly and may have consequences on product release cycle, but we weighted [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fprettyprint.me%2F2009%2F09%2F20%2Fmavenizing-our-code-base%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fprettyprint.me%2F2009%2F09%2F20%2Fmavenizing-our-code-base%2F" height="61" width="51" /></a></div><p><a title="Maven" href="http://maven.apache.org/">Maven</a> is a build tool for Java. It&#8217;s more than that actually, but let&#8217;s just call it a build tool.</p>
<p><img class="alignnone size-full wp-image-195" title="Maven - Welcome to Apache Maven-1" src="http://prettyprint.me/wp-content/uploads/2009/09/Maven-Welcome-to-Apache-Maven-1.png" alt="Maven - Welcome to Apache Maven-1" width="401" height="119" /></p>
<p>In <a href="http://www.outbrain.com/">outbrain</a> we decided we want to replace good old <a href="http://ant.apache.org/">ant</a> with maven.</p>
<p>Changing the company wide used build tool is not a decision taken lightly and may have consequences on product release cycle, but we weighted our options and decided to go for it, so I thought it might be worth mentioning our endeavor.</p>
<p>Everyone familiar with Java programming has probably used ant or at least heard of it. For many years it has been the de-facto standard build tool with large and growing audience, numerous plugins, excellent documentation and IDE support (for example most Java IDEs can automatically generate ant build files). But ant has its shortcomings which we, at outbrain decided we just couldn&#8217;t live with. We found maven to fill up most of the gaps.</p>
<h2>How do ant and maven differ?</h2>
<p>Maven is newer and was built from scratch with many of the lessons learned by ant in mind. Both projects are written and maintained by the high quality, high standard <a href="http://www.apache.org/">apache software foundation</a>, home of many other wonderful open source products. Both ant and maven are still actively developed and maintained, so it would not be fair to say that maven replaces ant, though many developers tend to think so (including myself).</p>
<p>Ant and maven differ in many ways, but at least to me these are the winning points that actually make the difference and made choose maven:</p>
<h3>Maven is declarative. Ant is imperative.</h3>
<p>Here&#8217;s what an ant build file looks like for a simple java project:</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;project</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;MyProject&quot;</span> <span style="color: #000066;">default</span>=<span style="color: #ff0000;">&quot;dist&quot;</span> <span style="color: #000066;">basedir</span>=<span style="color: #ff0000;">&quot;.&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    simple example build file
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #808080; font-style: italic;">&lt;!-- set global properties for this build --&gt;</span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;src&quot;</span> <span style="color: #000066;">location</span>=<span style="color: #ff0000;">&quot;src&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;build&quot;</span> <span style="color: #000066;">location</span>=<span style="color: #ff0000;">&quot;build&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;dist&quot;</span>  <span style="color: #000066;">location</span>=<span style="color: #ff0000;">&quot;dist&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
&nbsp;
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;target</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;init&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #808080; font-style: italic;">&lt;!-- Create the time stamp --&gt;</span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;tstamp</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #808080; font-style: italic;">&lt;!-- Create the build directory structure used by compile --&gt;</span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;mkdir</span> <span style="color: #000066;">dir</span>=<span style="color: #ff0000;">&quot;${build}&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/target<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;target</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;compile&quot;</span> <span style="color: #000066;">depends</span>=<span style="color: #ff0000;">&quot;init&quot;</span></span>
<span style="color: #009900;">    <span style="color: #000066;">description</span>=<span style="color: #ff0000;">&quot;compile the source &quot;</span> <span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #808080; font-style: italic;">&lt;!-- Compile the java code from ${src} into ${build} --&gt;</span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;javac</span> <span style="color: #000066;">srcdir</span>=<span style="color: #ff0000;">&quot;${src}&quot;</span> <span style="color: #000066;">destdir</span>=<span style="color: #ff0000;">&quot;${build}&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/target<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;target</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;dist&quot;</span> <span style="color: #000066;">depends</span>=<span style="color: #ff0000;">&quot;compile&quot;</span></span>
<span style="color: #009900;">    <span style="color: #000066;">description</span>=<span style="color: #ff0000;">&quot;generate the distribution&quot;</span> <span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #808080; font-style: italic;">&lt;!-- Create the distribution directory --&gt;</span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;mkdir</span> <span style="color: #000066;">dir</span>=<span style="color: #ff0000;">&quot;${dist}/lib&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
&nbsp;
    <span style="color: #808080; font-style: italic;">&lt;!-- Put everything in ${build} into the MyProject-${DSTAMP}.jar file --&gt;</span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;jar</span> <span style="color: #000066;">jarfile</span>=<span style="color: #ff0000;">&quot;${dist}/lib/MyProject-${DSTAMP}.jar&quot;</span> <span style="color: #000066;">basedir</span>=<span style="color: #ff0000;">&quot;${build}&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/target<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;target</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;clean&quot;</span></span>
<span style="color: #009900;">    <span style="color: #000066;">description</span>=<span style="color: #ff0000;">&quot;clean up&quot;</span> <span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #808080; font-style: italic;">&lt;!-- Delete the ${build} and ${dist} directory trees --&gt;</span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;delete</span> <span style="color: #000066;">dir</span>=<span style="color: #ff0000;">&quot;${build}&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;delete</span> <span style="color: #000066;">dir</span>=<span style="color: #ff0000;">&quot;${dist}&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/target<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/project<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>And here&#8217;s the maven one:</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;project</span> <span style="color: #000066;">xmlns</span>=<span style="color: #ff0000;">&quot;http://maven.apache.org/POM/4.0.0&quot;</span> <span style="color: #000066;">xmlns:xsi</span>=<span style="color: #ff0000;">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span>
<span style="color: #009900;">  <span style="color: #000066;">xsi:schemaLocation</span>=<span style="color: #ff0000;">&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;modelVersion<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>4.0.0<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/modelVersion<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>MyProject<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>MyProject<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>simple example build file<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;packaging<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>jar<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/packaging<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/project<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>Ant line count: <strong>22</strong> (not including spaces, comments)</p>
<p>Maven line count: <strong>7</strong>. (and they are real easy ones)</p>
<p>Short is good, especially in software (except perl <img src='http://prettyprint.me/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> ). But except for the fact that mvn has shorter build files, there is something more important hidden here &#8211; declarative v.s. imperative.</p>
<p>With ant you have to tell it HOW to build. You have to tell it that it first needs to collect all java sources, then run the javac compiler on them, then collect all classes, then run the jar tool on them to make them a jar. That&#8217;s tedious, especially if you have to do it 30 times, for each and every project. In outbrain we have many projects so when we used ant you&#8217;d see the exact same ant code patterns again and again (including the mistakes, which survived copy-paste horror). Ant is hard to maintain and is also hard to write. Did any of the readers ever write an ant build file? I doubt that. I&#8217;ve been using ant for more than 5 years and never have I written a file from scratch. It&#8217;s always used to be either copy-paste or using the IDE support for automatic generation. This is a bad sign of superfluous language.</p>
<p>Maven is declarative. You don&#8217;t have to tell it HOW to build, only WHAT to build, so conceptually it&#8217;s a higher level build tool. With mvn you only have to say &#8220;Look, this is how I call my project and I want you to make a jar from it&#8221; that&#8217;s all, mvn will figure out the rest. It knows where to find the sources (convention) and it knows what steps it needs to take in oder to create a jar. It will compile your source files, will package all resources for you in that jar, will run tests and create that jar for you. You can intervene with this process, but you don&#8217;t have to. You can make jars, wars, ears and more.</p>
<p>Declarative is in many cases preferred over imperative. Think HTML vs. Java. HTML is declarative, Java is imperative. In HTML you say &lt;b&gt;bold&lt;/b&gt; which tells the browser you want the text to be bold. You don&#8217;t tell it how to make the text bold (e.g. how many pixels, what position etc) only that you want it bold and let the browser figure out how to handle it. In Java you&#8217;d have to tell it how to make the text bold, how to space the characters, how to space words around it, how to break lines etc. Declarative is in many cases a lot easier than imperative, you worry less.</p>
<p>Maven is declarative, you only have to say &#8220;this is my project, jar it&#8221;. With ant you have more control over what the build tool does, so you can go crazy with build scripts and&#8230; well&#8230; jar before compile, or clean after jar (instead of before it) or package the test code inside production code or whatever, you get the point, you have the freedom to err. 9 times out of 10 you don&#8217;t need the level of flexibility provided by ant and you&#8217;d be much safer using mvn.</p>
<h3>Dependency management.</h3>
<p>This is a big thing. That was actually the main reason I wanted to move out of ant. Maven has a wonderful dependency management system built in by default. Ant has nothing built in, although it has <a href="http://ant.apache.org/ivy/">ivy</a> as a plugin.</p>
<p>What is dependency management? There are external and internal dependencies. External dependencies are ones you download from the net, usually open source projects such as <a href="http://lucene.apache.org/">Lucene</a>, <a href="http://activemq.apache.org/">ActvieMQ</a>, and other open source projects. With maven you only have to declare your dependency on them and they get automatically downloaded. Example:</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>struts<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>struts-bean<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1.2.8<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<div>With ant you basically have two options. One is download the library yourself and throw it in some folder, call it 3rdParty and add it to the classpath (good luck with keeping track of versioning, who&#8217;s using what and your life) or use ivy, which is pretty decent, but as mentioned before not part of the default ant installation.</div>
<div>As for internal dependencies, which means your project which depends (uses) another one of your projects, mvn supports that as well. AFAIK ant does not. With ant, if you have more than one project in your company (and of course you do), you&#8217;d have to manually tweak the build scripts so they run in the correct order and dependencies are compiled before they are used. Although it&#8217;s possible, that&#8217;s sort of nightmarish as companies grows.</div>
<div>Dependency management is a killer feature for mvn and was actually the main reason that prompted me to pursue it. Although ant can have ivy, this was not zero-work, so I decided, heck it we&#8217;re going to put some work into it, let&#8217;s rebuild the whole thing and get a much better result. So we did.</div>
<div></div>
<h3>Conventions vs. configuration</h3>
<p>Conventions are good. They save a lot of time and prevent you from doing foolish mistakes (such as packaging test code into production).</p>
<p>By conventions I mean:</p>
<ul>
<li>Where is the source code?</li>
<li>Where is the test code?</li>
<li>Where are the resources?</li>
<li>Where are the web files?</li>
<li>etc</li>
</ul>
<p>With ant you had to create a directory for sources (call it src or Src or source or srce) and tell and where your sources are. Then you&#8217;d have to decide where to put your tests. You can push them in tst, test, tests, or even in the same source directory as production code is, maybe in a test package. Next you have to <strong>configure</strong> ant where to find test code, how to separate it from production code, and heck &#8211; how to run it (it really doesn&#8217;t know how to do it).</p>
<p>With mvn that&#8217;s much easier. Maven promotes conventions such as the <a href="http://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html">standard directory layout</a> which means all sources are at predefined location, all resources are as well etc. There are several advantages to that including that it&#8217;s easy to start a new project, you don&#8217;t have to think where everything goes, it&#8217;s hard to make mistakes by misplacing items, you don&#8217;t have to think about the build script and how to configure it and perhaps most important of all, you make all company employees conform to the same layout. That&#8217;s a huge gain for the company.</p>
<h3>Built-in functionality out of the box</h3>
<p>OK, there are plenty of other benefits to mvn but the post is already getting too long so let&#8217;s have the last one here.</p>
<p>With mvn you get tons of functionality out of the box. By creating a very simple build file with only the project definition in it you can:</p>
<ul>
<li>compile all sources</li>
<li>compile test</li>
<li>run unit tests</li>
<li>run integration tests</li>
<li>package as a jar/war or something else</li>
<li>deploy</li>
<li>run in tomcat</li>
<li>&#8230;and much more</li>
</ul>
<p>With ant what you had to do is for each one of the above listed goals, create an ant goal and configure ant by telling it how to run it. Some of them may be relatively trivial (but still require coding) and some of them aren&#8217;t easy at all&#8230; that kind of tells you why anters are very good with their CTRL+C and CTRL+V. And with copy-paste comes the pain of silly copy paste errors and difficult maintainability. Life with mvn is better <img src='http://prettyprint.me/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>Other great and not covered features: Eclipse and other IDE integration (automatically generating projects), great testing and debugging tools, excellent build output, excellent versioning and more.</p>
<h3>How did it go?</h3>
<p>So, how did it go? You guys have converted your entire codebase build tool. Isn&#8217;t that like <a href="http://www.joelonsoftware.com/articles/fog0000000069.html">Netscape&#8217;s near death experience</a> while rewriting their entire code base?</p>
<p>Well&#8230; no! The nice thing about mvn is that it&#8217;s easy to write and easy to learn. We did spend a couple of weeks on that task and had to resolve some unpredictable situations, but it had only a small impact on our schedule (and needless to say that I hope in the long term will have  the most positive impact on release schedule). Heck, we (at least I) even enjoyed it!</p>
<h3>Conclusions</h3>
<p>I&#8217;d definitely recommend mvn. If you&#8217;re starting a new project, choose mvn. If you have an existing codebase using ant and you&#8217;re thinking about moving to maven, know that it&#8217;s certainly feasible and in my opinion, well worth the effort. Expect some work, it&#8217;s not zero effort, but I promise you&#8217;ll enjoy it.</p>
<img src="http://feeds.feedburner.com/~r/PrettyPrintMe/~4/Wmif6qd_d3I" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://prettyprint.me/2009/09/20/mavenizing-our-code-base/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://prettyprint.me/2009/09/20/mavenizing-our-code-base/</feedburner:origLink></item>
	</channel>
</rss>
