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

<channel>
	<title>let x=x &#187; code</title>
	<atom:link href="http://www.crazymcphee.net/x/tag/code/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.crazymcphee.net/x</link>
	<description>programming idiom and methodology</description>
	<lastBuildDate>Tue, 13 Jul 2010 21:56:44 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Throw it away and write another one</title>
		<link>http://www.crazymcphee.net/x/2010/05/30/throw-it-away-and-write-another-one/</link>
		<comments>http://www.crazymcphee.net/x/2010/05/30/throw-it-away-and-write-another-one/#comments</comments>
		<pubDate>Sun, 30 May 2010 08:47:10 +0000</pubDate>
		<dc:creator>Scot Mcphee</dc:creator>
				<category><![CDATA[architecture]]></category>
		<category><![CDATA[professional practice]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[technical]]></category>
		<category><![CDATA[tools and techniques]]></category>
		<category><![CDATA[agile]]></category>
		<category><![CDATA[ANTLR]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[craftsmanship]]></category>
		<category><![CDATA[emergent design]]></category>
		<category><![CDATA[profession]]></category>
		<category><![CDATA[refactor]]></category>
		<category><![CDATA[rewrite]]></category>
		<category><![CDATA[test driven design]]></category>

		<guid isPermaLink="false">http://www.crazymcphee.net/x/?p=557</guid>
		<description><![CDATA[Most developers familiar with agile methods are familiar with the idea of the spike. A spike is a time-boxed task that concentrates on clarifying the unknowns in your project. Usually these are technological (&#8220;can this be done with this technology?&#8221;) but they are also sometimes in the area of the business domain (&#8220;is this a [...]]]></description>
			<content:encoded><![CDATA[<p>Most developers familiar with agile methods are familiar with the idea of the <em>spike</em>. A spike is a time-boxed task that concentrates on clarifying the unknowns in your project. Usually these are technological (&#8220;can this be done with this technology?&#8221;) but they are also sometimes in the area of the business domain (&#8220;is this a good idea?&#8221;) too. One key idea is that the at the end of the spike, it is thrown away. It&#8217;s not supposed to be used as production code, it&#8217;s just supposed to answer some questions about the project, to validate or invalidate particular approaches to a problem, to provide further clarity around unknowns, to explore risk, to help with estimation, etc. I think this can be a useful general idea when dealing with technology, even in a &#8220;production&#8221; context.</p>
<p>Recently I was learning <a href="http://www.antlr.org">ANTLR</a>, trying to decide whether this was a right technology to pursue a particular project which involved parsing a preexisting message format. After a week of a spike, we decided that it was worth pursuing and started on earnest on the grammar for our project. However a week into this process, I had an epiphany &#8230; I was doing some things wrong with the ANTLR grammar which were now slowing progress in adding the new characteristics it needed to be complete. Many developers know this feeling; the features of my grammar that I had built over the first week were naive and now hampering it from expanding into the new requirements. I took it on myself to kill the entire grammar and start again. It took less than a day and half to replicate that week&#8217;s worth of work (i.e. pass the test suite which had built up around it).  I&#8217;ve done this before; scrap the first attempt at building a domain and try again. Here my domain was the same (it was after all defined in both a standards specification and in the many hundreds of thousands of sample messages we captured from an existing system), but its implementation needed refinement.</p>
<p>So I think that the rule about throwing away spikes can in fact be made a general axiom of programming:</p>
<blockquote><p>When you are learning a new technology, make sure you  throw away the first thing you build that works &#8211; to avoid accumulating  your mistakes.</p></blockquote>
<p>Thanks to <a href="http://www.twasink.net/">Robert</a> for the important qualifier &#8220;that works&#8221;. <img src='http://www.crazymcphee.net/x/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>N.B. my views about <a title="The rewrite will be ready shortly" href="http://www.crazymcphee.net/x/2009/02/01/the-rewrite-will-be-ready-shortly/">system  rewrites</a> have not changed regardless.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.crazymcphee.net/x/2010/05/30/throw-it-away-and-write-another-one/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dynamically loading Spring contexts from the classpath at runtime</title>
		<link>http://www.crazymcphee.net/x/2010/04/29/dynamically-loading-spring-contexts-from-the-classpath-at-runtime/</link>
		<comments>http://www.crazymcphee.net/x/2010/04/29/dynamically-loading-spring-contexts-from-the-classpath-at-runtime/#comments</comments>
		<pubDate>Thu, 29 Apr 2010 06:45:11 +0000</pubDate>
		<dc:creator>Scot Mcphee</dc:creator>
				<category><![CDATA[infrastructure and frameworks]]></category>
		<category><![CDATA[tools and techniques]]></category>
		<category><![CDATA[applicationcontext]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[PathMatchingResourcePatternResolver]]></category>
		<category><![CDATA[spring]]></category>

		<guid isPermaLink="false">http://www.crazymcphee.net/x/?p=540</guid>
		<description><![CDATA[Using these three Spring features will enable us to be able to place a JAR file containing an interface implementation, and a Spring context XML file matching a particular pattern, into the classpath of our WAR, and on restart, we can dynamically pick up the newly inserted features into our application installation.]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m just going to document a way I&#8217;ve found to use Spring ApplicationContext to dynamically load other context XML configurations that it find in the classpath. We have a requirement to do this coming up on a product we&#8217;re building. Let me describe the sort of problem we are trying to solve (with many specifics omitted or glossed over):</p>
<blockquote><p>There is a web service inside a component, let&#8217;s call that component a &#8216;Node&#8217;, that receives something like (but not identical to!) an Event on its interface. Inside the Event is some data that the Node does not particularly care about (and actually has no access to &#8211; it&#8217;s just a <em>byte[]</em> as far as the Node can tell). However, the Node contains a Registry which enables components, lets call them Event Handlers, to register themselves with the Node, as available to process certain Events (i.e. decode that <em>byte[]</em> and do something with it) according to criteria which the EventHandler injects into the Node&#8217;s Registry.  EventHandler is an interface with a handful of simple methods related to handling the Event, and also registration with the Registry.</p>
<p>So, the process flow looks something like this: The Node first records the reception of the Event at the interface in a log. Then it tells the Registry about the Event, and the Registry produces the EventHandler(s) it needs to use.  The Registry gives the Node back the instances of the EventHandler interface. The Node then hands off the Event to the EventHandler, which does whatever it does unbeknownst to the Node, and returns a fairly simple EventResponse object. The Node records the EventResponse object in its log (i.e. a database) and returns it as the response to the web service call.</p>
<p>Consider the Node service method as looking something like this (you&#8217;ll have to excuse the Java 1.4-ness of this code, the WordPress code highlighting plugin apparently hates Java 5) :</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">List</span> receive<span style="color: #009900;">&#40;</span><span style="color: #003399;">Event</span> event<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #003399;">List</span> responses <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">ArrayList</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>EventHandler handler <span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">registry</span>.<span style="color: #006633;">lookup</span><span style="color: #009900;">&#40;</span>event.<span style="color: #006633;">getMetadata</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      Response response <span style="color: #339933;">=</span> handler.<span style="color: #006633;">handle</span><span style="color: #009900;">&#40;</span>event<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      saveResponse<span style="color: #009900;">&#40;</span>response, event, handler<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      responses.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span>response<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> responses<span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span></pre></div></div>

<p>To enable the wiring, the Registry has a method:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">  <span style="color: #000066; font-weight: bold;">void</span> register<span style="color: #009900;">&#40;</span>EventMetadata metadata, EventHandler handler<span style="color: #009900;">&#41;</span></pre></div></div>

<p>and among other methods the EventHandler interface defines:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">  <span style="color: #000066; font-weight: bold;">void</span> setRegistry<span style="color: #009900;">&#40;</span><span style="color: #003399;">Registry</span> registry<span style="color: #009900;">&#41;</span></pre></div></div>

<p>Currently the WAR file imports the Node.JAR and a group of EventHandler.JAR files which are specific implementations for handling different kinds of Events. We configure it in Spring currently so that the specific EventHandler is injected with the Registry object (from the Node.JAR). The EventHandler implementation then registers itself with the Registry in a call-back operation, telling it what sort of Events it will handle<em>.</em></p></blockquote>
<p><span style="text-decoration: underline;">This all works just fine at the moment</span>. The <span style="text-decoration: underline;">problem</span> with what we have is that it is all currently statically compiled into the WAR file.The WAR file specifies a Spring application context XML file which in turn loads the Spring configuration for the Node and Registry component, and every Spring application context for each Handler JAR included inside the WAR file&#8217;s <em>WEB-INF/lib</em> directory.</p>
<p>Now, we now don&#8217;t want every deployed instance of every Node to handle every possible Event. Currently we&#8217;ve got a small <em>.properties</em> file that actually tells another Spring component which EventHandlers are be to be instantiated or not. This is working fine when we only desire some Nodes to handle maybe one or two of a larger group of related Events. That is, where we currently don&#8217;t mind that the WAR file is identical in every respect on every Node &#8212; it&#8217;s just that each node contains a <em>.properties</em> file in its classpath that tells it which EventHandlers it is allowed to load and use (and therefore what Events it is capable of receiving, bearing in mind that when I say &#8216;Events&#8217; there is really only one concrete type of Event, I mean the encrypted data which is held <span style="text-decoration: underline;">within</span> the Event which is actually consumed by the Handler).</p>
<p>However, we are now in a situation where we want to use this same architecture for a completely different group of Events. We definitely don&#8217;t want to have to compile and assemble a new WAR file for different Nodes based on the Event cluster. We want to deploy a standardized <em>Node.WAR</em> which has available on its classpath a dynamic set of <em>XxxEventHandler.JAR</em> which can dynamically register themselves with the Node&#8217;s registry. There may be also a requirement for some related custom extension points in the future.</p>
<p>Initially we considered OSGi as the technology to enable this. After some discussion yesterday with people who know better about OSGi, this approach was rejected as impractical for the moment. Therefore last night I set out tooling about with the Spring 2.5.6 ApplicationContext and its related objects to see what could be done to enable dynamically-loaded JAR files within a parent Spring application context. Here is what I&#8217;ve discovered we can do, with only some small restrictions on developers writing the individual EventHandler implementations.</p>
<p>The first issue is, we need to locate a set of Spring application context XML file which should be on the classpath but not yet instantiated into any live Spring context.</p>
<p>Assuming we&#8217;re in a bean that&#8217;s <em>ContextAware</em> or otherwise has access to the Spring application context which is loading it, after the parent context has loaded and initialized (there are method hooks for this sort of thing) we can use the <em>org.springframework.core.io.support.PathMatchingResourcePatternResolver</em> class to search the classpath for a resource:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">  PathMatchingResourcePatternResolver pmrl <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> PathMatchingResourcePatternResolver<span style="color: #009900;">&#40;</span>context.<span style="color: #006633;">getClassLoader</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  Resource<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> resources <span style="color: #339933;">=</span> pmrl.<span style="color: #006633;">getResources</span><span style="color: #009900;">&#40;</span>
    <span style="color: #0000ff;">&quot;classpath*:/net/crazymcphee/dynamiccontext/*/Crazy*DynamicContext.xml&quot;</span>
  <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Looking at the Spring 2.5.6 source code we found that the String passed to the <em>getResources()</em> method isn&#8217;t a proper regular expression, which is a pity. So you can&#8217;t do something like look for <em>**/Crazy*DynamicContext.xml</em> and expect to match a file <em>Crazy*DynamicContext.xml</em> in any package. Also we found that it had to prefixed with that <em>classpath*:</em> &#8230; yes, the asterix, literally &#8230; else it wouldn&#8217;t search the classpath, as opposed to the file path. So we&#8217;re restricted in the above example to a file called <em>Crazy&lt;something&gt;DynamicContext.xml </em>in a package exactly one deep from <em>net.crazymcphee.dynamiccontext</em> &#8230; e.g. <em>net.crazymcphee.dynamiccontext.package.CrazyMcpheeDynamicPackage.xml</em> matches but <em>net.crazymcphee.dynamiccontext.package.sub.CrazySubDynamicPackage.xml </em>and <em>net.crazymcphee.dynamiccontext.CrazySuperDynamicPackage.xml </em>do not. Therefore we will have a restriction on what package the dynamic context can be in and what it&#8217;s name will be. I don&#8217;t think that&#8217;s too onerous on our developers &#8211; we just have to pick a sensible standard.</p>
<p>The next part of the problem is that we have to load the &#8216;Resource&#8217; thus found into a Spring context. This is pretty easy:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"> <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span>Resource r <span style="color: #339933;">:</span> resources<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
   GenericApplicationContext createdContext <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> GenericApplicationContext<span style="color: #009900;">&#40;</span>context<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
   XmlBeanDefinitionReader reader <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> XmlBeanDefinitionReader<span style="color: #009900;">&#40;</span>createdContext<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
   <span style="color: #000066; font-weight: bold;">int</span> i <span style="color: #339933;">=</span> reader.<span style="color: #006633;">loadBeanDefinitions</span><span style="color: #009900;">&#40;</span>r<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
 <span style="color: #009900;">&#125;</span></pre></div></div>

<p>The<em> int i</em> will be set to the number of beans found in the <em>createdContext</em>. The <em>createdContext</em> will have the original <em>context</em> as its parent context, so it can gain access to any beans defined there (and also, although we are yet to test this (!), it should also be intercepted by the AOP-based transaction interceptors in the parent, and so forth).</p>
<p>The only other part of the puzzle may be to query the <em>createdContext</em> to see if it has any target beans within it, luckily for us an ApplicationContext has a method <em>getBeansOfType(Class clazz)</em> which will load all the beans of a particular type:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">  <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span>Resource r <span style="color: #339933;">:</span> resources<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    GenericApplicationContext createdContext <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> GenericApplicationContext<span style="color: #009900;">&#40;</span>context<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    XmlBeanDefinitionReader reader <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> XmlBeanDefinitionReader<span style="color: #009900;">&#40;</span>createdContext<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">int</span> i <span style="color: #339933;">=</span> reader.<span style="color: #006633;">loadBeanDefinitions</span><span style="color: #009900;">&#40;</span>r<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #003399;">Map</span> map <span style="color: #339933;">=</span> createdContext.<span style="color: #006633;">getBeansOfType</span><span style="color: #009900;">&#40;</span>EventHandler.<span style="color: #000000; font-weight: bold;">class</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;">Object</span> o <span style="color: #339933;">:</span> map.<span style="color: #006633;">keySet</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>
      EventHandler handler <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>EventHandler<span style="color: #009900;">&#41;</span> createdContext.<span style="color: #006633;">getBean</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span><span style="color: #009900;">&#41;</span> o<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #666666; font-style: italic;">// do some programmatic manipulation with the EventHandler that we found here</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span></pre></div></div>

<p>Using these three Spring features will enable us to be able to place a JAR file containing an interface implementation, and a Spring context XML file matching a particular pattern, into the classpath of our WAR, and on restart, we can dynamically pick up the newly inserted features into our application installation. I&#8217;ll report back when we get an actual production prototype together that can do this. Hopefully it will be OK to put the code in the blog too (if we make it generic enough).</p>
<p>If you have any further ideas or refinements to this idea, please leave them in the comments!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.crazymcphee.net/x/2010/04/29/dynamically-loading-spring-contexts-from-the-classpath-at-runtime/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Java + WebDAV &#8230; a solution for the PITA</title>
		<link>http://www.crazymcphee.net/x/2010/04/20/java-webdav-a-solution-for-the-pita/</link>
		<comments>http://www.crazymcphee.net/x/2010/04/20/java-webdav-a-solution-for-the-pita/#comments</comments>
		<pubDate>Tue, 20 Apr 2010 06:33:50 +0000</pubDate>
		<dc:creator>Scot Mcphee</dc:creator>
				<category><![CDATA[tools and techniques]]></category>
		<category><![CDATA[apache httpd]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[library]]></category>
		<category><![CDATA[webdav]]></category>

		<guid isPermaLink="false">http://www.crazymcphee.net/x/?p=533</guid>
		<description><![CDATA[Spent the day tooling about with Java web DAV libraries and the Apache httpd server on a Centos machine. First, just let me start by saying that if your webDAV installation on Apache ain&#8217;t working as it should and you&#8217;re on a Redhat-style installation, have a good look at what SELinux is doing. If I&#8217;d [...]]]></description>
			<content:encoded><![CDATA[<p>Spent the day tooling about with Java web DAV libraries and the Apache httpd server on a <a href="http://www.tuxoz.com/2009/10/how-to-setup-webdav-on-centos/" target="_blank">Centos machine</a>. First, just let me start by saying that if your webDAV installation on Apache ain&#8217;t working as it should and you&#8217;re on a Redhat-style installation, have a good look at <a href="http://www.crypt.gen.nz/selinux/disable_selinux.html" target="_blank">what SELinux is doing</a>. If I&#8217;d looked sooner it would have saved me a couple of hours!</p>
<p>But the bigger headache was the Java libraries for handling WebDAV. There is the now-abandoned <a href="http://jakarta.apache.org/slide/" target="_blank">Apache Slide</a>, the based-on-Slide <a href="http://sourceforge.net/projects/webdavclient4j/" target="_blank">webdavclient4j</a>, and the way-more-complex-than-it-needs-to-be <a href="http://jackrabbit.apache.org/" target="_blank">Jackrabbit</a>. Slide and webdavclient4J have the appearance and feel of crusty, molten code from 2004. Jackrabbit is a full-featured <em>server</em> product &#8230; to quote, it is a <em>&#8220;hierarchical content store with support for structured and unstructured  content, full text search, versioning, transactions, observation&#8221;</em> &#8230; and I&#8217;m sure that&#8217;s real nice if that&#8217;s what you want, but I just need to automate push a file onto an Apache HTTPD instance and tell another service what URL it now lives at. It&#8217;s not rocket science. Jackrabbit has too many features, and too little simple documentation, to be truly useful for what I need.</p>
<p>Enter the easy to use WebDAV client, <a href="http://sardine.googlecode.com/">Sardine</a>. Here is the <a href="http://lookfirst.com/2010/01/sardine-very-partial-webdav-client-for.html" target="_blank">author&#8217;s post announcing it</a>.  It&#8217;s very simple to use:</p>
<pre>Sardine sardine = SardineFactory.begin();
List&lt;DavResource&gt; resources = sardine.getResources("http://yourdavserver.com/adirectory/");
for (DavResource res : resources)
{
     System.out.println(res);
}</pre>
<p>Anyway, simplicity &#8230; just the sort of thing I was looking for. Recommended.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.crazymcphee.net/x/2010/04/20/java-webdav-a-solution-for-the-pita/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Money-is-Money 0.17</title>
		<link>http://www.crazymcphee.net/x/2009/12/04/money-is-money-0-17/</link>
		<comments>http://www.crazymcphee.net/x/2009/12/04/money-is-money-0-17/#comments</comments>
		<pubDate>Fri, 04 Dec 2009 08:52:12 +0000</pubDate>
		<dc:creator>Scot Mcphee</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[library]]></category>
		<category><![CDATA[money]]></category>
		<category><![CDATA[money-is-money]]></category>
		<category><![CDATA[opensource]]></category>

		<guid isPermaLink="false">http://www.crazymcphee.net/x/?p=498</guid>
		<description><![CDATA[I just released a new version of Money-Is-Money, v0.17. If you&#8217;re interested, see the features here and here. My aim with it is to make the most accurate currency-aware Java money handling library available. This time I&#8217;ve added just a couple of new methods to get the whole and fractional amounts as Integers (I use [...]]]></description>
			<content:encoded><![CDATA[<p>I just released a new version of Money-Is-Money, v0.17. If you&#8217;re interested, see the features <a href="http://www.crazymcphee.net/x/2009/04/17/money-is-money-v016/">here</a> and <a href="http://www.crazymcphee.net/x/2009/04/17/money-is-money-v015-with-added-maven-repository/">here</a>. My aim with it is to make the most accurate currency-aware Java money handling library available. This time I&#8217;ve added just a couple of new methods to get the whole and fractional amounts as Integers (I use throughout BigDecimal and BigInteger to represent amounts, to avoid the fatal floating point errors).</p>
<p>To include it into your Maven POM you&#8217;ll have to add my repository to a profile in your settings.xml:</p>
<pre class="code" lang="xml">&lt;repositories&gt;
  &lt;repository&gt;
    &lt;id&gt;crazy-mcphee&lt;/id&gt;
    &lt;url&gt;http://modular.autonomous.org:80/artifactory-2.0.5/libs-releases-local&lt;/url&gt;
    &lt;snapshots&gt;
      &lt;enabled&gt;false&lt;/enabled&gt;
    &lt;/snapshots&gt;
    &lt;releases&gt;
      &lt;enabled&gt;true&lt;/enabled&gt;
    &lt;/releases&gt;
  &lt;/repository&gt;
&lt;/repositories&gt;</pre>
<p>At which point you can include the dependency in your pom.xml for your project:</p>
<pre class="code" lang="xml">&lt;dependency&gt;
  &lt;groupId&gt;org.autonomous&lt;/groupId&gt;
  &lt;artifactId&gt;money-is-money&lt;/artifactId&gt;
  &lt;version&gt;0.17&lt;/version&gt;
&lt;/dependency&gt;</pre>
<p>If you want to check the source code out with SVN the release is at <em>http://crazymcphee.net/svn/money/tags/money-is-money-0.17</em> and the latest trunk at <em>http://crazymcphee.net/svn/money/trunk</em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.crazymcphee.net/x/2009/12/04/money-is-money-0-17/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mistakes you can make with SOA</title>
		<link>http://www.crazymcphee.net/x/2009/11/03/mistakes-you-can-make-with-soa/</link>
		<comments>http://www.crazymcphee.net/x/2009/11/03/mistakes-you-can-make-with-soa/#comments</comments>
		<pubDate>Tue, 03 Nov 2009 07:49:45 +0000</pubDate>
		<dc:creator>Scot Mcphee</dc:creator>
				<category><![CDATA[professional practice]]></category>
		<category><![CDATA[rants]]></category>
		<category><![CDATA[technical]]></category>
		<category><![CDATA[tools and techniques]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[profession]]></category>
		<category><![CDATA[soa]]></category>
		<category><![CDATA[test driven design]]></category>
		<category><![CDATA[wizards considered harmful]]></category>

		<guid isPermaLink="false">http://www.crazymcphee.net/x/?p=494</guid>
		<description><![CDATA[Bob Lewis has a great column this month, &#8220;What if SOA is a mistake&#8220;? His penultimate paragraph asks: Lost in the shuffle is something basic: Programmer productivity. Friends who are hands-on with such matters tell me the available SOA development environments are less than half as productive as products like PowerBuilder and Delphi were, back [...]]]></description>
			<content:encoded><![CDATA[<p>Bob Lewis has a great column this month, &#8220;<a href="http://www.weblog.keepthejointrunning.com/wordpress/?p=3174" target="_blank">What if SOA is a mistake</a>&#8220;? His penultimate paragraph asks:</p>
<blockquote><p>Lost in the shuffle is something basic: Programmer productivity. Friends who are hands-on with such matters tell me the available SOA development environments are less than half as productive as products like PowerBuilder and Delphi were, back when they were viable.</p></blockquote>
<p>Putting aside the Powerbuilder and Delphi love for just one minute, this is something I&#8217;ve been banging on about now for the past year &#8230; the programming tooling that is foisted onto programmers by the choice of the deployment architecture. It&#8217;s just all <em>wrong</em>.</p>
<p>In my view, what makes a programming language really productive is <em>notepad</em>. Or <em>vi</em>, or <em>emacs, </em>or<em> gvim, </em>or<em> textmate</em>, take your pick. What I mean is &#8230; <em>the programming language has to be able to be programmed with a simple editor</em>. Yes, an advanced IDE will make things more productive, but the basics must also apply. Now a lot of SOA environments are simply <em>not programmable</em> without the specific IDE tied to it. Even worse, the IDEs are often completely custom jobs that require a developer to be re-trained &#8230; losing <em>years and years</em> of productive speed with muscle-memory style automatic ability to navigate the programmer&#8217;s usual editing tool. Seriously. This stuff is whack. A program language or an environment needs to be IDE-neutral. If you got a plumber around, would you insist that he only use the tools you supply from your home handyman kit? Or would you expect the plumber to have mastered a set of his own tools already? And making matters worse, it&#8217;s rarely <em>programmers</em> that choose these tools which are foisted on them. The server/deployment environment and the language used to implement need to be decoupled from the tools used to build it.</p>
<p>But an even <em>worse</em> failing of many of these SOA tool suites, is that they all strongly and irrevocably coupled to the deployment/runtime environment. Generally they totally lack the ability to keep up with modern programming practice. Like for instance, automated testing. Or even <em>unit tests</em>, let alone advanced and productive techniques such as Test-First approaches or Test Driven Design. The tools often lack refactoring support. All of these things are in my opinion, and in the opinion of many leading developers, absolutely essential to quality engineering practice and agile development outcomes like &#8220;delivery of working software&#8221;. Both the &#8220;delivering&#8221; and the &#8220;working&#8221; part means the whole process needs to be <em>repeatable</em>. That&#8217;s why automated integration testing, to name just one thing, is <em>essential</em> in modern development. But often the fancy custom development tooling is a complete barrier to achieving this.</p>
<p>But you won&#8217;t hear any of this from the big vendors. One big vendor recently announced their new version of their middleware product suite had a &#8216;focus on testability&#8217;, but you ask any of their presales guys to demonstrate this in an actual development environment. Ask them about continuous integration support, for example. Witness their blank looks. Their development product is completely orientated to &#8220;one button push from the IDE to production&#8221; modes of thinking the idea of continuous integration builds is almost totally antithetical to the very concepts of operation the product is organised around. They think that finally adding support for Subversion version control system, at least five years too late, is a wondrous achievement.</p>
<p>They are aiming for &#8216;programmerless programming&#8217;: of course in process just creating a new type of programmer. Every new generation of programmers simply have to learn the same hard-fought lessons of software engineering over and over again because each generation of tooling apparently scraps the paradigm over and over again in a vain attempt to create push-button, wizard-driven programming models. They nearly all suffer from &#8216;hello world&#8217; programming &#8211; the simple examples that sell them to IT management are trivial to conquer using the wizards, but more complex problems (i.e. real world ones) are flat-out impossible. Thus these tools are always mirages which look great at a huge distance on the horizon but are flat lifeless salt pans of bleached skulls and bones on closer examination (or, maybe they are more like tar pits that look like a nice waterhole but one step into it and you are sucked down   to your doom).</p>
<p>As you might be able to tell, I am utterly contemptuous of many of these SOA tool paradigms. I have nothing against SOA itself, <em>per se</em>. But there is nothing more productive than a programmer who understands the importance of simple and repeatable build and deployment automation using command line tools and who knows his programming <em>editor</em> inside out after ten years of use. Give that programmer a better language by all means, add incremental features to that IDE, allow the programmers to continuously improve their techniques, promote professional craftsmanship, yes, yes and a thousand times yes. But no amount of drag and drop wizards, push-button deployments, and &#8220;object inspector&#8221; property editors will ever usurp that deep knowledge a good programmer brings to both his language and his personal tooling choices.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.crazymcphee.net/x/2009/11/03/mistakes-you-can-make-with-soa/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>ORM-is-Dead meme</title>
		<link>http://www.crazymcphee.net/x/2009/10/19/orm-is-dead-meme/</link>
		<comments>http://www.crazymcphee.net/x/2009/10/19/orm-is-dead-meme/#comments</comments>
		<pubDate>Mon, 19 Oct 2009 07:31:32 +0000</pubDate>
		<dc:creator>Scot Mcphee</dc:creator>
				<category><![CDATA[architecture]]></category>
		<category><![CDATA[infrastructure and frameworks]]></category>
		<category><![CDATA[technical]]></category>
		<category><![CDATA[tools and techniques]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[dao]]></category>
		<category><![CDATA[hibernate]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[jpa]]></category>
		<category><![CDATA[orm]]></category>
		<category><![CDATA[persistence]]></category>

		<guid isPermaLink="false">http://www.crazymcphee.net/x/?p=488</guid>
		<description><![CDATA[I agree with Stephan, and  Aldo; ORMs increasingly get in the way. Collection mapping is one of those &#8220;hello world&#8221; problems. (The &#8220;hello world&#8221; example in the doco looks totally trivial and completely ideal [which is the problem], but suck-in-the-galaxy-greet-it-and-then-map-all-the-stars problem, which is more like what your real app looks like, is far less than [...]]]></description>
			<content:encoded><![CDATA[<p>I agree with <a href="http://codemonkeyism.com/orms/">Stephan</a>, and  <a href="http://www.hatfulofhollow.com/posts/code/farewell-to-orms.html">Aldo</a>; ORMs increasingly get in the way.</p>
<p>Collection mapping is one of those &#8220;hello world&#8221; problems. (The &#8220;hello world&#8221; example in the doco looks totally trivial and completely ideal [which is the problem], but suck-in-the-galaxy-greet-it-and-then-map-all-the-stars problem, which is more like what your real app looks like, is far less than trivial and not so easily achieved with the demonstrated toolkit). In my experience, collection mapping is the cause of all sorts of pain and performance perfidy.</p>
<p>Here&#8217;s a further situation where I find that they <em>really</em> get in the way. Consider integration with existing systems that use highly-normalised database schemas (designed by advanced SQL programmers who know what they are doing in that language).</p>
<p>This is not an uncommon scenario &#8211; we have this system &#8216;A&#8217; which (let&#8217;s say) has all our customer shipping, product, warehousing data in it. We don&#8217;t want to replace it. But we need to extend it so that e.g. available to web systems. Or maybe it needs to be integrated into the big fancy off-the-shelf CRM we&#8217;re installing. Something like that. We need to build some sort of service layer around this system &#8216;A&#8217; so that other systems can access its data and/or functions. It&#8217;s common to think that an ORM around that big complex database schema is going to help, but in my experience, it doesn&#8217;t for many of the reasons Stephan and Aldo list. That sort of highly-normal database schema in my experiences completely kills ORM object representations stone cold. You end up with so many LazyInitialisationExceptions and various other problems it sucks productivity out the developers and performance out of the system.</p>
<p>Also, I get a bit annoyed about ORM abstractions leaking into the web tier, this is especially prevalent with using annotations rather than ORM mapping files.</p>
<p>Different sorts of approaches are sometimes needed to be applied with careful thought in that scenario. Perhaps you need to model the &#8220;intermediate&#8221; domain you need directly, and then use, for example, simple DAO layers which operate directly on the domain you&#8217;ve defined. These DAO layers then might call functions (stored procs) in the database that do the problematic mapping in an efficent relational language (after all it&#8217;s the direct representation of the target data format).</p>
<p>I&#8217;m not saying that you have to do the above in every case, or that an ORM is always wrong, but anyway the point is, ORM isn&#8217;t a magic bullet like any other technology you have to consider carefully. Your application doesn&#8217;t always need one by default.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.crazymcphee.net/x/2009/10/19/orm-is-dead-meme/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Systems versus Individuals and technical debt</title>
		<link>http://www.crazymcphee.net/x/2009/09/05/systems-versus-individuals-and-technical-debt/</link>
		<comments>http://www.crazymcphee.net/x/2009/09/05/systems-versus-individuals-and-technical-debt/#comments</comments>
		<pubDate>Fri, 04 Sep 2009 23:38:48 +0000</pubDate>
		<dc:creator>Scot Mcphee</dc:creator>
				<category><![CDATA[professional practice]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[emergent design]]></category>
		<category><![CDATA[methodology]]></category>
		<category><![CDATA[profession]]></category>
		<category><![CDATA[refactor]]></category>
		<category><![CDATA[technical debt]]></category>

		<guid isPermaLink="false">http://www.crazymcphee.net/x/?p=468</guid>
		<description><![CDATA[I kind of disagree with this picture by Josh Susser regarding the &#8220;circle of death&#8221; in terms of code quality and late night effort. It is right enough as far as it goes but it doesn&#8217;t go far enough. First up, the easy way out &#8211; take a day off, go for a walk in [...]]]></description>
			<content:encoded><![CDATA[<p>I kind of disagree with <a href="http://blog.hasmanythrough.com/2009/9/3/circle-of-death">this picture</a> by Josh Susser regarding the &#8220;circle of death&#8221; in terms of code quality and late night effort. It is right enough as far as it goes but it doesn&#8217;t go far enough.</p>
<p>First up, the easy way out &#8211; take a day off, go for a walk in the park, have a nice dinner, get a good nights sleep. You should always work to &#8220;sustainable progress&#8221; and yes this means every hour you work over 40 hours a week means your quality is steadily decreasing until some point where every extra hour you put will take two to fix it later (in other words, negative impact). Even just pair programming will help prevent this in the first place as long at least one of you isn&#8217;t operating on half the sleep they need. But ultimately, all of this just blames the individual, when really poor code quality and technical debt are much more a function of the management system, methodology, total sum of the choices by every on the team, etc. (For a start, why are you up late in the first place? Was that your choice, or an outside imposed deadline?).</p>
<p>As James Adam and &#8220;iSteve&#8221; point out in the comments &#8211; technical debt is different from just &#8220;buggy software&#8221; and in my experience it&#8217;s usually function of management or other types of systemic choices (and &#8220;systemic&#8221; includes you, the programmer as well everyone else). What it really does is trade <em>easy change now</em> for <em>even harder change later</em>. It wants that sweet sweet sugar hit straight away but forgets about the &#8220;sugar coma&#8221; that comes a few minutes afterwards. It defers &#8220;paying the piper&#8221; until tomorrow for that lovely tune today. James Adam rightly says in his comment this <em>can be a valid choice</em>, but all of the team have to be fully aware of the <em>consequences</em> of that choice. One of which is typically that the longer  you defer the payment, the more debt you&#8217;ll accumulate, until all you are doing is paying off the interest and not getting to the principal.</p>
<p>As &#8220;iSteve&#8221; says, management (and maybe &#8220;management&#8221; might mean just you telling yourself this in your head) always promises to &#8220;fix it later&#8221; and never does allow that. &#8220;Just make the hack&#8221; and gloss over the problem is a mantra that we&#8217;ve all heard before. Where it gets painful is where every change is now taking twice as long as it should because of the accumulation of hacks. Every single one one of us has been there before, and are probably in various levels of it right now.</p>
<p>In my view this is the much more insidious circumstance because it is <em>systemic</em>.  After all the solution to a bad day&#8217;s work because I was too tired to think properly is to simply get a good night&#8217;s sleep, roll back yesterday&#8217;s coding, and do it again today. All I&#8217;ve done is lost a day&#8217;s work.  However, an organisation is likely to have accumulated months if not years of organisational cruft that makes changing their context that much harder than just rolling back yesterday&#8217;s poor code and trying again &#8211; it requires commitment to change from everyone who counts in the first instance.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.crazymcphee.net/x/2009/09/05/systems-versus-individuals-and-technical-debt/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tapestry 5 web framework</title>
		<link>http://www.crazymcphee.net/x/2009/08/26/tapestry-5-web-framework/</link>
		<comments>http://www.crazymcphee.net/x/2009/08/26/tapestry-5-web-framework/#comments</comments>
		<pubDate>Wed, 26 Aug 2009 12:09:18 +0000</pubDate>
		<dc:creator>Scot Mcphee</dc:creator>
				<category><![CDATA[infrastructure and frameworks]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[technical]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[opensource]]></category>
		<category><![CDATA[tapestry]]></category>
		<category><![CDATA[tapestry5]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[web framework]]></category>

		<guid isPermaLink="false">http://www.crazymcphee.net/x/?p=443</guid>
		<description><![CDATA[Lately I&#8217;ve been writing a Tapestry 5 based web application. I&#8217;ve used it before for a smaller application but this is the first time I&#8217;ve used it on a larger project. In a number of ways it is a very powerful framework to write web applications. The basics of Tapestry is that it is a [...]]]></description>
			<content:encoded><![CDATA[<p>Lately I&#8217;ve been writing a <a href="http://tapestry.apache.org/tapestry5/" target="_blank">Tapestry 5</a> based web application. I&#8217;ve used it before for a smaller application but this is the first time I&#8217;ve used it on a larger project. In a number of ways it is a very powerful framework to write web applications.</p>
<p>The basics of Tapestry is that it is a component-based web framework. Just about everything, including web pages, are components. Components may contain other components. The way it works is very simple and quite elegant, once you get used to it and weaned off the big-XML-file style of configuring a web application.</p>
<p>When you start, you have two main Java packages that are created for you (if you use the maven archetype, otherwise you will create these packages yourself). If your package root is say &#8220;net.crazymcphee.webapp&#8221;, then your two packages are &#8220;net.crazymcphee.webapp.pages&#8221; and &#8220;net.crazymcphee.webapp.components&#8221;. To configure a Tapestry 5 project with maven <a href="http://tapestry.apache.org/tapestry5/quickstart/">use this command</a> and answer the prompts:</p>
<pre>mvn archetype:generate \</pre>
<pre>    -DarchetypeCatalog=http://tapestry.formos.com/maven-snapshot-repository</pre>
<p>Don&#8217;t use the one in the <a href="http://tapestry.apache.org/tapestry5/tutorial1/first.html">tutorial</a> as it will not work! This is an excellent illustration of the first and most serious problem that Tapestry 5 has: the documentation not only has massive lacunas, it is also sometimes wrong and not updated.</p>
<p>Now, any class that you create in the &#8220;pages&#8221; package will automatically become a page in your application. But these classes need not be very complex at all. For example:</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;">net.crazymcphee.webapp.pages</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.util.Collections</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.util.List</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.tapestry5.annotations.Persist</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.tapestry5.annotations.Property</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.tapestry5.ioc.annotations.Inject</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">net.crazymcphee.webapp.model.Person</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">net.crazymcphee.webapp.services.PersonService</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> Persons <span style="color: #009900;">&#123;</span>
&nbsp;
    @Inject
    <span style="color: #000000; font-weight: bold;">private</span> PersonService personService<span style="color: #339933;">;</span>
    @Property
    @Persist
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">List</span> persons<span style="color: #339933;">;</span>
    @Property
    @Persist
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">String</span> searchTerm<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #003399;">Object</span> onSubmitFromSearch<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        persons <span style="color: #339933;">=</span> personService.<span style="color: #006633;">findPersons</span><span style="color: #009900;">&#40;</span>searchTerm<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000000; font-weight: bold;">this</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #003399;">Object</span> onSubmitFromClear<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        persons <span style="color: #339933;">=</span> <span style="color: #003399;">Collections</span>.<span style="color: #006633;">EMPTY_LIST</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000000; font-weight: bold;">this</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>You can see that this class doesn&#8217;t extend any infrastructure classes and has quite a simple structure. This is a fully functional page with two actions &#8211; one populates a list, the other clears it.</p>
<p>Now, to explain just a little here; PersonService is injected by Tapestry, but you need to configure in your AppModule which implementation you want to use. You can also use it with Spring as your IOC container but the one that comes with Tapestry is perfectly good enough for most applications.</p>
<p>The List, persons, and the searchTerm parameters are marked as @Property (so we don&#8217;t need to add getters and setters) and also @Persist so that the variables are preserved from request to request.</p>
<p>The methods &#8220;onSubmitFromSearch&#8221; and &#8220;onSubmitFromClear&#8221; are using a convention &#8211; &#8220;onSubmit&#8221; will also work, but assuming (as is true in this case) that we may have multiple forms on the one page, each method will only be fired from the &#8220;search&#8221; form in one instance, and the &#8220;clear&#8221; form in the other. These names are not special, it&#8217;s just (as you&#8217;ll see below) the forms will have these two names. They could be &#8220;Bill&#8221; and &#8220;Ben&#8221; in which case the methods would be &#8220;onSubmitFromBill&#8221; and &#8220;onSubmitFromBen&#8221;.</p>
<p>You will also note that these methods return the same page instance, which tells Tapestry to re-render the same page, but if you wanted to forward onto another page, you would add a instance variable, mark it with an @InjectPage annotation, and return that instance variable (after initialising it in your &#8220;onSubmit&#8221; method) instead of just returning &#8220;this&#8221;.</p>
<p>This page Persons, is available at {application-context-path}/persons. But there is one other part of the puzzle &#8211; the actual view. As mentioned, Tapestry uses convention over configuration and in this case, the convention is that the Page markup must be named the same: Persons.tml. Here is the matching tml file for the class above;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Andale Mono; color: #2a00ff;"><span style="color: #008080;">&lt;</span><span style="color: #3f7f7f;">html</span><span style="color: #000000;"> </span><span style="color: #7f007f;">t:type</span><span style="color: #000000;">=</span>&#8220;layout&#8221;<span style="color: #000000;"> </span><span style="color: #7f007f;">title</span><span style="color: #000000;">=</span>&#8220;Peoples I Might Know&#8221;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Andale Mono; color: #7f007f;"><span style="color: #000000;"> </span>t:sidebarTitle<span style="color: #000000;">=</span><span style="color: #2a00ff;">&#8220;Current Time&#8221;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Andale Mono; color: #2a00ff;"><span style="color: #000000;"> </span><span style="color: #7f007f;">xmlns:t</span><span style="color: #000000;">=</span>&#8220;http://tapestry.apache.org/schema/tapestry_5_1_0.xsd&#8221;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Andale Mono; color: #2a00ff;"><span style="color: #000000;"> </span><span style="color: #7f007f;">xmlns:p</span><span style="color: #000000;">=</span>&#8220;tapestry:parameter&#8221;<span style="color: #008080;">&gt;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Andale Mono; color: #3f5fbf;">&lt;!&#8211; Most of the page content, including &lt;head&gt;, &lt;body&gt;, etc. tags, comes from Layout.tml &#8211;&gt;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Andale Mono; min-height: 14.0px;">
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Andale Mono; min-height: 14.0px;">
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Andale Mono; color: #2a00ff;"><span style="color: #008080;">&lt;</span><span style="color: #3f7f7f;">t:form</span><span style="color: #000000;"> </span><span style="color: #7f007f;">t:id</span><span style="color: #000000;">=</span>&#8220;search&#8221;<span style="color: #008080;">&gt;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Andale Mono; color: #2a00ff;"><span style="color: #000000;"> </span><span style="color: #008080;">&lt;</span><span style="color: #3f7f7f;">t:textfield</span><span style="color: #000000;"> </span><span style="color: #7f007f;">t:id</span><span style="color: #000000;">=</span>&#8220;searchTerm&#8221;<span style="color: #000000;"> </span><span style="color: #7f007f;">validate</span><span style="color: #000000;">=</span>&#8220;required&#8221;<span style="color: #000000;"> </span><span style="color: #7f007f;">size</span><span style="color: #000000;">=</span>&#8220;20&#8243;<span style="color: #008080;">/&gt;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Andale Mono; color: #2a00ff;"><span style="color: #000000;"> </span><span style="color: #008080;">&lt;</span><span style="color: #3f7f7f;">t:submit</span><span style="color: #000000;"> </span><span style="color: #7f007f;">t:id</span><span style="color: #000000;">=</span>&#8220;searchPeople&#8221;<span style="color: #000000;"> </span><span style="color: #7f007f;">value</span><span style="color: #000000;">=</span>&#8220;search&#8221;<span style="color: #008080;">/&gt;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Andale Mono; color: #3f7f7f;"><span style="color: #008080;">&lt;/</span>t:form<span style="color: #008080;">&gt;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Andale Mono; min-height: 14.0px;">
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Andale Mono; color: #2a00ff;"><span style="color: #008080;">&lt;</span><span style="color: #3f7f7f;">t:grid</span><span style="color: #000000;"> </span><span style="color: #7f007f;">source</span><span style="color: #000000;">=</span>&#8220;persons&#8221;<span style="color: #008080;">/&gt;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Andale Mono; min-height: 14.0px;">
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Andale Mono; color: #2a00ff;"><span style="color: #008080;">&lt;</span><span style="color: #3f7f7f;">t:form</span><span style="color: #000000;"> </span><span style="color: #7f007f;">t:id</span><span style="color: #000000;">=</span>&#8220;clear&#8221;<span style="color: #008080;">&gt;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Andale Mono; color: #2a00ff;"><span style="color: #000000;"> </span><span style="color: #008080;">&lt;</span><span style="color: #3f7f7f;">t:submit</span><span style="color: #000000;"> </span><span style="color: #7f007f;">t:id</span><span style="color: #000000;">=</span>&#8220;clearPeople&#8221;<span style="color: #000000;"> </span><span style="color: #7f007f;">value</span><span style="color: #000000;">=</span>&#8220;clear&#8221;<span style="color: #008080;">/&gt;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Andale Mono; color: #3f7f7f;"><span style="color: #008080;">&lt;/</span>t:form<span style="color: #008080;">&gt;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Andale Mono; min-height: 14.0px;">
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Andale Mono; color: #3f7f7f;"><span style="color: #008080;">&lt;/</span>html<span style="color: #008080;">&gt;</span></p>
<p>Yes, it&#8217;s that bloody simple. The first form fires the &#8220;onSubmitFromSearch&#8221; method (with a little bit of validation, done in javascript) and the second method clears the list. In-between, there is this <span style="color: #008080;">&lt;</span><span style="color: #3f7f7f;">t:grid</span><span style="color: #000000;"> </span><span style="color: #7f007f;">source</span><span style="color: #000000;">=</span>&#8220;persons&#8221;<span style="color: #008080;">/&gt; <span style="color: #000000;">business, which, if the &#8216;persons&#8217; variable in the page class is populated, will show a list of its contents! </span></span></p>
<p>To test our app, we can use the command-line &#8216;mvn clean jetty:run&#8217;. When Jetty has run up, then we can point our browser at the web app: http://localhost:8080/sample-webapp/Persons, and with any luck we will see the following:</p>
<p><a href="http://www.crazymcphee.net/x/wp-content/uploads/2009/08/Picture-1.png"><img style="border: 0px initial initial;" title="Initial View" src="http://www.crazymcphee.net/x/wp-content/uploads/2009/08/Picture-1-300x171.png" alt="Initial View" width="300" height="171" /></a></p>
<p>Now, by default, Tapestry creates the web app to use the template design as shown above. Of course, you can make it look completely some other way &#8211; or even use a totally different template if you want. The page template is just a component that&#8217;s included.</p>
<p>So if you enter in a search term and click the search button, you&#8217;d expect to see a result like this:</p>
<p><a href="http://www.crazymcphee.net/x/wp-content/uploads/2009/08/Picture-2.png"><img class="alignnone size-medium wp-image-452" title="Search Result" src="http://www.crazymcphee.net/x/wp-content/uploads/2009/08/Picture-2-300x174.png" alt="Search Result" width="300" height="174" /></a></p>
<p>As you can see, the list is automatically populated with the details returned from the service method (in this particular instance, this are just a canned response, but normally of course they&#8217;d be the result of a database or a web service call of some type).</p>
<p>When you click the clear button, the list is cleared as you&#8217;d expect:</p>
<p><a href="http://www.crazymcphee.net/x/wp-content/uploads/2009/08/Picture-3.png"><img class="alignnone size-medium wp-image-453" title="Clear button result" src="http://www.crazymcphee.net/x/wp-content/uploads/2009/08/Picture-3-300x175.png" alt="Clear button result" width="300" height="175" /></a></p>
<p>Now, here&#8217;s a really powerful feature I find in Tapestry. Let&#8217;s say our automated acceptance tests assert that when the &#8216;Clear&#8217; button is pressed, the Search box as well as the persons list is cleared. What Tapestry allows us to to do, is keep Jetty running, edit the files in the IDE, and re-run the tests against the running app without restarting! We edit our method:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">    <span style="color: #003399;">Object</span> onSubmitFromClear<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        persons <span style="color: #339933;">=</span> <span style="color: #003399;">Collections</span>.<span style="color: #006633;">EMPTY_LIST</span><span style="color: #339933;">;</span>
        searchTerm<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000000; font-weight: bold;">this</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span></pre></div></div>

<p>In this case I&#8217;ve also added a bit of space around the clear button in the template as well:</p>
<p><a href="http://www.crazymcphee.net/x/wp-content/uploads/2009/08/Picture-4.png"><img class="alignnone size-medium wp-image-454" title="Picture 4" src="http://www.crazymcphee.net/x/wp-content/uploads/2009/08/Picture-4-300x175.png" alt="Picture 4" width="300" height="175" /></a></p>
<p>And now our failing test will pass.</p>
<p>Editing files like this in the running web app only works for Pages and I think Components. If I had to change the service or model classes I&#8217;d have to restart, but &#8220;mvn jetty:run&#8221; isn&#8217;t very a heavyweight process.</p>
<p>As I said above, Tapestry&#8217;s not perfect: it&#8217;s major flaw is the poor documentation. Convention-over-configuration is easy to grok &#8211; if you know the convention. If you don&#8217;t and the documentation doesn&#8217;t tell you, and you can&#8217;t find a sample of what you need, it can be very frustrating. There is an excellent user list though.</p>
<p>Its other major flaw may be the stability of the API. Tapestry 5 is different (and incompatible) from Tapestry 4 is different from Tapestry 3. But so far I&#8217;ve used it on a couple of projects and I&#8217;m really enjoying it. I really hate the oodles of XML boilerplate and massive amounts of configuration found in Spring and I find myself somewhat reluctant to use it unless I really have to. Tapestry solves for me a range of different problems and mostly it presents a very elegant way to create a componentised web application. You might like to give it a try.</p>
<p>Attached is the sample code used above. It took me about 10 minutes to write (far shorter than it took me to write this blog entry!) - <a href="http://www.crazymcphee.net/x/wp-content/uploads/2009/08/sample-webapp.tar.gz">sample-webapp.tar bundle</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.crazymcphee.net/x/2009/08/26/tapestry-5-web-framework/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>That feature is trivial</title>
		<link>http://www.crazymcphee.net/x/2009/07/31/that-feature-is-trivial/</link>
		<comments>http://www.crazymcphee.net/x/2009/07/31/that-feature-is-trivial/#comments</comments>
		<pubDate>Fri, 31 Jul 2009 07:00:09 +0000</pubDate>
		<dc:creator>Scot Mcphee</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[features]]></category>
		<category><![CDATA[stories]]></category>

		<guid isPermaLink="false">http://www.crazymcphee.net/x/?p=431</guid>
		<description><![CDATA[How many times as a developer do we get asked by our clients to create a new story to implement a feature assessed by the client as &#8220;trivial&#8221;? How many times do we get surprised by their reactions when we give them our story estimate. I&#8217;ve seen developers give this sort of optimistic estimate too, [...]]]></description>
			<content:encoded><![CDATA[<p>How many times as a developer do we get asked by our clients to create a new story to implement a feature assessed by the client as &#8220;trivial&#8221;? How many times do we get surprised by their reactions when we give them our story estimate. I&#8217;ve seen developers give this sort of optimistic estimate too, without considering all the wrinkles, like error handling, alternative usage scenarios, abusive usage &amp; security concerns, and all sorts of other issues that can be way bigger than the &#8220;happy-path&#8221; through the code. Here&#8217;s a neat little article from Brent Simmons that summarises the sort of user experience and technical design that has to go into the &#8220;Oh, it&#8217;s easy&#8221; feature.</p>
<p><a href="http://inessential.com/2009/07/30/anatomy_of_a_feature">inessential.com: Anatomy of a feature</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.crazymcphee.net/x/2009/07/31/that-feature-is-trivial/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>&#8216;//TODO&#8217; considered harmful</title>
		<link>http://www.crazymcphee.net/x/2009/06/06/todo-considered-harmful/</link>
		<comments>http://www.crazymcphee.net/x/2009/06/06/todo-considered-harmful/#comments</comments>
		<pubDate>Fri, 05 Jun 2009 14:14:12 +0000</pubDate>
		<dc:creator>Scot Mcphee</dc:creator>
				<category><![CDATA[professional practice]]></category>
		<category><![CDATA[tools and techniques]]></category>
		<category><![CDATA[agile]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[methodology]]></category>
		<category><![CDATA[profession]]></category>
		<category><![CDATA[refactor]]></category>

		<guid isPermaLink="false">http://www.crazymcphee.net/x/?p=386</guid>
		<description><![CDATA[Yesterday I said that developers should start being a little more militant about the craftsmanship of their code, i.e. pushing back on broken methodology that demands poorly-built code  be released into the wild. This sort of code is always inherently fragile and will break your software if it has not already. Today I just want [...]]]></description>
			<content:encoded><![CDATA[<p><a title="Just Say No (to broken processes)" href="http://www.crazymcphee.net/x/2009/06/05/just-say-no-to-broken-processes/">Yesterday I said that developers should start being a little more militant about the craftsmanship of their code</a>, i.e. pushing back on broken methodology that demands poorly-built code  be released into the wild. This sort of code is always inherently fragile and will break your software if it has not already.</p>
<p>Today I just want to meditate on a code artifact that often manifests itself in such environments. I speak of the comment //TODO seen frequently in such code. The idea that future &#8220;refactoring&#8221; goes on the &#8220;todo&#8221; list in such an environment is completely broken. An environment that allows that to happen means it will never get done. Do it now, or don&#8217;t do it. <a title="C2 Wiki - ToDo comments considered harmful" href="http://c2.com/cgi/wiki?TodoCommentsConsideredHarmful" target="_self">TODO is considered harmful</a>.</p>
<p>I have come around to the view that &#8216;//TODO&#8217; comments should make a build fail. Either:</p>
<ol>
<li>It is a future story yet to be implemented and placed into the backlog,</li>
<li>It is work in progress (and by definition doesn&#8217;t need a TODO because everything still needs to be &#8216;done&#8217;), or,</li>
<li>It is done, as in DONE-done, and therefore the story is complete and there&#8217;s nothing left &#8220;TO DO&#8221;.</li>
</ol>
<p>In other words, &#8220;//TODO&#8221; is a indicator of a process that&#8217;s not letting developers get to &#8220;done&#8221;. Identify the problem, propose a counter-measure and fix the process that stopping you from getting to completion.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.crazymcphee.net/x/2009/06/06/todo-considered-harmful/feed/</wfw:commentRss>
		<slash:comments>23</slash:comments>
		</item>
	</channel>
</rss>
