<?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; tools and techniques</title>
	<atom:link href="http://www.crazymcphee.net/x/category/tech/programming-tech/tools-and-techniques/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>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>Running Oracle XE on Mac OSX using virtualised JeOS</title>
		<link>http://www.crazymcphee.net/x/2009/08/27/oracle-xe-on-mac-osx/</link>
		<comments>http://www.crazymcphee.net/x/2009/08/27/oracle-xe-on-mac-osx/#comments</comments>
		<pubDate>Thu, 27 Aug 2009 06:30:20 +0000</pubDate>
		<dc:creator>Scot Mcphee</dc:creator>
				<category><![CDATA[infrastructure and frameworks]]></category>
		<category><![CDATA[technical]]></category>
		<category><![CDATA[tools and techniques]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[macintosh]]></category>
		<category><![CDATA[oracle]]></category>
		<category><![CDATA[oracle-xe]]></category>
		<category><![CDATA[osx]]></category>
		<category><![CDATA[unix]]></category>
		<category><![CDATA[virtualisation]]></category>
		<category><![CDATA[vmware]]></category>

		<guid isPermaLink="false">http://www.crazymcphee.net/x/?p=462</guid>
		<description><![CDATA[So Oracle in its wisdom doesn&#8217;t have Mac OSX version of its free database. This is of course really annoying to Mac users who need to develop systems that use Oracle databases &#8211; Oracle XE is a great little database especially for development environments. Recently I found myself in a situation where I would be [...]]]></description>
			<content:encoded><![CDATA[<p>So Oracle in its wisdom doesn&#8217;t have Mac OSX version of its free database. This is of course really annoying to Mac users who need to develop systems that use Oracle databases &#8211; Oracle XE is a great little database especially for development environments. Recently I found myself in a situation where I would be needing to bind a Hibernate object to a PL/SQL function in the target Oracle database rather than a table or view per se. As the function call is database specific, when developing the application I needed to use an Oracle database and could use e.g. HSQL or MySql as a substitute Oracle DB for development purposes. Oracle XE is a great way out here because it fully supports PL/SQL packages and functions and procedures.</p>
<p>I was off the client site so I couldn&#8217;t rely on a fast connection to their development databases. I just wrote a dummy function that was called the same as the real function with the same input and output parameters and instead of the complex function body it just wrapped a simple mock table of test data. Problem solved, Oracle XE to the rescue. But first you have get Oracle XE running on your Mac, this is what the rest of this article is about, because you can&#8217;t just download an Oracle XE edition for the Macintosh.</p>
<h3>Virtualisation is great &#8211; use a Linux VM</h3>
<p>However modern Virtualisation is your saviour. Put simply, you can use a virtualisation tool like Parallels, or my choice, VMWare Fusion, to run a virtualised version of Linux that contains the Oracle XE instance.</p>
<p>Because VMs can waste a bit of your local resources, luckily there is a specialised version of Ubuntu designed for running as a virtualised machine of this type. Its called JeOS (pron. <em>Juice</em>, apparently). It doesn&#8217;t have an X-window environment, just the shell, so it&#8217;s pretty lightweight and can run, with Oracle XE, in less than 512MB of memory. Perfect for getting a copy of Oracle XE onto your Macbook Pro.</p>
<p>It will however, eat up a couple of gigabytes of disk space, up to the maximum limit you choose for your disk size in the VMWare configuration. However it will only use the current amount of disk needed, as VMWare will expand the size of the image as needed (I&#8217;ll just assume that Parallels does something similar).</p>
<h3>Setting it up &#8211; basic instructions</h3>
<p><a href="http://tedwise.com/2008/10/03/running-oracle-for-development-on-the-mac/">This page here</a> &#8211; has a great set of instructions for getting JeOS installed and configured with Oracle XE on it. Follow the instructions there <em>exactly</em> &#8211; but only to the point where you install and configure Oracle XE &#8211; don&#8217;t go further than that.</p>
<p>Make sure you configure plenty of swap space as outlined in the instructions.</p>
<blockquote>
<h3>Setting it up on standard Ubuntu/Debian</h3>
<p>If you are running a full Ubuntu or other Debian based instance, the instructions are somewhat simpler. Install it as per normal in your VM. But make sure your swap space is twice the memory you have assigned to the VM! Oracle XE demands things to be like that.</p>
<p>Add</p>
<pre>deb http://oss.oracle.com/debian unstable main non-free</pre>
<p>to /etc/apt/sources.list and then:</p>
<pre>$ wget http://oss.oracle.com/el4/RPM-GPG-KEY-oracle  -O- | sudo apt-key add -
$ sudo apt-get update
$ sudo apt-get install oracle-xe</pre>
<p>These instructions were cribbed from <a href="http://www.oracle.com/technology/tech/linux/install/xe-on-kubuntu.html">here</a>.</p></blockquote>
<h3>After installing and configuring Oracle XE</h3>
<p>After you run the XE configuration (&#8216;$&#8217; represents the Unix shell prompt and should not be typed);</p>
<pre>$ sudo /etc/init.d/oracle-xe configure</pre>
<p>If you&#8217;re running on JeOS don&#8217;t yet make the machine &#8220;headless&#8221;! Or you might find there are issues with the &#8220;Apex&#8221; application. The problem is that the Apex application, which is a useful web-based administration program for Oracle XE (especially for developers who don&#8217;t want to be forced to use sqlplus for all their database administration), will only allow connections from localhost &#8211; and you don&#8217;t have X-window, or a browser, to access it (I don&#8217;t know if lynx will work with Apex and I wasn&#8217;t going to try).</p>
<h3>Get SSH installed</h3>
<p>First get SSH installed in JeOS so you can get to the command prompt remotely:</p>
<pre>$ sudo apt-get install ssh</pre>
<h3>Find out the VM&#8217;s IP address</h3>
<p>Now, if you type <em>ifconfig</em> (<em>/sbin/ifconfig</em> if that&#8217;s not found on your path) you will be able to determine the IP address of your VM running on your Macintosh. At this point you can connect to the VM using ssh from a Macintosh terminal window:</p>
<pre>$ ssh username@ip_address</pre>
<p>Actually, at this point you can go ahead and make the machine headless, if you want. I would recommend not to do that until you&#8217;re sure of everything you&#8217;ve configured.</p>
<h3>Configure environment to run sqlplus</h3>
<p>After you&#8217;ve logged back into the running Linux VM using ssh from the Mac Terminal, the next thing is you&#8217;ve got to get sqlplus access working to the XE instance you installed. Funnily enough, although the .deb file that is installed off the Oracle site creates an oracle user, it doesn&#8217;t in any way set that user up so you can use the command line tools. SO you can&#8217;t just su &#8211; oracle and get a functional environment.</p>
<p>Anyway, you will need to do two things to your environment; add the <em>ORACLE_HOME</em> environment variable and set up your <em>PATH</em> so it can find <em>sqlplus</em>.</p>
<pre>$ export ORACLE_HOME=/usr/lib/oracle/xe/app/oracle/product/10.2.0/server
$ export PATH=${PATH}:${ORACLE_HOME}/bin</pre>
<p>You should add these two lines to your <em>.profile</em> or <em>.bash_profile</em> file &#8211; probably best for the &#8216;oracle&#8217; user that the installation will have created. But you can actually set this up for any regular user that you configure in this VM. You can also just type them at the command line to get them in your current environment, if you have to.</p>
<h3>Configure Apex to accept non-localhost connections</h3>
<p>The web-based administration software for XE, called &#8220;APEX&#8221;, only binds to <em>localhost</em>. This is a big hassle if your VM copy of Linux (like JeOS) doesn&#8217;t have a GUI, because you don&#8217;t have a browser (lynx/links excluded, I did not try those!).  However, you can make Apex bind to the &#8220;external&#8221; IP address for your VM, but you&#8217;ll need to use <em>sqlplus</em>.</p>
<p>To run <em>sqlplus</em>, do the following:</p>
<pre>$ sqlplus system@XE
  Enter password:</pre>
<p>Enter the password you specified at the &#8216;oracle-xe configure&#8217; step above.</p>
<p>At the SQL prompt, enter the following command:</p>
<pre>SQL&gt; EXEC DBMS_XDB.SETLISTENERLOCALACCESS(FALSE);</pre>
<p>Now you&#8217;ll have to stop and start Oracle to make the configuration active:</p>
<pre>$ sudo /etc/init.d/oracle-xe restart</pre>
<p>After which, if you type</p>
<pre>$ netstat -tna</pre>
<p>You should find a line</p>
<pre>tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN</pre>
<p>This indicates a process is listening to the port 8080 on all IP addresses for connections coming from any other IP address. Assuming you specified port 8080 at the &#8216;oracle-xe configure&#8217; step. Sometimes I use 8888 especially if I have a Tomcat instance in the same VM, as Tomcat will also like to run on 8080 and I&#8217;d prefer it if it did.</p>
<h3>Test and use Apex</h3>
<p>Test this connection in your browser, in my case, the address was 10.1.2.17, but you will have to substitute your own VM&#8217;s IP address &#8211; <em>http://10.1.2.17:8080/apex</em>. I like to make an /etc/hosts entry that points to this address as &#8216;oracleXE&#8217;. That way I can use a symbolic name in my jdbc connection strings and actually switch which instance of XE I am using depending which VM I&#8217;ve fired up without editing the jdbc configuration of the application under development &#8211; I just change the /etc/hosts entry instead.</p>
<p>Anyway once you connect to apex you can login using the user name and password you set up during your XE install and configuration process (same as you used for <em>sqlplus</em>). The users will be sys and system, you can use them to create new users to contain your databases for development.</p>
<p>The same IP address as above will be used to connect to your Oracle database from the programs you are developing. The default port should be 1521 and the SID should be XE.</p>
<p>Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.crazymcphee.net/x/2009/08/27/oracle-xe-on-mac-osx/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>
		<item>
		<title>JAOO Brisbane 2009 highlights and thoughts</title>
		<link>http://www.crazymcphee.net/x/2009/05/13/jaoo-brisbane-2009-highlights-and-thoughts/</link>
		<comments>http://www.crazymcphee.net/x/2009/05/13/jaoo-brisbane-2009-highlights-and-thoughts/#comments</comments>
		<pubDate>Wed, 13 May 2009 12:55:54 +0000</pubDate>
		<dc:creator>Scot Mcphee</dc:creator>
				<category><![CDATA[architecture]]></category>
		<category><![CDATA[business]]></category>
		<category><![CDATA[professional practice]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[rants]]></category>
		<category><![CDATA[tools and techniques]]></category>
		<category><![CDATA[agile]]></category>
		<category><![CDATA[jaoo]]></category>
		<category><![CDATA[methodology]]></category>
		<category><![CDATA[profession]]></category>
		<category><![CDATA[scrum]]></category>
		<category><![CDATA[test first]]></category>
		<category><![CDATA[tools]]></category>
		<category><![CDATA[xp]]></category>

		<guid isPermaLink="false">http://www.crazymcphee.net/x/?p=356</guid>
		<description><![CDATA[I spent last Monday and Tuesday at the JAOO conference in Brisbane, and I have a couple of things which I want to say I thought interesting. (&#8216;JAOO&#8217; btw, because I see people asking about it on Twitter, is pronounced a bit like &#8220;yow&#8221; but with the &#8220;j&#8221; from German/Dutch like &#8220;jah&#8221;). Firstly, I found [...]]]></description>
			<content:encoded><![CDATA[<p>I spent last Monday and Tuesday at the <a href="http://www.jaoo.com.au/" target="_blank">JAOO</a> conference in Brisbane, and I have a couple of things which I want to say I thought interesting. (&#8216;JAOO&#8217; btw, because I see people asking about it on Twitter, is pronounced a bit like &#8220;yow&#8221; but with the &#8220;j&#8221; from German/Dutch like &#8220;jah&#8221;).</p>
<p>Firstly, I found the second day much better than the first. I did see <a href="http://www.michaelnygard.com/" target="_blank">Michael Nygard&#8217;s</a> two talks on Monday morning and got a lot a lot of useful information from those. Titled &#8216;Failure comes in flavours&#8217; the first was a great overview of the types of failure that applications running in production encounter, the second ways to avoid those failure modes. Basically it&#8217;s how many of the non-functional requirements can eat your app (and even the entire integration if you let the failure propagate easily) if you don&#8217;t give careful consideration to them. He&#8217;s got a <a href="http://www.pragprog.com/titles/mnee/release-it" target="_blank">book</a> so I&#8217;m going to check that out next.</p>
<p>The first day for me was severely spoilt by a poor vendor presentation (hint: one that is <em>not</em> Oracle, not that they would have necessarily done any better), which I should have known better to avoid. I already swim in the BPEL/BPM/SOA soup, I fully understand just how broken it is as an actual development concept (e.g. anti-test-first to name just <em>one</em>). I was fooled by the title to thinking maybe it had some insights to avoid the worst of these busted concepts, but no, the vendor&#8217;s tooling is all the rage if you drink the poor-tasting conceptual kool-aid. This stuff is marketed at managers and non-coding architects who choose to buy this stuff then dump it from a very great height into the laps of the poor developers who have to mangle it into a deliverable system (half the time with a development budget just a tenth the cost of the licence). Anyway back to the good stuff.</p>
<p>Mike Cannon-Brookes from <a href="http://www.atlassian.com/" target="_blank">Atlassian</a> (which makes great development tools, highly recommended) gave a mostly great closing speech on the first day which made me think about a couple of things. It wasn&#8217;t until the next morning however that it crystallised in my mind. It&#8217;s a bit of a minor criticism.</p>
<p>Mike threw out a minor line, an aside really, talking about Atlassian&#8217;s agile development methodology, and basically that said, people who say &#8216;you must do this&#8217; are wrong, because they miss your context. Here &#8216;this&#8217; is some type of agile process artefact like  maybe, pairing, or estimating in story points, or whatever. Well, it&#8217;s wrong and on two counts. The first count I realised just after the talk but couldn&#8217;t articulate it correctly in semi-drunken conversation. That first count is very simple. Mike&#8217;s timeline on his Atlassian experience has him, if I recall correctly, starting his company and creating the great tool Jira, in his early twenties. Now as he dissed &#8220;old people&#8221; in his talk I&#8217;m going to give some back. In your twenties you&#8217;ve got no idea <em>what works</em>, in a general sense. You might know (or think you know) <em>what works for you</em>, but that&#8217;s a completely different kettle of fish to <em>what works generally</em>. Why not? The word is <em>experience</em>. Its not until you reach &#8230; oh &#8230; I&#8217;ll say around 35 (and so maybe lose the capacity to build technical innovation, perhaps, as Mike asserted) that you can have real insights into <em>process</em> and <em>people</em>. It&#8217;s just because at this point, you just have not got enough <em>practice</em> at it (see Malcolm Gladwell&#8217;s recent book for some basic data about the power of practice).</p>
<p>But the bigger point I think is the word <em>context</em>. The phrase &#8216;my context is different&#8217;, is this classic phrase which <em>really</em> means &#8216;that won&#8217;t work here&#8217; and <em>that</em> really means, <em>I don&#8217;t want to change</em>. As a consultant , you hear this stuff all the time: &#8230; &#8220;We&#8217;re unique, our company is not like those other companies. We can&#8217;t do that here. Detailed estimates are really the most important part of the development process. The budget and the features must be fixed. We have a reporting process that allows the budget and features to be fixed. Pair programming doubles the time it takes to deliver the features. Quality doesn&#8217;t matter. Technical quality is  a business decision. The business are too busy to talk to you.&#8221; &#8230;  And a whole other other bunch of <em>epic agile fail</em>. Someone&#8217;s context is <em>exactly</em> why they aren&#8217;t as agile as their competitors and are looking at using &#8216;agile development&#8217; to help save them &#8230; but as long as they insist on <em>my context trumps all</em>, they will only get a fractional improvement and not an order-of-magnitude one. But Atlassian make great products, so it doesn&#8217;t mean you <em>have</em> to have &#8216;scrum&#8217;, or &#8216;XP&#8217; to do that, the greatness I guess, is orthogonal. However if you are looking to &#8216;do agile&#8217;, then <em>do agile</em>. Pick a method like Scrum or XP then do it all. How do you know pair programming will fail in your organisation if you don&#8217;t try it first? You don&#8217;t. Do it like it says to do it (e.g. the Kent Beck books) and after a few months experience for your team, use the lessons from the retrospectives that the team has discovered to improve the process. <em>Do not cripple the process with your &#8216;context&#8217; before you even try</em>.</p>
<p>And right on cue, on the second day along comes <a href="http://steve.cogentconsulting.com.au/" target="_blank">Steve Hayes</a> with a <em>great</em> presentation on exactly this topic: &#8220;How your choices affect your agility&#8221;. Steve is a fantastic speaker, entertaining and pretty insightful too I thought. I rated his talk the best talk of the conference. He said he got lots of red cards (participants could rate each talk as green==good, yellow==ok, red==bad) in his Sydney session &#8211; <em>what is the matter with your people</em>? It was a great talk. I loved the part about <em>naivety</em>. To propose a solution from the most naive perspective possible, and  what an <em>epic win </em>it is when a customer says &#8220;ok&#8221;! It means I understand the problem! I even tried this today with my client, I didn&#8217;t get the instant &#8220;OK&#8221; but working from the basis of that incredibly naive solution we did manage to eventually envisage <em>the simplest thing that could possibly work.</em> And I love that. So thanks tons for that insight, Steve!</p>
<p>Another great talk on the second day was <a href="http://www.lindarising.org/" target="_blank">Linda Rising&#8217;s</a> &#8216;Deception and Estimation&#8217; talk. Turns out (via psychology and evolutionary biology) we engage not in <em>rational</em> decision making but in <em>emotional</em> choices <em>all the time</em>. All choice is emotional. So we engage ourselves in self-deception <em>all the time</em>. And none of this is <em>bad</em> &#8230; <em>it&#8217;s good</em>. People who don&#8217;t engage in this constant self-deception are generally clinically insane. So get over it, and yourself, and when you&#8217;re estimating (and from the sounds of it, doing any sort of major-impact decision making) and get as <em>many perspectives as you can</em> from the most diverse range of people you can manage (to avoid <em>groupthink</em>, which is I guess, the situation where everyone&#8217;s self-deceptions all align). <a href="http://en.wikipedia.org/wiki/Joshua_Bloch" target="_blank">Joshua Bloch&#8217;s</a> second-day keynote was also highly worthy of praise. Good insight and excellent effective code examples (yes, in a <em>keynote</em>). Also worth the greatly discounted entry ticket price was the many interesting conversations I had with past colleagues and new friends on many different development issues.</p>
<p>In short, JAOO was generally of very high quality and I hope is keeps coming to Brisbane! Will definitely be going next year. Many thanks to all the organisers, presenters and sponsors.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.crazymcphee.net/x/2009/05/13/jaoo-brisbane-2009-highlights-and-thoughts/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Building Oracle 10g portlets in a continuous integration environment</title>
		<link>http://www.crazymcphee.net/x/2009/04/29/building-oracle-10g-portlets-in-a-continuous-integration-environment/</link>
		<comments>http://www.crazymcphee.net/x/2009/04/29/building-oracle-10g-portlets-in-a-continuous-integration-environment/#comments</comments>
		<pubDate>Wed, 29 Apr 2009 07:15:37 +0000</pubDate>
		<dc:creator>Scot Mcphee</dc:creator>
				<category><![CDATA[professional practice]]></category>
		<category><![CDATA[tools and techniques]]></category>
		<category><![CDATA[build]]></category>
		<category><![CDATA[continuous integration]]></category>
		<category><![CDATA[jsr168]]></category>
		<category><![CDATA[oracle]]></category>
		<category><![CDATA[portal]]></category>
		<category><![CDATA[tools]]></category>
		<category><![CDATA[wizards considered harmful]]></category>

		<guid isPermaLink="false">http://www.crazymcphee.net/x/?p=336</guid>
		<description><![CDATA[Ignoring all the hints (to use wizards and manual deployments) from the Oracle information as to how to go about creating JSR168 portlets for the Oracle 10g Portal server, we have successfully designed a continuous integration environment for the Oracle portal environment for a client. The Oracle 10g portal server is the old-school Oracle app-server [...]]]></description>
			<content:encoded><![CDATA[<p>Ignoring all the hints (to use wizards and manual deployments) from the Oracle information as to how to go about creating JSR168 portlets for the Oracle 10g Portal server, we have successfully designed a continuous integration environment for the Oracle portal environment for a client. The Oracle 10g portal server is the old-school Oracle app-server portal environment, not the BEA environment. As such it&#8217;s pretty old school (the database is the World), but it did surprise us with a command line utility (&#8216;<em>dcmctl</em>&#8216;) that allows us to programmatically deploy components such as portlet WARs into the application server using nothing but simple shell scripts. Unfortunately no such programmatic control has been found yet for the actual portal configuration, but we are working on that (if you know how to programmatically control the configuration of an Oracle 10g Portal with the command line please leave a comment!).</p>
<p>Simply put, using nothing but a <em>/bin/bash</em> script and <em>wget</em> we scrape the latest version of the relevant artefacts from the Artifactory Maven repository. These artefacts are deployed (published) into the repository by the Hudson continuous integration build.</p>
<p>As they say, a picture tells a thousand words and I&#8217;ve included a schematic of the environment we have created below (image links to PDF).</p>
<p> </p>
<p><a href="http://www.crazymcphee.net/x/wp-content/uploads/2009/04/build-process.pdf"><img class="alignnone size-full wp-image-338" title="build-process" src="http://www.crazymcphee.net/x/wp-content/uploads/2009/04/build-process.png" alt="build-process" width="418" height="281" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.crazymcphee.net/x/2009/04/29/building-oracle-10g-portlets-in-a-continuous-integration-environment/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Money-Is-Money v0.15 with added maven repository</title>
		<link>http://www.crazymcphee.net/x/2009/04/17/money-is-money-v015-with-added-maven-repository/</link>
		<comments>http://www.crazymcphee.net/x/2009/04/17/money-is-money-v015-with-added-maven-repository/#comments</comments>
		<pubDate>Fri, 17 Apr 2009 06:54:17 +0000</pubDate>
		<dc:creator>Scot Mcphee</dc:creator>
				<category><![CDATA[tools and techniques]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[library]]></category>
		<category><![CDATA[maven]]></category>
		<category><![CDATA[money]]></category>
		<category><![CDATA[opensource]]></category>
		<category><![CDATA[svn]]></category>

		<guid isPermaLink="false">http://www.crazymcphee.net/x/?p=322</guid>
		<description><![CDATA[In the course of an assignment for a client I&#8217;ve been giving Artifactory a good going-over. Artifactory is a Maven repository and mirror and is pretty cool and easy to set up &#8211; just drop the WAR file into a running Tomcat instance. On my Mac I ran it under Tomcat 6.0.18 with Java 5, [...]]]></description>
			<content:encoded><![CDATA[<p>In the course of an assignment for a client I&#8217;ve been giving <a title="Artifactory website" href="http://www.jfrog.org/products.php" target="_blank">Artifactory</a> a good going-over. Artifactory is a Maven repository and mirror and is pretty cool and easy to set up &#8211; just drop the WAR file into a running Tomcat instance. On my Mac I ran it under Tomcat 6.0.18 with Java 5, and on my personal Linux box (Ubuntu) I ran it with Tomcat 5.5 and Java 6. All is pretty sweet and it is fairly trivial to get Maven set up to use it. It&#8217;s just a matter of overriding the &#8216;central&#8217; repository in your <em>~/.m2/settings.xml</em> to point to you new local copy &#8211; by default it mirrors several useful repositories as well as the default one. Adding security (such as public read-only access and username/password for deployment of artefacts) takes only a few minutes on top of that.</p>
<p>In the course of all this testing though I thought it best to use it in something like real anger with the Maven release plugin rather than my rather artificial usage scenario I was building up between my two development machines.</p>
<p>As a result of all that I&#8217;ve released a version of my Monetary library, money-is-money. The version is 0.15 and the Maven repository for it can be found at <a title="Maven respoitory" href="http://modular.autonomous.org:80/artifactory-2.0.5/libs-releases-local/">http://modular.autonomous.org:80/artifactory-2.0.5/libs-releases-local</a></p>
<p>If you want to check the source code out with SVN out the release is at <em>http://crazymcphee.net/svn/money/tags/money-is-money-0.15</em> and the latest trunk at <em>http://crazymcphee.net/svn/money/trunk</em> (which at the time of writing is the same as the release of course, except it generates 0.16-SNAPSHOT).</p>
<p>To include it into your Maven POM you&#8217;ll have to add my respository 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.15&lt;/version&gt;
&lt;/dependency&gt;</pre>
<p>After that Maven should fetch the artifact from my repository automatically for you. Money-Is-Money is deliberately designed to void any external dependencies on anything other than Java libs, except for JUnit which only matters if you want to build from source. For more information please see <a href="http://www.crazymcphee.net/x/2009/02/11/money-is-money/" target="_self">this post</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.crazymcphee.net/x/2009/04/17/money-is-money-v015-with-added-maven-repository/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
