<?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>aboone.com</title>
	<atom:link href="http://www.aboone.com/feed" rel="self" type="application/rss+xml" />
	<link>http://www.aboone.com</link>
	<description>the photos and random thoughts of alex boone</description>
	<lastBuildDate>Tue, 16 Mar 2010 02:10:06 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Quick! How do I make a good web site?</title>
		<link>http://www.aboone.com/quick-how-do-i-make-a-good-web-site</link>
		<comments>http://www.aboone.com/quick-how-do-i-make-a-good-web-site#comments</comments>
		<pubDate>Tue, 16 Mar 2010 01:58:37 +0000</pubDate>
		<dc:creator>aboone</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://www.aboone.com/?p=83</guid>
		<description><![CDATA[I was recently approached by a friend for advice on how to tackle the task of making a web site.  As a career web developer, this is the type of inquiry I field every now and then, and I thought my answer might make a suitable blog post.  I will offer the disclaimer [...]]]></description>
			<content:encoded><![CDATA[<p>I was recently approached by a friend for advice on how to tackle the task of making a web site.  As a career web developer, this is the type of inquiry I field every now and then, and I thought my answer might make a suitable blog post.  I will offer the disclaimer that there are countless ways to accomplish this goal and I don&#8217;t consider these to be the right answers (or necessarily the answers I would provide today).  They just happened to be things that popped into my mind when answering his questions.</p>
<blockquote><p>Do you use any type of software to get started with web layouts or do you just code everything manually? </p></blockquote>
<p><span id="more-83"></span></p>
<p>There are obviously many ways to go about this. Tools like Adobe Dreamweaver are getting to be pretty advanced these days to the point where it is certainly possible to do the whole thing in WYSIWYG mode, and have the program generate good code and quality layouts. I don&#8217;t have much experience doing that though.</p>
<p>If there is one skill that is most important I would say it is a solid knowledge of CSS. I generally try to lay out my web sites entirely with CSS &#8211; that is, only using tables when representing tabular data. This web site is more of a conceptual example than actually useful information, but it shows the power of CSS and explains some of the reasons why you should build your layouts with stylesheets, not markup: (<a href="http://csszengarden.com/">CSS Zen Garden</a>).</p>
<blockquote><p>Are you using a program like Illustrator to create your illustrations/graphics?</p></blockquote>
<p>As far as the graphics are concerned, I generally work in Photoshop (this could also probably be done w/ Illustrator), to build a mockup of the site. Then, I will create &#8220;slices&#8221; in Photoshop which correspond to the structure I plan on using to put together the pieces, guided by my knowledge of CSS. (Read: 3 column layouts, also <a href="http://www.smashingmagazine.com/2009/10/19/the-mystery-of-css-float-property/">CSS &#8220;float&#8221; property</a> is of particular importance).  The good part about slices is that you can rework the mockup as a whole over time and then re-export the sliced up images for your web site.  This saves a lot of time over cutting up an image manually each time (because you know your client&#8217;s going to mess with the design, right?).</p>
<p>From a content aspect I would recommend using a content management system of some sort to drive the site if you are going to have regularly updated material and/or want to provide an easy way for non-technical people to enter the content. I have had a lot of success using <a href="http://wordpress.org">WordPress</a> for this in the past. It is known primarily as a blogging platform but it works well for creating full-blown content-managed sites as well.  As an example There are already nice-looking themes that you can pick up and re-work as well, so that may reduce your need to get that involved with the layout.  Simply find a theme where you like the structure, and tweak the graphics and CSS to customize it (as long as the license allows).</p>
<p>Finally, I would recommend setting up some sort of version control for the site, just because you never know when you will want to roll back, and it&#8217;s really nice to have all that history stored.  I use Subversion for all the sites I work on.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aboone.com/quick-how-do-i-make-a-good-web-site/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Create a Ridiculously Simple Status Image in a Java Servlet</title>
		<link>http://www.aboone.com/create-a-ridiculously-simple-status-image-in-a-java-servlet</link>
		<comments>http://www.aboone.com/create-a-ridiculously-simple-status-image-in-a-java-servlet#comments</comments>
		<pubDate>Fri, 20 Feb 2009 05:32:11 +0000</pubDate>
		<dc:creator>aboone</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[LinkedIn]]></category>

		<guid isPermaLink="false">http://www.aboone.com/?p=56</guid>
		<description><![CDATA[We were recently working on a project at work that required we submit some data by appending a dynamic image tag with JavaScript.  The data was transmitted in a GET request through a query string defined in the src attribute.  We wanted to return a 1&#215;1 image that could be tiled as a [...]]]></description>
			<content:encoded><![CDATA[<p>We were recently working on a project at work that required we submit some data by appending a dynamic image tag with JavaScript.  The data was transmitted in a GET request through a query string defined in the src attribute.  We wanted to return a 1&#215;1 image that could be tiled as a background image to indicate the status of the request.  With such a simple image requirement, I wanted to find a more elegant solution than streaming an existing image from a file.  My experience dealing with images in Java is extremely limited, and a quick Google search didn&#8217;t turn up a concise example, so this is mostly just here for reference (mine and others&#8217;).</p>
<p><code>BufferedImage buffer = new BufferedImage(IMG_SIZE, IMG_SIZE, BufferedImage.TYPE_INT_RGB);<br />
Graphics g = buffer.createGraphics();<br />
g.setColor(new Color(Integer.parseInt(success ? SUCCESS_COLOR : FAILURE_COLOR, 16)));<br />
g.fillRect(0,0,IMG_SIZE,IMG_SIZE);<br/><br />
resp.setContentType("image/png");<br/><br />
OutputStream os = resp.getOutputStream();<br />
ImageIO.write(buffer, "png", os);<br />
os.close();</code></p>
<p>IMG_SIZE in this case is 1 and assumes a square image.  You&#8217;ll notice the parseInt method call specifies a radix of 16, so that allows SUCCESS_COLOR and FAILURE_COLOR to be defined as hex strings, which to a web developer are second nature.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aboone.com/create-a-ridiculously-simple-status-image-in-a-java-servlet/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ice Storm</title>
		<link>http://www.aboone.com/ice-storm</link>
		<comments>http://www.aboone.com/ice-storm#comments</comments>
		<pubDate>Sat, 10 Jan 2009 17:46:53 +0000</pubDate>
		<dc:creator>aboone</dc:creator>
				<category><![CDATA[Economy]]></category>
		<category><![CDATA[Sports]]></category>
		<category><![CDATA[Travel]]></category>
		<category><![CDATA[Weather]]></category>

		<guid isPermaLink="false">http://www.aboone.com/?p=41</guid>
		<description><![CDATA[ Check out this photo, taken at Mt. Bachelor yesterday after a freezing rain storm hammered the northwest side of the mountain.  This is the lift house at the top of Northwest Express lift!  It&#8217;s not uncommon to see ice-covered chairs over there but this is ridiculous.  It kind of reminds me [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.mtbachelor.com/winter/services/gallery/galleryphoto86/@@details.html?start=0"><img alt="Northwest Express lift house after an ice storm" src="http://farm4.static.flickr.com/3404/3185407306_aee03cf2bc_m.jpg" title="Ice-covered lift house at Mt. Bachelor" width="180" height="240" align="right" hspace="8" /></a> Check out this photo, taken at Mt. Bachelor yesterday after a freezing rain storm hammered the northwest side of the mountain.  This is the lift house at the top of Northwest Express lift!  It&#8217;s not uncommon to see ice-covered chairs over there but this is ridiculous.  It kind of reminds me of Superman&#8217;s fortress of solitude.  Sounds like it will be a few days before they can crack the ice off the house and the towers to get this thing moving again (apparently Outback is the same story).  Between the economy and the wacky weather, the ski resorts (at least here in the NW) must be having a tough season.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aboone.com/ice-storm/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Think Big</title>
		<link>http://www.aboone.com/think-big</link>
		<comments>http://www.aboone.com/think-big#comments</comments>
		<pubDate>Tue, 02 Dec 2008 03:07:36 +0000</pubDate>
		<dc:creator>aboone</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[encoding]]></category>
		<category><![CDATA[international]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[LinkedIn]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[UTF-8]]></category>

		<guid isPermaLink="false">http://www.aboone.com/?p=40</guid>
		<description><![CDATA[After having recently audited a web application for proper character encoding support, I have one piece of advice for web developers in this area and that is: you should always support UTF-8 encoding across the board right from the start.
If you just take a few steps at the beginning of a project to enable Unicode [...]]]></description>
			<content:encoded><![CDATA[<p>After having recently audited a web application for proper character encoding support, I have one piece of advice for web developers in this area and that is: you should always support UTF-8 encoding across the board right from the start.</p>
<p>If you just take a few steps at the beginning of a project to enable Unicode encoding, you won&#8217;t ever have to worry about international character support, your application is &#8220;future-proofed.&#8221;  When the time comes for your application to go global, it&#8217;s ready to go.</p>
<p><span id="more-40"></span></p>
<p>For example, if you use PHP you can set the encoding with the following statement in your php.ini file:<br />
<code>default_charset = "utf-8"</code></p>
<p>Or with Java set the following jvm setting:<br />
<code>-Dfile.encoding=UTF-8</code></p>
<p>In your Apache config file, set:<br />
<code>AddCharset UTF-8 .utf8<br />
AddDefaultCharset UTF-8<br />
</code></p>
<p>You also need to set the database encoding to match up.  In MySQL you can do this by setting the following directive in your my.cnf file:<br />
<code>default-character-set=utf8</code></p>
<p>It is important to note that you also need to specify the encoding for the connection.  For a JDBC connection you can do this by adding the following parameters to the database URL:<br />
<code>useUnicode=true&#038;characterEncoding=UTF-8&#038;characterSetResults=UTF-8</code></p>
<p>Finally, if you are going to be sending emails from an application, you will want to specify the encoding in the Mime type as well.  Using JavaMail, this can be done while setting the text of a MimeBodyPart:<br />
<code>mimeBodyPart.setText(htmlContent, MimeUtility.getDefaultJavaCharset(), "html");</code></p>
<p>If you make a concerted effort to implement the same encoding across the board, it will certainly help in the long run, as you won&#8217;t ever have to deal with character encoding issues.</p>
<p>For more information and specifics about UTF-8 encoding, visit <a href="http://htmlpurifier.org/docs/enduser-utf8.html#findcharset">UTF-8: The Secret of Character Encoding</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.aboone.com/think-big/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Tools for Shooting Success</title>
		<link>http://www.aboone.com/tools-for-shooting-success</link>
		<comments>http://www.aboone.com/tools-for-shooting-success#comments</comments>
		<pubDate>Sat, 01 Nov 2008 21:59:43 +0000</pubDate>
		<dc:creator>aboone</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[Sports]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[LinkedIn]]></category>

		<guid isPermaLink="false">http://www.aboone.com/?p=39</guid>
		<description><![CDATA[ For the past couple months, I&#8217;ve been working on a web site for my cousin, basketball coach and author Brian McCormick.  The site centers around his latest book, 180 Shooter: 5 Steps to Shooting 90% from the Free Throw Line, 50% from the Floor and 40% from the 3-Point Line.
My favorite part of [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://180shooter.com?affiliate=aboone"><img src="http://180shooter.com/img/logo.gif" alt="180 Shooter" align="right" hspace="8" border="0"/></a> For the past couple months, I&#8217;ve been working on a web site for my cousin, basketball coach and author Brian McCormick.  The site centers around his latest book, 180 Shooter: 5 Steps to Shooting 90% from the Free Throw Line, 50% from the Floor and 40% from the 3-Point Line.</p>
<p><img src="http://180shooter.com/img/shotchart-small.gif" alt="180 Shooter Shot Chart" align="left" hspace="8" />My favorite part of the job was creating the shot tracker program, which is an interactive shot chart, similar to the one shown at left.  Coaches can input their players&#8217; makes and misses with a rich user interface, tracking a wide variety of criteria such as opponent, quarter, shot type, etc.  The coach can then report on the players&#8217; shooting statistics, broken down by these criteria, and visualize that data in a heat map overlay.  The result is knowing exactly where and under what conditions their players should take their shots.</p>
<p>There&#8217;s also a great individual practice program, which helps players follow along with the drills outlined in the 180 Shooter book.  The program guides players towards practice in the necessary areas to improve their shooting.  I would recommend for anyone wanting to <a href="http://180shooter.com?affiliate=aboone">become a better basketball shooter</a>, you should check out this web site.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aboone.com/tools-for-shooting-success/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Multiplayer Email 2.0</title>
		<link>http://www.aboone.com/multiplayer-email-20</link>
		<comments>http://www.aboone.com/multiplayer-email-20#comments</comments>
		<pubDate>Fri, 17 Oct 2008 05:13:52 +0000</pubDate>
		<dc:creator>aboone</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[LinkedIn]]></category>

		<guid isPermaLink="false">http://www.aboone.com/?p=37</guid>
		<description><![CDATA[
For almost 2 years, I&#8217;ve been working on a product called Email Center Pro &#8211; anyone who reads this blog probably already knows that.  It&#8217;s an email management solution for small to medium sized businesses that makes it super easy for a group of people to manage hundreds, even thousands of emails a day. [...]]]></description>
			<content:encoded><![CDATA[<p><img align="right" hspace="8" src="http://www.emailcenterpro.com/_graphical/images/header/ECPlogo_header.gif" alt="Email Center Pro" /></p>
<p>For almost 2 years, I&#8217;ve been working on a product called Email Center Pro &#8211; anyone who reads this blog probably already knows that.  It&#8217;s an <a href="http://emailcenterpro.com">email management solution</a> for small to medium sized businesses that makes it super easy for a group of people to manage hundreds, even thousands of emails a day.  </p>
<p>This is a big week, because we just launched version 2.0 of the software to our user base.  The new version has a completely rewritten JavaScript client and makes use of an entirely new RESTful web services API.  It&#8217;s got a lot of powerful new search features and introduces the dashboard which will soon allow users to customize their home page with analytics tools.  2.0 is a big step forward but it also lays the groundwork for the exciting things Email Center Pro will do in the very near future.</p>
<p>For anyone who has a web site, manages more than one email address, or has at least one other person involved with their business, I would whole-heartedly recommend this product.  Sure, I may be biased, but I have seen first-hand the real gains in efficiency that it provides for an organization.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aboone.com/multiplayer-email-20/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Carolina on my Mind</title>
		<link>http://www.aboone.com/carolina-on-my-mind</link>
		<comments>http://www.aboone.com/carolina-on-my-mind#comments</comments>
		<pubDate>Tue, 10 Jun 2008 14:47:47 +0000</pubDate>
		<dc:creator>aboone</dc:creator>
				<category><![CDATA[Travel]]></category>

		<guid isPermaLink="false">http://www.aboone.com/?p=36</guid>
		<description><![CDATA[I&#8217;m happy to say that I&#8217;ll be heading out to Chapel Hill with Amanda for the rest of the week for a wedding.  I&#8217;m very excited to get back to CH and of course happy to see all my friends again!  Congratulations, Kate and Joel!

]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m happy to say that I&#8217;ll be heading out to Chapel Hill with Amanda for the rest of the week for a wedding.  I&#8217;m very excited to get back to CH and of course happy to see all my friends again!  Congratulations, Kate and Joel!</p>
<p><img src="http://farm4.static.flickr.com/3114/2567156889_5b516be8b5.jpg" alt="The Old Well"/></p>
]]></content:encoded>
			<wfw:commentRss>http://www.aboone.com/carolina-on-my-mind/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Memorial Day</title>
		<link>http://www.aboone.com/memorial-day</link>
		<comments>http://www.aboone.com/memorial-day#comments</comments>
		<pubDate>Tue, 27 May 2008 01:09:32 +0000</pubDate>
		<dc:creator>aboone</dc:creator>
				<category><![CDATA[Economy]]></category>
		<category><![CDATA[Travel]]></category>

		<guid isPermaLink="false">http://www.aboone.com/?p=35</guid>
		<description><![CDATA[As I&#8217;m sitting in stop-and-go traffic outside of Sisters, I&#8217;m thinking to myself the sad irony of the situation.  It just so happens that this weekend of remembrance for our fallen soldiers is also one of the largest fuel consumption times of the year in America. Whether it&#8217;s cars, trucks, RVs or boats, Americans [...]]]></description>
			<content:encoded><![CDATA[<p>As I&#8217;m sitting in stop-and-go traffic outside of Sisters, I&#8217;m thinking to myself the sad irony of the situation.  It just so happens that this weekend of remembrance for our fallen soldiers is also one of the largest fuel consumption times of the year in America. Whether it&#8217;s cars, trucks, RVs or boats, Americans are guzzling gasoline today while our soldiers are dying in Iraq largely because of our nation&#8217;s dependence on foreign oil.</p>
<p><img src="http://farm3.static.flickr.com/2120/2525716371_75e891e0d0.jpg" alt="Memorial Day Traffic outside Sisters, Oregon" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.aboone.com/memorial-day/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>JavaScript iPhone Lock Slider with jQuery</title>
		<link>http://www.aboone.com/javascript-iphone-lock-slider-with-jquery</link>
		<comments>http://www.aboone.com/javascript-iphone-lock-slider-with-jquery#comments</comments>
		<pubDate>Mon, 19 May 2008 07:12:24 +0000</pubDate>
		<dc:creator>aboone</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[LinkedIn]]></category>

		<guid isPermaLink="false">http://www.aboone.com/?p=34</guid>
		<description><![CDATA[I was thinking the other day about the amount of form spam that most web sites get (and again just now as I moderated a ton of blog comments), and I was reminded of a proof of concept I saw a while back.  It required the user to utilize drag and drop functionality to [...]]]></description>
			<content:encoded><![CDATA[<p>I was thinking the other day about the amount of form spam that most web sites get (and again just now as I moderated a ton of blog comments), and I was reminded of a proof of concept I saw a while back.  It required the user to utilize drag and drop functionality to submit a form, thus verifying human interaction.  Then I thought of the iPhone&#8217;s unlock function and how it would make a cool <a href="http://en.wikipedia.org/wiki/Captcha">CAPTCHA</a>.</p>
<p>I&#8217;ve written a handy JavaScript class for including these types of sliders into a web site- stick around after the break for more details and cool configuration options.</p>
<div id="slider1"></div>
<p><script type="text/javascript" src="http://photos.aboone.com/slider/slider.js"></script></p>
<style type="text/css">
@import "http://photos.aboone.com/slider/slider.css";
/* blog-specific fixes */
.track-message {line-height: normal;}
</style>
<p><script type="text/javascript">
$(function(){
   var s1 = new Slider("slider1");
   s1.init();
});
</script></p>
<p><span id="more-34"></span></p>
<p>The basic use consists of creating a new Slider object, passing to the constructor a container id &#8211; the id of the element to render the slider to, and an optional config object which can set various properties of the slider.  Right now the supported options are: handler, color, message, mode and waver.  The handler parameter allows me to set an event handler to call some JS function when the slide is completed- this could be anything from submitting a form to opening the non-iPhone version of your site ;)</p>
<p><code><br />
var s2 = new Slider("slider2",{<br />
&nbsp;message: "turn off the lights!",<br />
&nbsp;color: "red",<br />
&nbsp;handler: function(){<br />
&nbsp;&nbsp;$("body").css("backgroundColor", "black");<br />
&nbsp;}<br />
});<br />
s2.init();<br />
</code></p>
<div id="slider2"></div>
<p>The third demo is using mode = &#8220;noclick&#8221;, which means that you don&#8217;t have to click on the slide handle in order to activate it.  I suppose this is truer to the iPhone experience, unfortunately as of right now this one is still slightly buggy.  The waver config option can be set in noclick mode to determine how far out of the track the cursor can waver, default is 75px.</p>
<p><code><br />
var s3 = new Slider("slider3",{<br />
&nbsp;message: "no click required!",<br />
&nbsp;color: "green",<br />
&nbsp;mode: "noclick",<br />
&nbsp;handler: function(){ $("body").css("backgroundColor", "white"); }<br />
});<br />
s3.init();<br />
</code></p>
<div id="slider3"></div>
<p>Well, that&#8217;s about it &#8211; I will add the disclaimer that this code has been tested very little, only in Firefox 2, Webkit and IE7.  Also slightly ironic is the fact that this code won&#8217;t work on Safari for iPhone, as it doesn&#8217;t support enough mouse events.</p>
<p>Feel free to use this code how you see fit as long as you maintain a link to this site.</p>
<p><script type="text/javascript">
$(function(){
   var s2 = new Slider("slider2",{
      message: "turn off the lights!",
      color: "red",
      handler: function(){ $("body").css("backgroundColor", "black"); }
  });
  s2.init();
  var s3 = new Slider("slider3",{
      message: "no click required!",
      color: "green",
      mode: "noclick",
      handler: function(){ $("body").css("backgroundColor", "white"); }
  });
  s3.init();
});
</script></p>
<p>EDIT: I should have added these originally, here are the files you will need-<br />
- <a href="http://photos.aboone.com/slider/slider.js">slider.js</a><br />
- <a href="http://photos.aboone.com/slider/slider.css">slider.css</a><br />
- <a href="http://photos.aboone.com/slider/images.zip">4 .png images (in .zip file)</a></p>
<p>In addition, you will need to include jQuery, which can be downloaded in various formats.  I used <a href="http://docs.jquery.com/Release:jQuery_1.2.3">jQuery 1.2.3</a>, which is already out of date, but I suspect this will work with a very wide range of jQuery versions.</p>
<p>If there&#8217;s enough demand for it and/or I get around to it, I&#8217;ll package up an official release with all the necessary files and a demo HTML page.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aboone.com/javascript-iphone-lock-slider-with-jquery/feed</wfw:commentRss>
		<slash:comments>31</slash:comments>
		</item>
		<item>
		<title>Managing Multi-Node EC2 Deployments with SVN, Ant and bash</title>
		<link>http://www.aboone.com/managing-multi-node-ec2-deployments-with-svn-ant-and-bash</link>
		<comments>http://www.aboone.com/managing-multi-node-ec2-deployments-with-svn-ant-and-bash#comments</comments>
		<pubDate>Tue, 18 Mar 2008 03:39:30 +0000</pubDate>
		<dc:creator>aboone</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[LinkedIn]]></category>

		<guid isPermaLink="false">http://www.aboone.com/?p=32</guid>
		<description><![CDATA[I&#8217;ve recently been doing quite a bit of work with Amazon Web Services.  Over the past few weeks I have been developing a simple way to manage multi-node applications using EC2.  Much of this is very project-specific but the methodology could easily be applied to a wide variety of deployments.  The techniques [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve recently been doing quite a bit of work with <a href="http://aws.amazon.com">Amazon Web Services</a>.  Over the past few weeks I have been developing a simple way to manage multi-node applications using EC2.  Much of this is very project-specific but the methodology could easily be applied to a wide variety of deployments.  The techniques described here were inspired by <a href="http://blog.apokalyptik.com/2007/01/09/amazon-ec2-cookbook-startup-flexibility/">this blog post</a>.  This article is intended for people who are already somewhat familiar with Amazon Web Services &#8212; for a brief introduction to S3 and EC2, view <a href="http://www.aboone.com/?p=23">my previous blog post</a>.  If you&#8217;re ready for it, read on.</p>
<p><span id="more-32"></span></p>
<p>One of the most frustrating things I encountered working with EC2 is the monotony of bundling and uploading the AMI each time I made changes to my server configuration.  Originally, my plan was to store the application code as part of the AMI so that when the server fired up, it was all ready to go with the latest version.  I quickly realized that this was going to get out of hand, especially when we decided to deploy our beta application on EC2 and it required updates on a weekly basis.  I progressed by storing the application code on S3, and downloading it manually when needed.  Then I read the CodeWord blog post and I implemented the following init script.</p>
<p><code>
<pre>
#! /bin/sh
#
# chkconfig: 2345 90 30
# description: EC2 bootstrapping process
#
RETVAL=0
case "$1" in
start)
$0 reload
if [ $? == 0 ]; then
   /opt/myapp/scripts/start.sh
fi
RETVAL=$?
;;
stop)
/opt/myapp/scripts/stop.sh
RETVAL=$?
;;
restart)
$0 stop
$0 start
RETVAL=$?
;;
reload)
cp /opt/myapp/scripts/download.sh /tmp/download.sh
if [ $? == 0 ]; then
   /tmp/download.sh
fi
RETVAL=$?
;;
*)
echo "Usage: $0 {start|stop|restart|reload}"
exit 1
;;
esac
exit $RETVAL
</pre>
<p></code></p>
<p>This init script was added to the appropriate runlevels with chkconfig and then bundled into the AMI, along with the environment setup (Java, Tomcat, Apache, whatever the case may be).  The only other piece of code that is necessary at bundle-time is the download.sh script, which tells the application how to get the deployment code and where to unpack it.  The reason I&#8217;m copying to a temp directory is because I am unpacking into the /opt/myapp directory and I don&#8217;t want to overwrite that file when it&#8217;s running.  The download script is built on s3cmd and looks something like this:</p>
<p><code>
<pre>
#!/bin/bash
deploy="web"
deploydir="/opt/myapp"
ext="tar.gz"
s3file="s3://myapp-deployments/$deploy.$ext"
ts=`date +%s`
/usr/bin/s3cmd -c /root/.s3cfg get $s3file /tmp/$ts.$ext
if [ $? == 0 ]; then
   tar xzfp /tmp/$ts.$ext -C $deploydir/ --overwrite
   if [ $? == 0 ]; then
        rm /tmp/$ts.$ext
        chmod 744 $deploydir/scripts/*
        echo "downloaded $s3file as $ts.$ext and extracted to $deploydir"
   fi
fi
</pre>
<p></code></p>
<p>This will allow me to pack up a quiver of deployment tarballs for each of my server types and stick them on a private bucket on S3.  (I could even improve this by using EC2&#8217;s user-data to specify a server type so I can use one multi-purpose image.  In my case, the instances are specific enough that it makes sense to maintain separate image types, with the deploy variable hard-coded.)  Then I can use this download script to grab the latest code, unpack it into the myapp directory, and run the freshly-downloaded start.sh script.  The script allows me to do things like start various services, create cron tasks, obtain a Dynamic DNS hostname, whatever I need to accomplish at startup time.  The original author checked out his packages from subversion, I opted to go the S3 route so that I didn&#8217;t have to open up our internal SVN repository to the public, and I found that it was much quicker to grab the code from S3 than from anywhere else, meaning it was ready to go as fast as possible.</p>
<p>The tarballs described above contain the necessary compiled Java classes and JAR files, any worthwile bash scripts, cron task definitions, even application config files.  To manage the creation of this install directory, I&#8217;m using an Ant task to throw together all the necessary files.  Certainly this is nothing revolutionary, an excerpt from my build.xml file is shown below.</p>
<p><code>
<pre>
&lt;target name="package-web" depends="package"&gt;
        &lt;!-- build scripts directory --&gt;
        &lt;echo message="Adding service scripts..."/&gt;
        &lt;copy todir="${basedir}/dist/web/scripts"&gt;
            &lt;fileset dir="${basedir}/scripts/service/web"&gt;
                &lt;include name="*"/&gt;
            &lt;/fileset&gt;
        &lt;/copy&gt;
        &lt;!-- copy necessary JAR files --&gt;
        &lt;echo message="Adding JAR files..."/&gt;
        &lt;copy todir="${basedir}/dist/web/lib"&gt;
                &lt;fileset dir="${basedir}/dist/java"/&gt;
        &lt;/copy&gt;
        &lt;!-- copy all the cron tasks --&gt;
        &lt;echo message="Adding cron jobs..."/&gt;
        &lt;copy todir="${basedir}/dist/web/cron"&gt;
                &lt;fileset dir="${basedir}/setup/cron/web"/&gt;
        &lt;/copy&gt;
        &lt;echo message="Copying bashrc file"/&gt;
        &lt;copy file="${basedir}/setup/bashrc/web" tofile="${basedir}/dist/web/bashrc"/&gt;
        &lt;echo message="tar/gzipping deployment..."/&gt;
        &lt;tar basedir="${basedir}/dist/web" destfile="${basedir}/build/web.tar.gz" compression="gzip"/&gt;
&lt;/target&gt;
</pre>
<p></code></p>
<p>I&#8217;m sure that if you&#8217;ve made it this far you can guess how Subversion fits into the picture.  All of the application code, scripts, config files, etc. get stored in the SVN repository.  That means not only do I have a complete revision history for all of my code, but I also have that protection for my configuration files and my &#8220;glue&#8221; code, a handful of perl and bash scripts.  One thing that I do, for posterity sake, is create a tag of my entire repository when I&#8217;m deploying a new version to S3.  The tag name contains the revision number and deployment date so that I can see all the previously released versions at a glance and easily roll back to a stable version should we (god forbid) release some buggy code.</p>
<p>So, this is a glimpse at how I&#8217;ve been able to stay organized with my use of EC2 as a server infrastructure for a distributed web application.  It&#8217;s really amazing how useful EC2 is, and I really think it will change the web hosting market drastically.  I hope to share a bit more of my architecture with you, including some monitoring tools that I&#8217;ve developed and a few other fun things, but that will have to wait until next time.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aboone.com/managing-multi-node-ec2-deployments-with-svn-ant-and-bash/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
