<?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>edave.net</title>
	<atom:link href="http://www.edave.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.edave.net</link>
	<description>The primarily Javascript related blog of Dave Elkan</description>
	<lastBuildDate>Sun, 13 May 2012 21:30:55 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Introducing the Node.js Hogan Template Compiler module</title>
		<link>http://www.edave.net/2012/05/13/hogan-template-compiler-module/</link>
		<comments>http://www.edave.net/2012/05/13/hogan-template-compiler-module/#comments</comments>
		<pubDate>Sun, 13 May 2012 04:44:57 +0000</pubDate>
		<dc:creator>dave</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[node.js]]></category>

		<guid isPermaLink="false">http://www.edave.net/?p=321</guid>
		<description><![CDATA[In my previous post I described why you should pre-compile your templates on the server. I&#8217;ve just created the Hogan Template Compiler module which makes it easier to implement the entire process. It&#8217;s a simple framework-agnostic npm module which: Pre-Compiles mustache templates and partials on the server. Stringifies partials for use in the browser. How [...]]]></description>
			<content:encoded><![CDATA[<p>In my <a href="http://www.edave.net/2012/02/25/sharing-pre-compiled-templates-between-server-and-client-with-hogan-js/">previous post</a> I described why you should pre-compile your templates on the server.</p>
<p>I&#8217;ve just created the <a href="https://github.com/dave-elkan/hogan-template-compiler">Hogan Template Compiler</a> module which makes it easier to implement the entire process. It&#8217;s a simple framework-agnostic npm module which:</p>
<ul>
<li>Pre-Compiles mustache templates and partials on the server.</li>
<li>Stringifies partials for use in the browser.</li>
</ul>
<h3>How the module works</h3>
<div>The diagram below describes how you can compile your templates <strong>once</strong> on the server and then re-use them in the browser. This means that the browser never has to compile the templates.</div>
<div><a href="http://www.edave.net/wp-content/uploads/2012/05/Screen-Shot-2012-05-13-at-2.23.08-PM.png"><img class="aligncenter size-full wp-image-326" title="Screen Shot 2012-05-13 at 2.23.08 PM" src="http://www.edave.net/wp-content/uploads/2012/05/Screen-Shot-2012-05-13-at-2.23.08-PM.png" alt="" width="709" height="475" /></a></div>
<p style="text-align: center;">
<ol>
<li>The Hogan Template Compiler  reads the templates and partials</li>
<li>The browser requests the complete HTML page (including server-rendered partials).</li>
<li>The browser loads the pre-compiled partials (in the form of a simple JavaScript file).</li>
<li>The browser renders additional pre-compiled partials when needed.</li>
</ol>
<h3><span style="text-align: left;">Why pre-compiling and sharing templates is a good idea</span></h3>
<p>There are heaps of benefits to pre-compiling and sharing templates! The biggest is performance.</p>
<h4>Performance</h4>
<p>Ajax onDomReady is suboptimal. It&#8217;s faster for the browser to display your web page if your server renders the entirety of every HTML response. This frees the browser from doing any additional ajax requesting or template compiling and rendering.</p>
<p>As an example, as it stands currently, if you go to <a href="https://twitter.com/#!/edave" target="_blank">someone&#8217;s twitter page</a> then the static HTML file you&#8217;re served from the server is your own tweet stream, not of the user you&#8217;ve requested. The other user&#8217;s tweets are fetched via ajax and rendered over the top. This results in the pop you see when you first load the page.</p>
<p>Now, I&#8217;m not second-guessing Twitter&#8217;s choice in this matter as obviously there&#8217;s heaps of technical limitations running at their scale. However, if they could return the static HTML of the page you&#8217;ve requested, then your browsing experience would be better.</p>
<p>The Hogan Template Compiler allows you to render the entirety of your templates on the server making it possible to totally deliver every page of your site as quickly as possible. Subsequent rendering can be done in the browser with the shared pre-compiled partials which are created for you. They&#8217;re simply loaded as a JavaScript file.</p>
<h4>SEO</h4>
<p>Another benefit of having the entire page rendered server-side is that Google and other search engines can easily index all of your content.</p>
<h4>One Template To Rule Them All</h4>
<p>Using the very same templates for rendering on the server and in the browser means that there&#8217;s one source of truth for how your pages are rendered. Some of the sites I&#8217;ve worked on have had fragmented templating systems meaning I&#8217;d be forced to update the server-side and client-side templates separately.</p>
<h4>Caching</h4>
<p>Since the pre-compiled partials are delivered as a static JavaScript file, the browser will cache this for as long as you want it to.</p>
<h3>How to use it</h3>
<pre class="brush: bash; gutter: false; title: ; notranslate">
$npm install hogan-template-compiler
</pre>
<p>Load the module and point it to your partials directory:</p>
<pre class="brush: jscript; title: ; notranslate">
var HoganTemplateCompiler = require('hogan-template-compiler'),

    templateDirectory = __dirname + &quot;/views&quot;,
    hoganTemplateCompiler = HoganTemplateCompiler({
        partialsDirectory: templateDirectory + &quot;/partials&quot;
    });
</pre>
<p>Compile a template manually:</p>
<pre class="brush: jscript; title: ; notranslate">
var compiledTemplate = hoganTemplateCompiler.compileTemplateFile(templateSourcePath);
</pre>
<p>Setup a route (in Express) to send the pre-compiled templates to the browser:</p>
<pre class="brush: jscript; title: ; notranslate">
app.get(&quot;/templates.js&quot;,  function(req, res) {
    res.contentType(&quot;.js&quot;);
    res.send(hoganTemplateCompiler.getSharedTemplates());
});
</pre>
<p>For a working example with Express; try the following:</p>
<pre class="brush: bash; gutter: false; title: ; notranslate">
$ git clone https://dave-elkan@github.com/dave-elkan/pre-compiled-hogan-templates.git
$ cd pre-compiled-hogan-templates
$ npm install -d
$ node app.js
</pre>
<h3>Get the Source</h3>
<p>Grab yourself a copy at <a href="https://github.com/dave-elkan/hogan-template-compiler" target="_blank">https://github.com/dave-elkan/hogan-template-compiler</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.edave.net/2012/05/13/hogan-template-compiler-module/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sharing pre-compiled templates between server and client with Hogan.js</title>
		<link>http://www.edave.net/2012/02/25/sharing-pre-compiled-templates-between-server-and-client-with-hogan-js/</link>
		<comments>http://www.edave.net/2012/02/25/sharing-pre-compiled-templates-between-server-and-client-with-hogan-js/#comments</comments>
		<pubDate>Sat, 25 Feb 2012 03:37:24 +0000</pubDate>
		<dc:creator>dave</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[node.js]]></category>

		<guid isPermaLink="false">http://www.edave.net/?p=272</guid>
		<description><![CDATA[At work we use Closure Templates to render HTML on the client. Closure Templates boast the lovely feature of being able to compile templates down to simple javascript functions on the server for use on the client. This is good because: it relieves the browser of having to compile your templates you don&#8217;t have to [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.atlassian.com/software/jira/overview">At work</a> we use <a href="https://developers.google.com/closure/templates/">Closure Templates</a> to render HTML on the client. Closure Templates boast the lovely feature of being able to compile templates down to simple javascript functions on the server for use on the client. This is good because:</p>
<ol>
<li>it relieves the browser of having to compile your templates</li>
<li>you don&#8217;t have to clutter your markup with template source and</li>
<li>you can render on the client and server with exactly the same template without sending HTML down the wire.</li>
</ol>
<p>The last point offers a significant SEO benefit: By combining server rendered markup for the first page a user visits and client-rendered <a href="https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history">pushState</a> delivered markup thereafter, you satisfy both your own desire to have a dynamic web app and also Google&#8217;s desire to read static HTML.</p>
<p>I was surprised there wasn&#8217;t any immediately obvious equivalent to Closure Templates for node.js. I went as far as trying (in vain) to get ejs to export stringified functions. I quickly threw out that pursuit when I found Hogan.js.</p>
<p><a href="http://twitter.github.com/hogan.js/">Hogan.js</a>, from Twitter, is an implementation of the <a href="http://mustache.github.com/">mustache</a> templating language for use in the browser and on the server with node.js.</p>
<h2>An example of creating and using shared templates with Hogan.js</h2>
<p>This example will render a simple article page using a mustache template which can be used by the server and the client. All of the snippets below are taken from a working Express app <a title="Shared, pre-compiled hogan templates example express app" href="https://github.com/dave-elkan/pre-compiled-hogan-templates">available on github</a>.</p>
<h4>Loading and compiling the shared templates</h4>
<p>The following function loads templates to share between the server and client from a specified directory and compiles them to a stringified javascript function.</p>
<pre class="brush: jscript; highlight: [27]; title: ; notranslate">
/**
 * Reads and compiles hogan templates from the shared template
 * directory to stringified javascript functions.
 */
function readSharedTemplates() {
    var sharedTemplateFiles = fs.readdirSync(sharedTemplateDirectory);

    // Here we'll stash away the shared templates compiled script (as a string) and the name of the template.
    app.sharedTemplates = [];

    // Hogan like it's partials as template contents rather than a path to the template file
    // so we'll stash each template in a partials object so they're available for use
    // in other templates.
    app.sharedPartials = {};

    // Iterate over each sharedTemplate file and compile it down to a javascript function which can be
    // used on the client
    sharedTemplateFiles.forEach(function(template, i) {
        var functionName = template.substr(0, template.lastIndexOf(&quot;.&quot;)),
            fileContents = removeByteOrderMark(fs.readFileSync(sharedTemplateDirectory + template, &quot;utf8&quot;));

        // Stash the partial reference.
        app.sharedPartials[functionName] = fileContents;
        // Stash the compiled template reference.
        app.sharedTemplates.push({
            id: functionName,
            script: hogan.compile(fileContents, {asString: true}),
            // Since mustache doesn't boast an 'isLast' function we need to do that here instead.
            last: i === sharedTemplateFiles.length - 1
        });
    });
}
</pre>
<h4>Delivering the pre-rendered templates</h4>
<p>The result of the hogan.compile function when you pass {asString: true} (highlighted above) will return a stringified javascript function which can be sent to the browser. The name of the template file is used as the id of the template.</p>
<p>The output of readSharedTemplates is sent to the following mustache template which renders them as a simple javascript object.</p>
<pre class="brush: jscript; title: ; notranslate">
var templates = {
{{#templates}}
    &quot;{{id}}&quot;: new Hogan.Template({{{script}}}){{^last}},{{/last}}
{{/templates}}
};
</pre>
<p>Note the triple mustaches around the script variable. This prevents the javascript being HTML escaped.</p>
<p>The output of this template looks something like this:</p>
<pre class="brush: jscript; title: ; notranslate">
var templates = {
    &quot;article&quot;: new Hogan.Template(function(c,p,i){i = i || &quot;&quot;;var b = i + &quot;&quot;;var _ = this;b += &quot;&lt;h2&gt;&quot;;b += (_.v(_.f(&quot;headline&quot;,c,p,0)));b += &quot;&lt;/h2&gt;&quot;;b += &quot;\n&quot; + i;b += &quot;&lt;p&gt;&quot;;b += (_.v(_.f(&quot;bodyText&quot;,c,p,0)));b += &quot;&lt;/p&gt;&quot;;b += &quot;\n&quot;;return b;;})
};
</pre>
<h4>Handling the requests</h4>
<p>The following request handler responds with the template javascript file. You don&#8217;t have to do it this way. You could easily add the template javascript as an inline script tag in the HTML response.</p>
<pre class="brush: jscript; title: ; notranslate">
/**
 * Request handler for pre-compiled hogan.js templates.
 *
 * This function uses a hogan template of it's own which renders
 * calls to Hogan.Tempate. See views/sharedTemplates.mustache.
 */
app.get(&quot;/templates.js&quot;, readSharedTemplatesMiddleware, function(req, res, next) {
    var content = sharedTemplateTemplate.render({
        templates: app.sharedTemplates
    });
    res.contentType(&quot;application/javascript&quot;);
    res.send(content);
});
</pre>
<p>For each request to this handler the readSharedTemplatesMiddleware function is call which reloads the shared templates in development mode.</p>
<p>The other request handler renders the HTML for the initial page. It uses the contents of the shared article.mustache file as a partial which is in turn loaded by layout.mustache (highlighted below).</p>
<pre class="brush: jscript; highlight: [15]; title: ; notranslate">
/**
 * Request handler for the homepage.
 *
 * Renders a hogan template on the server side which contains a form
 * which will update the article section on the client using the
 * pre-compiled template.
 */
app.get(&quot;/&quot;, function(req, res, next) {
    res.render(&quot;layout.mustache&quot;, {
        context: {
            headline: &quot;This is a server-side rendered headline&quot;,
            bodyText: &quot;This is some bodytext&quot;
        },
        partials: {
            &quot;article&quot;: app.sharedPartials[&quot;article&quot;]
        }
    });
});
</pre>
<h4>Rendering the shared template in the browser</h4>
<p>On the client we can refer to the pre-rendered template function by calling the templates.article function. i.e.</p>
<pre class="brush: jscript; title: ; notranslate">
templates.article({
    headline: &quot;This is a client-generated headline&quot;,
    bodyText: &quot;This is a client-generated body&quot;
});
</pre>
<p>will generate:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;h1&gt;This is a client-generated headline&lt;/h1&gt;
&lt;p&gt;This is a client-generated body&lt;/p&gt;
</pre>
<h2>Running the example</h2>
<p>To illustrate the use of a pre-compiled shared template on the client I&#8217;ve put a form in the output of layout.mustache which will update the server-rendered article using the client-side pre-compiled template.</p>
<p>Give it a run for yourself!</p>
<pre class="brush: bash; gutter: false; title: ; notranslate">
$ git clone git://github.com/dave-elkan/pre-compiled-hogan-templates.git
$ cd pre-compiled-hogan-templates
$ npm install -d
$ node app.js
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.edave.net/2012/02/25/sharing-pre-compiled-templates-between-server-and-client-with-hogan-js/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Layers &#8211; Layered Architecture for node.js made easy</title>
		<link>http://www.edave.net/2011/06/28/layers-layered-architecture-for-nodejs-made-easy/</link>
		<comments>http://www.edave.net/2011/06/28/layers-layered-architecture-for-nodejs-made-easy/#comments</comments>
		<pubDate>Tue, 28 Jun 2011 08:37:14 +0000</pubDate>
		<dc:creator>dave</dc:creator>
				<category><![CDATA[Javascript]]></category>

		<guid isPermaLink="false">http://www.edave.net/?p=236</guid>
		<description><![CDATA[EDIT &#8211; This guide is kinda out of date and probably not that applicable anymore. Try using a supported library like Flatiron or just plain old Express but by no means let me stop you if you want to take Layers and run with it. In my previous post A Layered Node.js Architecture using Express [...]]]></description>
			<content:encoded><![CDATA[<p>EDIT &#8211; This guide is kinda out of date and probably not that applicable anymore. Try using a supported library like <a href="http://flatironjs.org/">Flatiron</a> or just plain old <a href="http://expressjs.com">Express</a> but by no means let me stop you if you want to take Layers and run with it.</p>
<p>In my previous post <a href="http://www.edave.net/2011/03/22/a-layered-node-js-architecture-using-express/">A Layered Node.js Architecture using Express</a> I wrote on the benefits of using a layered architecture and how to implement one in a node.js web app. This post goes one step further by introducing <a href="https://github.com/dave-elkan/layers">Layers</a>, a module which will help automatically load and neatly setup the layers (and routes) of your web app.</p>
<p>Layers currently only supports Express, but adding support for other frameworks is simple. Feel free to submit a pull request!</p>
<p>The following is a description of how Layers works. For the impatient or code-hungry there is the working <a href="https://github.com/dave-elkan/layered-express">Layered Express</a> example from which the following snippets are taken.</p>
<p>Layers performs two basic operations:</p>
<ol>
<li>Loads all layer javascript files.</li>
<li>Loosely couples the layers and adds routes.</li>
</ol>
<h2>Installing</h2>
<pre class="brush: plain; gutter: false; title: ; notranslate">$ npm install layers</pre>
<h2>Example app</h2>
<p>Simply require it and instantiate with your app, the path to your layers, a function which returns your wiring (more on this in the next section) and, optionally, an options object. i.e.</p>
<pre class="brush: jscript; title: ; notranslate">
var Layers = require('layers').Express,
    wiring = require('./layers/wiring');
new Layers(app, __dirname + '/layers', wiring);
</pre>
<h3>File Layout</h3>
<p>In this example the layout of the directories is: </p>
<pre class="brush: plain; gutter: false; title: ; notranslate">
__dirname
   - layers
       - controllers
       - services
       - views
</pre>
<h3>Loading Layers</h3>
<p>Each directory nested immediately within the layers directory defines a layer.</p>
<p>Each of these layer directories are recursively scanned for javascript files which are imported using require. The result of the require is inspected for two possibilities: </p>
<ol>
<li>An object</li>
<li>A function which returns an object.</li>
</ol>
<p>The object loaded or returned from the function is appended to the app object under the layer&#8217;s namespace.</p>
<p>e.g.</p>
<pre class="brush: plain; gutter: false; title: ; notranslate">
/path/to/app/layers/controllers/BookController.js becomes app.controllers.bookController
/path/to/app/layers/services/AuthorService.js becomes app.services.authorService
</pre>
<p>One exception is made when loading the layer files: Any file whose name begins with &#8220;Base&#8221; is ignored.<br />
This name can be overriden by specifying the `excludePrefix` option.</p>
<h3>Wiring</h3>
<p>To wire the layers together you need to create a &#8216;wiring&#8217; function. This function takes the layer populated app object as it&#8217;s only parameter and returns a hash of arrays indexed by the route they service. i.e.</p>
<pre class="brush: jscript; title: ; notranslate">
module.exports = function(app) {
    var controllers = app.controllers,
        views = app.views;

    return {

        &quot;/&quot;: [{
                action: controllers.homeController.getAuthorAndBookList,
                views: {
                    html: views.homeView
                }
            }
        ],

        &quot;/books&quot;: [{
                action: controllers.bookController.getBookIndex,
                views: {
                    html: views.bookIndexView,
                    json: views.jsonView
                }
            }
        ],

        &quot;/book/:key&quot;: [{
                action: controllers.bookController.getBookByKey,
                views: {
                    html: views.bookView,
                    json: views.jsonView
                }
            }
        ],

        &quot;/authors&quot;: [{
                action: controllers.authorController.displayAuthorList,
                views: {
                    html: views.authorIndexView,
                    json: views.jsonView
                }
            }
        ],

        &quot;/authors/:key&quot;: [{
                action: controllers.authorController.displayAuthorByKey,
                views: {
                    html: views.authorView
                }
            }
        ]
    };
};
</pre>
<p>The format of the wiring object is important. Each route supports many handlers which all have to define action and view properties.</p>
<h4>Actions</h4>
<p>A handler&#8217;s Action is simply a reference to a function which accepts the request and response objects as well as the callback and next functions. They are called in the context of the app object which allows for easy access to all of the other layers.</p>
<p>Action functions generally belong to the Controller layer. They are responsible for pulling variables from the request, their validation and sending them to the Service layer. This contrived example does not allow any &#8217;1s&#8217; in the Author&#8217;s key which is silly, but stop and imagine authentication at this point.</p>
<p>You will also notice that this controller simply delegates to the service layer, but at the same time it shields it from the request and response objects.</p>
<p>The callback variable which is owned and created by Layers is passed straight through to the service layer.</p>
<pre class="brush: jscript; title: ; notranslate">
module.exports = {

    displayAuthorList: function(req, res, callback) {
        this.services.authorService.getList(callback);
    },

    displayAuthorByKey: function(req, res, callback, next) {
        var authorKey = req.params.key;
        if (authorKey.indexOf(&quot;1&quot;) &gt; -1) {
            callback(new Error(&quot;No ones allowed!&quot;));
        } else {
            this.services.authorService.getAuthorAndTheirBooks(authorKey, callback);
        }
    }
};
</pre>
<h4>Views</h4>
<p>Views are wrappers around your favourite templating system. They also accept the request and response objects but also a third object which is the result of the action. This object is the payload sent to the template.</p>
<p>BaseExpressView can be used as a basis for your own Express (jade) Views. You only need to specify the &#8220;getTemplate&#8221; function.</p>
<h3>Conclusion</h3>
<p>Layers is a simple way to get your app up and running quickly in something which resembles a scalable way. It allows you to specify all of your routes in one place and to specify an ordered list of actions for each of them. It will load and run your layer code and namespace it on your app object for easy access.</p>
<p>Love to hear some feedback if you have any.</p>
<p>EDIT: Updated to replace gists with local code snippets. Gist wasn&#8217;t always loading.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.edave.net/2011/06/28/layers-layered-architecture-for-nodejs-made-easy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Layered Node.js Architecture using Express</title>
		<link>http://www.edave.net/2011/03/22/a-layered-node-js-architecture-using-express/</link>
		<comments>http://www.edave.net/2011/03/22/a-layered-node-js-architecture-using-express/#comments</comments>
		<pubDate>Tue, 22 Mar 2011 11:49:57 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Javascript]]></category>

		<guid isPermaLink="false">http://www.edave.net/?p=193</guid>
		<description><![CDATA[Using layers in your app is a good way to ensure separation of concerns. This post is not an in-depth description to this architecture pattern but more a quick description of each layer&#8217;s purpose and how I&#8217;ve implemented them in node using express. For the impatient, you can peruse the code of the working example here. [...]]]></description>
			<content:encoded><![CDATA[<p>Using <a href="http://en.wikipedia.org/wiki/Abstraction_layer">layers</a> in your app is a good way to ensure <a href="http://en.wikipedia.org/wiki/Separation_of_concerns">separation of concerns</a>. This post is not an in-depth description to this architecture pattern but more a quick description of each layer&#8217;s purpose and how I&#8217;ve implemented them in node using express. For the impatient, you can <a href="https://github.com/daveelkan/layered-express">peruse the code of the working example here</a>.</p>
<h3>Software used</h3>
<ul>
<li><a href="http://nodejs.org">Node 0.4.3</a></li>
<li><a href="http://expressjs.org">Express 2.0.0</a></li>
<li><a href="http://visionmedia.github.com/expresso/">Expresso 0.7.3</a></li>
<li><a href="https://github.com/christkv/node-mongodb-native">node-mongodb-native 0.9.1</a></li>
<li><a href="https://github.com/coopernurse/node-pool">generic-pool 1.0.4</a></li>
<li><a href="http://mongodb.org/">MongoDB 1.6.3</a></li>
</ul>
<h2>View Layer</h2>
<ol>
<li>Accept some data</li>
<li>Apply any required formatting</li>
<li>Render</li>
</ol>
<p>View instances wrap a template and supplies additional functions to help take the burdon off the templating system, whichever one you use. For example, text transformations, regular expressions, etc are best done outside of the template in a simple testable function.  In the following AuthorView example, whilst being contrived, the format function sets the Authors name to upper case.<br />
<script src="https://gist.github.com/851632.js?file=AuthorView.js"></script></p>
<h2>Controllers</h2>
<ol>
<li>Map a URI</li>
<li>Extract some parameters</li>
<li>Kick off some work (it&#8217;s not concerned what nor how it gets done)</li>
<li>Send the result to a View for rendering</li>
</ol>
<p><script src="https://gist.github.com/851632.js?file=Controller.js"></script></p>
<p>This example illustrates the use of Controller.setupGetRoute, a convenience function which takes a route&#8217;s path, an action and a hash of Views mapped to the Accept header they respond to. The action property is a function in the current Controller instance which extracts the required parameters from the request and forwards them onto the Service Layer. Note the lack of error handling in the following AuthorController example. All errors resulting from the Service layer are passed from Controller.setupGetRoute directly to the callback, preventing clutter in the Controller instances.</p>
<p>For each request, the the Accept header is used to map the request to a View. If a match is made, the corresponding View&#8217;s render function is called with the request and response objects along with the result of the call to the action.</p>
<p>I accept that express middleware can be used instead of this call to the Service layer, however if you do you have to attach the result of the action to the request object. That feels a bit muddled to me.</p>
<p><script src="https://gist.github.com/851632.js?file=AuthorController.js"></script></p>
<h2>Service Layer</h2>
<ol>
<li>Do something for the Controller</li>
<li>Return the result to the Controller</li>
</ol>
<p>Try to think of the Service layer as the &#8220;do anything the Controller wants&#8221; layer. It consists of specific use-case functions, as in the following AuthorService gist. This function pull the author requested from the datastore and then grabs their books for good measure and returns the them both (or an error).  The most important thing about the Service layer is that it separates the Controllers from the datastore or other sources of complexity. This ensures that writing (and testing) Controllers remains a simple task.</p>
<p>Services are inter-dependent singletons and are attached to the app. i.e. In the example below, the AuthorService uses the BookService to get the Author&#8217;s Books.</p>
<p><script src="https://gist.github.com/862947.js?file=AuthorService.js"></script></p>
<h2>Data Access Layer</h2>
<ol>
<li>Put, Get, Update and Delete datastore entries.</li>
</ol>
<p>The Data Access Layer is our last layer. It is hard-tied to the datastore of your choice and manages every interaction with it. Once again, encapsulation is the key. Having all of your database code decoupled from your Controllers and Services makes them easier to test. It also makes moving from one datastore to another a much less painful process.</p>
<p>In the example code, each dao is tied to its own collection. In so, calling getList from AuthorDao will return a list of authors, from BookDao, books and so on. For now the example only handles Put and Get operations to keep the example from growing too large. Feel free to send a pull request!</p>
<h2>Working Example</h2>
<p>Pull a clone of the working example here: <a href="https://github.com/dave-elkan/layered-express">https://github.com/dave-elkan/layered-express</a></p>
<h2>Notes on Models</h2>
<p><a href="http://mongoosejs.com/">Mongoose</a> is making great strides to becoming <em>the</em> ORM for node. It does a wonderful job of taking care of the heavy lifting of MongoDB abstraction, validation, defaults, etc. However I don&#8217;t use it in this example as one of my main goals with using a layering technique is that sources of Error are centralised and handled in as few places as possible. Mongoose uses an &#8220;enriched model&#8221; pattern (where every model object has a save, update and delete function). Whilst this is very convenient, I wanted to enforce my database transactions to take place from one central point.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.edave.net/2011/03/22/a-layered-node-js-architecture-using-express/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New Macbook Pro SSD before and after benchmarks</title>
		<link>http://www.edave.net/2010/11/02/new-macbook-pro-ssd-before-and-after-benchmarks/</link>
		<comments>http://www.edave.net/2010/11/02/new-macbook-pro-ssd-before-and-after-benchmarks/#comments</comments>
		<pubDate>Tue, 02 Nov 2010 09:14:37 +0000</pubDate>
		<dc:creator>dave</dc:creator>
				<category><![CDATA[Quick Tech Solutions]]></category>

		<guid isPermaLink="false">http://www.edave.net/?p=183</guid>
		<description><![CDATA[Before (5400rpm) After (OCZ Vertex II 120GB) To say the least I&#8217;m more than happy. The over all score went from 165.24 to 260.85. Next stop. 8GB of RAM.]]></description>
			<content:encoded><![CDATA[<h2>Before (5400rpm)</h2>
<p><a href="http://www.edave.net/wp-content/uploads/2010/11/Screen-shot-2010-11-02-at-8.08.46-PM.png"><img class="aligncenter size-full wp-image-185" title="Screen shot 2010-11-02 at 8.08.46 PM" src="http://www.edave.net/wp-content/uploads/2010/11/Screen-shot-2010-11-02-at-8.08.46-PM.png" alt="" width="459" height="209" /></a></p>
<h2>After (OCZ Vertex II 120GB)</h2>
<p><a href="http://www.edave.net/wp-content/uploads/2010/11/Screen-shot-2010-11-02-at-8.08.34-PM.png"><img class="aligncenter size-full wp-image-184" title="Screen shot 2010-11-02 at 8.08.34 PM" src="http://www.edave.net/wp-content/uploads/2010/11/Screen-shot-2010-11-02-at-8.08.34-PM.png" alt="" width="467" height="213" /></a></p>
<p>To say the least I&#8217;m more than happy. The over all score went from 165.24 to 260.85.</p>
<p>Next stop. 8GB of RAM.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.edave.net/2010/11/02/new-macbook-pro-ssd-before-and-after-benchmarks/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>To Android Hell and back</title>
		<link>http://www.edave.net/2010/09/01/to-android-hell-and-back/</link>
		<comments>http://www.edave.net/2010/09/01/to-android-hell-and-back/#comments</comments>
		<pubDate>Wed, 01 Sep 2010 00:22:43 +0000</pubDate>
		<dc:creator>dave</dc:creator>
				<category><![CDATA[Android]]></category>

		<guid isPermaLink="false">http://www.edave.net/?p=151</guid>
		<description><![CDATA[I rooted my HTC Desire over three months ago using the great guide on android.modaco.com. Happily rooted for a month or so, I then took advantage of Paul&#8217;s r5 release of a Froyo Rom (now archived) which I installed with ROM Manager. It worked perfectly well and I was blown away by the massive performance [...]]]></description>
			<content:encoded><![CDATA[<p>I rooted my HTC Desire over three months ago using the <a href="http://android.modaco.com/content/htc-desire-desire-modaco-com/307365/14-jun-r6-riskfreeroot-htc-desire-rooting-guide-now-with-hboot-0-80-and-os-to-1-21-support/">great guide on android.modaco.com</a>. Happily rooted for a month or so, I then took advantage of <a href="http://android.modaco.com/content/htc-desire-desire-modaco-com/313149/mcr-r5-archive/">Paul&#8217;s r5 release of a Froyo Rom (now archived)</a> which I installed with <a href="http://www.androidcentral.com/android-quick-app-rom-manager">ROM Manager</a>. It worked perfectly well and I was blown away by the massive performance boost Froyo delivers.</p>
<p>So, being the inquisitive type, why <em>wouldn&#8217;t</em> I try <a href="http://android.modaco.com/content/htc-desire-desire-modaco-com/316565/24-aug-r8-modaco-custom-rom-for-htc-desire-with-online-kitchen-2-2-froyo/">r8 of the same ROM</a>? I used ROM Manager to make a backup and install the ROM, but upon rebooting, something went wrong. I got a new Android splash screen, but it just kept on splashing, with no actual Android goodness at the end!</p>
<p>eep! Lucky I made a backup!</p>
<p>So my phone was borked, but I didn&#8217;t panic (yet) and got on to fixing it.</p>
<p>In the end, I&#8217;m still not sure what happened, but here&#8217;s my solution:</p>
<ol>
<li>I eventually got the system to boot by choosing &#8220;Wipe cache partition&#8221; from Recovery mode only to find that <strong>the SD Card and USB had been disabled!</strong> This is where I panicked as that means no adb, no shell, no nothing!</li>
<li>My first step was to do as I usually do when something goes wrong and go back to step 1 and start again. This involved attempting to use the recovery script that came with my original rooting pack. This was a mistake and complete waste of time as my phone was already rooted.</li>
<li>I fixed the lack of SD Card by following <a href="http://android.modaco.com/content-page/299174/no-adb-no-sd/page/80/">some of the steps in this post</a>:
<ol>
<li>Enter fast boot mode with the USB cable attached.</li>
<li>Type <strong>fastboot oem enableqxdm 0</strong> at the command line (I used fastboot-mac from the guide linked at the top of this post)</li>
</ol>
</li>
<li>I fixed the lack of USB connectivity by <a href="http://android.modaco.com/content/htc-desire-desire-modaco-com/309939/usb-brick-rickrolled-b0rked-fixed/">following the steps in this post</a>.</li>
<li><a href="http://android.modaco.com/content/htc-desire-desire-modaco-com/309939/usb-brick-rickrolled-b0rked-fixed/"></a>I then made the mistake of restoring an old version of  Android (1.21). I put this down to a little bit of panic and having to multitask on other equally engaging tasks (i.e. work). Android 1.21 was great at crashing. I couldn&#8217;t even load the market place to install ROM Manager to restore my previous backup.</li>
<li>I eventually managed to restore my backup by using the recovery-update.zip file which is automatically packaged up with your ROM Manager backups by renaming it to update.zip and placing it at the root of my SD Card. I then performed the usual restore update.zip method in recovery mode.
<ol>
<li>Loading this update.zip loads <a href="http://www.clockworkmod.com/">Clockworkmod</a>, the brains behind ROM Manager. From here I was able to restore my backup.</li>
</ol>
</li>
</ol>
<p>Now, if only that burning desire to try again would go away&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.edave.net/2010/09/01/to-android-hell-and-back/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>5 hints on holding an old school LAN</title>
		<link>http://www.edave.net/2010/07/26/5-hints-on-holding-an-old-school-lan/</link>
		<comments>http://www.edave.net/2010/07/26/5-hints-on-holding-an-old-school-lan/#comments</comments>
		<pubDate>Mon, 26 Jul 2010 10:51:37 +0000</pubDate>
		<dc:creator>dave</dc:creator>
				<category><![CDATA[Gaming]]></category>

		<guid isPermaLink="false">http://www.edave.net/?p=136</guid>
		<description><![CDATA[Old school LANs are a great way to keep in touch with friends, as like &#8211; in the same room &#8211; not on Facebook, whilst reliving some of the greatest games ever made such as Red Alert 2, Duke Nukem 3D and Carmageddon. Here&#8217;s 5 hints to help you get your LAN up and running [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.edave.net/wp-content/uploads/2010/07/carma.jpg"><img class="alignright size-medium wp-image-141" title="Testing Carmageddon lan play" src="http://www.edave.net/wp-content/uploads/2010/07/carma-400x239.jpg" alt="" width="280" height="167" /></a>Old school LANs are a great way to keep in touch with friends, as like &#8211; in the same room &#8211; not on Facebook, whilst reliving some of the greatest games ever made such as Red Alert 2, Duke Nukem 3D and Carmageddon.</p>
<p>Here&#8217;s 5 hints to help you get your LAN up and running and making the most of it.</p>
<ol>
<li><strong>Anonymous file server and DHCP<br />
<span style="font-weight: normal;">99.9% of time spent at a LAN, especially one where you play old games not designed to run on modern operating systems, is stuffing around trying to get them to work. It is absolutely imperative that you have a dedicated anonymous file server upon which people can share the files required to run the games. This will eliminate unnecessary &#8221;sharing&#8221; setup time. It will also prevent file server downtime as it will not need to be rebooted unlike client computers busy installing games.<br />
Another thing to make it easier is to have a local DNS server. I have a Mac Mini server which comes bundled with Mac OSX Server. Even a novice home networker can setup a local domain. Coupling this with a DHCP server setup with a default search domain means your guests can enter something like </span><span style="font-weight: normal;">\\servername</span><span style="font-weight: normal;"> into their windows explorer or </span><span style="font-weight: normal;">smb:\\servername</span><span style="font-weight: normal;"> in OSX to connect. No IP addresses!</p>
<p></span></strong></li>
<li><strong>Sustenance<br />
<span style="font-weight: normal;">Gamers at LANs have highly very active brains and therefore need a high carb, high protein meal to allow them extreme accuracy with the Rail Gun. Contrary to modern belief, Pizza and Coke do NOT constitute any of these very important ingredients.<br />
If you&#8217;ve organised a LAN in the past you&#8217;ll know that as soon as it starts and you have your first coke / Jolt cola (or bourbon and coke if you&#8217;re so inclined) that everything goes CRAZY. As a part of the LAN setup process, construct, in a large pot, <a href="http://www.slowcookerrecipes.net.au/slowcooker-recipes.asp?id=15">a large stew using gravy beef and vegetables</a>. Put this in a slow cooker up to 10 hours ahead of dinner time and walk away. When the hunger calls simply dish up with some rice (can also be pre-prepared). This will keep your gamers alert and happy until the wee hours of the morning. Most importantly, it&#8217;s bloody cheap, ready when you want it and doesn&#8217;t involve picking up the phone!</p>
<p></span></strong></p>
<p style="text-align: center;"><strong><a href="http://www.edave.net/wp-content/uploads/2010/07/food.jpg"><img class="aligncenter size-full wp-image-143" title="Food" src="http://www.edave.net/wp-content/uploads/2010/07/food.jpg" alt="" width="500" height="299" /></a><br />
</strong></p>
</li>
<li><strong>Research<br />
<span style="font-weight: normal;">The older a game gets the harder it is to run.<br />
Make sure you&#8217;re up to speed with <a href="http://www.dosbox.com/">DosBox</a> (<a href="http://boxer.washboardabs.net/">Boxer on Mac</a>) and it&#8217;s ability to host IPX Tunnelling (IPX over TCP/IP).<br />
Experiment with the games you intend on playing ahead of time on your own. It took me a week of stuffing around to get Carmageddon running with 3DFX using a special version of <a href="http://vogons.zetafleet.com/viewtopic.php?t=16462">DosBox with Glide support</a>.</p>
<p></span></strong></li>
<li><span style="font-weight: normal;"><strong>Power<br />
<span style="font-weight: normal;">I&#8217;m sure you all know this, but ensure you spread your power load evenly across your wall sockets. Don&#8217;t go crazy with power boards hanging off power boards. Make sure extension cords are straight and not coiled when in use.</p>
<p></span></strong></p>
<p></span></li>
<li><span style="font-weight: normal;"><strong>Do what you came to do. Have fun!<br />
<span style="font-weight: normal;">Personally, when I go to a LAN, I get so excited and busy trying to fix all of the problems that all of my plans go out the window. It&#8217;s best to keep a list somewhere handy, say as your desktop background, which lists the games you want to play or things you want to do or share.<br />
So many times it&#8217;s 10 hours in and everyone&#8217;s thinking about going home that you remember you wanted to play Total Annihilation (a notoriously long game). So annoying!</span></strong></span></li>
</ol>
<p><a href="http://www.edave.net/wp-content/uploads/2010/07/lanners.jpg"><img class="aligncenter size-full wp-image-142" title="lanners" src="http://www.edave.net/wp-content/uploads/2010/07/lanners.jpg" alt="" width="500" height="299" /></a></p>
<p style="text-align: center;">
]]></content:encoded>
			<wfw:commentRss>http://www.edave.net/2010/07/26/5-hints-on-holding-an-old-school-lan/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Two months with Swype</title>
		<link>http://www.edave.net/2010/07/15/two-months-with-swype/</link>
		<comments>http://www.edave.net/2010/07/15/two-months-with-swype/#comments</comments>
		<pubDate>Thu, 15 Jul 2010 00:30:03 +0000</pubDate>
		<dc:creator>dave</dc:creator>
				<category><![CDATA[Android]]></category>

		<guid isPermaLink="false">http://www.edave.net/?p=129</guid>
		<description><![CDATA[I&#8217;m writing this review on my Android powered HTC Desire using a new, custom keyboard called Swype. Swype allows you to type whilst barely lifting your finger from the screen. As the name suggests, you swype your finger from letter to letter instead of tapping. This constructs a sort of letter trail which, once you [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m writing this review on my Android powered HTC Desire using a new, custom keyboard called Swype.</p>
<p>Swype allows you to type whilst barely lifting your finger from the screen. As the name suggests, you swype your finger from letter to letter instead of tapping. This constructs a sort of letter trail which, once you lift your finger is inspected and the top ranking word from the letters you swyped is inserted. If there is more than one match, it will offer up a list of suggested words.<br />
Other ham-fisted, clumsy typers like me will be happy to know that the trail by no means has to pass directly over each letter. Rather, as long as the trail is roughly near a letter it will be added to the mix, albeit with less priority (I think). When you experience this for the first time you realise that there&#8217;s a lot more going on behind the scenes than you might first think.</p>
<p>The experience of swyping is not second nature to anyone and there is a period of time where you find yourself wanting to revert to the default keyboard. However, for the persistent and forgiving, the reward with sticking with it will deliver a faster typing speed. How much faster? Fast enough to <a title="Swype user sets guinness world record for texting speed" href="http://www.mobilecrunch.com/2010/03/22/swype-user-sets-guinness-world-record-for-texting-speed/">win a place in the Guiness Book of Records</a> for the fastest text message typed, that&#8217;s how fast!</p>
<p>Speed, though, goes hand in hand with inaccuracy. At times I&#8217;ve found myself swyping in the wrong direction or blindly selecting the top most (and also wrong) suggestion, which is done automatically when you start swyping the next word.</p>
<p>So despite Swype being a totally different experience to a conventional on screen keyboard it&#8217;s easily withstood the hardest test of all. Not being noticed.</p>
<p>I&#8217;ve had Swype as my keyboard for over two months now and haven&#8217;t even thought of turning it off.</p>
<p>The <a href="http://beta.swype.com/">beta has closed</a>, but judging by the total lack of crashes I&#8217;ve experienced, the full version should be out shortly.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.edave.net/2010/07/15/two-months-with-swype/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The HTC Desire</title>
		<link>http://www.edave.net/2010/05/29/the-htc-desire/</link>
		<comments>http://www.edave.net/2010/05/29/the-htc-desire/#comments</comments>
		<pubDate>Sat, 29 May 2010 13:28:25 +0000</pubDate>
		<dc:creator>dave</dc:creator>
				<category><![CDATA[Android]]></category>

		<guid isPermaLink="false">http://www.edave.net/?p=98</guid>
		<description><![CDATA[It took over at least two years, but I finally got a smart phone. An HTC Desire. The iPhone, whilst appealing, never really seemed to end up in my possession for one reason or another. Adopting early or following the masses has never been my way. In fact, I&#8217;ll happily go the other way, with [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.htc.com/www/product/desire/gallery.html"><img class="size-full wp-image-101 alignright" title="HTC Desire" src="http://www.edave.net/wp-content/uploads/2010/05/desire.jpg" alt="" width="300" height="475" /></a></p>
<p>It took over at least two years, but I finally got a smart phone. An <a href="http://www.htc.com/www/product/desire/overview.html">HTC Desire</a>.</p>
<p>The iPhone, whilst appealing, never really seemed to end up in my possession for one reason or another. Adopting early or following the masses has never been my way. In fact, I&#8217;ll happily go the other way, with all of it&#8217;s bumps and bruises, just to show it can be done.</p>
<p>The HTC Desire is a fantastic phone. It&#8217;s smooth to touch and, being powered by a 1ghz snapdragon processor running Android, is also very smooth to interact with. The UI (powered by HTC&#8217;s Sense) flows from one state to the next. Nothing catches you by surprise.</p>
<p><strong>Comparison to iPhone</strong><br />
I&#8217;m no seasoned iPhone user, however we do have one in the family which I am more than guilty of pinching for my own benefit quite a bit. The HTC Desire is in some ways a better experience.</p>
<p>First and foremost is that Android works on a different level to iPhone OS. Android supports multi-tasking out of the box, whereas iPhone OS will not offer this until version 4.0 is release later this year. Android phones, by design, also have 4 more hardware buttons than the iPhone&#8217;s 1. I can hear simplicity purists out there shifting in their seats as they read this, but it actually makes the phone more versatile.</p>
<p>Apple use a software review process to ensure that all of the guidelines (including ui guidelines) are adhered to. Google, through the use of physical buttons, have designed a contract with the developer that cannot be broken. Let me explain (from left-most button to the right-).</p>
<p><strong>The home button</strong><strong><br />
</strong><strong> </strong><strong><span style="font-weight: normal;">As on the iPhone, the home button will snap you straight back to your home screen no matter what you&#8217;re currently doing. It also doubles as a &#8220;open processes&#8221; button when held down allowing you to swap between applications which are open in the background.</span></strong></p>
<p><strong>The menu button<span style="font-weight: normal;"><br />
The menu button opens a contextual menu offering more options for the current application or screen.</span></strong></p>
<p><strong>The scrolly thing<br />
<span style="font-weight: normal;">The scrolly thing, which is also the &#8220;click&#8221; button, is an optical mouse turned up-side-down. It functions in the same way a track-ball does, albeit with no moving parts. It&#8217;s another part of this phone which feels smooth to touch. </span></strong></p>
<p><strong>The back button<br />
<span style="font-weight: normal;">The back button is easily the best and most used button. I love this button as much as it is legal to love a button as it releases the full power of the multi-tasking ability of the phone.<br />
</span></strong><strong><span style="font-weight: normal;">Say I am reading my twitter feed and someone has posted a link which I want to follow. In the Apple world hitting this link would either a) close the current application and open Safari or b) open an instance of safari within the current application displaying the page (which is simply more work for the developer). From a legal standpoint it can also allow people to view websites in your application that you don&#8217;t want associated with it.<br />
</span></strong>In instance a the user, once they have finished reading the contents of the webpage, cannot get back to the Twitter stream without first closing Safari and re-opening the Twitter application.</p>
<p><strong><span style="font-weight: normal;"> However, on the Desire a simple click of the back button will instantly take you back to the Twitter stream. This is something the iPhone can never do due to it&#8217;s lack of a back button. </span></strong></p>
<p><strong><span style="font-weight: normal;">The back button also closes open dialogues or modal windows and takes you back when browsing websites.</span></strong></p>
<p><strong>The search button<br />
<span style="font-weight: normal;">Being a Google connected device, search is obviously quite prevalent in the design of this operating system. That said, I don&#8217;t actually use it that much.<br />
The search button will open a search dialogue which pertains to the current application (if the application supports it or the whole phone if done if otherwise). If done from the web browser, the search context is obviously the web, if done from the calendar, the calendar will be searched. </span></strong></p>
<p><strong>The Internet</strong><br />
The web browser named simply &#8220;Internet&#8221; is an intuitive web-kit based app. It has a number of positives over Apple&#8217;s Mobile Safari.</p>
<ol>
<li>Zooming.<br />
When zooming, for example, into the text of an article the enlarged text is reformatted to fit to the width of the phone. This prevents the need for excessive side-ways scrolling as is required on the iPhone.<br />
This saves your eyes and fingers from excessive wear.</li>
<li>Flash.<br />
Nuf said.</li>
</ol>
<p><strong>Freedom<br />
<span style="font-weight: normal;">When using an Android powered phone like the HTC Sense you can do this amazing thing called &#8220;choosing for one&#8217;s self&#8221;. That is, you are not locked into anything. For example, a simple download from the Market (app store equivalent) will give you a <a href="http://www.thickbuttons.com/">totally different keyboard implementation</a>. Hell, you don&#8217;t even have to distribute your apps through the Market.</span></strong></p>
<p><strong>Down sides</strong><strong><br />
</strong><strong><span style="font-weight: normal;">There is only one bug that I&#8217;ve suffered from with the Android operating system. There&#8217;s a <a href="http://code.google.com/p/android/issues/detail?id=2207">known bug</a> with switching from Wifi to 3G. For some reason sometimes the 3G just doesn&#8217;t initialise again. The solution is to turn the phone onto Airplane mode and off again. </span></strong></p>
<p><strong>Conclusion<br />
<span style="font-weight: normal;">This phone has changed my life. I&#8217;m very happy with it even if it does give me an excuse to play <a href="http://androidandme.com/2009/05/reviews/robo-defense-120-levels-of-tower-defense-madness/">pointless tower defence games</a> on the bus. </span></strong></p>
]]></content:encoded>
			<wfw:commentRss>http://www.edave.net/2010/05/29/the-htc-desire/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using JacksonJson @JsonSerialiser annotation for a single property</title>
		<link>http://www.edave.net/2010/03/31/using-jacksonjson-jsonserialiser-annotation-for-a-single-property/</link>
		<comments>http://www.edave.net/2010/03/31/using-jacksonjson-jsonserialiser-annotation-for-a-single-property/#comments</comments>
		<pubDate>Tue, 30 Mar 2010 22:40:05 +0000</pubDate>
		<dc:creator>dave</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Quick Tech Solutions]]></category>

		<guid isPermaLink="false">http://www.edave.net/?p=85</guid>
		<description><![CDATA[When using Spring MVC and the Jackson JSON processor recently, I needed to only expose one property from a referenced object when serialising. Rather than have a new object defined with the single property, I used the @JsonSerialiser annotation to serialise only the property I was interested in. I will use a &#8216;PublicFile&#8217; Object as [...]]]></description>
			<content:encoded><![CDATA[<p>When using Spring MVC and the Jackson JSON processor recently, I needed to only expose one property from a referenced object when serialising.</p>
<p>Rather than have a new object defined with the single property, I used the @JsonSerialiser annotation to serialise only the property I was interested in.</p>
<p>I will use a &#8216;PublicFile&#8217; Object as an example.</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: #000000; font-weight: bold;">class</span> PublicFile <span style="color: #009900;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">String</span> path<span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">String</span> getPath<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">return</span> path<span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> setPath<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> path<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">path</span> <span style="color: #339933;">=</span> path<span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>If we were to serialise the an instance of this PublicFile Object using the Jackson Json processor, the result would be:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #009900;">&#123;</span>
    <span style="color: #3366CC;">&quot;publicfile&quot;</span><span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #3366CC;">&quot;path&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;file path value&quot;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>To return only the path property when serialising the instance to JSON, create a serialiser like:</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: #000000; font-weight: bold;">class</span> PublicFilePathJsonSerialiser <span style="color: #000000; font-weight: bold;">extends</span> JsonSerializer<span style="color: #339933;">&lt;</span>PublicFile<span style="color: #339933;">&gt;</span> <span style="color: #009900;">&#123;</span>
	@Override
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> serialize<span style="color: #009900;">&#40;</span>PublicFile file, JsonGenerator jgen,
			SerializerProvider provider<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">IOException</span>,
			JsonProcessingException <span style="color: #009900;">&#123;</span>
		jgen.<span style="color: #006633;">writeString</span><span style="color: #009900;">&#40;</span>file.<span style="color: #006633;">getPath</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>And then reference it in your class:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">@JsonSerialize<span style="color: #009900;">&#40;</span>using <span style="color: #339933;">=</span> PublicFilePathJsonSerialiser.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> PublicFile <span style="color: #009900;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">String</span> path<span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">String</span> getPath<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">return</span> path<span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> setPath<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> path<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">path</span> <span style="color: #339933;">=</span> path<span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>This produces:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #009900;">&#123;</span>
    <span style="color: #3366CC;">&quot;publicfile&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;file path value&quot;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://www.edave.net/2010/03/31/using-jacksonjson-jsonserialiser-annotation-for-a-single-property/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic page generated in 1.695 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2012-05-14 08:09:08 -->
<!-- Compression = gzip -->
