<?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>Mission Data Blog &#187; Web Development</title>
	<atom:link href="http://www.missiondata.com/blog/category/web-development/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.missiondata.com/blog</link>
	<description>Louisville-based Web Development &#038; Software Engineering</description>
	<lastBuildDate>Tue, 18 May 2010 14:24:23 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Treetop: Grammar&#8217;s Cool</title>
		<link>http://www.missiondata.com/blog/web-development/85/treetop-grammars-cool/</link>
		<comments>http://www.missiondata.com/blog/web-development/85/treetop-grammars-cool/#comments</comments>
		<pubDate>Wed, 13 Feb 2008 01:27:39 +0000</pubDate>
		<dc:creator>darrend</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.missiondata.com/blog/uncategorized/85/treetop-grammars-cool/</guid>
		<description><![CDATA[Treetop was one of the more exciting projects I saw at last year&#8217;s RubyConf. Nathan Sobo&#8217;s Treetop talk is available online and I urge you to watch it. Nathan did a great job of explaining the basics of syntactic analysis, and then got into the specifics of using Treetop&#8217;s implementation of parsing expression grammars to [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://treetop.rubyforge.org/">Treetop</a> was one of the more exciting projects I saw at last year&#8217;s RubyConf. <a href="http://rubyconf2007.confreaks.com/d1t1p5_treetop.html">Nathan Sobo&#8217;s Treetop talk</a> is available online and I urge you to watch it. Nathan did a great job of explaining the basics of syntactic analysis, and then got into the specifics of using Treetop&#8217;s implementation of <a href="http://en.wikipedia.org/wiki/Parsing_expression_grammar">parsing expression grammars</a> to put the concepts to work. </p>
<p>Treetop appeared to gather all the concepts together into an understandable domain specific language. All of the tokenization and node structure can go into a single file, and the interactive nature of Ruby makes for the perfect sand box. I felt like I could get somewhere if I invested just an hour into this. I was happy to find that my impressions were correct. </p>
<p>After a short time I had caught on enough to start writing my own code. Once over the hump the rest was easy. I was able to write and test a Treetop grammar for parsing CSV files within a few hours. I chose CSV parsing because I was already familiar with the format, and I could compare my implementation to not just one but two existing Ruby libraries.<br />
<span id="more-85"></span></p>
<pre><code>commaseparatedfile.treetop</code></pre>
<pre><code>grammar CommaSeparatedFile
  rule lines
    line (newline line)*
    {
      def values
        vals = []
        vals &lt;&lt; line.values
        more.elements.each { |additional| vals &lt;&lt; additional.line.values }
        vals
      end
    }
  end

  rule line
    valueline / emptyline
  end

  rule emptyline
    '' {
      def values
        []
      end
    }
  end

  rule valueline
    leading:(value separator)* trailing:value
    {
      def values
        list = []
        list += leading.elements.collect { |lead| lead.value.text_value } if leading
        list &lt;&lt; trailing.text_value if trailing
        list
      end
    }
  end

  rule value
    quotedvalue / nakedvalue
  end

  rule quotedvalue
    '"' wrapped:( !'"' . / '""' )* '"' {
      def text_value
        wrapped.text_value.gsub(/""/,'"')
      end
    }
  end

  rule nakedvalue
    (!(separator / newline ) .)*
  end

  rule separator
    ','
  end

  rule newline
    [\n]
  end
end</code></pre>
<p>One concept that became clear to me is that the tokens that are defined in the grammar are objects in the resulting tree returned after input is parsed. Ruby code embedded in the Treetop&#8217;s node definitions are added as methods to the object declared by that node.</p>
<p>In the simple harness below, the <code>lines</code> object returned from the parse call below is the object representation of the <code>rule lines</code> node above, defined as the root of the parse tree. The <code>values</code> method I call below is defined above in the definition of the <code>lines</code> node.</p>
<pre><code>require 'rubygems'
require 'treetop'
require 'commaseparatedfile' 

parser = CommaSeparatedFileParser.new
lines = parser.parse("this,that,these,those")
puts lines.values.inspect #-&gt; [["this", "that", "these", "those"]]</code></pre>
<p>I think it was much simpler for me to write this parsing as a grammar instead of trying to combine regular expressions with Ruby code. The grammar above handles multiple lines and quote-wrapped values, and escaped quotes.</p>
<p>It was actually fun to write as well, and I&#8217;m still learning a lot. Notice that my <code>lines</code> node and my <code>valueline</code> node both approach a similar problem (a list of 0 or more items) differently. For the lines the grammar grabs one line followed by 0 or more separators followed by lines. For the valueline I grab 0 ore more values followed by separators and terminate on the last value. Is one approach better than the other? Are they both junk? I can&#8217;t wait to figure that out.</p>
<p>My poor parser is left in the dust by both Ruby&#8217;s <a href="http://www.ruby-doc.org/stdlib/libdoc/csv/rdoc/index.html">stdlib csv library</a>, and the <a href="http://fastercsv.rubyforge.org/">fastercsv gem</a>. I ran these tests under the 1.8.5 version of Ruby. The <a href="http://www.missiondata.com/blog/wp-content/uploads/2008/02/kentuckycsv.gz">dataset I used</a> is 44k in total and has 961 records.</p>
<pre>
                       user     system      total        real
stdlib_csv:        0.210000   0.000000   0.210000 (  0.217275)
faster_csv:        0.040000   0.000000   0.040000 (  0.060788)
treetop_grammar:   2.910000   0.010000   2.920000 (  3.126020)
</pre>
<p>I don&#8217;t know what sort of speed I should reasonably expect, actually. I&#8217;d hoped that my compiler would be competitive with the standard library&#8217;s csv parsing. It&#8217;s possible that my grammar&#8217;s definition could be innefficient. If anyone has any ideas let me know. </p>
<p>After playing around with Treetop I&#8217;ll definitely tinker some more. There are many other features I haven&#8217;t explored yet, like extending a base grammar to create a new grammar. PEGs have implementations in other languages so this isn&#8217;t a Ruby-only facility, either. </p>
<p>On a side note, I used stdlib&#8217;s benchmark to generate the numbers above. Pretty swank stuff.</p>
<pre><code>require 'rubygems'
require 'treetop'
require 'commaseparatedfile'
require 'fastercsv'
require 'csv'
require 'benchmark'

def with_stdlib_csv(csv)
  parsed = CSV.parse(csv)
  parsed.size
end

def with_fastercsv(csv)
  rows = FasterCSV.parse(csv)
  rows.size
end

def with_treetop_parser(csv)
  parser = CommaSeparatedFileParser.new
  parsed = parser.parse(csv)
  parsed.values.size
end

csv = File.read('../kentucky.csv')

Benchmark.bmbm("treetop_parser:".length) do |x|
  x.report("stdlib_csv:") { with_stdlib_csv(csv) }
  x.report("faster_csv:") { with_fastercsv(csv) }
  x.report("treetop_grammar:") { with_treetop_parser(csv) }
end</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.missiondata.com/blog/web-development/85/treetop-grammars-cool/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Handling Session Timeouts (and other errors) using Ajax</title>
		<link>http://www.missiondata.com/blog/web-development/83/handling-session-timeouts-and-other-errors-using-ajax/</link>
		<comments>http://www.missiondata.com/blog/web-development/83/handling-session-timeouts-and-other-errors-using-ajax/#comments</comments>
		<pubDate>Fri, 11 Jan 2008 20:18:11 +0000</pubDate>
		<dc:creator>steveny</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://www.missiondata.com/blog/uncategorized/83/handling-session-timeouts-and-other-errors-using-ajax/</guid>
		<description><![CDATA[Ajax can bring a much more responsive and intuitive feel to web applications.  However, many times developers overlook error cases when using Ajax.  What if the request fails?  In one particular case a user&#8217;s session may have timed out before they made an Ajax call.  This post describes one such way [...]]]></description>
			<content:encoded><![CDATA[<p><a href='http://en.wikipedia.org/wiki/Ajax_(programming)'>Ajax</a> can bring a much more responsive and intuitive feel to web applications.  However, many times developers overlook error cases when using Ajax.  What if the request fails?  In one particular case a user&#8217;s session may have timed out before they made an Ajax call.  This post describes one such way of handling this in a somewhat friendly way.<br />
<span id="more-83"></span></p>
<h3>Handling session timeouts on non-Ajax requests </h3>
<p>The first step to handing session timeouts with AJAX is to handle them for non-Ajax requests first.  One way of doing this is trapping the URL the user is attempting to access  (but not authenticated to), redirecting them to a login page, and upon success, redirecting them back to their original request.</p>
<p>If they aren&#8217;t authenticated, send them to the login page:</p>
<pre>
<code>if(!loggedIn())
{
  response.sendRedirect("/login.jsp?uri=" + URLEncoder.encode(fullURI, "UTF8"));
}</code>
</pre>
<p>Hide the original request in the page:</p>
<pre>
<code>&lt;form action="/account/login" method='POST'&gt;
  &lt;input type="hidden" name="uri" value="&lt;%=request.getParameter("uri")%&gt;"&gt;
  &lt;label for="user_login"&gt;ID:&lt;/label&gt;
  &lt;input type="text" id="user_login" name="user_login" value=""/&gt;
  &lt;label for="user_password"&gt;Password:&lt;/label&gt;
  &lt;input type="password" id="user_password" name="user_password"/&gt;
  &lt;input type="submit" name="login" value=""/&gt;
&lt;/form&gt;</code>
</pre>
<p>&#8230;and after a successful signup, send them back to where they wanted to go:</p>
<pre>
<code>if(authenticated())
{
  response.sendRedirect(request.getParameter("uri"));
}</code>
</pre>
<h3>Handling Session Timeouts for Ajax Requests </h3>
<p>The first thing we need to know is if it is an ajax request or not.  Since I am going to use <a href='http://www.prototypejs.org/'>prototype</a> for all my ajax calls it is as straight forward as looking for the special header prototype sends on each request:</p>
<pre>
<code>private boolean isXMLHttpRequest(HttpServletRequest request)
{
  return request.getHeader("x-requested-with") != null &amp;&amp; request.getHeader("x-requested-with").equals("XMLHttpRequest");
}</code>
</pre>
<p>Once we know the request type, we will send a non-200 <a href='http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html'>HTTP status code</a> if their is an authentication error.  From the standards, the most appropriate status code is a 401 (Unauthorized).  This code, however, comes with some baggage.  On a non-ajax HTTP request all browsers will respond by displaying an authentication dialog.  Most browsers don&#8217;t do this on ajax calls.  Most.  Safari decided that it should pop up the authentication dialog on ajax requests.  Without going too deeply into how this is probably correct and we should be using HTTP to its full advantage and using HTTP authentication instead of a custom authentication scheme, I don&#8217;t want this behavior.  I landed on using the much less appropriate 403 (Forbidden).</p>
<p>So, if the user isn&#8217;t authenticated  (such as with an expired session), send the 403 response back to the browser:</p>
<pre>
<code>if(isXMLHttpRequest(request))
{
  response.sendError(403);
}</code>
</pre>
<p>Now we handle the 403 on the browser side of things:</p>
<pre>
<code>new Ajax.Request('/search',
     {asynchronous:true,
       evalScripts:true,
       onException: function(req,exception) {
         alert('An exception "' + exception + '" was thrown accessing "' + request.url + '"' )
         return true
       },
       on403: function(t) {
         alert('Your session appears to have expired.  You will asked to log in again and returned here.')
         window.location.reload()
         return true
       },
       onFailure: function(request) {
         alert('An unhandled error occured ' + t.status + ': ' + t.statusText);
         return true
       },
       onLoading:function(request){Element.show('loading')},
       onComplete:function(request){Element.hide('loading')},
       onSuccess: function(t) {
         //do something with the results
       },
       parameters:Form.serialize(this)
     })</code>
</pre>
<p>The interesting bit of this call is the on403 method.  Prototype will call onXXX() where XXX is a non-200 HTTP response code.  When a 403 is returned, I simply reload the current page.  Since we handled the scenario of authenticating and returning to the requested page for the non-Ajax call, this &#8216;just works&#8217;.  You may wish to do something else here, including some nifty ajax widget that authenticates in-line and makes the call again.</p>
<p>Now that we have an Ajax request that suits our needs, we will want to use it throughout our project.  Instead of repeating the same code over and over again, let&#8217;s <a href='http://c2.com/cgi/wiki?DontRepeatYourself'>DRY</a> it up.</p>
<h3>Creating a Wrapper Class</h3>
<p>Since I am going to use this scheme for <a href='http://www.prototypejs.org/api/ajax/request'>Ajax.Request</a> and <a href='http://www.prototypejs.org/api/ajax/updater'>Ajax.Updater</a> I created two wrapper classes that use a common function for setting the options.  This scheme allows you to override any of the default options I use in the wrapper:</p>
<pre>
<code>Ajax.MyRequest = Class.create(Ajax.Request, {
  initialize: function($super, url, options) {
    $super(url,_options(options));
  }
})

Ajax.MyUpdater = Class.create(Ajax.Updater, {
  initialize: function($super, container, url, options) {
    $super({success:container},url,_options(options));
  }
})

function _options(options) {
  return Object.extend({
     asynchronous:true,
     evalScripts:true,
     onException: function(request,exception) {
       Element.hide('loading')
       alert('An exception "' + exception + '" was thrown accessing "' + request.url + '"' )
       return true
     },
     on403: function(t) {
       Element.hide('loading')
       alert('Your session appears to have expired.  You will asked to log in again and returned here.')
       window.location.reload()
       return true
     },
     onFailure: function(t) {
       Element.hide('loading')
       alert('An unhandled error occured ' + t.status + ': ' + t.statusText);
     },
     onLoading:function(request){Element.show('loading')},
     onComplete:function(request){window.setTimeout('Element.hide("loading");', 100);}
  }, options || {});
}</code>
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.missiondata.com/blog/web-development/83/handling-session-timeouts-and-other-errors-using-ajax/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Latest on Rails Performance</title>
		<link>http://www.missiondata.com/blog/web-development/70/latest-on-rails-performance/</link>
		<comments>http://www.missiondata.com/blog/web-development/70/latest-on-rails-performance/#comments</comments>
		<pubDate>Mon, 02 Apr 2007 01:02:53 +0000</pubDate>
		<dc:creator>carsonm</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.missiondata.com/blog/uncategorized/70/latest-on-rails-performance/</guid>
		<description><![CDATA[Updated Rails 1.2 performance numbers have been released. While these number look pretty good it is hard to get a good idea of exactly what the performance of Rails is. A couple of other benchmarks that include Rails such as performance tests for 6 frameworks and Grails vs Rails benchmarks show a different picture. Both [...]]]></description>
			<content:encoded><![CDATA[<p>Updated <a href="http://railsexpress.de/blog/articles/2007/04/01/rails-1-2-performance">Rails 1.2 performance</a> numbers have been released. While these number look pretty good it is hard to get a good idea of exactly what the performance of Rails is. A couple of other benchmarks that include Rails such as <a href="http://www.alrond.com/en/2007/jan/25/performance-test-of-6-leading-frameworks/">performance tests for 6 frameworks</a> and <a href="http://grails.org/Grails+vs+Rails+Benchmark">Grails vs Rails benchmarks</a> show a different picture. Both of these come up with much worse performance than the first. Maybe the issue is that the second two benchmarks are using <a href="http://httpd.apache.org/docs/2.0/programs/ab.html">Apache ab</a> but the first uses a <a href="http://railsexpress.de/blog/articles/2007/04/01/new-railsbench-release-0-9-2">new version</a> of <a href="http://railsbench.rubyforge.org/">rails bench</a>. Of course most people probably aren&#8217;t that worried about the benchmarks that much because you can find ways to make anything fast as shown with <a href="http://joyeur.com/2007/02/04/a-brief-update-with-some-numbers-for-hardware-load-balanced-mongrels">Rails doing 4000 requests a second</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.missiondata.com/blog/web-development/70/latest-on-rails-performance/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tomcat + UTF8 + HTTP Get</title>
		<link>http://www.missiondata.com/blog/web-development/69/tomcat-utf8-http-get/</link>
		<comments>http://www.missiondata.com/blog/web-development/69/tomcat-utf8-http-get/#comments</comments>
		<pubDate>Mon, 19 Mar 2007 15:53:21 +0000</pubDate>
		<dc:creator>steveny</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[tomcat]]></category>

		<guid isPermaLink="false">http://www.missiondata.com/blog/java/69/tomcat-utf8-http-get/</guid>
		<description><![CDATA[By default tomcat doesn&#8217;t UTF-8 encode get parameters like it does post parameters.  This doesn&#8217;t seem to be the case with other application servers.  So before you get yourself into trouble with your internationalized web application, make sure you make this change.
]]></description>
			<content:encoded><![CDATA[<p>By default tomcat doesn&#8217;t UTF-8 encode get parameters like it does post parameters.  This doesn&#8217;t seem to be the case with <a href="http://www.caucho.com/">other</a> application servers.  So before you get yourself into trouble with your internationalized web application, make sure you make <a href="http://tomcat.apache.org/faq/connectors.html#utf8">this change</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.missiondata.com/blog/web-development/69/tomcat-utf8-http-get/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Building a better world with Google Spreadsheets</title>
		<link>http://www.missiondata.com/blog/web-development/65/building-a-better-world-with-google-spreadsheets/</link>
		<comments>http://www.missiondata.com/blog/web-development/65/building-a-better-world-with-google-spreadsheets/#comments</comments>
		<pubDate>Wed, 06 Dec 2006 15:51:04 +0000</pubDate>
		<dc:creator>steveny</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://blogs.missiondata.com/uncategorized/65/building-a-better-world-with-google-spreadsheets/</guid>
		<description><![CDATA[I was tickled when I ran across the GoogleLookup and GoogleFinance functions in Google Spreadsheets.  I was very tickled when I found there was a REST API for interacting with the spreadsheets.
So not only can you lookup the current volume of Google stock in a spreadsheet (=GoogleFinance(&#8221;GOOG&#8221;, &#8220;volume&#8221;)) or find out Roger Clemens&#8217;s ERA [...]]]></description>
			<content:encoded><![CDATA[<p>I was tickled when I ran across the <a href="http://docs.google.com/support/spreadsheets/bin/answer.py?answer=54199&#038;ctx=sibling">GoogleLookup</a> and <a href="http://docs.google.com/support/spreadsheets/bin/answer.py?answer=54198&#038;ctx=sibling">GoogleFinance</a> functions in <a href="">Google Spreadsheets</a>.  I was <b>very</b> tickled when I found there was a <a href="http://code.google.com/apis/gdata/spreadsheets.html">REST API</a> for interacting with the spreadsheets.</p>
<p>So not only can you lookup the current volume of Google stock in a spreadsheet (=GoogleFinance(&#8221;GOOG&#8221;, &#8220;volume&#8221;)) or find out Roger Clemens&#8217;s ERA (=GoogleLookup(&#8221;Roger Clemens&#8221;,&#8221;earned run average&#8221;)) you can access those values real time using an open API.  I cobbled together a quick ruby program that can retrieve values from a private or public (published) Google spreadsheet.  </p>
<p><span id="more-65"></span></p>
<p>The public sample should work for everyone since I published that spreadsheet for the world to see.  You will need to provide your own credentials and spreadsheet key to use the authenticated example.  I will caution that this is just a proof of concept that has limited functionality, weak parsing, and no error checking.</p>
<pre>
<code>#!/usr/bin/env ruby

require 'net/http'
require 'net/https'
require 'uri'
require 'rubygems'
require 'hpricot'

#
# Make it east to use some of the convenience methods using https
#
module Net
  class HTTPS &lt; HTTP
    def initialize(address, port = nil)
      super(address, port)
      self.use_ssl = true
    end
  end
end

class GoogleSpreadSheet
  def initialize(spreadsheet_key)
    @spreadsheet_key = spreadsheet_key
    @headers = nil
  end

  def authenticate(email, password)
    url = URI.parse('https://www.google.com/accounts/ClientLogin')
    response = Net::HTTPS.post_form(url,
      {'Email'=&gt;email,
       'Passwd'=&gt;password,
       'source'=&gt;"ruby-ss-example-1",
       'service'=&gt;'wise' })
    @headers = {
     'Authorization' =&gt; "GoogleLogin auth=#{response.body.split(/=/).last}",
     'Content-Type'  =&gt; 'application/atom+xml'
    }
  end

  def evaluate_cell(cell)
    path = "/feeds/cells/#{@spreadsheet_key}/1/#{@headers ? "private" : "public"}/basic/#{cell}"
    doc = Hpricot(request(path))
    result = (doc/"content[@type='text']").inner_html
  end

  private
  def request(path)
    http = Net::HTTP.new('spreadsheets.google.com', 80)
    response,data = http.get(path, @headers)
    data
  end
end

gs = GoogleSpreadSheet.new('p39irgfu5fsFokTPyPCG8Lg')
puts gs.evaluate_cell("A1")
puts gs.evaluate_cell("A2")
puts gs.evaluate_cell("B1")

gs = GoogleSpreadSheet.new(&lt;your spreadsheet key&gt;)
gs.authenticate(&lt;your email&gt;, &lt;your password&gt;)
puts gs.evaluate_cell("E132")</code>
</pre>
<p>The fun really just starts here.  You can edit existing spreadsheets too (although you can &#8216;t create or delete them yet).  As <a href='http://blogs.missiondata.com/author/richier/'>Rich</a> pointed out to me a few days ago, it won&#8217;t be too long before we are adding &#8216;export to Google spreadsheet&#8217; functions to our web applications.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.missiondata.com/blog/web-development/65/building-a-better-world-with-google-spreadsheets/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>IE7 adds native XMLHTTPRequest object</title>
		<link>http://www.missiondata.com/blog/web-development/64/ie7-adds-native-xmlhttprequest-object/</link>
		<comments>http://www.missiondata.com/blog/web-development/64/ie7-adds-native-xmlhttprequest-object/#comments</comments>
		<pubDate>Thu, 26 Oct 2006 12:43:58 +0000</pubDate>
		<dc:creator>steveny</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[ajax]]></category>

		<guid isPermaLink="false">http://blogs.missiondata.com/?p=64</guid>
		<description><![CDATA[The recently released IE7 supports a native XMLHTTPRequest object.  On the surface this can be considered a good thing and should be commended.  However, to the people that erroneously (in hindsight) assumed that&#8230;
  window.XMLHttpRequest == ! (not) IE
&#8230;they are in for some strange behavior  (here, here, here, and here for example).
The [...]]]></description>
			<content:encoded><![CDATA[<p>The recently released IE7 supports <a href=" http://blogs.msdn.com/ie/archive/2006/01/23/516393.aspx">a native XMLHTTPRequest object</a>.  On the surface this can be considered a good thing and should be commended.  However, to the people that erroneously (in hindsight) assumed that&#8230;</p>
<p><code>  window.XMLHttpRequest == ! (not) IE</code></p>
<p>&#8230;they are in for some strange behavior  (<a href="http://web.archive.org/web/20041104081337js_/creatimation.net/extra/live-request/liveRequest.js">here</a>, <a href="http://web.archive.org/web/20041012102019/http://beta4.com/~avi/liveUpdater.js">here</a>, <a href="http://lakeshore.sourceforge.net/">here</a>, and <a href="http://www.google.com/codesearch?q=if+%28window.XMLHttpRequest%29+initialize+it+once&#038;btnG=Search+Code">here</a> for example).</p>
<p>The problem occurs when the code is optimized for non-IE browsers and does not recreate the XMLHTTPRequest object on each event.  Back when  &#8220;window.XMLHttpRequest == !IE&#8221; was true, this code worked as expected: IE browsers created a new XMLHttpRequest object on each event and non-IE browsers reused the same XMLHttpRequest object.  Now IE7 will correctly process the first event but then fails on the second (and subsequent) requests because you still can&#8217;t reuse XMLHttpRequest objects.</p>
<p>We chose to just remove the optimization all together and recreate the object on each event for all browsers.  Others may wish to come up with some other check that will allow them to keep it. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.missiondata.com/blog/web-development/64/ie7-adds-native-xmlhttprequest-object/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Cleaning Up Rails Sessions, Revisited</title>
		<link>http://www.missiondata.com/blog/web-development/63/cleaning-up-rails-sessions-revisited/</link>
		<comments>http://www.missiondata.com/blog/web-development/63/cleaning-up-rails-sessions-revisited/#comments</comments>
		<pubDate>Sat, 16 Sep 2006 16:15:30 +0000</pubDate>
		<dc:creator>Rich Rodriguez</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://blogs.missiondata.com/?p=63</guid>
		<description><![CDATA[In an earlier post, we detailed a method for removing stale Rails session files. In more recent version of Rails, there is a Rake task built in for this administration task.
rake tmp:sessions:clear # Clears all files in tmp/sessions
]]></description>
			<content:encoded><![CDATA[<p>In an earlier <a href="http://blogs.missiondata.com/?p=58">post</a>, we detailed a method for removing stale Rails session files. In more recent version of Rails, there is a Rake task built in for this administration task.</p>
<p><code class="console">rake tmp:sessions:clear # Clears all files in tmp/sessions</code></p>
]]></content:encoded>
			<wfw:commentRss>http://www.missiondata.com/blog/web-development/63/cleaning-up-rails-sessions-revisited/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Cleaning up stale rails sessions (removing ruby_sess files)</title>
		<link>http://www.missiondata.com/blog/web-development/58/cleaning-up-stale-rails-sessions-removing-ruby_sess-files/</link>
		<comments>http://www.missiondata.com/blog/web-development/58/cleaning-up-stale-rails-sessions-removing-ruby_sess-files/#comments</comments>
		<pubDate>Thu, 08 Jun 2006 11:59:02 +0000</pubDate>
		<dc:creator>carsonm</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[System Administration]]></category>

		<guid isPermaLink="false">http://blogs.missiondata.com/?p=58</guid>
		<description><![CDATA[I&#8217;m not sure if something isn&#8217;t set up correctly of if this is just a fact of life with rails but the sessions it creates never seem to go away. I think before rails 1.1 the sessions where stored in /tmp and now they are stored in the apps directory along with everything else so [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m not sure if something isn&#8217;t set up correctly of if this is just a fact of life with rails but the sessions it creates never seem to go away. I think before rails 1.1 the sessions where stored in /tmp and now they are stored in the apps directory along with everything else so they is probably no internal mechanism to delete them. I only noticed because after about a month of an certain app running the disk on the machine started to fill up. After digging a little I found 50K ruby_sess.* files hanging out in the rails session directory.</p>
<p>Anyway it was easy enough to clean up the stale ruby_sess files by going into the rails webapp/session directory and then running the following command:</p>
<pre>
<code>find -type f -name "ruby_sess*" -exec rm -f {} \;</code>
</pre>
<p>I&#8217;m not sure why the app is creating sessions but it isn&#8217;t something that stores state so I didn&#8217;t have to worry about killing active sessions here. If you do need to worry about that you will probably want to toss a time on the find command.</p>
<p>After looking a little more I found a <a href="http://www.realityforge.org/articles/2006/03/01/removing-stale-rails-sessions">post about this</a> that has a ruby way of cleaning up the sessions.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.missiondata.com/blog/web-development/58/cleaning-up-stale-rails-sessions-removing-ruby_sess-files/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Ruby&#8217;s DBI or ActiveRecord</title>
		<link>http://www.missiondata.com/blog/web-development/41/rubys-dbi-or-activerecord/</link>
		<comments>http://www.missiondata.com/blog/web-development/41/rubys-dbi-or-activerecord/#comments</comments>
		<pubDate>Sun, 09 Apr 2006 18:35:18 +0000</pubDate>
		<dc:creator>chuckf</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://blogs.missiondata.com/?p=41</guid>
		<description><![CDATA[While creating a small CGI web application in Ruby the question came up about how much slower ActiveRecord is than DBI. Considering that ActiveRecord is initialized each time the CGI runs the performance hit could be significant.
So why not use Rails instead? The server that I am running the application on has limited resources. Rails [...]]]></description>
			<content:encoded><![CDATA[<p>While creating a small CGI web application in Ruby the question came up about how much slower ActiveRecord is than DBI. Considering that ActiveRecord is initialized each time the CGI runs the performance hit could be significant.</p>
<p>So why not use Rails instead? The server that I am running the application on has limited resources. Rails is reported to need about 20 MB of memory and the node I have is already paging out memory to disk.</p>
<p>To emulate the webserver getting hit repeatedly with connections I created a connect_dbi.rb and and connect_ar.rb that insert the same row into a Tests database table. The ActiveRecord test also has the model file test.rb</p>
<p>The test was run using a PostGreSQL database on Ubuntu 5.10 with Ruby 1.8.4. The table was truncated between tests. I just wanted to get an idea of the performance difference between ActiveRecord and DBI. So this isn&#8217;t the strictest performance test but does provide an idea of the magnitude of difference.</p>
<p><span id="more-41"></span><br />
The test was executed from the command line using &#8220;ruby -e&#8221; to call the connect_dbi.rb and connect_ar.rb files 100 times each. This creates a new database connection each time the script is executed. ActiveRecord generates a series of error messages about unavailable database adapters each time it is started so these messages were capatured in the activeError file. DBI doesn&#8217;t produce any errors but I wanted to keep the execution as similar as possible so there is also a dbiError file created.</p>
<h3>connect_dbi.rb</h3>
<pre><code>#! /usr/bin/ruby -w
require 'rubygems'
require 'dbi'

dbh = DBI.connect('dbi:Pg:tmp_test:localhost','ruby_user','ruby_pass')

begin

dbh.transaction do |dbh|
dbh.prepare("INSERT INTO tests(rank, created_at, message) VALUES(?,?,?)") do |sth|
sth.execute(5, Time.now, 'abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz ')
end
end

rescue DBI::ProgrammingError =&gt; exception
puts "Exception: #{exception.message}"
end
</code></pre>
<h3>connect_ar.rb</h3>
<pre><code>#! /usr/bin/ruby -w

require 'rubygems'
require_gem 'activerecord'

ActiveRecord::Base.establish_connection(
:adapter  =&gt; "postgresql",
:host     =&gt; "localhost",
:username =&gt; "ruby_user",
:password =&gt; "ruby_pass",
:database =&gt; "tmp_test"
)

test = Test.new("rank" =&gt; 5, "created_at" =&gt; "#{Time.now}", "message" =&gt; 'abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz ')
test.save</code></pre>
<h3>test.rb</h3>
<pre><code>class Test &lt; ActiveRecord::Base

end
</code></pre>
<p>The GNU/Linux time command was used to obtain timings.</p>
<p>As the results show DBI appears to be about three times faster than using ActiveRecord. This is most likely because of the initialization ActiveRecord does each time the connection is established. Considering that the test is only using one table and one ActiveRecord model class this is a fairly significant difference.</p>
<pre><code>~/projects/dbi_test $ time ruby -e '100.times { %x{./connect_ar.rb}}' 2&gt; activeError

real    0m25.916s
user    0m21.575s
sys     0m2.807s

~/projects/dbi_test $ time ruby -e '100.times { %x{./connect_dbi.rb}}' 2&gt; dbiError

real    0m8.154s
user    0m6.620s
sys     0m0.733s</code></pre>
<pre>All results are in seconds.  Each test was run ten times.
<h3>DBI Results</h3>
<table cellspacing="0" cellpadding="2" border="1">
<tr>
<th></th>
<th>Mean</th>
<th>Standard Deviation</th>
</tr>
<tr>
<td>Real</td>
<td>7.7133</td>
<td>0.9448</td>
</tr>
<tr>
<td>User</td>
<td>6.2027</td>
<td>0.8530</td>
</tr>
<tr>
<td>Sys</td>
<td>6.2027</td>
<td>0.2760</td>
</tr>
</table>
<h3>ActiveRecord Results</h3>
<table cellspacing="0" cellpadding="2" border="1">
<tr>
<th></th>
<th>Mean</th>
<th>Standard Deviation</th>
</tr>
<tr>
<td>Real</td>
<td>26.9003</td>
<td>1.8849</td>
</tr>
<tr>
<td>User</td>
<td>21.9256</td>
<td>1.4959</td>
</tr>
<tr>
<td>Sys</td>
<td>2.8038</td>
<td>0.4610</td>
</tr>
</table>
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.missiondata.com/blog/web-development/41/rubys-dbi-or-activerecord/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>AJAX file upload progress for Java using commons fileupload and prototype</title>
		<link>http://www.missiondata.com/blog/web-development/28/file-upload-progress-with-ajax-and-java-and-prototype/</link>
		<comments>http://www.missiondata.com/blog/web-development/28/file-upload-progress-with-ajax-and-java-and-prototype/#comments</comments>
		<pubDate>Sun, 02 Apr 2006 21:15:15 +0000</pubDate>
		<dc:creator>carsonm</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://blogs.missiondata.com/?p=28</guid>
		<description><![CDATA[This has been done before with PHP (AJAX upload progress meter for PHP) etc but I needed something a little different because I wanted to upload a file and then have it loaded into a database. I looked around and found that someone had already made something that used the commons file upload package to [...]]]></description>
			<content:encoded><![CDATA[<p>This has been done before with PHP (<a href="http://bluga.net/projects/uploadProgressMeter/">AJAX upload progress meter for PHP</a>) etc but I needed something a little different because I wanted to upload a file and then have it loaded into a database. I looked around and found that someone had already made something that used the commons file upload package to do the upload part (<a href="http://www.telio.be/blog/2006/01/06/ajax-upload-progress-monitor-for-commons-fileupload-example/">AJAX Upload progress monitor for Commons-FileUpload Example</a>). It wasn&#8217;t exactly what I was looking for but it a good start.</p>
<p>To understand the way this works I think it is easiest to break it down into parts:</p>
<ol>
<li>A file upload extention that counts bytes as they are uploaded</li>
<li>An interface that monitors the progress of something running on the server</li>
<li>AJAX to pull the monitoring into the current screen</li>
</ol>
<p><span id="more-28"></span></p>
<h3>Counting bytes when files are uploaded</h3>
<p>This was taken from the <a href="http://www.telio.be/blog/2006/01/06/ajax-upload-progress-monitor-for-commons-fileupload-example/">example listed above</a>. It extends and wraps parts of the commons File Upload classes so that you can count the bytes as they are uploaded to the server. You can download the <a href="http://blogs.missiondata.com/wp-content/uploads/2006/03/fileupload-ext.zip">source with build file</a> or the <a href="http://blogs.missiondata.com/wp-content/uploads/2006/03/fileupload-ext1.zip">binary</a>. You will also need the <a href="http://jakarta.apache.org/site/downloads/downloads_commons-fileupload.cgi">commons file upload</a>, <a href="http://jakarta.apache.org/site/downloads/downloads_commons-io.cgi">commons io</a> and <a href="http://jakarta.apache.org/site/downloads/downloads_commons-logging.cgi">commons logging</a>. If you download the source put the commons jars in the lib directory before building.</p>
<p>The code is fairly simple to follow. MonitoredDiskFileItemFactory replaces DiskFileItemFactory and the construction of a MonitoredDiskFileItemFactory takes a OutputStreamListener that will be passed on down the chain. The new factory creates MonitoredDiskFileItems instead of DiskFileItems for each file uploaded. When the file needs to be written to disk a MonitoredOutputStream is given back instead of a normal OutputStream. The MonitoredOutputStream calls the OutputStreamListener methods as the bytes are written and with that you now have a way to monitor the byte count as the file is created on the server.</p>
<p>Now to test this all out we can just have an OutputStreamListener that writes its progress out to a logfile or something.</p>
<pre>
<code>public class FileUploadListener implements OutputStreamListener
{
  private long totalFileSize;
  private long currentFileRead;

  public FileUploadListener(long totalFileSize)
  {
    this.totalFileSize = totalFileSize;
    this.currentFileRead = 0;
  }

  public void start()
  {
    log.debug("Upload started. Total file size: " + totalFileSize);
  }

  public void bytesRead(int byteCount)
  {
    log.debug("Read bytes. Currently " + byteCount + " out of " + totalFileSize + " bytes.");
    currentFileRead+=byteCount;
  }

  public void error(String error)
  {
    log.debug("Hit an error: " + error);
  }

  public void done()
  {
    log.debug("Upload done.");
  }

  public long getTotalRead()
  {
    return currentFileRead;
  }

  public long getTotalSize()
  {
    return totalFileSize;
  }
}</code>
</pre>
<p>Now we try it out. You can put this in a servlet or jsp so I&#8217;m only going to list the parts that matter.</p>
<pre>
<code>  FileUploadListener listener = new FileUploadListener(request.getContentLength());
  session.setAttribute("LISTENER", listener);
  FileItemFactory factory = new MonitoredDiskFileItemFactory(listener);
  ServletFileUpload upload = new ServletFileUpload(factory);
  List items = upload.parseRequest(request);
  for (Iterator i = items.iterator(); i.hasNext();)
  {
    FileItem fileItem = (FileItem) i.next();
    if (!fileItem.isFormField())
    {
       // code here to process the file
     }
   }</code>
</pre>
<p>I&#8217;m going to assume you can find the correct way to do the actual form upload part.</p>
<p>Note: One issue that you will face at some point is where the upload post goes to becuase when you get to the AJAXy part of things you want the post to stay on the same page. You can use a hidden iframe and the form&#8217;s &#8220;target&#8221; parameter to do this (I have an example later). This is one thing the Java examples I found didn&#8217;t have but the PHP examples did and I&#8217;m not sure exactly how the Java examples work without it.</p>
<h3>Monitoring progress on the server</h3>
<p>The next step is to monitor the progress of the upload on the server. What you are monitoring on the server doesn&#8217;t even need to be the upload. For the work I was doing the upload goes fairly quickly but what happens to the file after the upload takes a little longer. I wanted to monitor both and that is one reason I think it helps to break this up into parts because you aren&#8217;t limited to just monitoring file uploads.</p>
<p>The main thing to keep in mind here is that the application server is multithreaded and you can make more than one request to the server at the same time. You probably know that you can open a tab in firefox or another window in ie and use the same session from the current webapp you are using. Knowing that you can create a page that monitors the status of things as they are running on the server. </p>
<p>From the example above you could toss the listener into the users session. Then insead of logging you just add a couple variables to keep track of the number of bytes that have been uploaded. Then create a simple jsp that pulls the Listener out of the session and dumps its data to a page. Open two windows, one to the upload page and another one to the status page. Start the upload and then start refreshing the status. You should see that the values change as the file is uploaded.</p>
<pre>
<code>&lt;%@page%&gt;
&lt;%
  FileUploadListener listener = (FileUploadListener)session.getAttribute("LISTENER");
%&gt;
Total size: &lt;%=listener.getTotalSize()%&gt;&lt;br/&gt;
Read count: &lt;%=listener.getTotalRead()%&gt;&lt;br/&gt;</code>
</pre>
<p>Of course you will probably want more than just the total size and bytes read as well as more formating like a little progress bar or something but I&#8217;ll leave that up to you. </p>
<h3>AJAX integration with prototype</h3>
<p>You have the major parts to the upload progress done and now all you need is the AJAX part. To do this I chose to use <a href="http://prototype.conio.net/">prototype</a> because it cuts right to what you want to do. One call is all you need to use: Ajax.PeriodicalUpdater.</p>
<p>The Ajax.PeriodicalUpdater call will update a container (in my case a div) on a set interval. Here is an example of how to have it update a div with an id of &#8220;status&#8221; every second.</p>
<pre>
<code>    new Ajax.PeriodicalUpdater(
                                'status',
                                'status.jsp',
                                {asynchronous:true, frequency:1, method:'get'});</code>
</pre>
<p>The first argument is the id of the div, the second is the jsp that contains the data to stick into the div every second and the 3rd arguement is a set of options. There are more options availabe if you need them.</p>
<p>You would want to kick the update off whenever the form is posted. When the post is complete the iframe used as a place to post to will load with the results of the servlet or jsp that you posted to. If you return some javascript as a result for the iframe you will be able to create a final &#8220;finished&#8221; message on the page to let the user know the upload has completed and stop the processing of the AJAX updater.</p>
<p>So there you have it. The basics of setting up an upload progress bar using java and AJAX. I have left out a good bit but you should have enough to at least get you started.</p>
<p>By request I have created a simple example that pulls everything together. The source contains everything you need to create a war file including all source and an ant build file.</p>
<p><a href="/blog/examples/testupload.zip">Example Source</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.missiondata.com/blog/web-development/28/file-upload-progress-with-ajax-and-java-and-prototype/feed/</wfw:commentRss>
		<slash:comments>38</slash:comments>
		</item>
	</channel>
</rss>
