<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">
  <channel>
    <title>juretta.com</title>
    <link>http://www.juretta.com</link>
    <language>en</language>
    <webMaster>Stefan Saasen</webMaster>
    <pubDate>2009-11-05T23:59:00+13:00</pubDate>
    <copyright>Copyright 2007-2009</copyright>
    <ttl>60</ttl>
    <description />
    
    <creativeCommons:license>http://creativecommons.org/licenses/by/2.0/</creativeCommons:license><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/juretta" type="application/rss+xml" /><feedburner:browserFriendly>This is an XML content feed. It is intended to be viewed in a newsreader or syndicated to another site.</feedburner:browserFriendly><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item>
      <title>Disable basic authentication for CouchDB running behind an Apache reverse proxy</title>
      <link>http://feedproxy.google.com/~r/juretta/~3/68ESUtahoJU/</link>
      <pubDate>Sat May 30 00:00:00 +1200 2009</pubDate>
      <guid isPermaLink="false">http://www.juretta.com/log//log/2009/05/30/authentication-couchdb-futon-behind-apache-reverse-proxy/</guid>
      <description>&lt;p&gt;I am currently using CouchDB version 0.9 for quite a few different projects on the production machine.
CouchDB only accepts local connections, I ususally use either an SSH tunnel or an Apache virtual host
to access the Futon administration interface.&lt;/p&gt;

&lt;p&gt;The virtual host uses basic authentication and a reverse proxy to expose the CouchDB HTTP API and Futon.
Apache will pass the authentication header to CouchDB which in turn invokes its authentication handler.
As I am using CouchDB using a variety of different clients (Java based web application running in Tomcat, Rabbit MQ, a
CouchDB/Rails project that is being tested by a Hudson continuous integration server, CLI apps and so forth) and I am
not exposing CouchDB anyway I am not really keen on using the authentication mechanism CouchDB provides.&lt;/p&gt;

&lt;p&gt;So I basically would like to let Apache take care of the access control and not having CouchDB invoking its
authentication handler.&lt;/p&gt;

&lt;p&gt;As far as I know there are basically two approaches to this problem.&lt;/p&gt;

&lt;p&gt;The first is to set a &lt;code&gt;null_authentication_handler&lt;/code&gt; in your CouchDB &lt;code&gt;local.ini&lt;/code&gt; file (usually in $INSTALL_PREFIX/etc/couchdb/local.ini):&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;[httpd]&lt;/span&gt;
&lt;span class="na"&gt;authentication_handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;{couch_httpd, null_authentication_handler}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Unfortunately the 0.9 release version does not seem to contain the &lt;code&gt;null_authentication_handler&lt;/code&gt; and works on more
recent CouchDB versions only.&lt;/p&gt;

&lt;p&gt;This basically means that the proxy in front of CouchDB needs to strip the &lt;code&gt;Authentication&lt;/code&gt; header.&lt;/p&gt;

&lt;p&gt;This can be done for Apache by enabling the &lt;code&gt;mod_headers&lt;/code&gt; module (&lt;code&gt;a2enmod headers&lt;/code&gt; on Debian for example) and
using the following line to unset the &lt;code&gt;Authentication&lt;/code&gt; header:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nb"&gt;RequestHeader&lt;/span&gt; unset Authorization
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The following listing shows a setting similar to the one I am using for the virtual host:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nt"&gt;&amp;lt;VirtualHost&lt;/span&gt; &lt;span class="s"&gt;*:80&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nb"&gt;ServerName&lt;/span&gt; couchdb.example.com
        &lt;span class="nb"&gt;ServerAdmin&lt;/span&gt; admin@example.com


        &lt;span class="nb"&gt;ProxyRequests&lt;/span&gt; &lt;span class="k"&gt;Off&lt;/span&gt;
        &lt;span class="nb"&gt;ProxyPreserveHost&lt;/span&gt; &lt;span class="k"&gt;Off&lt;/span&gt;
        &lt;span class="nb"&gt;AllowEncodedSlashes&lt;/span&gt; &lt;span class="k"&gt;On&lt;/span&gt;
        &lt;span class="nb"&gt;KeepAlive&lt;/span&gt; &lt;span class="k"&gt;Off&lt;/span&gt;

        &lt;span class="nt"&gt;&amp;lt;Proxy&lt;/span&gt; &lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nb"&gt;Order&lt;/span&gt; deny,allow
            &lt;span class="nb"&gt;Allow&lt;/span&gt; from &lt;span class="k"&gt;all&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/Proxy&amp;gt;&lt;/span&gt;

        &lt;span class="nt"&gt;&amp;lt;Location&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nb"&gt;AuthType&lt;/span&gt; Basic
                &lt;span class="nb"&gt;AuthName&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Couchdb Admin&amp;quot;&lt;/span&gt;
                &lt;span class="nb"&gt;AuthUserFile&lt;/span&gt; &lt;span class="sx"&gt;/etc/apache2/passwd&lt;/span&gt;
                &lt;span class="nb"&gt;Require&lt;/span&gt; valid-user
        &lt;span class="nt"&gt;&amp;lt;/Location&amp;gt;&lt;/span&gt;

        &lt;span class="nb"&gt;ProxyPass&lt;/span&gt; / http://localhost:5984/ nocanon
        &lt;span class="nb"&gt;ProxyPassReverse&lt;/span&gt; / http://localhost:5984/
        &lt;span class="nb"&gt;RequestHeader&lt;/span&gt; unset Authorization

        &lt;span class="nb"&gt;ErrorLog&lt;/span&gt; &lt;span class="sx"&gt;/var/log/apache2/couchdb.example.com-error_log&lt;/span&gt;
        &lt;span class="nb"&gt;CustomLog&lt;/span&gt; &lt;span class="sx"&gt;/var/log/apache2/couchdb.example.com-access_log&lt;/span&gt; common
&lt;span class="nt"&gt;&amp;lt;/VirtualHost&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/juretta?a=68ESUtahoJU:YAa1kGs2bSQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/juretta?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/juretta?a=68ESUtahoJU:YAa1kGs2bSQ:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/juretta?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/juretta?a=68ESUtahoJU:YAa1kGs2bSQ:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/juretta?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/juretta/~4/68ESUtahoJU" height="1" width="1"/&gt;</description>
      
    <feedburner:origLink>http://www.juretta.com/log//log/2009/05/30/authentication-couchdb-futon-behind-apache-reverse-proxy/</feedburner:origLink></item>
    
    <item>
      <title>Goodby Rails, kind of...</title>
      <link>http://feedproxy.google.com/~r/juretta/~3/glWO7IkoDZE/</link>
      <pubDate>Fri May 29 00:00:00 +1200 2009</pubDate>
      <guid isPermaLink="false">http://www.juretta.com/log//log/2009/05/29/goodbye-rails/</guid>
      <description>&lt;p&gt;I started this blog about 4 years ago using a custom built Rails blog engine using Rails 0.8.
A Rails based blog engine wasn't around at that time and I wanted to build something using Rails anyway.&lt;/p&gt;

&lt;p&gt;Having a custom built blog engine has its benefits and drawbacks. The rather basic administration interface
was a pain to use and running two Mongrel instances for a nearly static website seemed to be a
misallocation of ressources anyway.&lt;/p&gt;

&lt;p&gt;So instead of switching to another full-fledged blog engine I switched to using &lt;a href="http://github.com/mojombo/jekyll/tree/master" title="Jekyll"&gt;Jekyll&lt;/a&gt; to generate a static version of the blog.&lt;/p&gt;

&lt;p&gt;Tom Preston-Werner (the author of Jekyll) writes about his reasons for creating Jekkyl in
&lt;a href="http://tom.preston-werner.com/2008/11/17/blogging-like-a-hacker.html"&gt;Blogging Like a Hacker&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote cite="http://tom.preston-werner.com/2008/11/17/blogging-like-a-hacker.html"&gt;
I was tired of complicated blogging engines like WordPress and Mephisto. I wanted to write great posts, not style a zillion template pages, moderate comments all day long, and constantly lag behind the latest software release.
&lt;/blockquote&gt;


&lt;p&gt;Jekyll is the complete opposite, it is a:&lt;/p&gt;

&lt;blockquote&gt;
    [...] simple, blog aware, static site generator. It takes a template directory (representing the raw form of a website), runs it through Textile and Liquid converters, and spits out a complete, static website suitable for serving with Apache or your favorite web server.
&lt;/blockquote&gt;


&lt;p&gt;With a basic directory layout and a simple configuration file creating a static copy of your blog is merely running
the &lt;code&gt;jekyll&lt;/code&gt; command in your blog directory.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;stefan@macbook-pro:~/webs/juretta.com/www &lt;span class="o"&gt;[&lt;/span&gt;0&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;tree -L 3
.
|-- Rakefile
|-- _config.yml
|-- site
|   |-- 404.html
|   |-- _includes
|   |   &lt;span class="sb"&gt;`&lt;/span&gt;-- entry-preview.html
|   |-- _layouts
|   |   |-- default.html
|   |   &lt;span class="sb"&gt;`&lt;/span&gt;-- post.html
|   |-- _posts
|   |   |-- 2008-11-11-hudson_test_drive_part_1_rails.html
|   |   |-- 2008-12-11-hudson_at_wellrailed.html
|   |   |-- 2009-05-24-activemq-jms-stomp.markdown
|   |   &lt;span class="sb"&gt;`&lt;/span&gt;-- 2009-05-29-goodbye-rails.markdown
|   |-- about
|   |   &lt;span class="sb"&gt;`&lt;/span&gt;-- index.html
|   |-- atom.xml
|   |-- favicon.ico
|   |-- images
|   |-- index.html
|   |-- javascripts
|   |-- rss.xml
|   |-- sitemap.xml
|   &lt;span class="sb"&gt;`&lt;/span&gt;-- stylesheets
&lt;span class="sb"&gt;`&lt;/span&gt;-- web
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Running &lt;code&gt;jekyll&lt;/code&gt; in this directory will copy all the static files in &lt;code&gt;site&lt;/code&gt; into &lt;code&gt;web&lt;/code&gt; and will transform your
content files (HTML, Markdown, Textile based) applying a series of layout files (Read more on the Jekyll Wiki pages: &lt;a href="http://wiki.github.com/mojombo/jekyll/usage"&gt;Usage&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Running &lt;code&gt;jekyll --server&lt;/code&gt; will transform the files and fires up a local WEBrick server running on &lt;code&gt;http://localhost:4000&lt;/code&gt;.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;stefan@macbook-pro:~/webs/juretta.com/www &lt;span class="o"&gt;(&lt;/span&gt;master&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;0&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;rake server
&lt;span class="o"&gt;(&lt;/span&gt;in /Users/stefan/webs/juretta.com/www&lt;span class="o"&gt;)&lt;/span&gt;
juicer merge --force --document-root ./site ./site/stylesheets/base.css
Produced site/stylesheets/base.min.css from
  site/stylesheets/undohtml.css
  site/stylesheets/screen.css
  site/stylesheets/form.css
  site/stylesheets/syntax.css
  site/stylesheets/base.css
jekyll --server
Configuration from ./_config.yml
Building site: site -&amp;gt; web
Successfully generated site: site -&amp;gt; web
&lt;span class="o"&gt;[&lt;/span&gt;2009-05-29 17:49:10&lt;span class="o"&gt;]&lt;/span&gt; INFO  WEBrick 1.3.1
&lt;span class="o"&gt;[&lt;/span&gt;2009-05-29 17:49:10&lt;span class="o"&gt;]&lt;/span&gt; INFO  ruby 1.8.6 &lt;span class="o"&gt;(&lt;/span&gt;2007-09-24&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;i686-darwin9.2.0&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;2009-05-29 17:49:10&lt;span class="o"&gt;]&lt;/span&gt; INFO  WEBrick::HTTPServer#start: &lt;span class="nv"&gt;pid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;7634 &lt;span class="nv"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;4000
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Throw in some &lt;a href="http://www.cjohansen.no/en/ruby/juicer_a_css_and_javascript_packaging_tool"&gt;juicer&lt;/a&gt; goodness and a nice git post-receive hook and your new post is only a single &lt;code&gt;git push&lt;/code&gt; away.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/juretta?a=glWO7IkoDZE:l7WNLetrMFI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/juretta?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/juretta?a=glWO7IkoDZE:l7WNLetrMFI:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/juretta?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/juretta?a=glWO7IkoDZE:l7WNLetrMFI:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/juretta?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/juretta/~4/glWO7IkoDZE" height="1" width="1"/&gt;</description>
      
    <feedburner:origLink>http://www.juretta.com/log//log/2009/05/29/goodbye-rails/</feedburner:origLink></item>
    
    <item>
      <title>ActiveMQ, Stomp, JMS and the empty message body</title>
      <link>http://feedproxy.google.com/~r/juretta/~3/EpzkbV4Bi0Y/</link>
      <pubDate>Sun May 24 00:00:00 +1200 2009</pubDate>
      <guid isPermaLink="false">http://www.juretta.com/log//log/2009/05/24/activemq-jms-stomp/</guid>
      <description>&lt;p&gt;For a project I am currently working on I needed to hook up BlazeDS and ActiveMQ.
While everything went fine and without any disruption, I ran into a minor problem after I decided to use a Ruby based script to sent notifications to a topic based message queue.&lt;/p&gt;

&lt;p&gt;The setup looks remotely like this:&lt;/p&gt;

&lt;p&gt;&lt;img src="/images/posts/2009/activemq-stomp-1.png" alt="Activemq/BlazeDS setup" /&gt;&lt;/p&gt;

&lt;p&gt;BlazeDS and ActiveMQ are using the &lt;a href="http://java.sun.com/products/jms/"&gt;Java Message Service (JMS)&lt;/a&gt; API for message exchange. The Ruby script is using the &lt;a href="http://stomp.codehaus.org/"&gt;Stomp&lt;/a&gt; (Streaming Text Orientated Messaging Protocol) interface to ActiveMQ.&lt;/p&gt;

&lt;p&gt;Stomp is a really simple interface that looks vaguely like HTTP - it can even be used by using a simple Telnet connection to the message queue.&lt;/p&gt;

&lt;p&gt;A simple stomp based message frame looks like this:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;SEND
destination:/queue/a

hello queue a
^@
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The message frame starts with a single Stomp command name (one of SEND, SUBSCRIBE, UNSUBSCRIBE, BEGIN, COMMIT,
ABORT, ACK, DISCONNECT) followed by a newline, the message header consisting of &lt;code&gt;key: value&lt;/code&gt; pairs, a blank line and
the message body followed by a null character (NUL).&lt;/p&gt;

&lt;p&gt;The Ruby based equivalent to send a simple text message looks like this:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;rubygems&amp;#39;&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;stomp&amp;#39;&lt;/span&gt;

&lt;span class="n"&gt;conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Stomp&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;USER&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;PASSWORD&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;61613&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt; 
&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;/topic/messageTopic&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:persistent&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;true&amp;#39;&lt;/span&gt;
&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;disconnect&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;ActiveMQ is responsible for mapping Stomp messages to JMS and this is where the trouble began.&lt;/p&gt;

&lt;p&gt;JMS defines five message types: TextMessage, MapMessage, BytesMessage, StreamMessage and ObjectMessage.
Stomp does not define distinct message types, the content of the message body can be anything as long as you take care
of proper handling of the terminating null character.&lt;/p&gt;

&lt;p&gt;The result of sending messages using the Ruby Stomp based message producer was unexpected.
All the messages had an empty message body when received by the Flex based clients.&lt;/p&gt;

&lt;p&gt;Stepping through the BlazeDS code (the method &lt;code&gt;messageReceived(JMSMessageEvent evt)&lt;/code&gt; in &lt;code&gt;flex.messaging.services.messaging.adapters.JMSAdapter&lt;/code&gt; is a good candidate for a breakpoint)
shows that all the messages sent by the Ruby Stomp client are converted to JMS &lt;code&gt;BytesMessage&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;&lt;img src="/images/posts/2009/activemq-stomp-2.jpg" alt="Message Mapping - JMS BytesMessage" /&gt;&lt;/p&gt;

&lt;p&gt;ActiveMQ uses the &lt;code&gt;content-length&lt;/code&gt; header to determine if a Stomp message should be mapped to a JMS TextMessage or a BytesMessage (http://activemq.apache.org/stomp.html) - if a Stomp message contains a &lt;code&gt;content-length&lt;/code&gt; header field
it will be converted to a BytesMessage otherwise it will be converted to a TextMessage.&lt;/p&gt;

&lt;p&gt;Digging into the Ruby Stomp code shows that every message that is being sent by the Ruby client will contain the
&lt;code&gt;content-length&lt;/code&gt; header. This is the reason for the conversion to the &lt;code&gt;BytesMessage&lt;/code&gt; and the empty message body when
the message is received by the BlazeDS clients.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://github.com/js/stomp/blob/b73073cb39a02bdc175586d815a5d9f3028f9496/lib/stomp/connection.rb"&gt;lib/stomp/connection.rb&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_transmit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="vi"&gt;@transmit_semaphore&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;synchronize&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;
    &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;content-length: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;content-type: text/plain; charset=UTF-8&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\0&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The Stomp gem actually follows the Stomp specification.&lt;/p&gt;

&lt;p&gt;From the Stomp protocol specification:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;It is recommended that SEND frames include a content-length header which is a byte count for the length of the message
body. If a content-length header is included, this number of bytes should be read, regardless of whether or not there
are null characters in the body. The frame still needs to be terminated with a null byte and if a content-length is
not specified, the first null byte encountered signals the end of the frame.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Using the stock Ruby stomp gem and a standard BlazeDS/ActiveMQ setup seems to be a bit of a problem. You either have to
take care of the message conversion yourself or you have to change the behaviour of the stomp library.
As the official Stomp protocol recommends the inclusion of the 'content-length' header the current
implementation seems to be correct.
Changing the default behaviour therefore does not seem to be the best option. I decided to add a
monkeypatch that can be used with ActiveMQ and changes the method &lt;code&gt;_transmit&lt;/code&gt; in order to suppress
the content-length header.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Stomp&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Connection&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_transmit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="vi"&gt;@transmit_semaphore&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;synchronize&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;suppress_content_length&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
          &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;content-length&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
          &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delete&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;suppress_content_length&amp;#39;&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
        &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;
        &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;content-type: text/plain; charset=UTF-8&amp;quot;&lt;/span&gt;
        &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;
        &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;
        &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\0&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="n"&gt;endd&lt;/span&gt;

&lt;span class="n"&gt;conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Stomp&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;USER&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;\&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;PASSWORD&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;61613&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt; 
&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;/topic/messageTopic&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Wellington: (&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;\&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;suppress_content_length&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;disconnect&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This fixes the problem and results in the desired behaviour. A bug has been filed and we'll see if there is a good
way to enhance the Stomp gem to work properly with ActiveMQ without changing the current behaviour.&lt;/p&gt;

&lt;p&gt;Meanwhile a fork of the stomp git repository including the ActiveMQ changes (hopefully without breaking existing client code) can be found here:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://github.com/juretta/stomp/tree/activemq-jms-mapping"&gt;http://github.com/juretta/stomp/tree/activemq-jms-mapping&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/juretta?a=EpzkbV4Bi0Y:wfSzud8WhlM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/juretta?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/juretta?a=EpzkbV4Bi0Y:wfSzud8WhlM:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/juretta?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/juretta?a=EpzkbV4Bi0Y:wfSzud8WhlM:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/juretta?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/juretta/~4/EpzkbV4Bi0Y" height="1" width="1"/&gt;</description>
      
    <feedburner:origLink>http://www.juretta.com/log//log/2009/05/24/activemq-jms-stomp/</feedburner:origLink></item>
    
    <item>
      <title>Hudson at WellRailed</title>
      <link>http://feedproxy.google.com/~r/juretta/~3/zbTaps7mBuQ/</link>
      <pubDate>Thu Dec 11 00:00:00 +1300 2008</pubDate>
      <guid isPermaLink="false">http://www.juretta.com/log//log/2008/12/11/hudson_at_wellrailed/</guid>
      <description>&lt;p&gt;
I had the pleasure to give a short talk about Rails and Hudson at the Wellington Rails user group (WellRailed) meeting in November.
&lt;/p&gt;

&lt;p&gt;
I talked about using the &lt;a href="https://hudson.dev.java.net/"&gt;Hudson extensible continuous integration engine&lt;/a&gt; to run Rails tests and using git as the SCM.
&lt;/p&gt;

&lt;p&gt;
The slides are availble here: &lt;a href="http://static.coravy.com/talks/WellRailed-Hudson-Rails-git.pdf"&gt;static.coravy.com/talks/WellRailed-Hudson-Rails-git.pdf&lt;/a&gt;
&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/juretta?a=zbTaps7mBuQ:t8IzccCxNF8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/juretta?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/juretta?a=zbTaps7mBuQ:t8IzccCxNF8:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/juretta?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/juretta?a=zbTaps7mBuQ:t8IzccCxNF8:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/juretta?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/juretta/~4/zbTaps7mBuQ" height="1" width="1"/&gt;</description>
      
    <feedburner:origLink>http://www.juretta.com/log//log/2008/12/11/hudson_at_wellrailed/</feedburner:origLink></item>
    
    <item>
      <title>Hudson test drive (Part 1: Rails)</title>
      <link>http://feedproxy.google.com/~r/juretta/~3/VMCzezqQ5Hg/</link>
      <pubDate>Tue Nov 11 00:00:00 +1300 2008</pubDate>
      <guid isPermaLink="false">http://www.juretta.com/log//log/2008/11/11/hudson_test_drive_part_1_rails/</guid>
      <description>&lt;p&gt;
I've been using &lt;a href="https://hudson.dev.java.net/"&gt;Hudson&lt;/a&gt; for quite a while now and it just rocks. Gone are my CruiseControl (for Java) and CruiseControl.rb (for Ruby/Rails) installations. I even ditched most of my crontab entries and have Hudson manage the repeated tasks for me.
&lt;/p&gt;

&lt;blockquote cite="http://hudson.gotdns.com/wiki/display/HUDSON/Meet+Hudson"&gt;
Hudson monitors executions of repeated jobs, such as building a software project or jobs run by cron. Among those things, current Hudson focuses on the following two jobs:
1. Building/testing software projects continuously just like CruiseControl or DamageControl. [...]
2. Monitoring executions of externally-run jobs, such as cron jobs and procmail jobs, even those that are run on a remote machine. [...]
&lt;/blockquote&gt;

&lt;p&gt;
Compared to CruiseControl configuring jobs in Hudson is really easy and straightforward. You can easily give it a test ride without even installing Hudson in your servlet container. Let's give it a try.
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;stefan@macbook-pro:~&lt;span class="nv"&gt;$ &lt;/span&gt;curl -OL http://hudson.gotdns.com/latest/hudson.war
  % Total    % Received % Xferd  
                                 
100 19.6M  100 19.6M    0     0  
stefan@macbook-pro:~&lt;span class="nv"&gt;$ &lt;/span&gt;java -jar hudson.war 
&lt;span class="o"&gt;[&lt;/span&gt;Winstone 2008/10/24 12:33:11&lt;span class="o"&gt;]&lt;/span&gt; - Beginning extraction from war file
hudson home directory: /Users/stefan/.hudson
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
This will start an instance of hudson which can be accessed at &lt;a href="http://localhost:8080/"&gt;http://localhost:8080/&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
Hudson will create a &lt;code&gt;.hudson&lt;/code&gt; directory to store files and plugins. You can set the &lt;code&gt;HUDSON_HOME&lt;/code&gt; environment variable to use a different directory.
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;stefan@macbook-pro:~&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;HUDSON_HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/opt/local/hudson
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
Due to its multi purpose nature it's easy to build different kinds of software projects. If you can build your projetc using a command line script you might be able to build it using Hudson.
&lt;/p&gt;

&lt;h3&gt;Hudson and Rails&lt;/h3&gt;

&lt;p&gt;
Part one covers building &lt;a href="http://www.rubyonrails.org/"&gt;Rails&lt;/a&gt; projects with Hudson. I'm going to cover building Java and Flex projects in future posts.
&lt;/p&gt;

&lt;p&gt;
In order to build a Rails project as soon as a commit is made, we need a couple of plugins. I'm going to use the &lt;a href="http://git.or.cz/"&gt;git&lt;/a&gt; scm for this example. The default Hudson installation supports SVN out of the box but with the &lt;a href="http://hudson.gotdns.com/wiki/display/HUDSON/Git+Plugin"&gt;Hudson git plugin&lt;/a&gt; using git as your scm is a piece of cake.
&lt;/p&gt;

&lt;p&gt;
Go to &lt;strong&gt;Manage hudson&lt;/strong&gt; (http://localhost:8080/manage) &amp;gt; &lt;strong&gt;Manage plugins&lt;/strong&gt; (http://localhost:8080/pluginManager/) and click on the &lt;em&gt;Available&lt;/em&gt; tab. Choose the following plugins:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Git Plugin&lt;/li&gt;
  &lt;li&gt;Rake plugin&lt;/li&gt;
  &lt;li&gt;Ruby Plugin&lt;/li&gt;
&lt;!--  &lt;li&gt;Ruby metrics plugin&lt;/li&gt;--&gt;
&lt;/ul&gt;

&lt;p&gt;
and click on the &lt;strong&gt;Install&lt;/strong&gt; Button (bottom right).
&lt;/p&gt;

&lt;p&gt;
Hudson needs to be restarted in order to activate the plugins. Stop the currently running proceess (&lt;code&gt;CTRL+C&lt;/code&gt;) and start Hudson again (&lt;code&gt;java -jar hudson.war&lt;/code&gt;).
&lt;/p&gt;

&lt;h3&gt;Configure your Rails project&lt;/h3&gt;

&lt;p&gt;
Hudson can run your Rake test task without further modification. But it would be really nice if the test output could be aggregated in Hudson.
&lt;/p&gt;

&lt;p&gt;
We are going to install the ci_reporter gem (http://caldersphere.rubyforge.org/ci_reporter/) for this purpose.
&lt;/p&gt;

&lt;blockquote cite="http://caldersphere.rubyforge.org/ci_reporter/"&gt;
CI::Reporter is an add-on to Test::Unit and RSpec that allows you to generate XML reports of your test and/or spec runs. The resulting files can be read by a continuous integration system that understands Ant‘s JUnit report XML format, thus allowing your CI system to track test/spec successes and failures. 
&lt;/blockquote&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;stefan@macbook-pro:~&lt;span class="nv"&gt;$ &lt;/span&gt;sudo gem install ci_reporter
Successfully installed ci_reporter-1.5.1
1 gem installed
Installing ri documentation &lt;span class="k"&gt;for &lt;/span&gt;ci_reporter-1.5.1...
Installing RDoc documentation &lt;span class="k"&gt;for &lt;/span&gt;ci_reporter-1.5.1...
&lt;/pre&gt;
&lt;/div&gt;

Add the following lines to your Rakefile (or clone the git repository with the Rails example project: &lt;br /&gt;&lt;code&gt;git clone http://github.com/juretta/hudson-example-project-rails/tree/master&lt;/code&gt;).

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;rubygems&amp;#39;&lt;/span&gt;
&lt;span class="c1"&gt;# Install:&lt;/span&gt;
&lt;span class="c1"&gt;#  sudo gem install ci_reporter&lt;/span&gt;
&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;ci_reporter&amp;#39;&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;ci/reporter/rake/test_unit&amp;#39;&lt;/span&gt; &lt;span class="c1"&gt;# use this if you&amp;#39;re using Test::Unit&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
Run the following rake task and the ci_reporter gem should create xml files in the &lt;code&gt;results&lt;/code&gt; directory of your project.
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;stefan@macbook-pro:~&lt;span class="nv"&gt;$ &lt;/span&gt;rake ci:setup:testunit &lt;span class="nb"&gt;test&lt;/span&gt;:units &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nb"&gt;test&lt;/span&gt;:functionals &lt;span class="nv"&gt;CI_REPORTS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;results
&lt;/pre&gt;
&lt;/div&gt;


&lt;h3&gt;Add a new job&lt;/h3&gt;

&lt;p&gt;
Go to the Hudson homepage and click on &lt;strong&gt;New Job&lt;/strong&gt; (http://localhost:8080/newJob). Choose a Job name, select &lt;strong&gt;Build a free-style software project&lt;/strong&gt; and click &lt;em&gt;Ok&lt;/em&gt;.
&lt;/p&gt;

&lt;p&gt;
You should now be on the project configuration page (http://localhost:8080/job/YOUR-PROJECT-NAME/configure). 
&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the &lt;em&gt;Source Code Management&lt;/em&gt; section choose &lt;strong&gt;git&lt;/strong&gt;. Enter your git repository URL (The Rails project used in this example is hosted on github: git://github.com/juretta/hudson-example-project-rails.git).
&lt;/li&gt;
&lt;!--
&lt;li&gt;Ignore &lt;em&gt;Build Triggers&lt;/em&gt; for now - we will come to that one later.&lt;/li&gt;
--&gt;
&lt;li&gt;Click on &lt;em&gt;Add build step&lt;/em&gt; and choose &lt;em&gt;Invoke Rake&lt;/em&gt;. Enter &lt;em&gt;db:migrate ci:setup:testunit test:units test:functionals CI_REPORTS=results RAILS_ENV=test&lt;/em&gt; into the &lt;strong&gt;Task&lt;/strong&gt; field.&lt;/li&gt;
&lt;li&gt;In the &lt;em&gt;Post-build Actions&lt;/em&gt; section check &lt;em&gt;Publish JUnit test result report&lt;/em&gt; and enter &lt;code&gt;results/*.xml&lt;/code&gt; into the &lt;strong&gt;Test report XMLs&lt;/strong&gt; field.&lt;/li&gt;
&lt;!--
&lt;li&gt;Resist the temptation to check &lt;em&gt;Publish Rcov report&lt;/em&gt; - we will come to that later.&lt;/li&gt;
&lt;li&gt;Check &lt;em&gt;Publish Rails stats report&lt;/em&gt; instead and click &lt;strong&gt;Save&lt;/strong&gt;&lt;/li&gt;
--&gt;
&lt;li&gt;Click &lt;strong&gt;Save&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
You can click &lt;strong&gt;Build now&lt;/strong&gt; to trigger the first build of your Rails project. 
&lt;/p&gt;

&lt;p&gt;
We now want to trigger the build automatically as soon as we do a git commit.
Edit the &lt;code&gt;post-receive&lt;/code&gt; file in the &lt;code&gt;hooks&lt;/code&gt; directory of your git repository (.git/hooks/post-receive).
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;http://localhost:8080/job/YOUR-PROJECT-NAME/build&amp;#39;&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Run Hudson build&amp;quot;&lt;/span&gt;
wget &lt;span class="nv"&gt;$URL&lt;/span&gt; &amp;gt; /dev/null 2&amp;gt;&amp;amp;1
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
Make the file executable.
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;stefan@macbook-pro:~&lt;span class="nv"&gt;$ &lt;/span&gt;chmod u+x .git/hooks/post-receive
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
The hook script now triggers a build after each commit.
&lt;/p&gt;


&lt;h3&gt;The Ruby metrics plugin&lt;/h3&gt;

&lt;p&gt;
The Ruby metrics plugin shows Rails stats (LOC) and rcov reports. 
Unfortunately with the latest version of Hudson the Ruby metrics Plugin does not seem to work. 
&lt;br /&gt;
You should definitely give it a try. If you get an HTTP 500 Status code with a &lt;code&gt;org.apache.commons.jelly.JellyTagException&lt;/code&gt;
&lt;br /&gt;
remove (or disable) the following line:
&lt;br /&gt;
&lt;code&gt;&amp;lt;st:include it="${it.owner}" page="sidepanel.jelly" /&amp;gt;&lt;/code&gt; in
&lt;br /&gt; 
&lt;code&gt;$HUDSON_HOME/plugins/rubyMetrics/WEB-INF/classes/hudson/plugins/rubyMetrics/railsStats/RailsStatsBuildAction/index.jelly&lt;/code&gt;
&lt;/p&gt;


&lt;p&gt;
Have fun with Hudson!
&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/juretta?a=VMCzezqQ5Hg:aTGOs85H6bk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/juretta?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/juretta?a=VMCzezqQ5Hg:aTGOs85H6bk:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/juretta?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/juretta?a=VMCzezqQ5Hg:aTGOs85H6bk:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/juretta?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/juretta/~4/VMCzezqQ5Hg" height="1" width="1"/&gt;</description>
      
    <feedburner:origLink>http://www.juretta.com/log//log/2008/11/11/hudson_test_drive_part_1_rails/</feedburner:origLink></item>
    
    <item>
      <title>URI-Template gem released</title>
      <link>http://feedproxy.google.com/~r/juretta/~3/3B7nzpx8wmg/</link>
      <pubDate>Sat Mar 15 00:00:00 +1300 2008</pubDate>
      <guid isPermaLink="false">http://www.juretta.com/log//log/2008/03/15/uri-template_gem_released/</guid>
      <description>&lt;p&gt;
URITemplate is a parser for URI Templates as defined in the URI Template specification (http://bitworking.org/projects/URI-Templates).
&lt;/p&gt;

&lt;blockquote cite="http://bitworking.org/projects/URI-Templates/"&gt;
URI Templates are strings that contain embedded variables that are transformed into URIs after embedded variables are substituted. This specification defines the structure and syntax of URI Templates.
&lt;/blockquote&gt;

&lt;p&gt;
A simple example shows the usage:
&lt;code&gt;http://example.com/search?q={searchTerms}&amp;num={count}&lt;/code&gt; can be expanded to
&lt;/p&gt;

&lt;pre&gt;http://example.com/search?q=hello%20world&amp;num=5
http://example.com/search?q=ruby&amp;num=100
&lt;/pre&gt;

&lt;p&gt;
by supplying different variables for &lt;code&gt;searchTerms&lt;/code&gt; and &lt;code&gt;count&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
&lt;a href="http://bitworking.org/projects/URI-Templates/"&gt;http://bitworking.org/projects/URI-Templates/&lt;/a&gt; is the homepage of the current draft.
&lt;a href="http://code.google.com/p/uri-templates/"&gt;http://code.google.com/p/uri-templates/&lt;/a&gt; hosts the current reference implementation in Python.
&lt;p&gt;


Install the Ruby gem:
&lt;pre class="shell"&gt;
macbook-pro:~ stefan$ sudo gem install uri-templates
&lt;/pre&gt;


&lt;strong&gt;Treetop - go look at it&lt;/strong&gt;
&lt;p&gt;
After playing around with &lt;a href="http://www.cs.queensu.ca/~thurston/ragel/"&gt;Ragel&lt;/a&gt; and &lt;a href="http://www.antlr.org/"&gt;ANTLR&lt;/a&gt; I decided to use the excellent &lt;a href="http://treetop.rubyforge.org/"&gt;Treetop (Parsing expression grammar implementation)&lt;/a&gt; to implement the URI template specification. Although the draft explicitly states that you do not need a full full-fledged parser, Treetop made it really easy to implement just that.
&lt;/p&gt;

&lt;p&gt;
Get the source:
&lt;/p&gt;

&lt;pre class="shell"&gt;
macbook-pro:~ stefan$ git clone git://scm.juretta.com/uri-templates.git
&lt;/pre&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/juretta?a=3B7nzpx8wmg:KA9djPVgGIg:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/juretta?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/juretta?a=3B7nzpx8wmg:KA9djPVgGIg:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/juretta?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/juretta?a=3B7nzpx8wmg:KA9djPVgGIg:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/juretta?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/juretta/~4/3B7nzpx8wmg" height="1" width="1"/&gt;</description>
      
    <feedburner:origLink>http://www.juretta.com/log//log/2008/03/15/uri-template_gem_released/</feedburner:origLink></item>
    
    <item>
      <title>New Zealand Daylight Saving Time Change: Mac OS X and Java</title>
      <link>http://feedproxy.google.com/~r/juretta/~3/xwxW1k3PHnU/</link>
      <pubDate>Fri Oct 05 00:00:00 +1300 2007</pubDate>
      <guid isPermaLink="false">http://www.juretta.com/log//log/2007/10/05/new_zealand_daylight_saving_time_change_mac_os_x_and_java/</guid>
      <description>It appears that Apple missed the new rules for Daylight Saving Time (DST) in New Zealand in even the most recent versions of Mac OS X 10.4 Tiger. 

&lt;blockquote cite="http://www.dia.govt.nz/diawebsite.nsf/wpg_URL/Services-Daylight-Saving-Index"&gt;
&lt;strong&gt;From this year [2007]&lt;/strong&gt;, Daylight Saving will run for a period of 27 weeks. It now commences from the last Sunday in September, when 2.00am becomes 3.00am, and ends on the first Sunday in April the following year, when 3.00am becomes 2.00am. 
&lt;/blockquote&gt;

&lt;p&gt;
Mac OS X still thinks that the Daylight Saving time starts on Oct. 7th.
&lt;/p&gt;

&lt;p&gt;
The &lt;a href="http://docs.info.apple.com/article.html?artnum=306486"&gt;knowledgebase entry&lt;/a&gt; is rather disappointing
&lt;/p&gt;

&lt;blockquote cite="http://docs.info.apple.com/article.html?artnum=306486"&gt;
Deselect (uncheck) 'Set Date &amp; Time automatically' if it's enabled.
&lt;br /&gt;
Manually set the correct time.
&lt;/blockquote&gt;

&lt;p&gt;
A better approach is to update the timezone database that is used to compute the correct time for your timezone in relation to UTC (Read &lt;a href="http://en.wikipedia.org/wiki/Time_zone"&gt;more&lt;/a&gt;):
&lt;br /&gt;
&lt;code&gt;GMT_TIME + LOCAL_TIME_ZONE_OFFSET + DST_OFFSET.&lt;/code&gt;
&lt;/p&gt;

&lt;p&gt;
First check if you have to update the timezone information (assuming you have selected NZST/NZDT as your local timezone):
&lt;/p&gt;

&lt;pre class="shell"&gt;
macbook-pro:~ stefan$ zdump -v /etc/localtime | grep 2007
/etc/localtime Sat Mar 17 13:59:59 2007 UTC = Sun Mar 18 02:59:59 2007 NZDT isdst=1 
/etc/localtime Sat Mar 17 14:00:00 2007 UTC = Sun Mar 18 02:00:00 2007 NZST isdst=0 
/etc/localtime Sat Oct 6 13:59:59 2007 UTC = Sun Oct 7 01:59:59 2007 NZST isdst=0 
/etc/localtime Sat Oct 6 14:00:00 2007 UTC = Sun Oct 7 03:00:00 2007 NZDT isdst=1
&lt;/pre&gt;

&lt;p&gt;
This shows that the Mac thinks that the daylight saving time (NZDT) will start on Sun Oct 7. &lt;strong&gt;That's wrong&lt;/strong&gt;.
&lt;/p&gt;

&lt;p&gt;
To update the Mac OS X timezone database download the latest tzdata2007_.tar.gz from ftp://elsie.nci.nih.gov/pub/. As of Oct 1 it's ftp://elsie.nci.nih.gov/pub/tzdata2007h.tar.gz
&lt;/p&gt;

&lt;pre class="shell"&gt;
macbook-pro:~ stefan$ curl -O ftp://elsie.nci.nih.gov/pub/tzdata2007h.tar.gz
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  158k  100  158k    0     0   4851      0  0:00:33  0:00:33 --:--:--  7928
&lt;/pre&gt;

Extract the archive and run the &lt;code&gt;zic&lt;/code&gt; timezone compiler

&lt;pre class="shell"&gt;
macbook-pro:~ stefan$ mkdir tzdata; tar -xvzf tzdata2007h.tar.gz -C tzdata
macbook-pro:~ stefan$ cd tzdata; sudo zic australasia
&lt;/pre&gt;

&lt;p&gt;
You might want to reboot the system to enable the new timezone information.
&lt;/p&gt;


Check again:
&lt;pre class="shell"&gt;
macbook-pro:~ stefan$ zdump -v /etc/localtime | grep 2007
/etc/localtime  Sat Mar 17 13:59:59 2007 UTC = Sun Mar 18 02:59:59 2007 NZDT isdst=1
/etc/localtime  Sat Mar 17 14:00:00 2007 UTC = Sun Mar 18 02:00:00 2007 NZST isdst=0
/etc/localtime  Sat Sep 29 13:59:59 2007 UTC = Sun Sep 30 01:59:59 2007 NZST isdst=0
/etc/localtime  Sat Sep 29 14:00:00 2007 UTC = Sun Sep 30 03:00:00 2007 NZDT isdst=1
&lt;/pre&gt;

&lt;strong&gt;Java Update&lt;/strong&gt;&lt;br /&gt;
&lt;p&gt;
The JRE uses its own timezone database (unfortunately). We need to update this information as well.
&lt;/p&gt;

&lt;p&gt;
Got to &lt;a href="http://java.sun.com/javase/downloads/index.jsp"&gt;http://java.sun.com/javase/downloads/index.jsp&lt;/a&gt; and get the &lt;strong&gt;JDK DST Timezone Update Tool - 1.2.2&lt;/strong&gt;.
&lt;/p&gt;
&lt;p&gt;
Expand the archive and run the tzupdater.jar: &lt;code&gt;sudo java -Djava.vendor="Sun Microsystems Inc." -jar tzupdater.jar -v -u &lt;/code&gt;
&lt;/p&gt;

&lt;pre class="shell"&gt;
macbook-pro:~ stefan$ sudo java -Djava.vendor="Sun Microsystems Inc." -jar tzupdater.jar -v -u 
Password:
java.home: /System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Home
java.vendor: Sun Microsystems Inc.
java.version: 1.6.0-dp
JRE time zone data version: tzdata2006a
Embedded time zone data version: tzdata2007g
Extracting files... done.
Renaming directories... done.
Validating the new time zone data... done.
Time zone data update is complete.
&lt;/pre&gt;

Quick check:
&lt;pre class="shell"&gt;
Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("Pacific/Auckland"));
cal.setTimeInMillis(new Date().getTime());	
System.out.format("%1$tT (%1$tB %1$td %1$tY)", cal, new Locale("de", "DE"));
&lt;/pre&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/juretta?a=xwxW1k3PHnU:y_uFv-z_nlk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/juretta?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/juretta?a=xwxW1k3PHnU:y_uFv-z_nlk:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/juretta?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/juretta?a=xwxW1k3PHnU:y_uFv-z_nlk:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/juretta?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/juretta/~4/xwxW1k3PHnU" height="1" width="1"/&gt;</description>
      
    <feedburner:origLink>http://www.juretta.com/log//log/2007/10/05/new_zealand_daylight_saving_time_change_mac_os_x_and_java/</feedburner:origLink></item>
    
    <item>
      <title>javap</title>
      <link>http://feedproxy.google.com/~r/juretta/~3/xu6CXL_7JpU/</link>
      <pubDate>Thu Oct 04 00:00:00 +1300 2007</pubDate>
      <guid isPermaLink="false">http://www.juretta.com/log//log/2007/10/04/javap/</guid>
      <description>&lt;blockquote&gt;
The  javap  command  disassembles  a  Java(tm) class file.  The options
       determine the output.  If no options are used,  javap  prints  out  the
       package, protected, and public fields and methods of the classes passed
       to it.  The javap command displays its output to stdout. 
&lt;/blockquote&gt;

Usage: 
&lt;pre class="shell"&gt;
macbook-pro:~ stefan$ javap -private java.util.Calendar
Compiled from "Calendar.java"
public abstract class java.util.Calendar extends java.lang.Object implements java.io.Serializable,java.lang.Cloneable,java.lang.Comparable{
    public static final int ERA;
    public static final int YEAR;
    public static final int MONTH;
    public static final int WEEK_OF_YEAR;
    public static final int WEEK_OF_MONTH;
    public static final int DATE;
    public static final int DAY_OF_MONTH;
    public static final int DAY_OF_YEAR;
    public static final int DAY_OF_WEEK;
    public static final int DAY_OF_WEEK_IN_MONTH;
    public static final int AM_PM;
    public static final int HOUR;
    public static final int HOUR_OF_DAY;
    public static final int MINUTE;
    public static final int SECOND;
    public static final int MILLISECOND;
    public static final int ZONE_OFFSET;
    public static final int DST_OFFSET;
    public static final int FIELD_COUNT;
    public static final int SUNDAY;
&lt;/pre&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/juretta?a=xu6CXL_7JpU:5555GwEJGwY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/juretta?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/juretta?a=xu6CXL_7JpU:5555GwEJGwY:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/juretta?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/juretta?a=xu6CXL_7JpU:5555GwEJGwY:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/juretta?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/juretta/~4/xu6CXL_7JpU" height="1" width="1"/&gt;</description>
      
    <feedburner:origLink>http://www.juretta.com/log//log/2007/10/04/javap/</feedburner:origLink></item>
    
    <item>
      <title>List open ports on your machine (Mac OS X)</title>
      <link>http://feedproxy.google.com/~r/juretta/~3/JgaEgj4GWSs/</link>
      <pubDate>Wed Aug 08 00:00:00 +1200 2007</pubDate>
      <guid isPermaLink="false">http://www.juretta.com/log//log/2007/08/08/list_open_ports_on_your_machine_mac_os_x_/</guid>
      <description>&lt;p&gt;
netstat on Mac OS X is not what you might be used to on a Linux machine (on Linux you can use &lt;code&gt;netstat -atp | grep -i "listen"&lt;/code&gt;). To show all open ports applications on your machine are listening to you can use this workaround:
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;macbook:~ sudo lsof -i -P | grep -i &lt;span class="s2"&gt;&amp;quot;listen&amp;quot;&lt;/span&gt;
netinfod    33    root    7u  IPv4 0x3f76e08      0t0    TCP localhost:1033 &lt;span class="o"&gt;(&lt;/span&gt;LISTEN&lt;span class="o"&gt;)&lt;/span&gt;
AppleFile  142    root   29u  IPv6 0x3973c50      0t0    TCP *:548 &lt;span class="o"&gt;(&lt;/span&gt;LISTEN&lt;span class="o"&gt;)&lt;/span&gt;
AppleFile  142    root   30u  IPv4 0x3f76018      0t0    TCP *:548 &lt;span class="o"&gt;(&lt;/span&gt;LISTEN&lt;span class="o"&gt;)&lt;/span&gt;
mysqld     175   mysql   11u  IPv4 0x415c018      0t0    TCP *:3306 &lt;span class="o"&gt;(&lt;/span&gt;LISTEN&lt;span class="o"&gt;)&lt;/span&gt;
slpd       214    root    2u  IPv4 0x415c710      0t0    TCP *:427 &lt;span class="o"&gt;(&lt;/span&gt;LISTEN&lt;span class="o"&gt;)&lt;/span&gt;
eclipse    277 stefans   23u  IPv6 0x39733a0      0t0    TCP *:8118 &lt;span class="o"&gt;(&lt;/span&gt;LISTEN&lt;span class="o"&gt;)&lt;/span&gt;
eclipse    277 stefans   25u  IPv6 0x3973a24      0t0    TCP *:49372 &lt;span class="o"&gt;(&lt;/span&gt;LISTEN&lt;span class="o"&gt;)&lt;/span&gt;
eclipse    277 stefans   27u  IPv6 0x51d20e0      0t0    TCP *:6836 &lt;span class="o"&gt;(&lt;/span&gt;LISTEN&lt;span class="o"&gt;)&lt;/span&gt;
eclipse    277 stefans   29u  IPv6 0x51d2764      0t0    TCP *:14685 &lt;span class="o"&gt;(&lt;/span&gt;LISTEN&lt;span class="o"&gt;)&lt;/span&gt;
cupsd      279    root    0u  IPv4 0x3f75c9c      0t0    TCP localhost:631 &lt;span class="o"&gt;(&lt;/span&gt;LISTEN&lt;span class="o"&gt;)&lt;/span&gt;
java      1037 stefans    7u  IPv6 0x3972d1c      0t0    TCP *:1527 &lt;span class="o"&gt;(&lt;/span&gt;LISTEN&lt;span class="o"&gt;)&lt;/span&gt;
java      1052 stefans    9u  IPv6 0x3971538      0t0    TCP *:49979 &lt;span class="o"&gt;(&lt;/span&gt;LISTEN&lt;span class="o"&gt;)&lt;/span&gt;
java      1052 stefans   15u  IPv6 0x3972f48      0t0    TCP *:44441 &lt;span class="o"&gt;(&lt;/span&gt;LISTEN&lt;span class="o"&gt;)&lt;/span&gt;
java      1052 stefans   23u  IPv6 0x51d4174      0t0    TCP *:49987 &lt;span class="o"&gt;(&lt;/span&gt;LISTEN&lt;span class="o"&gt;)&lt;/span&gt;
java      1118 stefans   12u  IPv6 0x51d3240      0t0    TCP *:50055 &lt;span class="o"&gt;(&lt;/span&gt;LISTEN&lt;span class="o"&gt;)&lt;/span&gt;
java      1118 stefans   38u  IPv6 0x568f3a0      0t0    TCP *:50061 &lt;span class="o"&gt;(&lt;/span&gt;LISTEN&lt;span class="o"&gt;)&lt;/span&gt;
java      1118 stefans   48u  IPv4 0x3f76394      0t0    TCP *:8000 &lt;span class="o"&gt;(&lt;/span&gt;LISTEN&lt;span class="o"&gt;)&lt;/span&gt;
java      3422 stefans   11u  IPv6 0x5a28de8      0t0    TCP *:51669 &lt;span class="o"&gt;(&lt;/span&gt;LISTEN&lt;span class="o"&gt;)&lt;/span&gt;
java      3422 stefans   13u  IPv6 0x6111990      0t0    TCP *:8080 &lt;span class="o"&gt;(&lt;/span&gt;LISTEN&lt;span class="o"&gt;)&lt;/span&gt;
java      3422 stefans   14u  IPv6 0x56af764      0t0    TCP *:8443 &lt;span class="o"&gt;(&lt;/span&gt;LISTEN&lt;span class="o"&gt;)&lt;/span&gt;
java      3422 stefans   37u  IPv6 0x5f69764      0t0    TCP *:51672 &lt;span class="o"&gt;(&lt;/span&gt;LISTEN&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

From the lsof man page:
&lt;blockquote&gt;
Lsof [...] lists information about files opened by processes [...]. An open file may be a regular file, a directory, a block special file, a character special file, an executing text reference, a library, a stream  or  a  network  file
(Internet socket, NFS file or UNIX domain socket.)  A specific file or all the files in a file system may be selected by path.
&lt;/blockquote&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/juretta?a=JgaEgj4GWSs:89Jdcjz0HSA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/juretta?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/juretta?a=JgaEgj4GWSs:89Jdcjz0HSA:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/juretta?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/juretta?a=JgaEgj4GWSs:89Jdcjz0HSA:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/juretta?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/juretta/~4/JgaEgj4GWSs" height="1" width="1"/&gt;</description>
      
    <feedburner:origLink>http://www.juretta.com/log//log/2007/08/08/list_open_ports_on_your_machine_mac_os_x_/</feedburner:origLink></item>
    
    <item>
      <title>Monitoring network traffic with ngrep</title>
      <link>http://feedproxy.google.com/~r/juretta/~3/JZPTNn6VJ1w/</link>
      <pubDate>Fri Jul 27 00:00:00 +1200 2007</pubDate>
      <guid isPermaLink="false">http://www.juretta.com/log//log/2007/07/27/monitoring_network_traffic_with_ngrep/</guid>
      <description>&lt;p&gt;

There are many tools to monitor network traffic.
Wading through lines and lines of tcpdump output can be cumbersome sometimes.
ngrep to the rescue. From their website:
&lt;/p&gt;

&lt;blockquote cite="http://ngrep.sourceforge.net/"&gt;
ngrep strives to provide most of GNU grep's common features, applying them to the network layer.
&lt;/blockquote&gt;

&lt;p&gt;
To install ngrep on a Mac OS X machine you can use the &lt;code&gt;port&lt;/code&gt; command if you have &lt;a href="http://darwinports.com/"&gt;darwinports&lt;/a&gt; installed.
&lt;/p&gt;

&lt;div class="shell"&gt;macbook:~ sudo port install ngrep
&lt;/div&gt;

To monitor network traffic using the htt protocol use the following command:

&lt;div class="shell"&gt;macbook:~ sudo ngrep -d en0 -W byline port 80

##
T 66.35.250.209:80 -&gt; 10.200.1.40:50710 [AP]
HTTP/1.1 200 OK.
Date: Fri, 27 Jul 2007 13:45:05 GMT.
Server: Apache/1.3.33 (Unix) PHP/4.3.10.
Last-Modified: Tue, 28 Nov 2006 13:54:21 GMT.
ETag: "219bab-160c-456c3f8d".
Accept-Ranges: bytes.
Content-Length: 5644.
Connection: close.
Content-Type: text/html.
[...]
&lt;/div&gt;

&lt;p&gt;
To monitor the traffic to a certain host include the host information:
&lt;/p&gt;

&lt;div class="shell"&gt;macbook:~ sudo ngrep -d en0 -W byline host google.com
&lt;/div&gt;

&lt;p&gt;
&lt;em&gt;Hint use &lt;code&gt;ifconfig&lt;/em&gt; to figure out which device to use (in my case it is en0, it might be eth0 for example on your machine).
&lt;/p&gt;

&lt;p&gt;
Ngrep homepage: &lt;a href="http://ngrep.sourceforge.net/"&gt;http://ngrep.sourceforge.net/&lt;/a&gt;
&lt;br /&gt;
For usage information you can find more information here: &lt;a href="http://ngrep.sourceforge.net/usage.html"&gt;http://ngrep.sourceforge.net/usage.html&lt;/a&gt;.
&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/juretta?a=JZPTNn6VJ1w:pim2RapBsVw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/juretta?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/juretta?a=JZPTNn6VJ1w:pim2RapBsVw:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/juretta?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/juretta?a=JZPTNn6VJ1w:pim2RapBsVw:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/juretta?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/juretta/~4/JZPTNn6VJ1w" height="1" width="1"/&gt;</description>
      
    <feedburner:origLink>http://www.juretta.com/log//log/2007/07/27/monitoring_network_traffic_with_ngrep/</feedburner:origLink></item>
    
  </channel>
</rss>
