<?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>Srirangan</title>
	<atom:link href="http://srirangan.net/feed" rel="self" type="application/rss+xml" />
	<link>http://srirangan.net</link>
	<description>Programmer + Product Developer</description>
	<lastBuildDate>Thu, 16 Feb 2012 16:00:46 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Speaking at JSFoo, Chennai 2012</title>
		<link>http://srirangan.net/2012-02-speaking-at-jsfoo-chennai-2012</link>
		<comments>http://srirangan.net/2012-02-speaking-at-jsfoo-chennai-2012#comments</comments>
		<pubDate>Thu, 16 Feb 2012 16:00:46 +0000</pubDate>
		<dc:creator>Srirangan</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[node.js]]></category>
		<category><![CDATA[review19]]></category>

		<guid isPermaLink="false">http://srirangan.net/?p=1003</guid>
		<description><![CDATA[I will be speaking at India&#8217;s largest JavaScript and Node.js event JSFoo Chennai 2012 on the 18th of February 2012. Excited to demo Review19 and share my insights on the evolution of next generation web apps. Looking forward to seeing &#8230; <a href="http://srirangan.net/2012-02-speaking-at-jsfoo-chennai-2012">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I will be speaking at India&#8217;s largest JavaScript and Node.js event <a href="http://jsfoo.in/chennai2012/">JSFoo</a> Chennai 2012 on the 18th of February 2012. </p>
<p>Excited to demo <a href="http://www.review19.com">Review19</a> and share my insights on the evolution of next generation web apps. Looking forward to seeing you there!</p>
<p><a href="http://funnel.hasgeek.com/jsfoo-chennai/218-ajax-is-history-build-real-time-apps-in-javascript">Details of my talk</a> | <a href="http://jsfoo.in/chennai2012/venue">Venue</a> | <a href="http://jsfoo.in/chennai2012/schedule">Schedule</a> | <a href="http://jsfoo.in/">JSFoo</a></p>
]]></content:encoded>
			<wfw:commentRss>http://srirangan.net/2012-02-speaking-at-jsfoo-chennai-2012/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Published on HowToNode.org</title>
		<link>http://srirangan.net/2012-02-published-on-howtonode-org</link>
		<comments>http://srirangan.net/2012-02-published-on-howtonode-org#comments</comments>
		<pubDate>Mon, 13 Feb 2012 04:22:55 +0000</pubDate>
		<dc:creator>Srirangan</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[node.js]]></category>

		<guid isPermaLink="false">http://srirangan.net/?p=1000</guid>
		<description><![CDATA[Submitted two of my recent posts to HowToNode.org. Love their excellent Git / GitHub based publishing workflow, excellent way to attract good content from programmers. Here are the links: * Node.js and MongoDB &#8211; Getting started with MongoJS * Really &#8230; <a href="http://srirangan.net/2012-02-published-on-howtonode-org">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Submitted two of my recent posts to <a href="http://howtonode.org">HowToNode.org</a>. </p>
<p>Love their excellent Git / GitHub based publishing workflow, excellent way to attract good content from programmers.</p>
<p>Here are the links:<br />
* <a href="http://howtonode.org/node-js-and-mongodb-getting-started-with-mongojs">Node.js and MongoDB &#8211; Getting started with MongoJS</a><br />
* <a href="http://howtonode.org/really-simple-file-uploads">Really simple file uploads with Express</a></p>
]]></content:encoded>
			<wfw:commentRss>http://srirangan.net/2012-02-published-on-howtonode-org/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Node.js and MongoDB &#8211; Getting started with MongoJS</title>
		<link>http://srirangan.net/2012-02-node-js-and-mongodb-getting-started-with-mongojs</link>
		<comments>http://srirangan.net/2012-02-node-js-and-mongodb-getting-started-with-mongojs#comments</comments>
		<pubDate>Mon, 06 Feb 2012 12:53:39 +0000</pubDate>
		<dc:creator>Srirangan</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[mongodb]]></category>
		<category><![CDATA[mongojs]]></category>
		<category><![CDATA[node.js]]></category>

		<guid isPermaLink="false">http://srirangan.net/?p=957</guid>
		<description><![CDATA[It won&#8217;t be an exaggeration if one claims that in the past few months Node.js and MongoDB have literally taken the software and web industries by storm. Not just bleeding-edge startups but even medium and large enterprises are leveraging these &#8230; <a href="http://srirangan.net/2012-02-node-js-and-mongodb-getting-started-with-mongojs">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>It won&#8217;t be an exaggeration if one claims that in the past few months Node.js and MongoDB have literally taken the software and web industries by storm. </p>
<p>Not just bleeding-edge startups but even medium and large enterprises are leveraging these two technologies to deliver a better experience to their users by build more capable, performant and scalable apps.</p>
<p>So what is Node.js?</p>
<blockquote><p>Node.js is a platform built on Chrome&#8217;s JavaScript runtime for easily building fast, scalable network applications. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, perfect for data-intensive real-time applications that run across distributed devices.</p></blockquote>
<p>..and what is MongoDB?</p>
<blockquote><p>MongoDB is a scalable, high-performance, open source NoSQL database.</p></blockquote>
<p>This post will cover the basics and get you started with your Node.js + MongoDB app. Make sure you have <a href="http://nodejs.org/#download">Node.js installed</a> and <a href="http://www.mongodb.org/downloads">MongoDB setup</a> on your developer machine.</p>
<p>Let&#8217;s verify your Node.js installation and start the MongoDB server:</p>
<pre>
$ node -v
$ mongod
</pre>
<p><strong>Introducing MongoJS</strong><br />
<a href="https://github.com/gett/mongojs">MongoJS</a> is a brilliant little Node.js package that lets you access MongoDB using an API that is extremely similar to MongoDB&#8217;s JavaScript shell.</p>
<p><strong>Installing MongoJS</strong><br />
Once Node.js has been setup correctly on your machine, you can use its internal package manager <a href="http://npmjs.org/">NPM</a> to install MongoJS:</p>
<pre>
$ npm install mongojs
</pre>
<p>We can now start building our JavaScript application and connect to our MongoDB server:</p>
<pre>
// app.js
var databaseUrl = "mydb"; // "username:password@example.com/mydb"
var collections = ["users", "reports"]
var db = require("mongojs").connect(databaseUrl, collections);
</pre>
<p>The <code>databaseUrl</code> can contain the database server host and port along with the database name to connect to. By default the host is &#8220;<code>localhost</code>&#8221; and the port is &#8220;<code>27017</code>&#8220;. If you&#8217;re using the default, which is likely on a developer environment, the <code>databaseUrl</code> can contain just the actual database name for our app.</p>
<p>The <code>collections</code> is a set (array) of collections our application uses. It isn&#8217;t mandatory but is preferred as it allows us to emulate a MongoDB JavaScript client like API within our Node.js app.</p>
<p>Here&#8217;s an example for finding documents within a collection specifically in this case to find all female users.</p>
<pre>
// app.js
db.users.find({sex: "female"}, function(err, users) {
  if( err || !users) console.log("No female users found");
  else users.forEach( function(femaleUser) {
    console.log(femaleUser);
  } );
});
</pre>
<p>Notice how our initial query is a near duplication of the corresponding query in MongoDB&#8217;s console. In addition to the query, in our Node.js source code (i.e. app.js) we pass a callback function to handle the results of the query. </p>
<p>Node.js implements an event based concurrency paradigm and almost everything is always a callback. This allows your Node.js app to be non-blocking and high performing. </p>
<p>What happens in our specific callback is self-explanatory &#8212; we check for errors and results, and if the query returns female users they are logged to the console.</p>
<p>Okay, how do I save a new user in my collection? Exactly how you would do it in the console, your code will look like this:</p>
<pre>
// app.js
db.users.save({email: "srirangan@gmail.com", password: "iLoveMongo", sex: "male"}, function(err, saved) {
  if( err || !saved ) console.log("User not saved");
  else console.log("User saved");
});
</pre>
<p>Here&#8217;s an example for updating a record / document:</p>
<pre>
// app.js
db.users.update({email: "srirangan@gmail.com"}, {$set: {password: "iReallyLoveMongo"}}, function(err, updated) {
  if( err || !updated ) console.log("User not updated");
  else console.log("User updated");
});
</pre>
<p>Okay, now we run this app in the console:</p>
<pre>
$ node app.js
</pre>
<p>And there we have it, an incredibly simple quick start for Node.js + MongoDB enthusiasts. Happy coding!</p>
]]></content:encoded>
			<wfw:commentRss>http://srirangan.net/2012-02-node-js-and-mongodb-getting-started-with-mongojs/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>At what stage should scalability be addressed?</title>
		<link>http://srirangan.net/2012-02-at-what-stage-should-scalability-be-addressed</link>
		<comments>http://srirangan.net/2012-02-at-what-stage-should-scalability-be-addressed#comments</comments>
		<pubDate>Mon, 06 Feb 2012 05:36:52 +0000</pubDate>
		<dc:creator>Srirangan</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[scalability]]></category>

		<guid isPermaLink="false">http://srirangan.net/?p=937</guid>
		<description><![CDATA[In this post I will try to be as non-partisan as possible with respect to technology, platforms, programming languages, databases etc. Do forgive me if I fail in this attempt. Here&#8217;s the question on hand: When should business, leadership, dev &#8230; <a href="http://srirangan.net/2012-02-at-what-stage-should-scalability-be-addressed">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>In this post I will try to be as non-partisan as possible with respect to technology, platforms, programming languages, databases etc. Do forgive me if I fail in this attempt.</p>
<p>Here&#8217;s the question on hand:<br />
<strong>When should business, leadership, dev teams and other stakeholders address the scalability question.</strong></p>
<p>It&#8217;s a dilema I face and others depend on my advise so I&#8217;m pooling in your wisdon. </p>
<p>Allow me to ellaborate the question. We&#8217;re building a product and we have two choices:</p>
<p><strong>Choice 1</strong></p>
<p>Go in for a technology that is extremely popular. It has been around in the mainstream for at least half a decade. It&#8217;s a good business choice because of the maturity of the environment, the availability of talent / outsourcing firms and positive feedback overall. </p>
<p>However there are some questions over scalability. There are many case-studies where headline grabbing companies have had to abandon this technology and go in for a complete / partial rewrite on another platform. </p>
<p>The argument here goes like this:</p>
<blockquote><p>&#8220;If we use this technology and we face scalability problems few months down the line, it&#8217;s a good problem to have because it means we have done really well. So lets go ahead with this for now, even if it means a rewrite six months down the line.&#8221;</p></blockquote>
<p><strong>Choice 2</strong></p>
<p>We can opt for another much younger technology. It has an active community but comparatively less mature environment / toolkits. In comparison to Choice 1, it is harder to find good and affordable talent. </p>
<p>The programming language here is extremely expressive yet heavily misunderstood.</p>
<p>However there are bona fide scaling credentials. It&#8217;s been a choice for organisations that are proven technology leaders. And its perhaps a safer bet in the long run on the scalability parameter.</p>
<p><strong>Your call</strong></p>
<p>As a programmer / hacker / geek, Choice 2 is an obvious winner. At least for me its a no-brainer.</p>
<p>However put yourself in a product owner / manager / CTO / decision-making role. Does your opinion change?</p>
<p>Welcoming all your comments, thanks!</p>
]]></content:encoded>
			<wfw:commentRss>http://srirangan.net/2012-02-at-what-stage-should-scalability-be-addressed/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Really simple file uploads with Node.js and Express</title>
		<link>http://srirangan.net/2012-02-really-simple-file-uploads-with-node-js-and-express</link>
		<comments>http://srirangan.net/2012-02-really-simple-file-uploads-with-node-js-and-express#comments</comments>
		<pubDate>Sun, 05 Feb 2012 08:55:44 +0000</pubDate>
		<dc:creator>Srirangan</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[express.js]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[node.js]]></category>

		<guid isPermaLink="false">http://srirangan.net/?p=926</guid>
		<description><![CDATA[Few days ago I was working on a fairly typical web application and I faced the challenge of implementing a fairly typical web application feature &#8211; file uploads. It was the first time I was implementing file uploads with Node &#8230; <a href="http://srirangan.net/2012-02-really-simple-file-uploads-with-node-js-and-express">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Few days ago I was working on a fairly typical web application and I faced the challenge of implementing a fairly typical web application feature &#8211; file uploads. It was the first time I was implementing file uploads with Node (and Express) and I did what anyone else would do &#8211; I googled it.</p>
<p>Unfortunately all the articles / posts out there are either outdated, too complex or plain wrong. So I did the next most obvious thing &#8211; post a question on the mailing list. As always Mr. Holowaychuk was incredibly quick to respond. His answer lead me to do what I should have done in the first place &#8211; read the docs.</p>
<p><strong>The upload form</strong></p>
<p>This is the most obvious part of the challenge. You&#8217;re probably familiar with this already. Anyway, for the sake of completeness of this article, here it is.</p>
<p>You will need a form in your browser for the file upload. I use Jade to generate my HTML and here how it looks:</p>
<pre>
form(action="...", method="post", enctype="multipart/form-data")
  input(type="file", name="displayImage")
</pre>
<p>The form.action will point to a route that handles the file upload. More below.</p>
<p><strong>Accessing the uploaded file</strong></p>
<p>If you&#8217;re using recents versions of Node and Express, file uploads are a piece of cake. And I&#8217;ll back this claim but before we go any further make sure you&#8217;re familiar with routes, requests and responses in Express.</p>
<p>Okay, now let&#8217;s justify the &#8220;piece of cake&#8221; claim. In our file upload route, the req parameter has req.files available. Here&#8217;s an example of what the req.files would contain:</p>
<pre>
{
  displayImage: {
    size: 11885,
    path: '/tmp/1574bb60b4f7e0211fd9ab48f932f3ab',
    name: 'avatar.png',
    type: 'image/png',
    lastModifiedDate: Sun, 05 Feb 2012 05:31:09 GMT,
    _writeStream: {
      path: '/tmp/1574bb60b4f7e0211fd9ab48f932f3ab',
      fd: 14,
      writable: false,
      flags: 'w',
      encoding: 'binary',
      mode: 438,
      bytesWritten: 11885,
      busy: false,
      _queue: [],
      drainable: true
    },
    length: [Getter],
    filename: [Getter],
    mime: [Getter]
  }
}
</pre>
<p>In the <code>req.files</code> object above, the property <code>displayImage</code> is the name of the file field in your HTML form and <code>req.files</code> will contain one property each for every valid HTML file form field.</p>
<p>The file object contains the <code>type</code>, <code>size</code> and <code>name</code> properties for your server side validations.</p>
<p><strong>Saving the uploaded file</strong></p>
<p>Assuming the file is valid, you use the <code>path</code> property for the next step. The <code>path</code> would typically contain a location in the tmp folder. Your application logic could either require you to access the contents of the file or simply move the uploaded file to another location.</p>
<pre>
fs.readFile(req.files.displayImage.path, function (err, data) {
  // ...
  var newPath = __dirname + "/uploads/uploadedFileName";
  fs.writeFile(newPath, data, function (err) {
    res.redirect("back");
  });
});
</pre>
<p>In the <code>fs.readFile</code> callback, we have the data parameter through which we can access the contents of the file. The example above is taken from an application that needed to modify the file and save it in a new location. Thus <code>fs.writeFile</code> is used to write data to the newPath.</p>
<p>If your app needs to simply move the uploaded file without modifying the contents <code>fs.rename</code> can be used as more simpler option.</p>
<p>&#8212;</p>
<p>That&#8217;s all there is to it. I&#8217;ve done file uploads in many server side languages including Python, Java, Scala and PHP and I don&#8217;t think its ever been this simple. </p>
<p>So much for JavaScript being labeled as an inferior server side language.</p>
]]></content:encoded>
			<wfw:commentRss>http://srirangan.net/2012-02-really-simple-file-uploads-with-node-js-and-express/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>JSFoo Chennai 2012 &#8211; Ajax is history &#8211; Build real time apps in JavaScript</title>
		<link>http://srirangan.net/2012-02-jsfoo-chennai-2012-ajax-is-history-build-real-time-apps-in-javascript</link>
		<comments>http://srirangan.net/2012-02-jsfoo-chennai-2012-ajax-is-history-build-real-time-apps-in-javascript#comments</comments>
		<pubDate>Sun, 05 Feb 2012 04:39:05 +0000</pubDate>
		<dc:creator>Srirangan</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jsfoo]]></category>
		<category><![CDATA[node.js]]></category>
		<category><![CDATA[review19]]></category>

		<guid isPermaLink="false">http://srirangan.net/?p=921</guid>
		<description><![CDATA[Submitted a proposal for JSFoo Chennai 2012 titled Ajax is history &#8211; Build real time apps in JavaScript. Quick preview: Objective How to build the next generation of real-time browser based apps with JavaScript and related technologies. Description Ajax is &#8230; <a href="http://srirangan.net/2012-02-jsfoo-chennai-2012-ajax-is-history-build-real-time-apps-in-javascript">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Submitted a proposal for JSFoo Chennai 2012 titled <a href="http://funnel.hasgeek.com/jsfoo-chennai/218-ajax-is-history-build-real-time-apps-in-javascript">Ajax is history &#8211; Build real time apps in JavaScript</a>.</p>
<p>Quick preview:</p>
<blockquote><p><strong>Objective</strong><br />
How to build the next generation of real-time browser based apps with JavaScript and related technologies.</p>
<p><strong>Description</strong><br />
Ajax is history. After having built Review19 &#8212; Review19.com provides next generation real-time collaborative tools &#8212; I&#8217;d like to share my approach, the technologies used, the architecture followed by a quick demo and code walk through.</p>
<p><strong>Requirements</strong><br />
* Good sense of humor<br />
* Appreciation for random katrina kaif pics inserted between slides<br />
* Knowledge of web app development in general<br />
* More JavaScript (Node, NPM etc.) stack knowledge, the better</p></blockquote>
<p>If you&#8217;re interested, don&#8217;t forget to <a href="http://funnel.hasgeek.com/jsfoo-chennai/218-ajax-is-history-build-real-time-apps-in-javascript">vote</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://srirangan.net/2012-02-jsfoo-chennai-2012-ajax-is-history-build-real-time-apps-in-javascript/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How I built a real-time collaborative app with MongoDB</title>
		<link>http://srirangan.net/2012-01-how-i-built-a-real-time-collaborative-app-with-mongodb</link>
		<comments>http://srirangan.net/2012-01-how-i-built-a-real-time-collaborative-app-with-mongodb#comments</comments>
		<pubDate>Sat, 14 Jan 2012 13:10:03 +0000</pubDate>
		<dc:creator>Srirangan</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[mongodb]]></category>
		<category><![CDATA[node.js]]></category>
		<category><![CDATA[review19]]></category>

		<guid isPermaLink="false">http://srirangan.net/?p=904</guid>
		<description><![CDATA[This is an account of how Review19 was built in just a couple of weeks and how MongoDB was an excellent choice for this genre of browser based, real-time collaborative apps. First things first &#8212; what is Review19? Review19 is &#8230; <a href="http://srirangan.net/2012-01-how-i-built-a-real-time-collaborative-app-with-mongodb">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>This is an account of how <a href="http://www.review19.com">Review19</a> was built in just a couple of weeks and how <a href="http://www.mongodb.org/">MongoDB</a> was an excellent choice for this genre of browser based, real-time collaborative apps.</p>
<p>First things first &#8212; what is Review19? Review19 is the next generation, real-time project collaboration tool for web, creative and software teams. Think of it as a minimalist, real-time Pivotal Tracker alternative. It&#8217;s like Trello, but caters to a focused target audience.</p>
<p>Give it a shot, try out <a href="http://www.review19.com">Review19</a>. If you&#8217;re stuck behind a proxy that doesn&#8217;t like web sockets, here&#8217;s the <a href="http://review19.com:3000">failover link</a>.</p>
<h2>The Technology Stack</h2>
<p>Obviously an app can&#8217;t be built with a data store alone. </p>
<p>In addition to a MongoDB based storage engine, the APIs and backend for Review19 are built on the Node.js platform and make use of popular frameworks including Express and Socket.io.</p>
<p>The frontend client app &#8212; which is under heavy refactoring as we speak &#8212; leverages advances in browser capability with respect to JavaScript execution and CSS renderings. The frameworks here include jQuery, jQuery UI and Sugar among others.</p>
<p>Why am I mentioning all of this? The overall technology stack needs to be known to highlight a huge advantage:</p>
<h2>JSON. Everywhere!</h2>
<p>I&#8217;ve been a professional programmer for ten years now and I&#8217;ve had the fortune (misfortune?) of working with a diverse set of technologies. </p>
<p>I happen to have dealt with:</p>
<ul>
<li>the typical enterprise Java stack &#8211; Spring, Hibernate etc.</li>
<li>
recent advances in Java technologies including Scala, LiftWeb, Play! etc.</li>
<li>
built apps in Python using Django, Tornado and Google App Engine</li>
<li>
built apps in PHP and its set of frameworks</li>
<li>
built apps in Adobe Flex working with different types backend APIs</li>
</ul>
<p>In each of these technologies, a developer has to deal with the mundane task of transforming his model between the client, server and data store. Better development teams would automate this process with the use of ORMs or helper frameworks. However this would still need the inclusion of these dependencies and the configuration of these frameworks.</p>
<p>While developing Review19 with the chosen technologies, things worked out of the box. It was JSON on the server, JSON on the client and, thanks to MongoDB, JSON on the data store. The productivity benefit was huge, especially for an independent developer like me, or small teams with tough deadlines.</p>
<p>The advantage of this cannot be underplayed. It strikes you right away when you build your first proof-of-concept and it stays with you throughout your development cycle. </p>
<h2>Flexibility is not just a buzz-word</h2>
<p>About 10-12 months ago, I was working on a project for an SF Bay startup that wanted to built an analytics / BI suite running on top of customer databases. </p>
<p>It wasn&#8217;t a very complex project, but just a large and poorly managed one. I remember being asked repeatedly about how the database was being versioned. The answer &#8220;it was being versioned in the code&#8221; wasn&#8217;t good enough for the &#8216;expert&#8217; and his evil overlords.</p>
<p>Hmm.. generating and storing multiple versions of the data model as an .sql file in your source code repository. Sounds familiar? Of course it does. And it sounds just as painful as it sounds familiar. Even if this process is somehow painstakingly automated and devs don&#8217;t have to deal with it any more, you still often end up with multiple version of SQL files never being used.</p>
<p>Whatever your application be, the entities / models are bound to evolve with time. Things will change, sometimes so much that they won&#8217;t share even the slightest resemblance with the original designs. </p>
<p>With MongoDB, however, the data store adapts seamlessly to your app. There isn&#8217;t the slightest need to run scripts, create tables, alter columns etc. on the data store prior to each deployment. This is how it&#8217;s done for Review19 and I&#8217;d assume for a majority of projects using MongoDB.</p>
<p>This will bring a small morale boost and a large productivity boost for your dev and devops teams.</p>
<h2>Node.js + MongoDB = MongoJS</h2>
<p>MongoDB is one of the most mature NoSQL options available today and that maturity is proven by the rich set of APIs MongoDB provides that allow you to perform basic and advanced operations on your data.</p>
<p>Furthermore the MongoDB Querying APIs are ridiculously simple, yet powerful and easy to master. In fact its so easy to learn that you wouldn&#8217;t miss the very same SQL that you spent years to master.</p>
<p>A majority of MongoDB evangelists and proponents I&#8217;ve interacted with swear by this capability. After spending sometime on the MongDB Interactive Shell, I could see what they meant.</p>
<p>I needed to access the same capabilities in my Node.js backend app. Node.js has got a well maintained MongoDB driver and a lot of interesting abractions on top of that driver. </p>
<p>My choice zeroed in on <a href="https://github.com/gett/mongojs">MongoJS</a> and the clinching argument was the MongoJS mission statement:</p>
<blockquote><p>&#8220;A node.js module for mongodb, that emulates the mongodb API as much as possible.&#8221;</p></blockquote>
<p>Your actual executable JavaScript code looks exactly the same to what you do the MongoDB console. How can this not be a #win? I like minimalism and MongoJS was as minimalist as possible.</p>
<p>There are a lot of other options as well for Node.js &#8211; MongoDB interaction and it would be best to cover them in detail in a future post.</p>
<h2>Speed</h2>
<p>Did I mention Review19 is incredibly fast? Almost in all the feedback received, the users mention among other things how fast it is and how it improved their experience.</p>
<p>I understand that application architecture has a role to play in this but one can&#8217;t take all the credit for the speed and performance witnessed by Review19 users. One must thank the underlying platforms it was built on which includes Node.js and MongoDB.</p>
<p>I&#8217;m sure you&#8217;ll find all the MongoDB speed benchmarks you want. They&#8217;re just a Google search away. What I intend to highlight here is that in a real world collaborative app which has a single instance running on standard, non-fancy hardware, Node.js and MongoDB are serving the needs brilliantly. </p>
<p>Remember this is a real-time collaboration app where instead of frequent smaller requests, a frontend client has a long lived connection with the backend server. This is exactly the kind of app that would have faced scaling issues few years ago and would have needed a lot of infrastructure both in terms of code and hardware.</p>
<p>Node.js and MongoDB make this economical for independent devs like me without the resources big corps can provide.</p>
<h2>Conclusion</h2>
<p>I&#8217;m extremely pleased with the technology choices made in which of course MongoDB is a critical component. I&#8217;ve completed the entire product cycle from conceptualization and design to testing, development and deployments.  </p>
<p>Described above are ways MongoDB made this enitre process simpler, kept deployments easy and provided all the features and more needed by Review the app.</p>
<p>Now I look forward the the next set of challenges which include maintaining, scaling and enhancing the system. And I promise to let you know how that goes. Stay tuned to this blog! ;-)</p>
]]></content:encoded>
			<wfw:commentRss>http://srirangan.net/2012-01-how-i-built-a-real-time-collaborative-app-with-mongodb/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>How Trello is *not* different</title>
		<link>http://srirangan.net/2012-01-how-trello-is-not-different</link>
		<comments>http://srirangan.net/2012-01-how-trello-is-not-different#comments</comments>
		<pubDate>Sat, 07 Jan 2012 05:36:27 +0000</pubDate>
		<dc:creator>Srirangan</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[mongodb]]></category>
		<category><![CDATA[node.js]]></category>
		<category><![CDATA[review19]]></category>
		<category><![CDATA[trello]]></category>
		<category><![CDATA[web sockets]]></category>

		<guid isPermaLink="false">http://srirangan.net/?p=887</guid>
		<description><![CDATA[Joel Spolsky, a figure lot of us look up to, made a very interesting post about Trello and how it is different. Note &#8211; Before reading any further, you should know I am the creator of Review19, a tool quite &#8230; <a href="http://srirangan.net/2012-01-how-trello-is-not-different">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Joel Spolsky, a figure lot of us look up to, made a very interesting <a href="http://www.joelonsoftware.com/items/2012/01/06.html">post</a> about <a href="https://trello.com/">Trello</a> and how it is different.</p>
<blockquote><p>Note &#8211; Before reading any further, you should know I am the creator of <a href="http://review19.com/">Review19</a>, a tool quite similar to Trello.
</p></blockquote>
<p>I loved Spolsky&#8217;s post, except the title. Trello didn&#8217;t seem different at all. Going by a lot of Spolsky&#8217;s parameters, Review19 and Trello are <em>very</em> similar.</p>
<p>Here&#8217;s trying to shed more light on my claim:</p>
<h2>Hosted Only</h2>
<p>Review19 &#8211; Yes<br />
Trello &#8211; Yes</p>
<p>Both Review19 and Trello are hosted only solutions, at least as of now. You cannot buy a license and install privately on your servers.</p>
<h2>Continuous Delivery</h2>
<p>Review19 &#8211; Yes<br />
Trello &#8211; Yes</p>
<p>Just like Google Chrome &#8212; which still maintains versions &#8212; but is released / delivered continuously for all intents and purposes both Review19 and Trello share this development / delivery model.</p>
<h2>Inexhaustive Testing</h2>
<p>Review19 &#8211; Yes<br />
Trello &#8211; Yes</p>
<p>Joel&#8217;s team at Fog Creek, by choice, don&#8217;t exhaustively test Trello before each release. Review19 is being development and maintained by a single individual, i.e. me, it&#8217;s not really possible to exhaustively test Review19 either. Sorry about that!</p>
<h2>Work in public</h2>
<p>Review19 &#8211; Yes<br />
Trello &#8211; Yes</p>
<p>Trello works in public by offering a public status board. Review19 puts itself out their through a public mailing list and roadmap. Volunteers are added to a private status board.</p>
<h2>Get big fast</h2>
<p>Review19 &#8211; Yes<br />
Trello &#8211; Yes</p>
<p>Trello aims to get 100 million users. I&#8217;d be an idiot if I didn&#8217;t want that for Review19 either. ;-)</p>
<h2>Free</h2>
<p>Review19 &#8211; Yes<br />
Trello &#8211; Yes</p>
<h2>Plugin architecture</h2>
<p>Review19 &#8211; Yes<br />
Trello &#8211; Yes</p>
<p>The merits of such an architecture are obvious. Review19 uses client and server side JavaScript modules for achieving such an architecture. I&#8217;m not sure how Trello does it but we have no reason to doubt Joel&#8217;s remark.</p>
<h2>Node.js</h2>
<p>Review19 &#8211; Yes<br />
Trello &#8211; Yes</p>
<h2>MongoDB</h2>
<p>Review19 &#8211; Yes<br />
Trello &#8211; Yes</p>
<h2>Web Sockets</h2>
<p>Review19 &#8211; Yes<br />
Trello &#8211; Yes</p>
<h2><em>How Review19 is different</em></h2>
<h2>Horizontal</h2>
<p>Review19 &#8211; No<br />
Trello &#8211; Yes</p>
<p>Trello is for everybody. Review19 is for distributed or colocated web, creative and software teams. Spolsky notes the benefits of being vertical, I agree.</p>
<p>Spolsky wants Trello to be horizontal, I can understand. I did consider making Review19 horizontal but chose against it.</p>
<h2>Video conferencing</h2>
<p>Review19 &#8211; Yes<br />
Trello &#8211; No</p>
<p>Review19&#8242;s target audience &#8212; web, creative and software teams &#8212; are often distributed around the world. Offering an in-browser, video conferencing option is a critical feature for Review19.</p>
<h2>CoffeeScript</h2>
<p>Review19 &#8211; No<br />
Trello &#8211; Yes</p>
<p>No thanks, I see far too many benefits of staying with JavaScript at least as of now.</p>
<h2>APIs top priority?</h2>
<p>Review19 &#8211; I wish!<br />
Trello &#8211; Yes</p>
<p>I wish! I&#8217;m only a single guy working full-time on multiple projects to earn my living. Review19 will have APIs, at some point of time!</p>
]]></content:encoded>
			<wfw:commentRss>http://srirangan.net/2012-01-how-trello-is-not-different/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>An Introduction to Functional Programming in JavaScript</title>
		<link>http://srirangan.net/2011-12-functional-programming-in-javascript</link>
		<comments>http://srirangan.net/2011-12-functional-programming-in-javascript#comments</comments>
		<pubDate>Sun, 25 Dec 2011 16:06:20 +0000</pubDate>
		<dc:creator>Srirangan</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[fp]]></category>
		<category><![CDATA[functional programming]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://srirangan.net/?p=808</guid>
		<description><![CDATA[For me, in many ways, 2011 has been the year of the rediscovery of JavaScript. I have been programming in JavaScript for many years (like most other programmers) but now I&#8217;ve come to appreciate JavaScript the language a little better. &#8230; <a href="http://srirangan.net/2011-12-functional-programming-in-javascript">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>For me, in many ways, 2011 has been the year of the rediscovery of JavaScript. I have been programming in JavaScript for many years (like most other programmers) but now I&#8217;ve come to appreciate JavaScript the language a little better.</p>
<p>2011 was also when I had to dig into Scala. Thus I was compelled to implement more solutions in a functional manner. </p>
<p>Like many programmers unfamiliar with Functional Programming or others familiar with Functional Programming but more comfortable with Object Oriented Programming, it was daunting at first. </p>
<p>But persist through and one starts to see the benefits of Functional Programming (or at least understand it enough and execute your projects).</p>
<p>If you&#8217;re looking for a quick start in Functional Programming, JavaScript is the perfect language for you. Here&#8217;s why:</p>
<ul>
<li>Almost all programmers have tweaked and / or written JavaScript code at some point of time &#8212; hence there should be a certain familiarity</li>
<li>JavaScript comes as close to a standardized programming language we&#8217;ll get &#8212; it&#8217;s the only programming language available across all web browsers</li>
<li>JavaScript comes with a very familiar C like syntax and should be readable to most programmers</li>
<li>Functions have always been first class members in JavaScript, support for Functional Programming is very good and in many ways JavaScript has been ahead of its time</li>
<li>JavaScript doesn&#8217;t have Java like Class based Object Oriented Programming support so in many ways you&#8217;re forced to be Functional in JavaScript</li>
</ul>
<p>These should be enough reasons, so without meandering any further in the introduction, I present <em>Functional Programming with JavaScript</em>:</p>
<hr/>
<h2>Functions in JavaScript</h2>
<p>Almost everyone reading would have seen <strong>function declarations</strong> in JavaScript. However JavaScript lets you explicitly express functions as objects.</p>
<p>In fact, all <strong>function declarations</strong> are automatically converted to <strong>function expressions</strong> and hoisted. </p>
<p>By <strong>hoisting</strong>, the converted function expression is automatically placed in the beginning and thus is available in lines before it has been declared.</p>
<p><script src="https://gist.github.com/1519440.js"> </script></p>
<hr/>
<p>JavaScript functions are also different in the sense that each function, regardless of how it is defined, has dynamic arguments and a dynamic context.</p>
<p>A JavaScript function can, of course, access its arguments by their variable names. </p>
<p>By dynamic arguments, I mean, in the function body, we are provided an <strong>arguments</strong> array which contain all the arguments sequentially in the order they were passed. This means any function can be called with any set of arguments, thus giving us a lot of flexibility.</p>
<p>By dynamic context, I am refering to the <strong>this</strong> object. Typically the <strong>this</strong> object defaults sensibly to the context of the function. However it is possible to explicitly call a function with a user defined <strong>this</strong> / context object.</p>
<p><script src="https://gist.github.com/1519443.js"> </script></p>
<p>Notice how <code>functionName.apply()</code> allows us to explicitly set the context and pass arguments.</p>
<hr/>
<p>I must point out that JavaScript presents us with <strong>functional scoping</strong> instead of <strong>block scoping</strong> (C, C++ etc.). This usually becomes more relevant when you need to implement Object Oriented patterns in JavaScript but more on that in a later blog post.</p>
<p>Another trick for you is the capability to define <strong>self-executing anonymous function</strong>. These can be creatively used to implement modular namespaces / packages. Here are some examples:</p>
<p><script src="https://gist.github.com/1519445.js"> </script></p>
<hr/>
<h2>Higher Order Functions</h2>
<p>We know functions in JavaScript are nothing but objects. Does this mean functions can be passed around as arguments to other functions? And can one function return another function?</p>
<p>The answer to both questions is &#8220;Yes&#8221;. And such functions which taking in other functions are arguments and / or return functions are typically called <strong>higher order functions</strong>.</p>
<p>In the example below, we will define a higher order function <code>forEach</code>. This function takes in two arguments: a <code>list</code> and an <code>action</code>. The first argument list is an array containing containing objects and the second argument action is a function that will be invoked for each item in list.</p>
<p><script src="https://gist.github.com/1519447.js"> </script></p>
<p>The simple example above shows how a named function <code>logItem</code> and an <code>anonymous function</code> are being passed as arguments to the higher order function <code>forEach</code>.</p>
<hr/>
<h2>Map / Reduce Implementations</h2>
<p>In the example above, we saw how the <code>forEach</code> algorithm was expressed as a function and reused multiple times as an when required. We avoided repeating loops and thus made the code more readable.</p>
<p>This is one of the prime reasons to write functional code. If done correctly, you&#8217;ll be able to abstract out complex algorithms, replace it with a nice function call and keep code condensed and readable.</p>
<p>To further stress this idea, we need a better example. For each was too simple an algorithm to abstract. Let&#8217;s try implementing higher order functions for <strong>Map and Reduce algorithms</strong>.</p>
<p>We start with the Map function. What is the map function? Our <code>map</code> function should allow the user to perform a particular action over each item of a <code>list</code>, and then return a <code>result</code> list containing results of actions performed on each list item.</p>
<p>Simple enough, show me the code!</p>
<p><script src="https://gist.github.com/1519448.js"> </script></p>
<p>Notice we reuse the <code>forEach</code> function from the previous example. Our <code>map</code> function takes in two arguments, the first one being the <code>mappingFunction</code> that is to be applied on every item of the second argument <code>list</code>.</p>
<p>The implementation for <code>map</code> is straightforward. We prepare an array result, iterate through the list, call the <code>mappingFunction</code> for each item in <code>list</code>, push the result in the result array return it when all done.</p>
<p>As an example, we are calling map function and passing the function <code>doubleIt</code> as the <code>mapperFunction</code> on each item of an anonymous list.</p>
<p>Time for the <code>reduce</code> function. What is the reduce algorithm? The <code>reduce</code> function will be given a <code>combine</code> function, a <code>base</code> value and a <code>list</code>. We need to apply the <code>combine</code> function on the base value and each value in the list and finally return the result. In short, Reduce function takes in a list, combines it and gives us a single result.</p>
<p><script src="https://gist.github.com/1519449.js"> </script></p>
<p>This solution again makes use of the previous create <code>forEach</code> function. Our <code>reduce</code> function is simple, it iterates through the <code>list</code>, applies <code>combine</code> on <code>base</code> and each list item, stores the result in base and returns it after completion.</p>
<p>As a usage example, we use <code>reduce</code> to get a count of the negative numbers in a list.</p>
<p>These two examples are fairly simple and still show us how, with functional programming, we can effectively abstract out algorithms as functions, use them as and when required and still retain simplicility and readability in the code.</p>
<hr/>
<h2>Closures in JavaScript</h2>
<p>If you&#8217;ve heard of Functional Programming, there&#8217;s a very good chance you&#8217;ve also heard about <strong>closures</strong>. They are often mentioned in the same breath.</p>
<p>But what are closures? Think of closures as a composite of two things:</p>
<ol>
<li>A function being returned by another function</li>
<li>A closed environment in which this returned function is forced to execute</li>
</ol>
<p>This is what a closure is.</p>
<p>In our first example of a closure implementation, we have <code>getAreaFunction</code> which reads the shape argument and returns an appropriate area function.</p>
<p><script src="https://gist.github.com/1519450.js"> </script></p>
<p>Notice how <code>getAreaFunction</code> returns an anonymous function. This returned function contains a switch case on shape which is available in the <em>environment</em>.</p>
<p>Finally, of course, we see how to use the closure as a <em>function factory</em> to get area functions for different types of shapes.</p>
<hr/>
<p>In our second closure example, we see how closures are used to implement private class members in JavaScript.</p>
<p><script src="https://gist.github.com/1519451.js"> </script></p>
<p>I&#8217;ll not explain Object Oriented Programming implementations in JavaScript as part of this post. They aren&#8217;t complex but are different, surely worthy of a dedicated post.</p>
<p>If you&#8217;re already familiar with OOP concepts and their implementations in JavaScript, note how the class <code>Shape</code> (which is, yes, expressed as a function) contains a private function <code>area</code> and isn&#8217;t exposed.</p>
<p>Instead an instance function <code>getArea</code> is available which does internally make use of the private function <code>area</code>.</p>
<p>This is one of the most common use-cases of closures in JavaScript.</p>
<hr/>
<p>Another classic use-case for closures in JavaScript is to avoid the annoying problem that crops up every time you try to set event handlers within a loop.</p>
<p>Consider the following example:</p>
<p><script src="https://gist.github.com/1519452.js"> </script></p>
<p>In the for loop, we first assign an <code>onclick</code> handler to all the red boxes. However, thanks to functional scoping, all three red boxes have onclick handlers with <code>redBoxId</code> value 3.</p>
<p>However for green boxes we assign <code>onclick</code> handlers in a slightly different manner. We have a self executing anonymous function which returns another function which then is assigned as the onclick handler.</p>
<p>Due to functional scopes, each <code>onclick</code> handler for the green boxes have correct values for <code>greenBoxId</code>.</p>
<hr/>
<p>I realize this has been a fairly lengthy post. Will end it now. Hopefully this would have served as a good enough introduction to Functional Programming concepts and their corresponding implementations in JavaScript.</p>
<p>All code available on <a href="https://github.com/Srirangan/javascript-playground/tree/master/functional-javascript">GitHub</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://srirangan.net/2011-12-functional-programming-in-javascript/feed</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>JavaScript &#8211; Function Declarations vs. Function Expressions</title>
		<link>http://srirangan.net/2011-12-javascript-function-declarations-vs-function-expressions</link>
		<comments>http://srirangan.net/2011-12-javascript-function-declarations-vs-function-expressions#comments</comments>
		<pubDate>Sat, 24 Dec 2011 06:31:36 +0000</pubDate>
		<dc:creator>Srirangan</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://srirangan.net/?p=791</guid>
		<description><![CDATA[Here&#8217;s an example of a function declaration in JavaScript: function sayMyName() { console.log("!Xobile"); } Looks very familiar. And is probably the most obvious way programmers have created functions since the beginning of time JavaScript. In JavaScript, everything is an object. &#8230; <a href="http://srirangan.net/2011-12-javascript-function-declarations-vs-function-expressions">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s an example of a function declaration in JavaScript:</p>
<pre>
function sayMyName() {
  console.log("!Xobile");
}
</pre>
<p>Looks very familiar. And is probably the most obvious way programmers have created functions since the beginning of <del>time</del> JavaScript.</p>
<p>In JavaScript, everything is an object. What happens internally is this declaration gets converted into an expression.</p>
<p>What&#8217;s an expression? An expression is any statement that produces a value.</p>
<p>Thus, a function expression becomes:</p>
<pre>
var sayMyName = function() {
  console.log("!Xobile");
};
</pre>
<p>Function declarations try to hide the fact that the function is indeed an object. </p>
<p>While this may be okay in some cases, it could create confusion when the function is actually being used as a object i.e. being returned, passed around, modified etc.</p>
<p>JavaScript programming (and the programming world in general) is becoming more functional by the day, and it may be a better practice to avoid function declarations altogether in favor of function expressions.</p>
<p>But why? Hoisting. </p>
<p>Function declarations are automatically &#8220;hoisted&#8221;. The compiler automatically expresses all function declarations at the top of the code regardless of where in the code the function is declared.</p>
<p>This may or may not be a problem depending on the scope-complexity of your code. However it is something that happens automatically, whether you want it or not, and it may be advisable to take such control away from the compiler.</p>
<p>Especially since scoping is very different in JavaScript compared to traditional languages. More on JavaScript scoping in a future blog post.</p>
]]></content:encoded>
			<wfw:commentRss>http://srirangan.net/2011-12-javascript-function-declarations-vs-function-expressions/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Why you must use Review19 for your project</title>
		<link>http://srirangan.net/2011-12-why-you-must-use-review19-for-your-project</link>
		<comments>http://srirangan.net/2011-12-why-you-must-use-review19-for-your-project#comments</comments>
		<pubDate>Wed, 07 Dec 2011 08:12:34 +0000</pubDate>
		<dc:creator>Srirangan</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[mongodb]]></category>
		<category><![CDATA[node.js]]></category>
		<category><![CDATA[review19]]></category>
		<category><![CDATA[socket.io]]></category>

		<guid isPermaLink="false">http://srirangan.net/?p=772</guid>
		<description><![CDATA[Last week I rolled out a new preview release of Review19. Review19 is a simple and intuitive project management tool. It is just as suited for teams distributed around the world as it is for colleagues working in the same &#8230; <a href="http://srirangan.net/2011-12-why-you-must-use-review19-for-your-project">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Last week I rolled out a new preview release of <a href="http://review19.com:3000"><strong>Review19</strong></a>.</p>
<p>Review19 is a simple and intuitive project management tool. It is just as suited for teams distributed around the world as it is for colleagues working in the same office.</p>
<p><a href="http://review19.com"><img class="alignright" src="http://review19.com/images/thumbnail-screenshot1.png"/></a></p>
<p>However it doesn&#8217;t try to be a universal, multi-purpose app. Review19 has been built, finetuned and polished specifically for web, creative and software teams.</p>
<p>To begin you create a project and invite members to your project team. Then you (and your team) can add tickets which can be features, enhancements, bugs or chores. Tickets have a description with optional additional details and one or more sub-tasks. In addition, tickets have a priority and can be assigned to a team member.</p>
<p><a href="http://review19.com"><img class="alignright" src="http://review19.com/images/thumbnail-screenshot3.png"/></a></p>
<p>On the status board, you see all tickets arranged in columns for backlog, scheduled, in progress and complete. Tickets can be dragged across columns and filters can be applied based on user or ticket type.</p>
<p>Oh by the way, while you do all this, the changes you make are synced realtime and your team members can see them and vice-versa. The user interface, built exclusively in HTML5+CSS, keeps this app really simple and intuitive for first time users.</p>
<p><a href="http://review19.com"><img class="alignright" src="http://review19.com/images/thumbnail-screenshot2.png"/></a></p>
<p>Then there is the &#8220;Conference&#8221; tab, which lets you engage with your team members with video chats and text chat sessions. The video chat runs in-browser with the flash plugin and doesn&#8217;t require any external application be downloaded / installed.</p>
<p>Personally for me, the most exciting part of Review19 is the yet unreleased roadmap which ensures continuous improvements of the core product along with some more incredible features currently unseen in similar products.</p>
<p>Give <a href="http://review19.com"><strong>Review19</strong></a> a spin and let me know how it works out!</p>
]]></content:encoded>
			<wfw:commentRss>http://srirangan.net/2011-12-why-you-must-use-review19-for-your-project/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>A brand new Review19</title>
		<link>http://srirangan.net/2011-12-a-brand-new-review19</link>
		<comments>http://srirangan.net/2011-12-a-brand-new-review19#comments</comments>
		<pubDate>Fri, 02 Dec 2011 02:20:08 +0000</pubDate>
		<dc:creator>Srirangan</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[google app engine]]></category>
		<category><![CDATA[node.js]]></category>
		<category><![CDATA[review19]]></category>

		<guid isPermaLink="false">http://srirangan.net/?p=755</guid>
		<description><![CDATA[Last night I rolled out a completely new version of Review19. Umm.. what is Review19? Review19 tries to be a simpler alternative to the likes of Atlassian JIRA and Pivotal Tracker. Its design was driven by the principle of &#8220;less &#8230; <a href="http://srirangan.net/2011-12-a-brand-new-review19">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Last night I rolled out a completely new version of <a href="http://www.review19.com">Review19</a>.</p>
<p><em>Umm.. what is Review19?</em></p>
<p>Review19 tries to be a simpler alternative to the likes of Atlassian JIRA and Pivotal Tracker. Its design was driven by the principle of &#8220;less is more&#8221; yet it can boast of better usability and features.</p>
<p>The new Review19 is a move away from Google App Engine towards Node.js and other open source technologies. The reason is to avoid vendor lock in and leverage new technologies where the Google App Engine SDK lags behind.</p>
<p>However the new Review19 is lot more than just a migration of underlying technology. Presenting some of the more significant updates:</p>
<ul>
<li><strong>Video Conferencing</strong> &#8211; Conduct video chat sessions with your project team within your web browser. Goodbye Skype!</li>
<li><strong>Kanban + Scrum Board</strong> &#8211; No complex work flows imposed, just works</li>
<li>Tickets support <strong>features</strong>, <strong>bugs</strong>, <strong>chores</strong> and <strong>enhancements</strong></li>
<li>Sub-tasking support within tickets</li>
<li>Numerous usability and user interface enhancements, less glare and intuitive interactions</li>
</ul>
<p>Give it a spin, try out <a href="http://www.review19.com">Review19</a> at <a href="http://www.review19.com">http://www.review19.com</a></p>
<p>Interested in your feedback, feel free to drop in a message. Join the <a href="https://groups.google.com/forum/#!forum/review19-community">mailing list</a> for more.</p>
]]></content:encoded>
			<wfw:commentRss>http://srirangan.net/2011-12-a-brand-new-review19/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Notifier.js &#8211; Elegant Javascript notifications</title>
		<link>http://srirangan.net/2011-11-notifier-js-elegant-javascript-notifications</link>
		<comments>http://srirangan.net/2011-11-notifier-js-elegant-javascript-notifications#comments</comments>
		<pubDate>Thu, 03 Nov 2011 11:21:28 +0000</pubDate>
		<dc:creator>Srirangan</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[notifications]]></category>
		<category><![CDATA[notifier.js]]></category>
		<category><![CDATA[Open source]]></category>

		<guid isPermaLink="false">http://srirangan.net/?p=723</guid>
		<description><![CDATA[Before starting a major project, I&#8217;m laying out the groundwork and creating some of the libraries required. This includes Notifier.js &#8212; a Javascript library for Gnome / Growl type non-blocking notifications. It depends on Jquery. At 68 lines of code, &#8230; <a href="http://srirangan.net/2011-11-notifier-js-elegant-javascript-notifications">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Before starting a major project, I&#8217;m laying out the groundwork and creating some of the libraries required.</p>
<p>This includes <a href="http://opensource.srirangan.net/notifier.js/">Notifier.js</a> &#8212; a Javascript library for Gnome / Growl type non-blocking notifications. <a href="http://s7.postimage.org/at9xw1diz/notifierjs_screenshot.png"><img class="alignright" title="Notifier.js" src="http://s7.postimage.org/at9xw1diz/notifierjs_screenshot.png" alt="" width="270" /></a></p>
<p>It depends on Jquery. At 68 lines of code, Notifier.js can be classified as minimalist.</p>
<p>Notifier.js supports <code>success</code>, <code>info</code>, <code>warning</code> and <code>error</code> notifications.</p>
<p>Notifications show up at the top-right corner and fade away in 5 seconds (by default). Click and it fades away even sooner.</p>
<p>Multiple notifications at the same time stash up in a vertical list.</p>
<p>Notifier.js has been designed for easy inclusion in any existing small or large project.</p>
<p><a href="http://opensource.srirangan.net/notifier.js/">Demo</a> | <a href="https://github.com/downloads/Srirangan/notifer.js/notifier.js.zip">Download (.zip archive, 26.8KBs)</a></p>
<p>The source code and usage examples can be found on GitHub &#8211; <a href="https://github.com/Srirangan/notifer.js">https://github.com/Srirangan/notifer.js</a></p>
<p>Feel free to use it, fork it and provide feedback / pull requests.</p>
]]></content:encoded>
			<wfw:commentRss>http://srirangan.net/2011-11-notifier-js-elegant-javascript-notifications/feed</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Getting Nginx + PHP 5.3 to work, properly!</title>
		<link>http://srirangan.net/2011-10-getting-nginx-php-5-3-to-work-properly</link>
		<comments>http://srirangan.net/2011-10-getting-nginx-php-5-3-to-work-properly#comments</comments>
		<pubDate>Sun, 09 Oct 2011 12:16:30 +0000</pubDate>
		<dc:creator>Srirangan</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://srirangan.net/?p=711</guid>
		<description><![CDATA[Over the past few days, I moved a few Apache2 + PHP webapps (including this WordPress blog) from a shared host to a dedicated CentOS server. By default the server came with Apache2 (httpd) web server, but I wanted to &#8230; <a href="http://srirangan.net/2011-10-getting-nginx-php-5-3-to-work-properly">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Over the past few days, I moved a few Apache2 + PHP webapps (including this WordPress blog) from a shared host to a dedicated CentOS server. By default the server came with Apache2 (httpd) web server, but I wanted to use Nginx instead. Why Nginx? It&#8217;s *much* faster and scales better with lower resource usage.</p>
<p>Installing Nginx, PHP and MySQL wasn&#8217;t a problem and there were tonnes of resources on the internet to help me through. Where I did face a challenge was to get Nginx and PHP to play nicely.</p>
<p>Before I explain what went wrong, I will note the differences in the way Apache2 and Nginx handle PHP. </p>
<p>For Apache2, in many cases, PHP is configured as an internal module. Alternatively it can also be used in CGI mode. However, no matter how it&#8217;s configured, it is the web server&#8217;s responsibility to interface with PHP (which means having to spawn PHP instances as an when required).</p>
<p>In the case of Nginx, things are very different. Casually put, Nginx acts as a proxy server and will redirect requests to a PHP-CGI server instance running on your box. This means, of course, you are now responsible for spawning a PHP-CGI server instance and configuring Nginx to use it.</p>
<p>Not so bad, so I went ahead and did it. Here&#8217;s where the real problem comes in. </p>
<p>After some time, I found that the PHP-CGI instance automatically hung up and needed to be restarted. In the browser this showed up as 502 Bad Gateway errors. I Google&#8217;d it for a few hours and couldn&#8217;t find a definite solution. However few links did indicate that some PHP modules were the cause for the PHP-CGI crash. The best solution out there I could find was to setup a cron to re-up the PHP-CGI instance every N minutes. </p>
<p>But even if this cron interval is 1 minute, it still leaves a low but significant probability that a user sees the error, refreshes immediately, sees the error again and quits your website. Not acceptable.</p>
<p>My quick fix solution? Reduce this probability. How?</p>
<h2>Setup multiple instances of PHP-CGI</h2>
<pre>
$ php-cgi -b 127.0.0.1:9000 &#038;
$ php-cgi -b 127.0.0.1:9001 &#038;
$ php-cgi -b 127.0.0.1:9002 &#038;
$ php-cgi -b 127.0.0.1:9003 &#038;
$ php-cgi -b 127.0.0.1:9004 &#038;
</pre>
<h2>Setup the cron to re-up the PHP-CGI instances if they&#8217;re down</h2>
<pre>
$ crontab
*/2  *  *  *  *  php-cgi -b 127.0.0.1:9000
*/2  *  *  *  *  php-cgi -b 127.0.0.1:9001
*/2  *  *  *  *  php-cgi -b 127.0.0.1:9002
*/2  *  *  *  *  php-cgi -b 127.0.0.1:9003
*/2  *  *  *  *  php-cgi -b 127.0.0.1:9004
</pre>
<h2>Configure Nginx to choose from this pool</h2>
<pre>
http {
    ...
    upstream phpfcgi {
        server 127.0.0.1:9000;
        server 127.0.0.1:9001;
        server 127.0.0.1:9002;
        server 127.0.0.1:9003;
        server 127.0.0.1:9004;
    }
    ...
    server {
        server_name        {server name};
        root               {path to document root};

        location / {
            index          index.php;
        }

        location ~\.php$ {
            fastcgi_pass    phpfcgi;
            fastcgi_index   index.php;
            include         fastcgi_params;
            fastcgi_param   SCRIPT_FILENAME $document_root/$fastcgi_script_name;
        }
    }

}
</pre>
<p>This reduces the probability of the user to repeatedly see the 502 Bad Gateway errors. This can be improved by having the cron trigger a script which checks if the php-cgi process has hung up before attempting to restart it.</p>
<p>But a real solution would be to figure out which PHP module *really* is causing the php-cgi to hang in the first place and fix this bug.</p>
<p>I&#8217;ve also stumbled across something called PHP-FPM but I don&#8217;t know enough about it to as yet. You might consider checking that out.</p>
<p>Hope this helps.</p>
]]></content:encoded>
			<wfw:commentRss>http://srirangan.net/2011-10-getting-nginx-php-5-3-to-work-properly/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Download Sources and Docs with SBT</title>
		<link>http://srirangan.net/2011-09-download-sources-docs-sbt</link>
		<comments>http://srirangan.net/2011-09-download-sources-docs-sbt#comments</comments>
		<pubDate>Fri, 30 Sep 2011 01:51:02 +0000</pubDate>
		<dc:creator>Srirangan</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[intellij idea]]></category>
		<category><![CDATA[sbt]]></category>
		<category><![CDATA[scala]]></category>

		<guid isPermaLink="false">http://srirangan.net/?p=696</guid>
		<description><![CDATA[Working on a Scala project and figuring out how to get SBT to download sources and docs for all dependencies? It took a while to figure out but this is what works for SBT 0.10 or higher: sbt update-classifiers For &#8230; <a href="http://srirangan.net/2011-09-download-sources-docs-sbt">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Working on a Scala project and figuring out how to get SBT to download sources and docs for all dependencies? </p>
<p>It took a while to figure out but this is what works for SBT 0.10 or higher:</p>
<pre>  sbt update-classifiers</pre>
<p>For my Scala projects, I return to using an IDE &#8212; IntelliJ IDEA Community (Ultimate is a bit bloated and slow for my liking). The SBT-Idea project links dependencies, sources and docs to your IDEA project with this command:</p>
<pre>  sbt gen-idea</pre>
<p>Make sure you&#8217;ve included SBT Idea as a plugin: <a href="https://github.com/mpeltonen/sbt-idea">https://github.com/mpeltonen/sbt-idea</a></p>
]]></content:encoded>
			<wfw:commentRss>http://srirangan.net/2011-09-download-sources-docs-sbt/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hot reload / Build on save for Adobe Flex</title>
		<link>http://srirangan.net/2011-09-hot-reload-build-on-save-for-adobe-flex</link>
		<comments>http://srirangan.net/2011-09-hot-reload-build-on-save-for-adobe-flex#comments</comments>
		<pubDate>Mon, 26 Sep 2011 06:48:56 +0000</pubDate>
		<dc:creator>Srirangan</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Adobe Flex]]></category>
		<category><![CDATA[node.js]]></category>

		<guid isPermaLink="false">http://srirangan.net/?p=667</guid>
		<description><![CDATA[If you&#8217;re not using Adobe Flash Builder for developing Adobe Flex apps, you might be missing the build on save (or build automatically / hot reload) feature. Here&#8217;s a little Node.js utility that does the same. While working on Flex &#8230; <a href="http://srirangan.net/2011-09-hot-reload-build-on-save-for-adobe-flex">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re not using Adobe Flash Builder for developing Adobe Flex apps, you might be missing the  build on save (or build automatically / hot reload) feature. </p>
<p>Here&#8217;s a little Node.js utility that does the same. While working on Flex with gedit (or any other text editor), just keep &#8220;hotflex&#8221; running in the background. It watches all MXML and AS3 files and rebuilds the project on save.</p>
<h2>Screenshots</h2>

<a href='http://srirangan.net/2011-09-hot-reload-build-on-save-for-adobe-flex/hotflex-build-success' title='hotflex-build-success'><img width="150" height="150" src="http://srirangan.net/wp-content/uploads/2011/09/hotflex-build-success-150x150.png" class="attachment-thumbnail" alt="hotflex-build-success" title="hotflex-build-success" /></a>
<a href='http://srirangan.net/2011-09-hot-reload-build-on-save-for-adobe-flex/hotflex-build-fail' title='hotflex-build-fail'><img width="150" height="150" src="http://srirangan.net/wp-content/uploads/2011/09/hotflex-build-fail-150x150.png" class="attachment-thumbnail" alt="hotflex-build-fail" title="hotflex-build-fail" /></a>

<h2>Dependencies</h2>
<p>Node.js and NPM are required, refer to &#8211; <a href="http://srirangan.net/2011-09-setup-node-js-and-npm-on-ubuntu">Setup Node.js and NPM on Ubuntu</a></p>
<p>For notifications on Ubuntu, install libnotify-bin:</p>
<pre>    sudo apt-get install libnotify-bin</pre>
<p>The Flex SDK is, of course, required and the Flex SDK&#8217;s bin folder should be on the $PATH.</p>
<h2>Install</h2>
<p>From NPM:</p>
<pre>    sudo npm install hotflex -g</pre>
<p>From GitHub:</p>
<pre>    git clone git://github.com/Srirangan/hotflex.git
    cd hotflex
    sudo npm install -g</pre>
<h2>Configure</h2>
<p>You will need to create a <code>hotflex.json</code> file containing the following parameters:</p>
<pre>    { "source": "./src/main/flex/main.mxml"
    , "sourceFolder": "./src"
    , "target": "./bin/main.swf"
    , "lib": "./lib"
    }</pre>
<p>The <code>lib</code> parameter is optional while the rest are mandatory.</p>
<h2>Run</h2>
<p>Execute <code>hotflex</code> from the folder containing the <code>hotflex.json</code> file, preferably your project root.</p>
<pre>hotflex</pre>
<h2>Meta</h2>
<p>GitHub repository &#8211; <a href="https://github.com/Srirangan/hotflex">https://github.com/Srirangan/hotflex</a><br />
NPM &#8211; <a href="http://search.npmjs.org/#/hotflex">http://search.npmjs.org/#/hotflex</a></p>
<h2>Todo</h2>
<ul>
<li>Integration with Adobe Flex Compiler Shell <code>fcsh</code> for faster builds</li>
<li>Integration for Growl for OSX notifications. Currently notifications work for Ubuntu.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://srirangan.net/2011-09-hot-reload-build-on-save-for-adobe-flex/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Setup Node.js and NPM on Ubuntu</title>
		<link>http://srirangan.net/2011-09-setup-node-js-and-npm-on-ubuntu</link>
		<comments>http://srirangan.net/2011-09-setup-node-js-and-npm-on-ubuntu#comments</comments>
		<pubDate>Sun, 25 Sep 2011 13:23:49 +0000</pubDate>
		<dc:creator>Srirangan</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[node.js]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://srirangan.net/?p=653</guid>
		<description><![CDATA[Avoid installing Node.js on Ubuntu from the repositories. They are out-dated. The best option is to download the sources and build. Node.js sources can be downloaded from http://nodejs.org/#download Alternatively, if you&#8217;re a GitHub user, you can clone the repository with: &#8230; <a href="http://srirangan.net/2011-09-setup-node-js-and-npm-on-ubuntu">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Avoid installing <a href="http://nodejs.org/">Node.js</a> on Ubuntu from the repositories. They are out-dated. The best option is to download the sources and build.</p>
<p>Node.js sources can be downloaded from <a href="http://nodejs.org/#download" title="Download Node.js">http://nodejs.org/#download</a><br />
Alternatively, if you&#8217;re a GitHub user, you can clone the repository with:</p>
<pre>git clone git://github.com/joyent/node.git</pre>
<p>Next step, navigate to the Node.js source root folder and execute the following:</p>
<pre>./configure
make
sudo make install</pre>
<p><a href="http://npmjs.org/">NPM</a> is a package manager for Node similar to Apache Maven, Gradle, SBT etc.</p>
<blockquote><p>npm is a package manager for node. You can use it to install and publish your node programs. It manages dependencies and does other cool stuff.</p></blockquote>
<p>Install it with this one line command:</p>
<pre>curl http://npmjs.org/install.sh | sh</pre>
]]></content:encoded>
			<wfw:commentRss>http://srirangan.net/2011-09-setup-node-js-and-npm-on-ubuntu/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>What Java engineers need to know about Node.js</title>
		<link>http://srirangan.net/2011-09-what-java-engineers-need-to-know-about-node-js</link>
		<comments>http://srirangan.net/2011-09-what-java-engineers-need-to-know-about-node-js#comments</comments>
		<pubDate>Sun, 18 Sep 2011 18:48:15 +0000</pubDate>
		<dc:creator>Srirangan</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[node]]></category>
		<category><![CDATA[node.js]]></category>

		<guid isPermaLink="false">http://srirangan.net/?p=620</guid>
		<description><![CDATA[If you&#8217;re new to Node.js and are transitioning from Java, it will not be the same as learning just another programming language. There will be a few surprises, good surprises. Here&#8217;s attempt to capture a few of these &#8220;paradigm shifts&#8221; &#8230; <a href="http://srirangan.net/2011-09-what-java-engineers-need-to-know-about-node-js">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re new to Node.js and are transitioning from Java, it will not be the same as learning just another programming language. There will be a few surprises, good surprises. </p>
<p>Here&#8217;s attempt to capture a few of these &#8220;paradigm shifts&#8221; you may have to make. ;-)</p>
<h2>Non-blocking + Asynchronous</h2>
<p>Line #4 need not execute before line #6. Your design should not require it to do so. Express your implementation as actions and responses i.e. events and handlers.</p>
<p>For instance, in Java you may write:</p>
<pre>
List users = userService.listUsersByStatus(pending);
users.doSomething();
// Something else happens
</pre>
<p>In Node, this would be expressed as:</p>
<pre>
userService.listUsersByStatus(pending, function(users) {
  users.doSomething()
});
// Something else happens
</pre>
<p>The difference in these two examples is that in Java &#8220;something else happens&#8221; always executes after <code>users.doSomething()</code>.</p>
<p>This is not the case in Node, &#8220;something else happens&#8221; would typically execute before <code>users.doSomething()</code>.</p>
<p><code>users.doSomething()</code> is called in an anonymous method that serves as a callback for <code>userService.listUsersByStatus()</code>.</p>
<h2>Less code! Less architecture! Less layers!</h2>
<p>JEE tries to over-do everything. Node keeps it very simple. There isn&#8217;t any need to ritually create a complex package structure, superstitiously over-design with interfaces, spit out cross generational implementations and follow other bloated JEE patterns.</p>
<p>This doesn&#8217;t mean that Node forces you to cramp all your code into a single file either. You can lay it out and distribute it among modules as required. These modules are objects by default and the underlying design principle is minimalism.</p>
<p>For example, a hot topic for debate on Hacker News &#8211; ORMs. In Node, you can do an ORM if you want. But is it required? </p>
<p>Given that the persisted objects are to be consumed by a browser, most of the times passing a MongoDB object to browser (JS) object is sufficient. My opinion on ORMs is that, if possible, they should be avoided. However I&#8217;m digressing from topic and this post is not about ORMs.</p>
<h2>No Application Containers</h2>
<p>You don&#8217;t deploy a Node webapp on Tomcat. You are much closer to the OS. Typically the entry point of a Node app would listen to a socket and *be* a server.</p>
<p>For example, here&#8217;s an ExpressJS webapp:</p>
<pre>
var app = express.createServer();

app.get('/', function(req, res){
res.send('Hello World');
});

app.listen(3000);
</pre>
<p>This and its asynchronous nature gives Node apps its high performance, low latencies and real-time capabilities.</p>
<h2>IDEs Aren&#8217;t Required</h2>
<p>I can&#8217;t think of working with Java without my trusted JetBrains IntelliJ IDEA. I&#8217;ve used Eclipse and NetBeans in the past and they have worked great as well. Without these IDEs for a modern Java Enterprise project, I would be handicapped.</p>
<p>Not so for Node. I&#8217;ve been productive without an IDE and while I do miss IntelliJ IDEAs amazing Javascript refactoring features, I gained tremendous performance with a text editor (gedit) and with handy plugins available the trade-off is worth it.</p>
<p>Just a small list of what Java programmers should expect if moving to Node, feel free to add on!</p>
]]></content:encoded>
			<wfw:commentRss>http://srirangan.net/2011-09-what-java-engineers-need-to-know-about-node-js/feed</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Node.js &#8211; Hot reloading with notifications for Ubuntu</title>
		<link>http://srirangan.net/2011-09-node-js-hot-reloading-with-notifications-for-ubuntu</link>
		<comments>http://srirangan.net/2011-09-node-js-hot-reloading-with-notifications-for-ubuntu#comments</comments>
		<pubDate>Sun, 11 Sep 2011 05:29:56 +0000</pubDate>
		<dc:creator>Srirangan</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[hot reloading]]></category>
		<category><![CDATA[hotnode]]></category>
		<category><![CDATA[node.js]]></category>
		<category><![CDATA[opensource]]></category>

		<guid isPermaLink="false">http://srirangan.net/?p=613</guid>
		<description><![CDATA[I needed hot reloading for my Node.js project. Google&#8217;d and found Hotnode which worked great .. until .. realized it supports Growl notifications (OSX) instead of Ubuntu&#8217;s sexy native notifs. Tweaked it and made it notify for Ubuntu and we &#8230; <a href="http://srirangan.net/2011-09-node-js-hot-reloading-with-notifications-for-ubuntu">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I needed hot reloading for my Node.js project. Google&#8217;d and found <a href="https://github.com/saschagehlich/hotnode">Hotnode</a> which worked great .. until .. realized it supports Growl notifications (OSX) instead of Ubuntu&#8217;s sexy native notifs.</p>
<p>Tweaked it and made it notify for Ubuntu and we have <a href="https://github.com/Srirangan/hotnode">Hotnode with Ubuntu Notifications</a>.</p>
<p>Let&#8217;s get started:</p>
<h1>Install it..</h1>
<p>Dependencies:<br />
<code>sudo apt-get install libnotify-bin</code></p>
<p>Hotnode:<br />
<code>git clone git://github.com/Srirangan/hotnode.git<br />
cd hotnode<br />
sudo npm install -g</code></p>
<h1>Use it..</h1>
<p>Use:<br />
<code>hotnode server.js</code></p>
<p>Instead of:<br />
<code>node server.js</code></p>
<p>..there you go!</p>
]]></content:encoded>
			<wfw:commentRss>http://srirangan.net/2011-09-node-js-hot-reloading-with-notifications-for-ubuntu/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Google faces backlash over new App Engine pricing</title>
		<link>http://srirangan.net/2011-09-google-faces-backlash-for-new-app-engine-pricing</link>
		<comments>http://srirangan.net/2011-09-google-faces-backlash-for-new-app-engine-pricing#comments</comments>
		<pubDate>Thu, 01 Sep 2011 03:57:18 +0000</pubDate>
		<dc:creator>Srirangan</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[cloud]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[google app engine]]></category>

		<guid isPermaLink="false">http://srirangan.net/?p=584</guid>
		<description><![CDATA[As Google App Engine moves out of &#8220;preview&#8221;, a new pricing model has been revealed. This new pricing model is expected to come into effect sometime in September. Google has made available to App Engine users comparisons of their current &#8230; <a href="http://srirangan.net/2011-09-google-faces-backlash-for-new-app-engine-pricing">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>As Google App Engine moves out of &#8220;preview&#8221;, a <a href="http://www.google.com/enterprise/cloud/appengine/pricing.html">new pricing model</a> has been revealed. This new pricing model is expected to come into effect sometime in September. Google has made available to App Engine users comparisons of their current bills versus expected bills with the new pricing model.</p>
<p>Things don&#8217;t look pretty. In short this is what has happened:</p>
<ul>
<li>&#8220;Free&#8221; quotas have been drastically reduced</li>
<li>Price of various billiable &#8220;units&#8221; has seen a sharp rise</li>
</ul>
<p>The reaction of the Google App Engine customer base has been predictable. Here are some quotes from the official Google App Engine mailing list / group:</p>
<blockquote><p>&#8220;We are going from $5,400/month to $26,500/month (Python) &#8211; and this is only one of our apps. We are going to work hard to optimize our application because we really like App Engine, but failing that, we may have to move elsewhere.&#8221; &#8212; Jason Collins</p>
<p>&#8220;Sorry google, but that doesn&#8217;t work for me. It makes more sense to go back to django and run the apps on a box in my home. I&#8217;ve disabled my apps as of today.&#8221; &#8212; Johnny G</p>
<p>&#8220;Is it really 10 times the original cost.!! Now we will be paying from $200/month to $2000/month under new billing. Just out of our reach, does not make any business sense to stay with GAE.&#8221; &#8212; smwatch</p>
<p>&#8220;I love Google App Engine, but right now I am at a loss for what to do. My current billing is $4.98/day. Under the new system it is $34.41/day, and that is with the 50% frontend discount. The effort that would be involved in porting my app to a different architecture is far beyond what I could accomplish in the next few weeks, and to be honest I don&#8217;t want to move off of App Engine.&#8221; &#8212; Michael Robellard</p>
<p>&#8220;It&#8217;s 300% for me (3x what I pay now). Most of the cost is datastore writes and reads, followed by instance hours.&#8221; &#8212; Waleed</p>
<p>&#8220;For my app, Aug 26, estimated increase of ~150%.&#8221; &#8212; Will Xu</p>
<p>&#8220;For mine (python): 317% I think I am forced to leave GAE to EC2.&#8221; &#8212; Raymond C</p></blockquote>
<p>Is Google setting a precedent for unreliable and unstable cloud billing? Are they pricing themselves out of this market?</p>
<p>If you go by the most popular thread in the Google App Engine community &#8211; <a href="https://groups.google.com/d/topic/google-appengine/obfGjbIkOTI/discussion">Keep it short: Who is forced to leave GAE?</a> &#8211; then the answer is yes!</p>
]]></content:encoded>
			<wfw:commentRss>http://srirangan.net/2011-09-google-faces-backlash-for-new-app-engine-pricing/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Review19 is here.</title>
		<link>http://srirangan.net/2011-08-review19-is-here</link>
		<comments>http://srirangan.net/2011-08-review19-is-here#comments</comments>
		<pubDate>Wed, 31 Aug 2011 15:48:33 +0000</pubDate>
		<dc:creator>Srirangan</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[products]]></category>
		<category><![CDATA[review19]]></category>

		<guid isPermaLink="false">http://srirangan.net/?p=579</guid>
		<description><![CDATA[Excited to reveal the first public release of Review19 &#8211; The next generation, real-time project collaboration tool. The complete announcement from the mailing list: The first public release of Review19 is out. Review19 is the next generation, real-time project collaboration &#8230; <a href="http://srirangan.net/2011-08-review19-is-here">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Excited to reveal the first public release of <a href="http://www.review19.com">Review19</a> &#8211; <a href="http://www.review19.com">The next generation, real-time project collaboration tool</a>.</p>
<p>The complete announcement from the <a href="https://groups.google.com/forum/#!forum/review19-community">mailing list</a>:</p>
<blockquote><p>The first public release of Review19 is out.</p>
<p>Review19 is the next generation, real-time project collaboration tool. It serves as an alternative to Pivotal Tracker, Atlassian JIRA / GreenHopper and other agile / project management tools.</p>
<p>Review19 supports stories, sprints, story board and teams. The interface is simple. No complex rules and work-flows are imposed. Run your project as you like.</p>
<p>Review19 is real-time software. AJAX / asynchronous calls are history. All team members experience real-time collaboration and synchronicity with Review19 eliminating errors and confusions.</p>
<p>Review19 can be accessed at <a href="http://www.review19.com/" target="_blank">http://www.review19.com/</a></p>
<p>Review19 is built on Google App Engine, Python, HTML5, JQuery and CSS. It works on recent versions of all real browsers and has been extensively tested on Google Chrome.</p></blockquote>
<p><a href="http://www.review19.com/">Review19</a> was the result of my disillusionment with Pivotal Tracker which promised so much for so long.</p>
<p>A key design principle for <a href="http://www.review19.com/">Review19</a> is for it to be <strong>real-time</strong>. Real-time as in <strong>real-time collaboration</strong>. All team members see updates as they happen. Real-time as in Google Docs or Google Wave (RIP).</p>
<p>Simplicity. Pivotal Tracker / Atlassian JIRA etc. were simply too complex to use. They did too much. <a href="http://www.review19.com/">Review19</a> does very little. Imposes very few rules and helps you implement almost any workflow (Lean, Agile, Scrum, Kanban etc.)</p>
<p>Please try out <a href="http://www.review19.com/">Review19</a>. Join the <a href="https://groups.google.com/forum/#!forum/review19-community">community</a> and share your <a href="https://groups.google.com/forum/#!forum/review19-community">feedback</a>. Thanks!</p>
]]></content:encoded>
			<wfw:commentRss>http://srirangan.net/2011-08-review19-is-here/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to install the DotCloud CLI on Ubuntu</title>
		<link>http://srirangan.net/2011-06-how-to-install-the-dotcloud-cli-on-ubuntu</link>
		<comments>http://srirangan.net/2011-06-how-to-install-the-dotcloud-cli-on-ubuntu#comments</comments>
		<pubDate>Fri, 10 Jun 2011 10:32:23 +0000</pubDate>
		<dc:creator>Srirangan</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[cloud]]></category>
		<category><![CDATA[dotcloud]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://srirangan.net/?p=546</guid>
		<description><![CDATA[If you aren&#8217;t familiar with DotCloud by now, you ought to be. DotCloud is a cloud platform built on top of Amazon EC2 that is programmer friendly and not targeted specifically at sysadmins. It will not lock you in to &#8230; <a href="http://srirangan.net/2011-06-how-to-install-the-dotcloud-cli-on-ubuntu">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>If you aren&#8217;t familiar with <a href="https://www.dotcloud.com" rel="nofollow">DotCloud</a> by now, you ought to be. </p>
<p>DotCloud is a cloud platform built on top of Amazon EC2 that is programmer friendly and not targeted specifically at sysadmins. It will not lock you in to any platform and supports a wide range of open source technologies including MySQL, Node.Js, PHP, PostgreSQL, Python, Redis, Ruby, Java, Perl, SMTP, MongoDB, Solr etc.</p>
<p>DotCloud provides a CLI (Command Line Interface) for performing every action possible including creating new applications, deploying new services, pushing code, running remote commands etc. However Python and related tools are required to get DotCloud CLI working on your Ubuntu machine.</p>
<p>Follow the steps below to get started:</p>
<p><code># Install Python (Ubuntu should have it by default)<br />
$ sudo apt-get install python</code></p>
<p><code># Download <a href="http://pypi.python.org/pypi/setuptools" rel="nofollow">setuptools</a> and install it with the following command<br />
$ sudo sh ~/Downloads/setuptools-0.6c11-py2.7.egg</code></p>
<p><code># Use easy_install to setup the DotCloud CLI<br />
$ sudo easy_install dotcloud</code></p>
<p>That&#8217;s it! You&#8217;re now all set to <a href="http://docs.dotcloud.com/tutorials/" rel="nofollow">create your first DotCloud app</a>!</p>
]]></content:encoded>
			<wfw:commentRss>http://srirangan.net/2011-06-how-to-install-the-dotcloud-cli-on-ubuntu/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Get started with Django .. django-kick-start!</title>
		<link>http://srirangan.net/2011-05-get-started-with-django-django-kick-start</link>
		<comments>http://srirangan.net/2011-05-get-started-with-django-django-kick-start#comments</comments>
		<pubDate>Sun, 22 May 2011 02:49:45 +0000</pubDate>
		<dc:creator>Srirangan</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://srirangan.net/?p=537</guid>
		<description><![CDATA[The Django Framework is an extremely popular and powerful Python based framework for web application development. The project began way back in 2003 and have for the past few years really matured and has gained mainstream and enterprise adoption. I &#8230; <a href="http://srirangan.net/2011-05-get-started-with-django-django-kick-start">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>The Django Framework is an extremely popular and powerful Python based framework for web application development. The project began way back in 2003 and have for the past few years really matured and has gained mainstream and enterprise adoption.</p>
<p>I recently conducted an intensive training session titled &#8220;django-kick-start&#8221; at the Inphina iBat dated 21st May 2011.</p>
<p><a href="https://github.com/Srirangan/django-kick-start">Download source code</a></p>
<p><iframe src="https://docs.google.com/present/embed?id=dwhrwm2_130c99bszf6&#038;size=m" frameborder="0" width="555" height="451"></iframe></p>
]]></content:encoded>
			<wfw:commentRss>http://srirangan.net/2011-05-get-started-with-django-django-kick-start/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Flex 4.5 with IntelliJ IDEA &#124; Screenshot Guided Tour</title>
		<link>http://srirangan.net/2011-05-flex-4-5-with-intellijidea-screenshot-guided-tour</link>
		<comments>http://srirangan.net/2011-05-flex-4-5-with-intellijidea-screenshot-guided-tour#comments</comments>
		<pubDate>Wed, 11 May 2011 12:16:10 +0000</pubDate>
		<dc:creator>Srirangan</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[flex]]></category>
		<category><![CDATA[intellijidea]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://srirangan.net/?p=509</guid>
		<description><![CDATA[I used to be a Windows, Flash Builder, Eclipse user but I have since migrated to Ubuntu 11.04 and IntelliJIDEA. I would have migrated earlier than I eventually did but one of the things holding me back was the lack &#8230; <a href="http://srirangan.net/2011-05-flex-4-5-with-intellijidea-screenshot-guided-tour">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I used to be a Windows, Flash Builder, Eclipse user but I have since migrated to Ubuntu 11.04 and IntelliJIDEA. I would have migrated earlier than I eventually did but one of the things holding me back was the lack of a mature Flex development environment on Ubuntu.</p>
<p>This has now changed and am working with Flex 4.5 SDK on IntelliJIDEA + Ubuntu and I feel more productive than ever before. Listed below are steps for you to get started with developing Flex 4.5 applications on IntelliJIDEA:</p>
<ol>
<li><strong>Assumption</strong> &#8211; You have downloaded Flex SDK 4.5 and have a working installation on IntelliJIDEA. Additionally you have downloaded the Flash debug player (projector) for Linux.</li>
<li><strong>Add Flex 4.5 SDK to Global SDKs</strong> &#8211; Launch the <em>Project Structure</em> window through the file menu or <em>Ctrl + Alt + Shift + S</em>. Under <em>Platform Settings</em> select the <em>SDKs</em> option and add the <em>Flex 4.5 SDK</em>. You should know the path where Flex 4.5 SDK has been extracted.</li>
<li><strong>Add Flex 4.5 SDK as a Module Dependency</strong> &#8211; Under <em>Project Structure</em> select <em>Modules</em>, further select your Flex module and set Flex 4.5 SDK as <em>Module SDK</em> and it to the <em>Dependencies</em> if not already present.</li>
<li><strong>Fast Flex Compiler</strong> &#8211; Open <em>Settings</em> via the file menu or <em>Ctrl + Alt + S</em>, select <em>Flex Compiler</em> and choose the <em>Flex compiler shell</em> for fast Flex compilations. Using <em>Built-in compiler shell</em> did not work for me with Flex 4.5 SDK.</li>
<li><strong>Edit configuration with Flash debugger</strong> &#8211; Create a new Flex run configuration and select the Flash Player Debugger as the Launch Application.</li>
<li><strong>All set to go!</strong></li>
</ol>

<a href='http://srirangan.net/2011-05-flex-4-5-with-intellijidea-screenshot-guided-tour/attachment/1' title='Platform - Flex 4.5 SDK'><img width="150" height="150" src="http://srirangan.net/wp-content/uploads/2011/05/1-150x150.png" class="attachment-thumbnail" alt="Platform - Flex 4.5 SDK" title="Platform - Flex 4.5 SDK" /></a>
<a href='http://srirangan.net/2011-05-flex-4-5-with-intellijidea-screenshot-guided-tour/attachment/2' title='Module integration with Flex 4.5 SDK'><img width="150" height="150" src="http://srirangan.net/wp-content/uploads/2011/05/2-150x150.png" class="attachment-thumbnail" alt="Module integration with Flex 4.5 SDK" title="Module integration with Flex 4.5 SDK" /></a>
<a href='http://srirangan.net/2011-05-flex-4-5-with-intellijidea-screenshot-guided-tour/attachment/3' title='Flex Compiler Shell'><img width="150" height="150" src="http://srirangan.net/wp-content/uploads/2011/05/3-150x150.png" class="attachment-thumbnail" alt="Flex Compiler Shell" title="Flex Compiler Shell" /></a>
<a href='http://srirangan.net/2011-05-flex-4-5-with-intellijidea-screenshot-guided-tour/attachment/4' title='Run configuration with Flash Debugger'><img width="150" height="150" src="http://srirangan.net/wp-content/uploads/2011/05/4-150x150.png" class="attachment-thumbnail" alt="Run configuration with Flash Debugger" title="Run configuration with Flash Debugger" /></a>

]]></content:encoded>
			<wfw:commentRss>http://srirangan.net/2011-05-flex-4-5-with-intellijidea-screenshot-guided-tour/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Setting up Scala dev environment on Ubuntu 11.04</title>
		<link>http://srirangan.net/2011-04-setting-up-scala-dev-environment-on-ubuntu-11-04</link>
		<comments>http://srirangan.net/2011-04-setting-up-scala-dev-environment-on-ubuntu-11-04#comments</comments>
		<pubDate>Sat, 30 Apr 2011 11:14:18 +0000</pubDate>
		<dc:creator>Srirangan</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[scala]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://srirangan.net/?p=499</guid>
		<description><![CDATA[Recently moved to Ubuntu 11.04 from Windows 7 and not regretting it one bit. Used Ubuntu Software Center and Synaptic Package Manager to set up much of my development environment without any hassles. However I couldn&#8217;t use the Synaptic Package &#8230; <a href="http://srirangan.net/2011-04-setting-up-scala-dev-environment-on-ubuntu-11-04">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Recently moved to Ubuntu 11.04 from Windows 7 and not regretting it one bit. Used Ubuntu Software Center and Synaptic Package Manager to set up much of my development environment without any hassles. However I couldn&#8217;t use the Synaptic Package Manager to install Scala as it had an older version published in the repository &#8212; Scala 2.7.x.</p>
<p>If, like me, you need to install Scala 2.8.1 or Scala 2.9.1 on Ubuntu, follow the steps below:</p>
<ol>
<li><a href="http://www.scala-lang.org/downloads">Download</a> your desired version of Scala</li>
<li>Extract the package in <strong>/opt/</strong></li>
<li>Edit .bashrc with the command <strong>gedit .bashrc</strong></li>
<li>Export variable SCALA_HOME: <strong>export SCALA_HOME=/opt/scala-2.8.1.final</strong></li>
<li>Update PATH to include SCALA binaries: <strong>export PATH=$SCALA_HOME/bin:$PATH</strong></li>
<li>Save .bashrc, log out and log in</li>
<li>Verify the Scala installation: <strong>scala -version</strong></li>
<li>Install / configure your favorite IDE</li>
</ol>
<p>You&#8217;re ready to go, start hacking..</p>
]]></content:encoded>
			<wfw:commentRss>http://srirangan.net/2011-04-setting-up-scala-dev-environment-on-ubuntu-11-04/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>How to introduce Scala in the enterprise</title>
		<link>http://srirangan.net/2011-04-how-to-introduce-scala-in-the-enterprise</link>
		<comments>http://srirangan.net/2011-04-how-to-introduce-scala-in-the-enterprise#comments</comments>
		<pubDate>Fri, 22 Apr 2011 10:19:09 +0000</pubDate>
		<dc:creator>Srirangan</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[scala]]></category>

		<guid isPermaLink="false">http://srirangan.net/?p=485</guid>
		<description><![CDATA[Are you a Scala fanboy enthusiast? Have you been following the Scala community and projects intently for a past couple of years? And have you been itching to implement Scala code, Scala libraries and tools in a real world scenario &#8230; <a href="http://srirangan.net/2011-04-how-to-introduce-scala-in-the-enterprise">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Are you a Scala <del datetime="2011-04-22T09:57:08+00:00">fanboy</del> enthusiast? Have you been following the Scala community and projects intently for a past couple of years?  And have you been itching to implement Scala code, Scala libraries and tools in a real world scenario only to find your team members / customers / IT leadership not receptive to the idea? </p>
<p>If so, here are some things you may want to try:</p>
<p><strong>Effectively communicate Scala&#8217;s benefits</strong></p>
<p>Scala has a lot of advantages &#8230; you know that and I know that but do <em>they</em> know that? </p>
<p>Does your IT leader know that Scala plays really nicely with the existing JVM (and CLR) environments? Do your fellow programmers know of the conciseness of Scala code? Is the older, hardened Java developer aware that most times Java Code *is* perfectly compatible and compilable Scala code? </p>
<p>Has your customer been told of the rapid development, scalability and maintainability edge Scala brings to the engagement?</p>
<p>If stakeholders see the benefit they will recognize the opportunity. And it may very well be that we have earned new allies in our crusade for Scala adoption. </p>
<p><strong>Share the case-studies</strong></p>
<p>The Scala programming language has been proven in high-scalability environments. Twitter got over its stability woes with its migration to Scala. LinkedIn picked Scalatra, a Scala web framework, for its newer modules. Foursquare is built entirely on the Scala Lift Web Framework while Guardian.co.uk recently spoke about their adoption of Scala. </p>
<p>These and many more case studies are out there available helping our understanding of the realistic challenges of Scala adoption, how they were overcome and what are the benefits that have been derived from the overall migration to Scala.</p>
<p><strong>Start with something small</strong></p>
<p>Take the initiative and start with something small and show them how it is done. </p>
<p>For example you may want to introduce a sub module in your existing enterprise project for testing with ScalaTests, build your project utilities with Scala, or implement a simple website / web application with a Scala based web frameworks instead.</p>
<p>Amaze the business with the rapid developement that you&#8217;ve achieved, amaze the geeks with your sexy Scala code. Go out there, implement it anyway and bedazzle them.</p>
<p><em>If things go wrong, you can always apologize and make use of Git or whatever other version control you have. ;-)</em></p>
<p><strong>Destroy the &#8220;It&#8217;s not enterprise ready!&#8221; argument</strong></p>
<p>You have great IDE support (IntelliJIDEA, NetBeans 7, Eclipse with ScalaIDE 2.9 beta). It integrates very nicely with Maven. You have SBT for projects from scratch. You have books and now you have training programmes.  It works seamlessly on your JVM / CLR based environments.</p>
<p>Given the current economic situation, it is pragmatic for business to consider the availability of Scala shops and especially Scala Offshoring partners. </p>
<p>Ask loudly *why* do they specifically think it is not enterprise ready? Chances are they don&#8217;t really have a good explanation. That&#8217;s not to say Scala doesn&#8217;t have its shortcomings, however, what Scala also has is a very enthusiastic and effective community.</p>
]]></content:encoded>
			<wfw:commentRss>http://srirangan.net/2011-04-how-to-introduce-scala-in-the-enterprise/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Simple Database Migrations with Scala and Querulous</title>
		<link>http://srirangan.net/2011-04-simple-database-migrations-with-scala-and-querulous</link>
		<comments>http://srirangan.net/2011-04-simple-database-migrations-with-scala-and-querulous#comments</comments>
		<pubDate>Tue, 12 Apr 2011 17:42:01 +0000</pubDate>
		<dc:creator>Srirangan</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[persistency]]></category>
		<category><![CDATA[querulous]]></category>
		<category><![CDATA[scala]]></category>

		<guid isPermaLink="false">http://srirangan.net/?p=469</guid>
		<description><![CDATA[We hate doing it, but one time or the other, each of us ends up writing a quick-and-dirty database migration utility for a project we&#8217;re working on. I recently had to do the same, and surprisingly the process was really &#8230; <a href="http://srirangan.net/2011-04-simple-database-migrations-with-scala-and-querulous">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>We hate doing it, but one time or the other, each of us ends up writing a quick-and-dirty database migration utility for a project we&#8217;re working on. I recently had to do the same, and surprisingly the process was really smooth .. largely thanks to <a href="http://www.google.com/search?q=scala+goodness" rel="nofollow">Scala goodness</a> and <a href="https://github.com/nkallen/querulous" rel="nofollow">Querulous</a>  &#8212; a very cool, simple and lightweight database library created by some folks at Twitter.</p>
<p>Let&#8217;s start by creating a Mavenized Scala project, check out <a href="http://srirangan.net/2011-03-getting-started-maven-archetype-for-scala">Getting Started – Maven Archetype for Scala</a>. </p>
<p>Does the Scala project build successfully? Good.</p>
<p>The next step, add the Querulous dependencies to your project <em>pom.xml</em> file:</p>
<pre>
&lt;dependencies&gt;
    ..
    &lt;dependency&gt;
      &lt;groupId&gt;com.twitter&lt;/groupId&gt;
      &lt;artifactId&gt;querulous&lt;/artifactId&gt;
      &lt;version&gt;2.0.1&lt;/version&gt;
    &lt;/dependency&gt;
    ..
&lt;/dependencies&gt;
..
  &lt;repositories&gt;
    ..
    &lt;repository&gt;
      &lt;id&gt;twitter.com&lt;/id&gt;
      &lt;url&gt;http://maven.twttr.com&lt;/url&gt;
    &lt;/repository&gt;
    ..
  &lt;/repositories&gt;
</pre>
<p>In our example, we will migrate a source database <em>boysDb</em> to a destination database <em>girlsDb</em>. No real migration business logic is being applied, think of it as a one-to-one migration.</p>
<p>We start off by declaring QueryEvaluators for our source and destination database schemas:</p>
<pre>
  val sourceDb = QueryEvaluator("localhost/boysdb", "root", "")
  val destinationDb = QueryEvaluator("localhost/girlsdb", "root", "")
</pre>
<p>QueryEvaluator object allows us to execute SQL queries on a referenced database.</p>
<p>Next step, get boys from the source database:</p>
<pre>
val boys = sourceDb.select("select id, name from boys") {
      row => (row.getInt(1), row.getString(2))
    }
</pre>
<p><em>boys</em> is a collection of <em>Tuple2[Int, String]</em> containing the <em>id</em> and <em>name</em> attributes of a <em>boy</em>.</p>
<p>For each boy, insert a girl:</p>
<pre>
boys.foreach(boy => insertGirls(boy))
</pre>
<p>Let&#8217;s now define our insertGirls() method</p>
<pre>
  def insertGirls(boy: Tuple2[Int, String]): Unit = {
    destinationDb.execute("insert into girls (id, name) values (?, ?)", boy._1, boy._2)
  }
</pre>
<p>..and we&#8217;re done. </p>
<p>Scala + Querulous makes it easy to connect to multiple database instances, makes querying extremely straightforward by exposing SQL directly without unnecessary ORM&#8217;ing or configuration / property file mess.</p>
<p>Full source code has been published on GitHub &#8211; <a href="https://github.com/Srirangan/scala-querulous-simple-migrations">https://github.com/Srirangan/scala-querulous-simple-migrations</a></p>
<p>For serious database migrations, do consider <a href="http://code.google.com/p/scala-migrations/" rel="nofollow">Scala Migrations</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://srirangan.net/2011-04-simple-database-migrations-with-scala-and-querulous/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Getting Started – Scala Persistence with Squeryl</title>
		<link>http://srirangan.net/2011-03-getting-started-%e2%80%93-scala-persistence-with-squeryl</link>
		<comments>http://srirangan.net/2011-03-getting-started-%e2%80%93-scala-persistence-with-squeryl#comments</comments>
		<pubDate>Fri, 18 Mar 2011 09:12:11 +0000</pubDate>
		<dc:creator>Srirangan</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[maven]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[persistency]]></category>
		<category><![CDATA[scala]]></category>
		<category><![CDATA[squeryl]]></category>

		<guid isPermaLink="false">http://srirangan.net/?p=428</guid>
		<description><![CDATA[Recently I had to implement simple entity persistence in Scala. I used Squeryl which defines itself as &#8220;a Scala ORM and DSL for talking with Databases with minimum verbosity and maximum type safety&#8221;. I tried it out and it was &#8230; <a href="http://srirangan.net/2011-03-getting-started-%e2%80%93-scala-persistence-with-squeryl">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Recently I had to implement simple entity persistence in Scala. I used <a href="http://squeryl.org/" rel="nofollow">Squeryl</a> which defines itself as <em>&#8220;a Scala ORM and DSL for talking with Databases with minimum verbosity and maximum type safety&#8221;</em>. I tried it out and it was extremely easy to get started with. </p>
<p>This blog post will cover the basics of Scala persistence using Squeryl and the target database system is MySQL.</p>
<blockquote><p>You will need a Scala project to work with. If you don&#8217;t have one already, you can <a href="http://srirangan.net/2011-03-getting-started-maven-archetype-for-scala">create a Scala project with the Maven archetype</a>.</p></blockquote>
<h2>Step 1 &#8211; Define dependencies</h2>
<p>Our first dependency is Squeryl. As I blog this, the latest Squeryl version is <strong>&#8220;0.9.4-RC6&#8243;</strong>. We need to make this available to our code. Additionally, we need to make available the MySQL Connector as this example persists data into a MySQL database. MySQL Connector is a run-time dependency internally consumed by Squeryl.</p>
<pre>
    &lt;dependency&gt;
      &lt;groupId&gt;org.squeryl&lt;/groupId&gt;
      &lt;artifactId&gt;squeryl_2.8.1&lt;/artifactId&gt;
      &lt;version&gt;0.9.4-RC6&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
      &lt;groupId&gt;mysql&lt;/groupId&gt;
      &lt;artifactId&gt;mysql-connector-java&lt;/artifactId&gt;
      &lt;version&gt;5.1.15&lt;/version&gt;
    &lt;/dependency&gt;
</pre>
<p>If you are using Apache Maven, add the code shown above to the <strong>&#8220;dependencies&#8221;</strong> element of your project <strong>&#8220;pom.xml&#8221;</strong> file. If you don&#8217;t use Maven, make sure the artifacts / JARs are available in your project.</p>
<h2>Step 2 &#8211; Define entities</h2>
<p>Squeryl entities are basic Scala objects.. <em>should we call them POSO&#8217;s?</em> Here I&#8217;ve defined a <strong>BaseEntity</strong> and extended it to define a <strong>User</strong> entity.</p>
<pre>
package net.srirangan.opensource.squerylexample.entities

import java.sql.Timestamp
import org.squeryl.KeyedEntity

class BaseEntity extends KeyedEntity[Long] {

  val id:Long = 0
  var lastModified = new Timestamp(System.currentTimeMillis)

}
</pre>
<p>All entities will extend and build on the <strong>BaseEntity</strong>. The BaseEntity introduces two fields <strong>&#8220;id&#8221;</strong> and <strong>&#8220;lastModified&#8221;</strong>.</p>
<pre>
package net.srirangan.opensource.squerylexample.entities

class User(var email:String, var password:String) extends BaseEntity {

  // Zero argument constructor required
  // Squeryl Roadmap says 0.9.5 will not need them :-)
  def this() = this("", "")

}
</pre>
<p>We&#8217;ve now defined the <strong>User</strong> extending the <strong>BaseEntity</strong>. In addition to the fields &#8220;id&#8221; and &#8220;lastModified&#8221;, a User instance will have <strong>&#8220;email&#8221;</strong> and <strong>&#8220;password&#8221;</strong> attributes. In addition, we have had to define a zero-argument constructor, however, the Squeryl road-map says that this would not be required from version <strong>&#8220;0.9.5&#8243;</strong> onwards.</p>
<h2>Step 3 &#8211; Define schema</h2>
<p>Squeryl requires us to define a Schema object. Our entity classes (i.e. <strong>User</strong>) needs to be mapped as <strong>tables</strong> inside the <strong>Schema</strong>. Table column properties (unique, index, auto_increment etc.) are also defined here.</p>
<pre>

package net.srirangan.opensource.squerylexample.schema

import org.squeryl._
import org.squeryl.PrimitiveTypeMode._
import net.srirangan.opensource.squerylexample.entities.User

object Schema extends Schema {

  val users = table[User]

  on(users)(user => declare(
      user.id is (autoIncremented),
      user.email is (unique)
    ))

}
</pre>
<p>In the code above, we map the User entity to the User table and we&#8217;ve declared the email column as unique and the id to be auto incremented. Custom table and column names are possible to define through Squeryl annotations provided, <a href="http://squeryl.org/schema-definition.html" rel="nofollow">check out</a> the Squeryl docs.</p>
<h2>Step 4 &#8211; Start database session</h2>
<p>Needless to mention, we will need an active database session if we are to perform CRUD operations on the database. Here&#8217;s how I&#8217;ve done it:</p>
<pre>
  import org.squeryl.Session
  import org.squeryl.SessionFactory
  import org.squeryl.adapters.MySQLAdapter

  val databaseUsername = "squeryl-example"
  val databasePassword = "squeryl-example"
  val databaseConnection = "jdbc:mysql://localhost:3306/squeryl-example"

  def startDatabaseSession():Unit = {
    Class.forName("com.mysql.jdbc.Driver")
      SessionFactory.concreteFactory = Some(() => Session.create(
          java.sql.DriverManager.getConnection(databaseConnection, databaseUsername, databasePassword),
          new MySQLAdapter)
        )
  }
</pre>
<h2>Step 5 &#8211; Generate schema</h2>
<p>Once we&#8217;ve initialized the database session, we can generate the database schema as shown below:</p>
<pre>
  import org.squeryl.PrimitiveTypeMode._
  import net.srirangan.opensource.squerylexample.schema.Schema

  startDatabaseSession()

  transaction {
    Schema.create
    println("Created the schema")
  }
</pre>
<h2>Step 6 &#8211; Insert and Update</h2>
<pre>
  import net.srirangan.opensource.squerylexample.entities.User

  transaction {
    val user1:User = new User("user1@domain.com", "oldPassword")
    Schema.users.insert(user1)
    println("Inserted user1")

    user1.password = "newPassword"
    Schema.users.update(user1)
    println("Updated user1")
  }
</pre>
<h2>Step 7 &#8211; Select</h2>
<pre>
    transaction {
      val queriedUser:User = Schema.users.where(user => user.id === 2L).single
      println(queriedUser.id + " -- " + queriedUser.email)
    }
</pre>
<p>The entire <a href="https://github.com/Srirangan/squeryl-example">squeryl-example</a> source code is available at <a href="https://github.com/Srirangan/squeryl-example">github.com/Srirangan/squeryl-example</a></p>
<p>More <a href="http://squeryl.org/further-examples.html" rel="nofollow">examples</a> on <a href="http://squeryl.org" rel="nofollow">Squeryl.org</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://srirangan.net/2011-03-getting-started-%e2%80%93-scala-persistence-with-squeryl/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Build a simple web crawler with Scala and GridGain</title>
		<link>http://srirangan.net/2011-03-build-a-simple-web-crawler-with-scala-and-gridgain</link>
		<comments>http://srirangan.net/2011-03-build-a-simple-web-crawler-with-scala-and-gridgain#comments</comments>
		<pubDate>Thu, 10 Mar 2011 17:48:05 +0000</pubDate>
		<dc:creator>Srirangan</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[gridgain]]></category>
		<category><![CDATA[scala]]></category>
		<category><![CDATA[scalability]]></category>

		<guid isPermaLink="false">http://srirangan.net/?p=395</guid>
		<description><![CDATA[Recently, as a proof-of-concept, I had to build a crawler. Of course I cannot share much details about that project other than to state that it&#8217;s an absolute privilege to be part of. :-) I set out to build this &#8230; <a href="http://srirangan.net/2011-03-build-a-simple-web-crawler-with-scala-and-gridgain">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Recently, as a proof-of-concept, I had to build a crawler. Of course I cannot share much details about that project other than to state that it&#8217;s an absolute privilege to be part of. :-)</p>
<p>I set out to build this crawler.</p>
<p>Prior experience had made aware of distributed computing technologies such as Hadoop and GridGain, so I knew there was my start. I immediately picked GridGain over Hadoop. Pretty obvious reasons: More examples, better support etc.</p>
<p>My next choice was a programming language. Java was the obvious choice but I took a risk and chose Scala. GridGain&#8217;s support for Scala and abundance of examples made this choice a bit easier. A quick, unofficial definition for those unaware: Scala is an Objective-Functional programming language that is very attractive to programmers and has proved itself in high-scalability situations (Twitter, LinkedIn, FourSquare etc.)</p>
<blockquote><p>Note &#8211; I am new to Scala and my Scala code may look more Java like than Functional. I&#8217;m still learning and future examples should be better. &#8220;Awesomeness of Scala code&#8221; not a valid parameter to judge this blog post!</p></blockquote>
<p>Professional etiquette (and NDAs + lawyers) will not allow me to share exact details of this crawler. After all, it is not my intellectual property. But for the sake of this example I will consider my target to be a simple web crawler that would be used by search engines to index the content on the internet.</p>
<p><strong>What would our web crawler do?</strong></p>
<ol>
<li>Start at some base URL</li>
<li>Index content of this URL</li>
<li>Search for more URLs to index</li>
<li>Repeat 2 &amp; 3 for these new URLs</li>
</ol>
<p>This blog post will not get into the operational logic of loading a URL, extracting keywords, adding to index, extracting URLs etc. That I believe has been done to death. Alternatively I will look at how to scale up the crawling process using Scala and GridGain.</p>
<p>Those already familiar with GridGain, for the sake of this example I would request you to merge the concepts of a GridTask and a GridJob. Here we will create custom GridTasks which have one corresponding, unique custom GridJob.</p>
<p>Our <strong>GridTask-GridJob Pairs</strong> will be:</p>
<ul>
<li>LoadUrlDataTask, LoadUrlDataJob</li>
<li>IndexKeywordsTask, IndexKeywordsJob</li>
</ul>
<p>Much of the game is being played in <strong>LoadUrlDataJob</strong>. Its role is envisioned as follows:</p>
<ol>
<li>Make HTTP request to URL</li>
<li>Gather response data from URL</li>
<li>Trigger IndexKeywordsTask for URL data</li>
<li>Fetch new URLs from URL data</li>
<li>Trigger LoadUrlDataTask for new URLs</li>
</ol>
<p>While the rest have simple roles:</p>
<ul>
<li><strong>LoadUrlDataTask </strong>= Return one LoadUrlDataJob</li>
<li><strong>IndexKeywordsTask</strong> = Return one IndexKeywordsJob</li>
<li><strong>IndexKeywordsJob </strong>= Parse data and index keywords</li>
</ul>
<p>In other words, an IndexKeywords job would index keywords and die. In contrast, a LoadUrlData job would trigger exactly one IndexKeyword job and trigger potentially multiple LoadUrlData jobs.</p>
<p>Let&#8217;s look at the sources:<br />
<script src="https://gist.github.com/864489.js"> </script><br />
<script src="https://gist.github.com/864494.js"> </script><br />
<script src="https://gist.github.com/864497.js"> </script><br />
<script src="https://gist.github.com/864499.js"> </script></p>
<p>Complete Mavenized sources for <a href="https://github.com/Srirangan/simplewebcrawler">Scala GridGain SimpleWebCrawler</a> can be found on GitHub.com &#8211; <a href="https://github.com/Srirangan/simplewebcrawler">https://github.com/Srirangan/simplewebcrawler</a></p>
<p><a href="http://srirangan.net/wp-content/uploads/2011/03/scaling-viz.png"><img class="alignright size-full wp-image-399" title="scaling-viz" src="http://srirangan.net/wp-content/uploads/2011/03/scaling-viz.png" alt="" width="245" height="332" /></a> A quick look at the role of LoadUrlDataJob and we know that this needs to scale and scale big. Here is a visualization showing three levels of LoadUrlData wherein each LoadUrlDataJob spawns three other LoadUrlDataJobs and one IndexKeywords Job.</p>
<p>GridGain takes care of this seamlessly and divides the tasks among available nodes without any configuration or instruction. Here are screenshots showing three nodes of GridGain, one inside my IDE while other two on the console.</p>
<p><a href="http://srirangan.net/wp-content/uploads/2011/03/output-1.png"><img class="size-full wp-image-400 alignnone" title="output-1" src="http://srirangan.net/wp-content/uploads/2011/03/output-1.png" alt="" width="300" height="169" /></a></p>
<p><a href="http://srirangan.net/wp-content/uploads/2011/03/output-2-3.png"><img class="size-full wp-image-401 alignnone" title="output-2-3" src="http://srirangan.net/wp-content/uploads/2011/03/output-2-3.png" alt="" width="300" height="169" /></a></p>
<p>Is this a perfect web crawler? No. Far from it. For one, you need to control its spawn-rate else your machine will die. :-)</p>
<p>But it is an example that does showcase the power of GridGain and the ease with which Scala / Scalar can leverage it.</p>
]]></content:encoded>
			<wfw:commentRss>http://srirangan.net/2011-03-build-a-simple-web-crawler-with-scala-and-gridgain/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Getting Started &#8211; Maven Archetype for Scala</title>
		<link>http://srirangan.net/2011-03-getting-started-maven-archetype-for-scala</link>
		<comments>http://srirangan.net/2011-03-getting-started-maven-archetype-for-scala#comments</comments>
		<pubDate>Sat, 05 Mar 2011 06:13:08 +0000</pubDate>
		<dc:creator>Srirangan</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[maven]]></category>
		<category><![CDATA[scala]]></category>

		<guid isPermaLink="false">http://srirangan.net/?p=389</guid>
		<description><![CDATA[This is a two minute tutorial to get start with Scala development with Maven. Things are easy as there is a cool archetype to automate most of the project creation  .. ;-) But first .. What is Scala? Here&#8217;s how Scala-lang.org &#8230; <a href="http://srirangan.net/2011-03-getting-started-maven-archetype-for-scala">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>This is a two minute tutorial to get start with Scala development with Maven. Things are easy as there is a cool archetype to automate most of the project creation  .. ;-)</p>
<p>But first .. What is Scala? Here&#8217;s how Scala-lang.org defines it:</p>
<blockquote><p>&#8220;Scala is a general purpose programming language designed to express common programming patterns in a concise, elegant, and type-safe way. It smoothly integrates features of object-oriented and functional languages, enabling Java and other programmers to be more productive. Code sizes are typically reduced by a factor of two to three when compared to an equivalent Java application.&#8221;</p></blockquote>
<p>Let&#8217;s get started. First, you need Maven pre-installed and configured. If you don&#8217;t have it ready, stop right here.</p>
<p>Start the console and enter the following <strong>archetype:generate</strong> command:</p>
<blockquote><p>$ mvn archetype:generate -DarchetypeGroupId=org.scala-tools.archetypes -DarchetypeArtifactId=scala-archetype-simple</p></blockquote>
<p>This enters the interactive mode and asks you to enter the project groupId, artifactId, version and other project coordinates. After which it generates a Scala project.</p>
<p>This should have been it, but unfortunately it is not. You need to edit the generated <strong>pom.xml</strong> and <em>uncomment </em>the <strong>repositories</strong> and <strong>pluginRepositories</strong> elements.</p>
<blockquote><p>&lt;repositories&gt;<br />
&lt;repository&gt;<br />
&lt;id&gt;scala-tools.org&lt;/id&gt;<br />
&lt;name&gt;Scala-Tools Maven2 Repository&lt;/name&gt;<br />
&lt;url&gt;http://scala-tools.org/repo-releases&lt;/url&gt;<br />
&lt;/repository&gt;<br />
&lt;/repositories&gt;</p>
<p>&lt;pluginRepositories&gt;<br />
&lt;pluginRepository&gt;<br />
&lt;id&gt;scala-tools.org&lt;/id&gt;<br />
&lt;name&gt;Scala-Tools Maven2 Repository&lt;/name&gt;<br />
&lt;url&gt;http://scala-tools.org/repo-releases&lt;/url&gt;<br />
&lt;/pluginRepository&gt;<br />
&lt;/pluginRepositories&gt;</p></blockquote>
<p>Don&#8217;t ask me why they are commented in the first place, but as of March 5th 2011 they are and it sucks that they are.</p>
<p>By now we have avoided &#8220;dependency not found, build error&#8221;  and thankfully this is the only modification required.</p>
<p>You should now be able to successfully build the project..</p>
<blockquote><p>$ mvn compile</p></blockquote>
<p>..and get started with real programming.</p>
]]></content:encoded>
			<wfw:commentRss>http://srirangan.net/2011-03-getting-started-maven-archetype-for-scala/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

