<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6872023396647681597</id><updated>2012-01-24T04:58:02.348-08:00</updated><title type='text'>Brian ONeill's Blog</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>66</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-3486811818993281799</id><published>2012-01-24T04:58:00.000-08:00</published><updated>2012-01-24T04:58:02.354-08:00</updated><title type='text'>Virgil: Remote Hadoop Job Deployment via REST</title><content type='html'>&lt;br /&gt;In the latest release, Virgil has taken its Hadoop support one step further allowing you to deploy jobs to remote Hadoop clusters via REST.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;We've taken the &lt;a href="http://code.google.com/a/apache-extras.org/p/virgil/wiki/mapreduce"&gt;Ruby example&lt;/a&gt; and added the ability to remotely deploy those ruby scripts. &lt;br /&gt;&lt;br /&gt;In our deployment model, we run Virgil, Cassandra and Hadoop on each node in the cluster, with an HTTP load balancer in front of the Virgil instances.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;With this latest release of Virgil, we've added a new shell script that allows you to start Virgil with the Hadoop configuration on the classpath.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;bin/virgil-hadoop -host localhost&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;This starts Virgil, remotely accessing the Cassandra on the localhost.&amp;nbsp; Additionally, we alter the Hadoop configuration (in $VIRGIL_HOME/mapreduce/conf/) set to use the collocated Hadoop cluster.&amp;nbsp; The Hadoop configuration is described in detail on the &lt;a href="http://code.google.com/a/apache-extras.org/p/virgil/wiki/hadoop"&gt;Virgil Wiki&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Then, when you sling ruby at the REST API, that ruby is deployed remotely to the entire cluster.&amp;nbsp;&amp;nbsp; Since we started Virgil using "localhost" that is used as the initial "seed address" in the Map/Reduce job, which means each it will its local Cassandra instance to access the Cassandra cluster minimizing the data passed around the network.&lt;br /&gt;&lt;br /&gt;Give it a try and let us know what you think.&lt;br /&gt;&lt;br /&gt;Next up: Cassandra Triggers.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-3486811818993281799?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/3486811818993281799/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=3486811818993281799' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/3486811818993281799'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/3486811818993281799'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2012/01/virgil-remote-hadoop-job-deployment-via.html' title='Virgil: Remote Hadoop Job Deployment via REST'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-7094873297560752551</id><published>2012-01-24T04:28:00.000-08:00</published><updated>2012-01-24T04:28:12.218-08:00</updated><title type='text'>Virgil goes DropWizard... who needs war files?</title><content type='html'>&lt;br /&gt;For years now I've been saying that &lt;a href="http://for%20years%20now%20i%27ve%20been%20saying%20that%20j2ee%20may%20be%20dead%20%28or%20dying%29./"&gt;J2EE may be dead&lt;/a&gt; (or dying).&amp;nbsp; Wherever possible, people are trying to cut down on code and configuration.&amp;nbsp; The lighter the better.&amp;nbsp; These days, even Tomcat seems heavy for the light-weight services we want to deploy.&amp;nbsp; Enter &lt;a href="https://github.com/codahale/dropwizard"&gt;DropWizard&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Thanks goes to Coda Hale for putting together DropWizard, a rock-solid lightweight REST stack.&amp;nbsp; Its got everything you could want: configuration, metrics, parsing, health checks, etc.&amp;nbsp; It can even serve up static content.&lt;br /&gt;&lt;br /&gt;With all those features, who needs war files?&lt;br /&gt;&lt;br /&gt;Recently we contributed to DropWizard, adding the ability to serve up static content from the root url, which allowed us to port Virgil over.&amp;nbsp; Since Virgil has an entirely ExtJS based UI, static content is all we needed for the UI. &lt;br /&gt;&lt;br /&gt;We just released a new version Virgil with DropWizard under the covers.&lt;br /&gt;&lt;br /&gt;Using DropWizard, Virgil now provides an &lt;a href="http://code.google.com/a/apache-extras.org/p/virgil/wiki/AdminUI"&gt;Admin UI&lt;/a&gt;.&amp;nbsp; Additionally, there are additional &lt;a href="http://code.google.com/a/apache-extras.org/p/virgil/source/browse/trunk/server/src/test/resources/virgil.yaml"&gt;configuration parameters&lt;/a&gt; for logging and the http server.&lt;br /&gt;&lt;br /&gt;If you get a chance, take a look at DropWizard.&amp;nbsp;&amp;nbsp; It might just have you replacing your old servlet container.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-7094873297560752551?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/7094873297560752551/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=7094873297560752551' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/7094873297560752551'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/7094873297560752551'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2012/01/virgil-goes-dropwizard-who-needs-war.html' title='Virgil goes DropWizard... who needs war files?'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-6584010474670130750</id><published>2011-12-19T19:17:00.000-08:00</published><updated>2011-12-19T19:17:24.215-08:00</updated><title type='text'>Programmatically submitting jobs to a remote Hadoop Cluster</title><content type='html'>&lt;br /&gt;I'm adding the ability to deploy a Map/Reduce job to a remote Hadoop cluster in &lt;a href="http://code.google.com/a/apache-extras.org/p/virgil/"&gt;Virgil&lt;/a&gt;. With this, Virgil allows users to make a REST POST to schedule a Hadoop job. (pretty handy) &lt;br /&gt;&lt;br /&gt;To get this to work properly, Virgil needed to be able to remotely deploy a job. Ordinarily, to run a job against a remote cluster you issue a command from the shell:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;hadoop jar $JAR_FILE $CLASS_NAME&amp;nbsp;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;We wanted to do the same thing, but from within the Virgil runtime.  It was easy enough to find the class we needed to use: RunJar.  RunJar's main() method stages the jar and submits the job.  Thus, to achieve the same functionality as the command line, we used the following:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&amp;nbsp;List&lt;string&gt; args = new ArrayList&lt;string&gt;();&amp;nbsp;&lt;/string&gt;&lt;/string&gt;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&lt;string&gt;&lt;string&gt;&amp;nbsp;args.add(locationOfJarFile);&amp;nbsp;&lt;/string&gt;&lt;/string&gt;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&lt;string&gt;&lt;string&gt;&amp;nbsp;args.add(className);&amp;nbsp;&lt;/string&gt;&lt;/string&gt;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&lt;string&gt;&lt;string&gt;&amp;nbsp;RunJar.main(args.toArray(new String[0]));&amp;nbsp;&lt;/string&gt;&lt;/string&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;That worked just fine, but would result in a local job deployment. To get it to deploy to a remote cluster, we needed Hadoop to load the cluster configuration.  For Hadoop, cluster configuration is spread across three files: core-site.xml, hdfs-site.xml, and mapred-site.xml.  To get the Hadoop runtime to load the configuration, you need to include these files on your classpath.  The key line is found in the configuration &lt;a href="http://hadoop.apache.org/common/docs/current/api/org/apache/hadoop/conf/Configuration.html"&gt;Hadoop Javadoc&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;"&lt;span style="background-color: white;"&gt;Unless explicitly turned off, Hadoop by default specifies two resources, loaded in-order from the classpath:"&lt;/span&gt;&lt;br /&gt;&lt;span style="background-color: white;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="background-color: white;"&gt;Once we dropped the cluster configuration onto the classpath, everything worked like a charm.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-6584010474670130750?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/6584010474670130750/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=6584010474670130750' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/6584010474670130750'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/6584010474670130750'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2011/12/programmatically-submitting-jobs-to.html' title='Programmatically submitting jobs to a remote Hadoop Cluster'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-7824252801337119890</id><published>2011-12-12T18:47:00.000-08:00</published><updated>2011-12-12T18:59:35.000-08:00</updated><title type='text'>Binaries available for download from Virgil</title><content type='html'>&lt;br /&gt;&lt;div style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-family: arial, sans-serif; font-size: 13px;"&gt;In response to a few requests for a&amp;nbsp;&lt;span class="il" style="background-attachment: initial; background-clip: initial; background-color: #ffffcc; background-image: initial; background-origin: initial;"&gt;binary&lt;/span&gt;&amp;nbsp;distribution, we just posted artifacts for Virgil.&lt;/div&gt;&lt;div style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-family: arial, sans-serif; font-size: 13px;"&gt;&lt;a href="http://code.google.com/a/apache-extras.org/p/virgil/downloads/list" style="color: #1155cc;" target="_blank"&gt;http://code.google.com/a/&lt;wbr&gt;&lt;/wbr&gt;apache-extras.org/p/virgil/&lt;wbr&gt;&lt;/wbr&gt;downloads/list&lt;/a&gt;&lt;/div&gt;&lt;div style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-family: arial, sans-serif; font-size: 13px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-family: arial, sans-serif; font-size: 13px;"&gt;For simplicity, we're keeping the version number aligned with the version of Cassandra.&amp;nbsp;&lt;/div&gt;&lt;div style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-family: arial, sans-serif; font-size: 13px;"&gt;(which is important when you are running with an embedded Cassandra ;)&lt;/div&gt;&lt;div style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-family: arial, sans-serif; font-size: 13px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-family: arial, sans-serif; font-size: 13px;"&gt;Also, we changed it so you can simply specify the Cassandra instance you want to run against as a command line parameter:&lt;/div&gt;&lt;div style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-family: arial, sans-serif; font-size: 13px;"&gt;&lt;a href="http://code.google.com/a/apache-extras.org/p/virgil/wiki/runmode" style="color: #1155cc;" target="_blank"&gt;http://code.google.com/a/&lt;wbr&gt;&lt;/wbr&gt;apache-extras.org/p/virgil/&lt;wbr&gt;&lt;/wbr&gt;wiki/runmode&lt;/a&gt;&lt;/div&gt;&lt;div style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-family: arial, sans-serif; font-size: 13px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-family: arial, sans-serif; font-size: 13px;"&gt;This makes it easy to point the GUI at different Cassandra instances.&amp;nbsp;&lt;/div&gt;&lt;div style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-family: arial, sans-serif; font-size: 13px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-family: arial, sans-serif; font-size: 13px;"&gt;Now, all you need to do is download the binary distribution, untar/unzip and type:&lt;/div&gt;&lt;div style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-family: arial, sans-serif; font-size: 13px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-family: arial, sans-serif; font-size: 13px;"&gt;bin/virgil -h CASSANDRA_HOST&lt;/div&gt;&lt;div style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-family: arial, sans-serif; font-size: 13px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-family: arial, sans-serif; font-size: 13px;"&gt;Let me know if anyone has any trouble.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-7824252801337119890?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/7824252801337119890/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=7824252801337119890' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/7824252801337119890'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/7824252801337119890'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2011/12/binaries-available-for-download-from.html' title='Binaries available for download from Virgil'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-5225002050575101272</id><published>2011-12-09T10:47:00.001-08:00</published><updated>2011-12-09T10:57:53.992-08:00</updated><title type='text'>Dependencies and Repositories in SBT 0.11 (vs 0.7) for Kestrel</title><content type='html'>I was trying to build Kestrel last night, which is written in Scala.&lt;br /&gt;&lt;br /&gt;After installing scala and sbt on my mac using homebrew, Kestrel wouldn't build because it requires an older version of sbt.  Instead of installing the old version of sbt, I took it as a good opportunity to learn what sbt was about.  In migrating the Kestrel build file to sbt 0.11, I found the documentation somewhat lacking.  (especially when compared to 0.7)  Thus, here are two tidbits that I had a hard time finding... (I actually had to dig through other github projects to see how they did it)&lt;br /&gt;&lt;br /&gt;I learned that sbt uses maven repositories as one source for dependencies.&amp;nbsp; Just like maven, you need to declare the dependencies and the available repositories.&amp;nbsp; Here is how you do it.&lt;br /&gt;&lt;br /&gt;I forked the Kestrel project and posted my new build.sbt here:&lt;br /&gt;&lt;a href="https://github.com/boneill42/kestrel/blob/master/build.sbt"&gt;https://github.com/boneill42/kestrel/blob/master/build.sbt&lt;/a&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;To add a dependency to your project add the following line to the build.sbt.&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;code&gt;libraryDependencies += "com.twitter" % "util-core" % "1.12.4"&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;In maven speak, the first string is the group identifier.The second string is the artifact identifier.And the third string is the version identifier.&lt;br /&gt;&lt;br /&gt;In this case, Kestrel required additional repositories.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;To add a repository to your project add the following line to the build.sbt.&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;div class="line" id="LC33"&gt;&lt;br /&gt;&lt;span class="n"&gt;  resolvers&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s"&gt;"twitter.com"&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="s"&gt;"http://maven.twttr.com/"&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;/pre&gt;The first string is the name of the repository.  The second string is the url for the repo.&lt;br /&gt;&lt;br /&gt;Hope that helps some people.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-5225002050575101272?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/5225002050575101272/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=5225002050575101272' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/5225002050575101272'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/5225002050575101272'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2011/12/dependencies-and-repositories-in-sbt.html' title='Dependencies and Repositories in SBT 0.11 (vs 0.7) for Kestrel'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-4257092768498777274</id><published>2011-12-01T10:16:00.000-08:00</published><updated>2011-12-20T05:09:38.784-08:00</updated><title type='text'>Hadoop/MapReduce on Cassandra using Ruby and REST!</title><content type='html'>In an effort to make Hadoop/MapReduce on Cassandra more accessible, we added a REST layer to Virgil that allows you to run map reduce jobs written in Ruby against column families in Cassandra by simply posting the ruby script to a URL.  This greatly reduces the skill set required to write and deploy the jobs, and allows users to rapidly develop analytics for data store in Cassandra.&lt;br /&gt;&lt;br /&gt;To get started, just write a map/reduce job in Ruby like the example included in Virgil:&lt;br /&gt;&lt;a href="http://code.google.com/a/apache-extras.org/p/virgil/source/browse/trunk/server/src/test/resources/wordcount.rb"&gt;http://code.google.com/a/apache-extras.org/p/virgil/source/browse/trunk/server/src/test/resources/wordcount.rb&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Then throw that script at Virgil with a curl:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;curl -X POST http://localhost:8080/virgil/job?jobName=wordcount\&amp;amp;inputKeyspace=dummy\&amp;amp;inputColumnFamily=book\&amp;amp;outputKeyspace=stats\&amp;amp;outputColumnFamily=word_counts --data-binary @src/test/resources/wordcount.rb&lt;/code&gt;&lt;br /&gt;In the POST, you specify the input keyspace and column family and the output keyspace and column family.   Each row is fed to the ruby map function as a Map, each entry in the map is column in the row.   The map function must return tuples (key/value pairs), which are fed back into Hadoop for sorting.&lt;br /&gt;&lt;br /&gt;Then, the reduce method is called with the keys and values from Hadoop.   The reduce function must return a map of maps, which represent the rows and columns that need to be written back to Cassandra. (keys are the rowkeys, sub maps are the columns)&lt;br /&gt;&lt;br /&gt;Presently, the actual job runs inside the Virgil JVM and the HTTP connection is left open until the job completes.  Over the next week or two, we'll fix that.  We intend to implement the ability to distribute that job across an existing Hadoop cluster.  Stay tuned.&lt;br /&gt;&lt;br /&gt;For more information see the Virgil wiki:&lt;br /&gt;&lt;a href="http://code.google.com/a/apache-extras.org/p/virgil/wiki/mapreduce"&gt;http://code.google.com/a/apache-extras.org/p/virgil/wiki/mapreduce&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-4257092768498777274?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/4257092768498777274/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=4257092768498777274' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/4257092768498777274'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/4257092768498777274'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2011/12/hadoopmapreduce-on-cassandra-using-ruby.html' title='Hadoop/MapReduce on Cassandra using Ruby and REST!'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-4907553295420198069</id><published>2011-11-30T11:05:00.000-08:00</published><updated>2011-11-30T11:23:27.215-08:00</updated><title type='text'>Concurrent use of embedded Ruby in Java (using JRuby)</title><content type='html'>Last night I was finishing up the map/reduce capabilities within &lt;a href="http://code.google.com/a/apache-extras.org/p/virgil/"&gt;Virgil&lt;/a&gt;.   We hope to allow people to post ruby scripts that will then get executed over a column family in Cassandra using map/reduce.  To do that, we needed concurrent use of a ScriptEngine that could evaluate the ruby script. In the below code snippets, script is a String that contains the contents of a ruby file with a method definition for foo.&lt;br /&gt;&lt;br /&gt;First, I started with JSR 223 and the ScriptEngine with the following code:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;public static final ScriptEngine ENGINE = new ScriptEngineManager().getEngineByName("jruby");&lt;br /&gt;ScriptContext context = new SimpleScriptContext();&lt;br /&gt;Bindings bindings = context.getBindings(ScriptContext.ENGINE_SCOPE);&lt;br /&gt;bindings.put("variable", "value");&lt;br /&gt;ENGINE.eval(script, context);&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;That worked fine in unit testing, but when used within map/reduce I encountered a dead-lock of sorts.  After some googling, I landed in the &lt;a href="https://github.com/jruby/jruby/wiki/RedBridge"&gt;Redbridge documentation&lt;/a&gt;.  There I found that jruby exposes a lower-level API (beneath JSR223) that exposes concurrent processing features.  I swapped the above code, for the following:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;this.rubyContainer = new ScriptingContainer(LocalContextScope.CONCURRENT);&lt;br /&gt;this.rubyReceiver = rubyContainer.runScriptlet(script);&lt;br /&gt;container.callMethod(rubyReceiver, "foo", "value");&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;That let me leverage a single engine for multiple concurrent invocations of the method foo, which is defined in the ruby script.&lt;br /&gt;&lt;br /&gt;This worked like a charm.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-4907553295420198069?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/4907553295420198069/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=4907553295420198069' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/4907553295420198069'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/4907553295420198069'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2011/11/concurrent-use-of-embedded-ruby-in-java.html' title='Concurrent use of embedded Ruby in Java (using JRuby)'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-2849680967077852945</id><published>2011-11-28T19:20:00.000-08:00</published><updated>2011-11-28T19:32:11.180-08:00</updated><title type='text'>Introducing run-modes to Virgil: support for embedded or remote cassandra instances</title><content type='html'>&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Since Virgil was originally developed as an embedded REST layer for the Cassandra Server, it ran as a daemon inside the server and performed operations directly against the CassandraServer classes.  Running in a single JVM had some performance gains over a separate server that communicated over Thrift (either directly or via Hector) since operations didn't have to take a second hop across the network (with the associated marshalling/unmarshalling)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We had a request come in to add the ability to run Virgil against a remote Cassandra:&lt;/div&gt;&lt;div&gt;&lt;a href="http://groups.google.com/group/virgil-users/browse_thread/thread/d8a99e026567b101"&gt;http://groups.google.com/group/virgil-users/browse_thread/thread/d8a99e026567b101&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;That seemed reasonable since there are a lot of existing cassandra clusters and users may just want to add a REST layer to support &lt;a href="http://code.google.com/a/apache-extras.org/p/virgil/wiki/gui"&gt;webapp/gui access&lt;/a&gt; or &lt;a href="http://code.google.com/a/apache-extras.org/p/virgil/wiki/solr"&gt;SOLR integration&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To support those cases, we added run-modes to the configuration:&lt;/div&gt;&lt;div&gt;&lt;a href="http://code.google.com/a/apache-extras.org/p/virgil/wiki/runmode"&gt;http://code.google.com/a/apache-extras.org/p/virgil/wiki/runmode&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Let us know what you think.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-2849680967077852945?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/2849680967077852945/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=2849680967077852945' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/2849680967077852945'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/2849680967077852945'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2011/11/introducing-run-modes-to-virgil-support.html' title='Introducing run-modes to Virgil: support for embedded or remote cassandra instances'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-2692221459704059452</id><published>2011-11-21T19:27:00.000-08:00</published><updated>2011-11-21T19:44:51.396-08:00</updated><title type='text'>Virgil: GUI for Cassandra now included in Virgil</title><content type='html'>&lt;div&gt;Sure, its read-only.&lt;/div&gt;&lt;div&gt;Sure, its focused on Strings.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;But it was written in only 100 lines of code using Virgil's REST layer for Cassandra and includes all of ExtJS's goodness. (if you are into that kind of thing)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You can see the entire the GUI is contained in a single javascript class:&lt;/div&gt;&lt;div&gt;&lt;a href="http://code.google.com/a/apache-extras.org/p/virgil/source/browse/trunk/src/main/webapp/main.js"&gt;http://code.google.com/a/apache-extras.org/p/virgil/source/browse/trunk/src/main/webapp/main.js&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;That javascript uses two GridPanel's: one to display column families grouped by keyspaces (on the east region panel), and another to display columns grouped by rowkeys (in the center panel).  Each of the GridPanel's uses a store backed by an ExtJS model.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To accomodate the GUI,  we added fetch capabilities the REST layer for both schema information and rows using key ranges.  I'll detail those capabilities in a follow up post.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For instructions on how to access the GUI and to see what it looks like check out the &lt;a href="http://code.google.com/a/apache-extras.org/p/virgil/wiki/gui"&gt;wiki page&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Even in its existing state, this a useful GUI to quickly inspect the contents of a Cassandra node. It is also a good demonstration of how you might include a javascript component for visualization into your own application with very little effort.&lt;/div&gt;&lt;div&gt;...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Virgil now includes an elementary REST interface. (thanks to Dave Strauss @ &lt;a href="https://getpantheon.com/news"&gt;Pantheon&lt;/a&gt; for his help defining the interface)  It also includes simple SOLR integration and a GUI.  Next up, map/reduce for the masses via REST.  Stay tuned.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As always, comments and contributions welcome and appreciated.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-2692221459704059452?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/2692221459704059452/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=2692221459704059452' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/2692221459704059452'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/2692221459704059452'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2011/11/virgil-gui-for-cassandra-now-included.html' title='Virgil: GUI for Cassandra now included in Virgil'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-2882020344826473788</id><published>2011-11-10T11:56:00.000-08:00</published><updated>2011-11-10T12:39:51.603-08:00</updated><title type='text'>PATCH methods on JAX-RS</title><content type='html'>&lt;div&gt;We added PATCH semantics for &lt;a href="http://code.google.com/a/apache-extras.org/p/virgil/"&gt;Virgil&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This was fairly straight forward, except we need to add support for a @PATCH annotation and PatchMethod for HttpClient.  &lt;/div&gt;&lt;br /&gt;&lt;div&gt;To do this, we created a PATCH annotation.  Take a look at &lt;a href="http://code.google.com/a/apache-extras.org/p/virgil/source/browse/trunk/src/main/java/org/apache/cassandra/http/ext/PATCH.java"&gt;PATCH.java&lt;/a&gt;.  The contents of which are shown below:&lt;/div&gt;&lt;code&gt;&lt;br /&gt;@Target({ElementType.METHOD})&lt;br /&gt;@Retention(RetentionPolicy.RUNTIME)&lt;br /&gt;@HttpMethod("PATCH")&lt;br /&gt;public @interface PATCH {&lt;br /&gt;}&lt;br /&gt;&lt;span class="Apple-style-span"  &gt;&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;div&gt;This then allows us to use @PATCH on an annotation on a &lt;a href="http://code.google.com/a/apache-extras.org/p/virgil/source/browse/trunk/src/main/java/org/apache/cassandra/http/CassandraRestService.java"&gt;REST service.&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;code&gt;&lt;br /&gt;   @PATCH&lt;br /&gt;   @Path("/data/{keyspace}/{columnFamily}/{key}")&lt;br /&gt;   @Produces({ "application/json" })&lt;br /&gt;   public void patchRow(@PathParam("keyspace") String keyspace,&lt;br /&gt;           @PathParam("columnFamily") String columnFamily, @PathParam("key") String key,&lt;br /&gt;           @QueryParam("index") boolean index, String body) throws Exception&lt;br /&gt;&lt;span class="Apple-style-span"  &gt;&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;div&gt;That worked like a charm.  Then we needed to call it using HttpClient.  To that, we created a PatchMethod class that extended PostMethod.  You can see that &lt;a href="http://code.google.com/a/apache-extras.org/p/virgil/source/browse/trunk/src/main/java/org/apache/cassandra/http/ext/PatchMethod.java"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt; Then we could use that just like any other HTTP method. &lt;/div&gt;&lt;code&gt;&lt;br /&gt;PatchMethod patch = new PatchMethod(BASE_URL + KEYSPACE + "/" + COLUMN_FAMILY + "/" + KEY);&lt;br /&gt; requestEntity = new StringRequestEntity("{\"ADDR1\":\"1235 Fun St.\",\"COUNTY\":\"Montgomery\"}",&lt;br /&gt;   "appication/json", "UTF8");&lt;br /&gt; patch.setRequestEntity(requestEntity);&lt;br /&gt;&lt;span class="Apple-style-span"  &gt;&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;div&gt;Hope that helps people.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-2882020344826473788?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/2882020344826473788/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=2882020344826473788' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/2882020344826473788'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/2882020344826473788'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2011/11/patch-methods-on-jax-rs.html' title='PATCH methods on JAX-RS'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-4656228507167818792</id><published>2011-11-10T11:18:00.000-08:00</published><updated>2011-11-10T11:38:42.016-08:00</updated><title type='text'>Virgil: PATCH semantics added to REST layer for Cassandra</title><content type='html'>&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://code.google.com/a/apache-extras.org/p/virgil/"&gt;Virgil&lt;/a&gt; now supports PATCH semantics for row updates in Cassandra via REST.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In REST, when a resource is modified rather than fully replaced by an HTTP operation, the IETF is proposing a new HTTP method, PATCH.&lt;/div&gt;&lt;div&gt;&lt;pre style="font-size: 12px; white-space: pre-wrap; max-width: 80em; padding-left: 0.7em; text-align: -webkit-auto; background-color: rgb(255, 255, 255); "&gt;&lt;a href="http://tools.ietf.org/html/rfc5789" rel="nofollow" style="color: rgb(0, 0, 204); "&gt;http://tools.ietf.org/html/rfc5789&lt;/a&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Virgil now allows users to use this HTTP method to add and modify columns in a single post (without reposting the entire row).  We've included an example in the &lt;a href="http://code.google.com/a/apache-extras.org/p/virgil/"&gt;Getting Started&lt;/a&gt; instructions.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Likewise, PUT operations will now replace the entire row, per HTTP semantics.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;(Thanks to David Strauss for suggesting this)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-4656228507167818792?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/4656228507167818792/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=4656228507167818792' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/4656228507167818792'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/4656228507167818792'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2011/11/virgil-patch-semantics-added-to-rest.html' title='Virgil: PATCH semantics added to REST layer for Cassandra'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-1584424200990180223</id><published>2011-11-04T13:37:00.001-07:00</published><updated>2011-11-04T13:47:27.597-07:00</updated><title type='text'>Cassandra integration w/ SOLR using Virgil</title><content type='html'>Up front, I'd like to say this is still pretty raw.  We'd love to get feedback and contributions.&lt;br /&gt;&lt;br /&gt;That said, Virgil now has the ability to integrate SOLR and Cassandra.  When you add and delete rows and columns via the REST interface, an index is updated in SOLR.&lt;br /&gt;&lt;br /&gt;For more information check out:&lt;br /&gt;http://code.google.com/a/apache-extras.org/p/virgil/wiki/solr&lt;br /&gt;&lt;br /&gt;Let us know what we can do better.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-1584424200990180223?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/1584424200990180223/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=1584424200990180223' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/1584424200990180223'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/1584424200990180223'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2011/11/cassandra-integration-w-solr-using.html' title='Cassandra integration w/ SOLR using Virgil'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-7195969022003121023</id><published>2011-10-24T19:05:00.000-07:00</published><updated>2011-10-24T19:30:58.877-07:00</updated><title type='text'>Virgil gets a command-line interface (virgil-cli)</title><content type='html'>&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Tonight I bundled the cassandra command-line interface (CLI) into virgil.   Since the CLI uses the thrift-based CassandraDaemon, the main method now starts a thrift server along side the REST server. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now, when you (or your application) issues commands through the REST interface, you can verify that they worked through the command-line interface.   For more information, &lt;a href="http://code.google.com/a/apache-extras.org/p/virgil/wiki/virgilcli"&gt;check out the wiki.&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Specifically, if you use the curl commands in the &lt;a href="http://code.google.com/a/apache-extras.org/p/virgil/"&gt;Getting Started section&lt;/a&gt;.  You should see the following in the command-line interface.&lt;/div&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;bone@zen:~/dev/code.google.com/virgil/trunk-&amp;gt; bin/virgil-cli -h localhost&lt;br /&gt;Connected to: "Test Cluster" on localhost/9160&lt;br /&gt;Welcome to the Cassandra CLI.&lt;br /&gt;&lt;br /&gt;Type 'help;' or '?' for help.&lt;br /&gt;Type 'quit;' or 'exit;' to quit.&lt;br /&gt;&lt;br /&gt;[default@unknown] use playground;&lt;br /&gt;Authenticated to keyspace: playground&lt;br /&gt;[default@playground] list toys;&lt;br /&gt;Using default limit of 100&lt;br /&gt;-------------------&lt;br /&gt;RowKey: swingset&lt;br /&gt;=&amp;gt; (column=bar, value=33, timestamp=1319508065134)&lt;br /&gt;=&amp;gt; (column=foo, value=1, timestamp=1319508065126)&lt;br /&gt;&lt;br /&gt;1 Row Returned.&lt;br /&gt;[default@playground] quit&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-7195969022003121023?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/7195969022003121023/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=7195969022003121023' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/7195969022003121023'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/7195969022003121023'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2011/10/virgil-gets-command-line-interface.html' title='Virgil gets a command-line interface (virgil-cli)'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-3499098193147097339</id><published>2011-10-20T18:14:00.001-07:00</published><updated>2011-10-22T05:10:07.653-07:00</updated><title type='text'>Virgil: a GUI and REST layer for Cassandra</title><content type='html'>Love Cassandra?  Love REST?&lt;br /&gt;Wish you could have both at the same time?&lt;br /&gt;Now you can.&lt;br /&gt;&lt;br /&gt;After much &lt;a href="https://issues.apache.org/jira/browse/CASSANDRA-3380"&gt;discussion&lt;/a&gt;, I'm happy to announce the birth of a new project, Virgil.  The project will provide a GUI and a services layer on top of Cassandra, exposing data and services via REST.&lt;br /&gt;&lt;br /&gt;Virgil already has a REST layer for CRUD operations against keyspaces, column families, and data.  We hope to quickly add Pig/Hadoop support via REST as well as a thin, javascript-based GUI that uses the REST services.&lt;br /&gt;&lt;br /&gt;How can you help nurture the baby?&lt;br /&gt;Head over to Apache Extras,&lt;br /&gt;&lt;a href="http://code.google.com/a/apache-extras.org/p/virgil/"&gt;http://code.google.com/a/apache-extras.org/p/virgil/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Star the project, and then get involved.&lt;br /&gt;&lt;a href="http://code.google.com/a/apache-extras.org/p/virgil/source/checkout"&gt;Grab the source code&lt;/a&gt; and &lt;a href="http://code.google.com/a/apache-extras.org/p/virgil/"&gt;give it a try&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-3499098193147097339?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/3499098193147097339/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=3499098193147097339' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/3499098193147097339'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/3499098193147097339'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2011/10/virgil-gui-and-rest-layer-for-cassandra.html' title='Virgil: a GUI and REST layer for Cassandra'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-3382168071018732612</id><published>2011-10-05T13:11:00.000-07:00</published><updated>2011-10-05T13:17:13.611-07:00</updated><title type='text'>Pig / Cassandra: binary operator expected</title><content type='html'>If you are trying to run Pig on Cassandra and you encounter: "binary operator expected"&lt;br /&gt;&lt;br /&gt;You are most likely running pig_cassandra against the latest release of Pig, which has two jar files in it one with hadoop and one without hadoop.  Your PIG_HOME is set to the root directory of your pig installation, which contains those two jar files.  The existence of TWO jar files breaks the pig_cassandra shell script. &lt;br /&gt;&lt;br /&gt;I've submitted a patch for this:&lt;br /&gt;https://issues.apache.org/jira/browse/CASSANDRA-3320&lt;br /&gt;(Please vote to get it included)&lt;br /&gt;&lt;br /&gt;Until that is committed, you can simply remove the jar file you don't want to use:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;rm -fr $PIG_HOME/pig-0.9.1-withouthadoop.jar&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;That should fix you.&lt;br /&gt;Happy pigging.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-3382168071018732612?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/3382168071018732612/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=3382168071018732612' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/3382168071018732612'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/3382168071018732612'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2011/10/pig-cassandra-binary-operator-expected.html' title='Pig / Cassandra: binary operator expected'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-6996065269071756220</id><published>2011-10-03T06:48:00.000-07:00</published><updated>2011-10-03T07:03:18.189-07:00</updated><title type='text'>Cassandra / Hadoop : Getting the row key (when iterating over all rows)</title><content type='html'>&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I thought I would save some people some time...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The word count example is fantastic, and is enough to get you going.   But, you it may leave you wondering how to get at the row key since the "key" passed into the map is the name of the column and not the key of the row.   Instead the key is in the context.  Take a look at the snippet below.&lt;/div&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;public void map(ByteBuffer key, SortedMap&amp;lt;ByteBuffer, IColumn&amp;gt; columns, Context context) &lt;br /&gt;   throws IOException, InterruptedException {&lt;br /&gt;  for (ByteBuffer columnKey : columns.keySet()){&lt;br /&gt;     String name = ByteBufferUtil.string(columns.get(columnKey).name());&lt;br /&gt;     String value = ByteBufferUtil.string(columns.get(columnKey).value());            &lt;br /&gt;     logger.info("[" + ByteBufferUtil.string(columnKey) + "]-&amp;gt;[" + name + "]:[" + value + "]");&lt;br /&gt;&lt;span class="Apple-style-span"&gt;      &lt;span class="Apple-style-span" &gt;logger.info("Context [" + ByteBufferUtil.string(context.getCurrentKey()) + "]); &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" &gt;            &lt;/span&gt;&lt;br /&gt;  }&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-6996065269071756220?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/6996065269071756220/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=6996065269071756220' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/6996065269071756220'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/6996065269071756220'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2011/10/cassandra-hadoop-iterating-over-all.html' title='Cassandra / Hadoop : Getting the row key (when iterating over all rows)'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-4177038445203272032</id><published>2011-09-14T13:09:00.000-07:00</published><updated>2011-09-19T10:50:36.241-07:00</updated><title type='text'>Cassandra / Hadoop : No local connection available</title><content type='html'>If you are trying to run the word_count example in Cassandra Hadoop, and you encounter the following exception:&lt;br /&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;java.lang.RuntimeException: java.lang.UnsupportedOperationException: no local connection available&lt;/span&gt;&lt;br /&gt;&lt;span&gt;    at org.apache.cassandra.hadoop.ColumnFamilyRecordReader.initialize(ColumnFamilyRecordReader.java:132)&lt;/span&gt;&lt;br /&gt;&lt;span&gt;    at org.apache.hadoop.mapred.MapTask$NewTrackingRecordReader.initialize(MapTask.java:418)&lt;/span&gt;&lt;br /&gt;&lt;span&gt;    at org.apache.hadoop.mapred.MapTask.runNewMapper(MapTask.java:620)&lt;/span&gt;&lt;br /&gt;&lt;span&gt;    at org.apache.hadoop.mapred.MapTask.run(MapTask.java:305)&lt;/span&gt;&lt;br /&gt;&lt;span&gt;    at org.apache.hadoop.mapred.LocalJobRunner$Job.run(LocalJobRunner.java:177)&lt;/span&gt;&lt;br /&gt;&lt;span&gt;Caused by: java.lang.UnsupportedOperationException: no local connection available&lt;/span&gt;&lt;br /&gt;&lt;span&gt;    at org.apache.cassandra.hadoop.ColumnFamilyRecordReader.getLocation(ColumnFamilyRecordReader.java:176)&lt;/span&gt;&lt;br /&gt;&lt;span&gt;    at org.apache.cassandra.hadoop.ColumnFamilyRecordReader.initialize(ColumnFamilyRecordReader.java:113)&lt;/span&gt;&lt;br /&gt;&lt;span&gt;    ... 4 more&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Then you have hit a problem with local IP resolution in Java.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Cassandra currently uses the following line to resolve IP addresses;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;            localAddresses = InetAddress.getAllByName(InetAddress.getLocalHost().getHostAddress());&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There are better ways to do this using the NetworkInterface, &lt;/div&gt;&lt;div&gt;&lt;a href="http://stackoverflow.com/questions/901755/how-to-get-the-ip-of-the-computer-on-linux-through-java"&gt;http://stackoverflow.com/questions/901755/how-to-get-the-ip-of-the-computer-on-linux-through-java&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://www.jguru.com/faq/view.jsp?EID=790132"&gt;http://www.jguru.com/faq/view.jsp?EID=790132&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;But until Cassandra uses that you'll need to make sure that the bit of code above resolves properly by manipulating your /etc/hosts to resolve localhost to match the configuration in Cassandra, which by default is looking for localhost bound to 127.0.0.1.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;I submitted a patch for this.  If you are having issues, please vote to get the patch accepted.&lt;br /&gt;&lt;a href="https://issues.apache.org/jira/browse/CASSANDRA-3211"&gt;https://issues.apache.org/jira/browse/CASSANDRA-3211&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-4177038445203272032?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/4177038445203272032/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=4177038445203272032' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/4177038445203272032'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/4177038445203272032'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2011/09/cassandra-haddop-no-local-connection.html' title='Cassandra / Hadoop : No local connection available'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-5282930600577121128</id><published>2011-08-31T18:03:00.000-07:00</published><updated>2011-08-31T18:08:35.293-07:00</updated><title type='text'>Master Data Management : Open Source Solutions???</title><content type='html'>&lt;p&gt;The movement towards digital records is generating exponential  amounts of data, tremendously valuable data.  But building a system to  manage that data and extract value from it requires acceptance of a  paradox; the system needs to be flexible and tolerant, while  simultaneously enforcing structure and standards.  This is hard. &lt;/p&gt; &lt;p&gt;Many of us have felt the pain of Master Data Management (MDM). In large enough enterprises,  even something as simple as keeping addresses current across multiple  lines of business is a herculean task.  Furthermore, it’s a problem  that’s difficult to ignore because poor data management can drive  substantial expense and leave invaluable opportunities on the table.&lt;/p&gt; &lt;p&gt;Since joining Health Market Science (HMS), a company focused on MDM  for the healthcare space, that sentiment has been reinforced tenfold.   Two things became immediately apparent:  the complexity of a complete  solution and the value of the same.&lt;/p&gt; &lt;p&gt;The problem is complex because there is a temporal aspect to the data.  A complete &lt;a href="http://www.healthmarketscience.com/solutions/masterfile-individuals"&gt;MDM solution&lt;/a&gt;  doesn't just provide a current view of entities, but a historical  perspective as well.  It provides that perspective across all the  entities and the all the relationships between those entities.  Then,  add in the fact that each source system may have a different schema  representing each entity and that the schema itself may evolve over  time.  Then, pile on all the necessary processing to analyze the data.   Entities need to be consolidated based on precedence rules,  standardized, and matched using fuzzy matching.  What a fantastic recipe  for a fun problem to solve.&lt;/p&gt; &lt;p&gt;But given the complexity, it isn't difficult to see why companies shy  away from an "in-house" MDM solution.  Solving these problems isn't  easy.  You may think that if you get yourself a good Data Architect and a  massive Oracle instance, you could crank something out.   You’ll soon  find that standard relational structures quickly become unwieldy and you  end up in “meta-meta” world building out schemas to manage schemas.    This can be extremely painful.&lt;/p&gt;&lt;p&gt;I'm wondering if people have seen any open source solutions capable of tackling this problem.  From what I can find, the open source  "MDM" solutions only tackle the Extract-Transform-Load (ETL) portion of the problem.  Unfortunately, that is the easy part.   Does anyone know of any open-source communities focused on delivering a complete solution, ETL through down into storage?&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-5282930600577121128?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/5282930600577121128/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=5282930600577121128' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/5282930600577121128'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/5282930600577121128'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2011/08/master-data-management-open-source.html' title='Master Data Management : Open Source Solutions???'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-4046464693078783355</id><published>2010-12-02T11:56:00.000-08:00</published><updated>2010-12-02T11:59:16.069-08:00</updated><title type='text'>Rails vs. Grails</title><content type='html'>&lt;p&gt;I was recently asked the question: Rails or Grails? I needed to summarize the key differences and industry sentiment. This was my response.&lt;/p&gt;&lt;p&gt;Before I make any subjective comments, let me start with some objective metrics I found:&lt;br /&gt;&lt;a href="http://www.expectationgap.com/posts/13"&gt;http://www.expectationgap.com/posts/13&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Now for my sentiments, I believe there are three key-dimensions: momentum, cloud-support, and people.&lt;/p&gt;&lt;h4&gt;Momentum&lt;/h4&gt;&lt;p&gt;Rails has the momentum as evidenced by the number of committers and plugins available.  Many of the rockstar developers I know are all now developing in Rails, supporting that community, etc.   The underlying Ruby language is incredibly expressive and allows dramatic productivity improvements. (write less code that can do more)&lt;/p&gt;&lt;p&gt;Only a handful of rockstars I know are developing on Grails.  Typically, those developing on Grails are in enterprises or markets that are comfortable with Java and they want to continue leveraging that investment. (infrastructure, app servers, production support, etc.)  Grails/Groovy does have the advantage that It can continue to leverage the output of the Java community (e.g. Spring).  The better projects within the Java community are quickly integrated into Grails. For example, Grails uses Hibernate and Spring Security under the hood.  As those projects improve, so will Grails.&lt;/p&gt;&lt;h4&gt;Cloud Support&lt;/h4&gt;&lt;p&gt;Rails and the cloud go hand in hand.  Again, of the rockstar Rails developers I know, nearly all of them are running on virtual hardware owned and managed by others.    Some of those let others manage the entire application server / platform (e.g. EngineYard).  In contrast, all of the Grails development I know of is running on hardware (virtualized) owned and managed by the  company itself in their own data centers (or rented space).   As mentioned before, this may actually have been the motivating factor to select Grails.  That is not to say that there isn’t cloud support for Grails.  And now that VMWare owns SpringSource,  this may change rapidly now that enterprises will have a trusted name (in VMWare) to host their Grails applications.&lt;/p&gt;&lt;h4&gt;People&lt;/h4&gt;&lt;p&gt;Rails has the momentum, more committers and potentially a more active community, but lets not fool ourselves -- there is an army of labor out there to sling Java code.  Offshore resources are readily available.  The market for Rails is developing, but demand isn’t yet high enough to drive consulting companies to substantially increase their supply.  As one of my good friends put it, “I’d love to develop in Ruby, but Java pays the bills.”.  It is that sentiment, that has may limit the availability of resources.&lt;/p&gt;&lt;p&gt;However, even with readily available Java resources, that doesn’t  guarantee the availability of Groovy resources.  Both Grails and Rails require a slightly different mindset.  If you take a Java developer and tell them to code in Groovy or Ruby, you’ll end up with Java code using Ruby/Groovy syntax.  (not good)  But at least the tooling, debugging practices, and libraries will all be familiar.&lt;/p&gt;&lt;p&gt;And just to stoke the fire...&lt;/p&gt;&lt;p&gt;Here are my entirely subjective scores:&lt;br /&gt;Momentum: Rails (9) vs. Groovy (4)&lt;br /&gt;Cloud Support: Rails (8) vs. Groovy( 5)&lt;br /&gt;People: Rails (6) vs. Groovy (8)&lt;br /&gt;---------------------------------------------------&lt;br /&gt;Rails (23) vs. Groovy (17)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-4046464693078783355?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/4046464693078783355/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=4046464693078783355' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/4046464693078783355'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/4046464693078783355'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2010/12/rails-vs-grails.html' title='Rails vs. Grails'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-8302172423311297584</id><published>2010-08-03T12:24:00.000-07:00</published><updated>2010-08-03T13:40:38.991-07:00</updated><title type='text'>XML Validation with Eclipse</title><content type='html'>When I'm doing serious schema work, I typically use XMLSpy, but for simple schema validation it isn't worth leaving the IDE.  As of late, I've been using the SpringSource IDE, which comes with XML plugins pre-installed.  With the plugins, XML validation is simple enough.  You just need to make sure you have the schemaLocation defined in your XML.&lt;br /&gt;&lt;br /&gt;Let's say I have a simple document:&lt;br /&gt;&lt;pre style="background-color: lightgrey;"&gt;&amp;lt;zoo&amp;gt;&lt;br /&gt;   &amp;lt;animal&amp;gt;cat&amp;lt;/animal&amp;gt;&lt;br /&gt;&amp;lt;/zoo&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;If you open the document, you can right click and Validate the document.  If there is no associated schema, you'll receive a warning that says:&lt;br /&gt;&lt;pre&gt;No grammar constraints (DTD or XML schema) detected for the document.&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;To rectify that, you'll need to specify the schema location in the XML.  That will require namespaces.  Let's assume we have the following simple schema with namespaces:&lt;br /&gt;&lt;pre style="background-color: lightgrey;"&gt;&amp;lt;xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"&lt;br /&gt;   targetNamespace="http://www.skookle.com/philly"&lt;br /&gt;   xmlns:philly="http://www.skookle.com/philly" &amp;gt;&lt;br /&gt; &amp;lt;xsd:complexType name="zoo"&amp;gt;&lt;br /&gt;  &amp;lt;xsd:sequence&amp;gt;&lt;br /&gt;   &amp;lt;xsd:element name="animal" type="xsd:string"/&amp;gt;&lt;br /&gt;  &amp;lt;/xsd:sequence&amp;gt;&lt;br /&gt; &amp;lt;/xsd:complexType&amp;gt;&lt;br /&gt; &lt;br /&gt; &amp;lt;xsd:element name="zoo" type="philly:zoo"/&amp;gt;&lt;br /&gt;&amp;lt;/xsd:schema&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now, lets revisit the simple XML to add namespaces and a schemaLocation element that references the above xsd. (zoo.xsd)&lt;br /&gt;&lt;pre style="background-color: lightgrey;"&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;philly:zoo xmlns:philly="http://www.skookle.com/philly"&lt;br /&gt;    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;br /&gt;    xsi:schemaLocation="http://www.skookle.com/philly zoo.xsd"&amp;gt;&lt;br /&gt;    &amp;lt;animal&amp;gt;cat&amp;lt;/animal&amp;gt;&lt;br /&gt;&amp;lt;/philly:zoo&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Note: To get the schemaLocation attribute you'll need the XMLSchema-instance namespace.&lt;br /&gt;&lt;br /&gt;Now, you can right-click on the XML and it will validate.  Also, you'll get the fancy element completion while you type. Rock on, even less reason to leave the IDE. =)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-8302172423311297584?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/8302172423311297584/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=8302172423311297584' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/8302172423311297584'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/8302172423311297584'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2010/08/xml-validation-with-eclipse.html' title='XML Validation with Eclipse'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-1668850364541305752</id><published>2010-03-27T19:54:00.000-07:00</published><updated>2010-03-27T19:59:01.230-07:00</updated><title type='text'>SSH Port Forwarding Example</title><content type='html'>Like everyone, it takes me a few tries before I get a port forwarding command line right.  Here is yet another example for everyone, just in case you happen to have this specific example.&lt;br /&gt;&lt;br /&gt;Lets say you want to get to your database, but it isn't exposed:&lt;br /&gt;CLIENT --&gt; DMZ --&gt; DB_HOST&lt;br /&gt;&lt;br /&gt;You want to forward some port on DMZ to the DB.  Lets say it is Oracle running on 1521.  Then, from the DMZ host you should issue the following command:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;  ssh -g -L 5000:DB_HOST:1521 boneill@DB_HOST &lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;At this point, you should be able to connect to DMZ:5000 as if it were DB:1521.&lt;br /&gt;&lt;br /&gt;REALLY REALLY IMPORTANT is the "-g", that allows remote connections to 5000.  Otherwise, it will just bind to the local interface and you won't be able to connect from CLIENT.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-1668850364541305752?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/1668850364541305752/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=1668850364541305752' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/1668850364541305752'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/1668850364541305752'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2010/03/ssh-port-forwarding-example.html' title='SSH Port Forwarding Example'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-1373309245490805297</id><published>2009-11-25T08:17:00.000-08:00</published><updated>2009-11-25T10:10:27.888-08:00</updated><title type='text'>SOAP Testing over HTTPS, using Siege instead of Ab</title><content type='html'>I've been using ab for a while now to perform load testing.  Recently, I ran into trouble however because ab doesn't work with HTTPS out of the box (at least on my Ubuntu install). That triggered an investigation into other tools. &lt;a href="http://www.joedog.org/index/siege-home"&gt;Siege&lt;/a&gt; fit the bill nicely.  Basically, I needed a way to perform an HTTP Post with a SOAP body.&lt;br /&gt;&lt;br /&gt;On ubuntu, it is a simple "apt-get install siege".&lt;br /&gt;&lt;br /&gt;Then, you create a siegerc file:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;verbose = true&lt;br /&gt;logging = true&lt;br /&gt;protocol = HTTP/1.1&lt;br /&gt;connection = keep-alive&lt;br /&gt;concurrent = 50 #Number of concurrent requests&lt;br /&gt;file = ./urls.txt&lt;br /&gt;delay = 0 #If you are using for benchmarking value should be 0&lt;br /&gt;benchmark = true&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;The settings are fairly obvious.  Note that the file parameter points to an additional file you'll need, which lists out all of the urls you want included in your test.  Below is an example:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;https://foo.com/ws/Blah POST &lt; soapMessage.xml&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Notice after the url we specify "POST", which makes it a POST method instead of GET.  Additionally, we pipe in the XML file which contains the SOAP message.&lt;br /&gt;&lt;br /&gt;Then we can simply invoke siege with:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;siege --rc=./siegerc --header="Authorization:Basic BASGHAJSG78236ds"&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Notice, we are supplying an extra header for Basic Auth.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-1373309245490805297?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/1373309245490805297/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=1373309245490805297' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/1373309245490805297'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/1373309245490805297'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2009/11/soap-testing-over-https-using-siege.html' title='SOAP Testing over HTTPS, using Siege instead of Ab'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-4164623057784986500</id><published>2009-09-22T11:56:00.001-07:00</published><updated>2009-09-22T12:07:44.129-07:00</updated><title type='text'>MySQL: LEFT Join with Constraints</title><content type='html'>I just fixed a bug in a colleague's select statement.  And I think it makes a good example.  So here it is: &lt;br /&gt;&lt;br /&gt;You have two tables foo and bar.  You are performing different types of analysis on the items in foo, and writing that analysis to bar.  Foo has a primary key "id".  And bar has three columns: "foo_id", "analysis" and "version".  The bar table contains the following entries.&lt;br /&gt;&lt;br /&gt;1, blah, 3&lt;br /&gt;1, erg, 2&lt;br /&gt;2, erg, 2&lt;br /&gt;&lt;br /&gt;This means that item 1 in foo has been analyzed for blah and erg versions 3 and 2 respectively.  Item 2 has been analyzed for only erg version 2.&lt;br /&gt;&lt;br /&gt;Now, lets say there are three items in foo and you want a query to pull back all of the items that need analysis for blah version 3.  The right answer is items 2, and 3.&lt;br /&gt;&lt;br /&gt;You may start with:&lt;br /&gt;&lt;pre&gt;select * from foo LEFT JOIN bar.foo_id = foo.id&lt;/pre&gt;&lt;br /&gt;This returns 4 rows:&lt;br /&gt;1, blah, 3&lt;br /&gt;1, erg, 2&lt;br /&gt;2, erg, 2&lt;br /&gt;3, null, null&lt;br /&gt;&lt;br /&gt;From this resultant table there is no good way to select foo.id's that have not been processed by the right version of blah.  However, if we add a join constraint to our select we can.  The select becomes:&lt;br /&gt;&lt;pre&gt;select * from foo LEFT JOIN bar.foo_id = foo.id AND bar.analysis = 'blah'&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This returns a beautiful table:&lt;br /&gt;1, blah, 3&lt;br /&gt;2, null, null&lt;br /&gt;3, null, null&lt;br /&gt;&lt;br /&gt;Essentially the left join takes place with only a subset of bar that meets the join constraint.&lt;br /&gt;&lt;br /&gt;NOTE: This is entirely different from the following:&lt;br /&gt;&lt;pre&gt;select * from foo LEFT JOIN bar.foo_id = foo.id WHERE bar.analysis = 'blah'&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;That query will only return the single row.  To manipulate the original join you would probably end up using a "NOT EXISTS IN" kind of construct.  Yuck.&lt;br /&gt;&lt;br /&gt;The JOIN with a constraint presents a nice clean simple solution that lets us figure out which foo items still need analysis.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-4164623057784986500?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/4164623057784986500/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=4164623057784986500' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/4164623057784986500'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/4164623057784986500'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2009/09/mysql-left-join-with-constraints.html' title='MySQL: LEFT Join with Constraints'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-3519536572134963095</id><published>2009-09-10T11:36:00.000-07:00</published><updated>2009-09-10T13:07:13.896-07:00</updated><title type='text'>ERROR 1005 (HY000): Rails Migrations for Unsigned Integers</title><content type='html'>&lt;pre&gt;&lt;br /&gt;ERROR 1005 (HY000): Can't create table './*/#sql-3e29_1209.frm' (errno: 150)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If you are getting this when trying to add a foreign key constraint make sure the columns are of the same type.  This includes attributes!  Specifically pay attention to signed vs. unsigned columns.  Just because two columns are integer (or int(10) or int(11)), you won't be able to create a foreign key constraint between them unless they are have the same sign.&lt;br /&gt;&lt;br /&gt;Furthermore, in a Rails Migration, to get a signed/unsigned column use the following:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    create_table :tblFoo, :primary_key =&gt; :UID  do |t|&lt;br /&gt;      t.column 'Bar', 'int(10) unsigned', :null =&gt; false&lt;br /&gt;      t.timestamps&lt;br /&gt;    end&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-3519536572134963095?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/3519536572134963095/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=3519536572134963095' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/3519536572134963095'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/3519536572134963095'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2009/09/error-1005-hy000-rails-migrations-for.html' title='ERROR 1005 (HY000): Rails Migrations for Unsigned Integers'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-3440386314106007375</id><published>2009-09-09T13:46:00.000-07:00</published><updated>2009-09-09T13:51:08.507-07:00</updated><title type='text'>Access denied for user 'debian-sys-maint'@'localhost'</title><content type='html'>I wanted to get replication setup to do backups offline as recommended by &lt;a href="http://onlamp.com/onlamp/2005/06/16/MySQLian.html"&gt; this article&lt;/a&gt;.  I did the backup and loaded it onto the slave.  When I went to restart, I received:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;ERROR 1045 (28000): Access denied for user 'debian-sys-maint'@'localhost'&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;It turns out I backed up the users table as well so it blew away the debian user.  I found the fix &lt;a href="http://ubuntuforums.org/showthread.php?t=112505"&gt; here &lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The trick is to reset the debian-sys-maint users password by looking in /etc/mysql/debian.cnf and performing the following with whatever password you find in there:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;GRANT ALL PRIVILEGES ON *.* TO 'debian-sys-maint'@'localhost' IDENTIFIED BY '&lt;password&gt;' WITH GRANT OPTION;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-3440386314106007375?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/3440386314106007375/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=3440386314106007375' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/3440386314106007375'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/3440386314106007375'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2009/09/access-denied-for-user-debian-sys.html' title='Access denied for user &apos;debian-sys-maint&apos;@&apos;localhost&apos;'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-7340248437185352852</id><published>2009-07-28T18:49:00.000-07:00</published><updated>2009-07-28T18:51:56.307-07:00</updated><title type='text'>Global Subversion Ignore Settings (Used for Eclipse Project Files)</title><content type='html'>I hate having to run a global svn propset ignore command.  Instead it is much easier to open up .subversion/config and edit the following in the file.&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;global-ignores = .project .target .classpath .settings *.o *.lo *.la #*# .*.rej *.rej .*~ *~ .#* .DS_Store&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Notice, I added all of the eclipse files to the ignore statement.  Once you update that file, that should be it. Next time you run svn status (or anything) it will take those ignore patterns into account.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-7340248437185352852?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/7340248437185352852/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=7340248437185352852' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/7340248437185352852'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/7340248437185352852'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2009/07/global-subversion-ignore-settings-used.html' title='Global Subversion Ignore Settings (Used for Eclipse Project Files)'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-3538303421884209349</id><published>2009-07-28T07:09:00.001-07:00</published><updated>2009-07-28T07:11:06.436-07:00</updated><title type='text'>Java Wordnet Library (JWNL) Jar file Repo Entry</title><content type='html'>Here is the maven pom entry for Java Wordnet Library (JWNL)&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;        &amp;lt;dependency&amp;gt;&lt;br /&gt;            &amp;lt;groupId&amp;gt;net.didion&amp;lt;/groupId&amp;gt;&lt;br /&gt;            &amp;lt;artifactId&amp;gt;jwnl&amp;lt;/artifactId&amp;gt;&lt;br /&gt;            &amp;lt;version&amp;gt;1.4&amp;lt;/version&amp;gt;&lt;br /&gt;        &amp;lt;/dependency&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-3538303421884209349?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/3538303421884209349/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=3538303421884209349' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/3538303421884209349'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/3538303421884209349'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2009/07/java-wordnet-library-jwnl-jar-file-repo.html' title='Java Wordnet Library (JWNL) Jar file Repo Entry'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-1119439877405351500</id><published>2009-07-27T21:05:00.000-07:00</published><updated>2009-07-27T21:09:39.509-07:00</updated><title type='text'>CSV (Comma Separated Values) Processing in Ruby</title><content type='html'>FasterCSV rocks.  You can find it here:&lt;br /&gt;http://fastercsv.rubyforge.org/&lt;br /&gt;&lt;br /&gt;Start by installing it using the gem.&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;sudo gem install fastercsv&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;After that, you are all set.  Just make sure you require rubygems first.&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;require 'rubygems'&lt;br /&gt;require 'fastercsv'&lt;br /&gt;&lt;br /&gt;i=0&lt;br /&gt;FasterCSV.foreach('blogs.csv') do |row|&lt;br /&gt;   i=i+1&lt;br /&gt;   puts("#{row[2]}")&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;As you can see from above, the row is an array that contains the values from the CSV file.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-1119439877405351500?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/1119439877405351500/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=1119439877405351500' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/1119439877405351500'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/1119439877405351500'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2009/07/csv-comma-separated-values-processing.html' title='CSV (Comma Separated Values) Processing in Ruby'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-9114469828188569161</id><published>2009-07-27T20:32:00.000-07:00</published><updated>2009-07-27T20:41:27.212-07:00</updated><title type='text'>ActiveRecord outside of Rails (even with ODBC)</title><content type='html'>There are three quick lines that you need in order to use ActiveRecord outside of Rails.  First, you need to load gems, then you can load ActiveRecord.  Then, you can pick and choose which of your models to use.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;require 'rubygems'&lt;br /&gt;require 'activerecord'&lt;br /&gt;require @@RAILS_APP_HOME + '/app/models/foo.rb'&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Then, you'll need this little snippet to establish the connection to the database for ActiveRecord:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;require 'rubygems'&lt;br /&gt;require 'activerecord'&lt;br /&gt;require 'yaml'&lt;br /&gt;&lt;br /&gt;@@DATABASE_CONFIGURATION = YAML::load(File.open(File.dirname(__FILE__) + '/config/databases.yml'))&lt;br /&gt;&lt;br /&gt;def establish_connection(database)&lt;br /&gt;  dbconfig = @@DATABASE_CONFIGURATION&lt;br /&gt;  ActiveRecord::Base.establish_connection(dbconfig[database])&lt;br /&gt;#  ActiveRecord::Base.logger = Logger.new(STDERR)&lt;br /&gt;  if (dbconfig['mode'] == 'odbc')&lt;br /&gt;    puts("Connecting to [#{database}]: ODBC,"+&lt;br /&gt;        " DSN=#{dbconfig[database]['dsn']}/#{dbconfig[database]['adapter']}"+&lt;br /&gt;        " [user=#{dbconfig[database]['username']}]")&lt;br /&gt;  else&lt;br /&gt;    puts("Connecting to [#{database}]: #{dbconfig[database]['adapter']}, "+&lt;br /&gt;        "#{dbconfig[database]['database']}@#{dbconfig[database]['host']}"+&lt;br /&gt;        " [user=#{dbconfig[database]['username']}]")&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;def remove_connection&lt;br /&gt;  ActiveRecord::Base.remove_connection&lt;br /&gt;end&lt;br /&gt;~                                                     &lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;I put the above snippet in a central ruby file, then require that file anywhere I need to use the ActiveRecord objects.  After a call to establish_connection, you can start using any model you've imported.  Note, you'll see a slightly different URL constructed for ODBC.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-9114469828188569161?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/9114469828188569161/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=9114469828188569161' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/9114469828188569161'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/9114469828188569161'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2009/07/activerecord-outside-of-rails-even-with.html' title='ActiveRecord outside of Rails (even with ODBC)'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-3947622115007759929</id><published>2009-07-22T07:06:00.000-07:00</published><updated>2009-07-22T07:35:18.641-07:00</updated><title type='text'>Hadoop: java.io.IOException: Type mismatch in key from map</title><content type='html'>We've been working with hadoop for a while now, and inevitably newbies run into this error the first time they go to create their own Hadoop job.  If you are running into this error, it is most likely a mismatch between your Map and/or Reduce implementation and the job configuration.&lt;br /&gt;&lt;br /&gt;Your Map implementation probably looks something like this:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;   public static class MapClass extends MapReduceBase&lt;br /&gt;            implements Mapper&lt;LongWritable, Text, Text, IntWritable&gt; {&lt;br /&gt;        private Text word = new Text();&lt;br /&gt;        public void map(LongWritable key, Text value,&lt;br /&gt;               OutputCollector&lt;Text, IntWritable&gt; output,&lt;br /&gt;               Reporter reporter) throws IOException {&lt;br /&gt;               ...&lt;br /&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Now, your map and reduce phases can have different output types and that is what sometimes causes the problems.  If your phases are producing different types, be sure to set those types in the JobConf.  You do this as follows....&lt;br /&gt;&lt;br /&gt;Then when configuring your job you need to declare the appropriate output classes.&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;        // Set the outputs for the Map&lt;br /&gt;        conf.setMapOutputKeyClass(Text.class);&lt;br /&gt;        conf.setMapOutputValueClass(IntWritable.class);&lt;br /&gt;&lt;br /&gt;        // Set the outputs for the Job&lt;br /&gt;        conf.setOutputKeyClass(Text.class);&lt;br /&gt;        conf.setOutputValueClass(ArrayWritable.class);&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Hope that saves people some time.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-3947622115007759929?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/3947622115007759929/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=3947622115007759929' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/3947622115007759929'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/3947622115007759929'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2009/07/hadoop-javaioioexception-type-mismatch.html' title='Hadoop: java.io.IOException: Type mismatch in key from map'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-1812538594535625327</id><published>2009-07-22T06:26:00.000-07:00</published><updated>2009-07-22T06:32:27.523-07:00</updated><title type='text'>Finding a java class in a Jar file (or a set of files)</title><content type='html'>Often classpath problems are hard to diagnose.  Sometimes you pick up an errant class on the classpath that conflicts with a version of the class that you need.  (Very evil people sometimes rip apart jars and package all of their dependent classes together in a single jar)&lt;br /&gt;&lt;br /&gt;Any who, however it happens, it is sometimes necessary to get a list of all classes everywhere, in all jar files.  Then you can search that list for duplicate instances of a class.&lt;br /&gt;&lt;br /&gt;I can't tell you how many times I've used this trick, especially with the sometimes unclear world of what is packaged into the JDK, application server, and what is in the actual application.&lt;br /&gt;&lt;br /&gt;Use this:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;find . -name '*.jar' -exec unzip -l {} \; &gt; all_classes.txt&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;That line finds all the jar files recursively from the current working directory, lists the contents of the archive, and pipes that output to a text file that can be searched.&lt;br /&gt;&lt;br /&gt;handy voodoo.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-1812538594535625327?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/1812538594535625327/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=1812538594535625327' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/1812538594535625327'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/1812538594535625327'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2009/07/finding-java-class-in-jar-file-or-set.html' title='Finding a java class in a Jar file (or a set of files)'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-7487089285768529937</id><published>2009-07-19T22:03:00.000-07:00</published><updated>2009-07-19T22:20:17.839-07:00</updated><title type='text'>UnsatisfiedLinkError with Surefire (on Mac OS X)</title><content type='html'>Wow, this was a needle in a hay stack.  I recently needed to use LinkGrammar on my Mac OS X, and I wanted to use it via the Java Native Interfaces (JNI).  I had been using LinkGrammar on my linux (ubuntu) boxes for some time.  So, I was no stranger to compiling it with the java support.  I even tested the compilation and install with:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;nm /usr/local/lib/liblink-grammar-java.a | grep Java&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;However, when I was running maven, I received an UnsatisfiedLinkError.  After MUCH googling I found:&lt;br /&gt;http://www.nabble.com/Trouble-with-Java-Native-Libraries-td20293666.html&lt;br /&gt;&lt;br /&gt;Simply setting the system property in maven for surefire is not sufficient, because maven changes the system property at runtime, which is too late for the VM to link to the library.  Thus you need to use the following in your build section of your pom:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;          &amp;lt;plugin&amp;gt;&lt;br /&gt;              &amp;lt;groupid&amp;gt;org.apache.maven.plugins&amp;lt;/groupid&amp;gt;&lt;br /&gt;              &amp;lt;artifactid&amp;gt;maven-surefire-plugin&amp;lt;/artifactid&amp;gt;&lt;br /&gt;              &amp;lt;configuration&amp;gt;&lt;br /&gt;                  &amp;lt;forkmode&amp;gt;once&amp;lt;/forkmode&amp;gt;&lt;br /&gt;                  &amp;lt;workingdirectory&amp;gt;target&amp;lt;/workingdirectory&amp;gt;&lt;br /&gt;                  &amp;lt;argline&amp;gt;-Djava.library.path=/usr/local/lib&amp;lt;/argline&amp;gt;&lt;br /&gt;              &amp;lt;/configuration&amp;gt;&lt;br /&gt;           &amp;lt;/plugin&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;After that, the VM will link to your libraries and surefire and all dependent tests should be able to see the java interfaces and access the necessary libraries.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-7487089285768529937?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/7487089285768529937/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=7487089285768529937' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/7487089285768529937'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/7487089285768529937'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2009/07/unsatisfiedlinkerror-with-surefire-on.html' title='UnsatisfiedLinkError with Surefire (on Mac OS X)'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-3273338712104649014</id><published>2009-07-16T21:21:00.000-07:00</published><updated>2009-07-16T21:23:41.218-07:00</updated><title type='text'>Rails Error: no such file to load -- application</title><content type='html'>I recently deployed an application I was building to production and received the following error:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;no such file to load -- application&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;It turns out that Rails changed the name of the application controller between versions.  My production environment was 2.2.2 and my development environment was 2.3.2.  Renaming the application_controller file fixed everything.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;mv app/controllers/application_controller.rb app/controllers/application.rb&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-3273338712104649014?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/3273338712104649014/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=3273338712104649014' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/3273338712104649014'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/3273338712104649014'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2009/07/rails-error-no-such-file-to-load.html' title='Rails Error: no such file to load -- application'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-2927067621733604942</id><published>2009-07-16T21:15:00.000-07:00</published><updated>2009-07-16T21:18:23.324-07:00</updated><title type='text'>Rake Production (Specifying an Environment to Rake)</title><content type='html'>I always forget how to specify an environment for rake commands. So I thought I would capture it here because, as it turns out, it is a hard thing to google.  &lt;br /&gt;&lt;code&gt;&lt;br /&gt;rake RAILS_ENV=production db:migrate&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-2927067621733604942?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/2927067621733604942/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=2927067621733604942' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/2927067621733604942'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/2927067621733604942'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2009/07/rake-production-specifying-environment.html' title='Rake Production (Specifying an Environment to Rake)'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-5677050962401923450</id><published>2009-07-16T07:28:00.001-07:00</published><updated>2009-07-16T07:31:42.137-07:00</updated><title type='text'>Exec format error (in cron)</title><content type='html'>If you are like me, you sometimes get lazy and forget to include the shell command at the top of your scripts.  This usually isn't a problem, but in certain cases (where the shell isn't set, or doesn't exist yet) it will cause problems.  So, even if your script is set to be executable (chmod +x), you'll receive an error like:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;Exec format error&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Just such a case manifests itself when using a script through cron (and run-parts).  To remedy this problem put the following at the beginning of the script:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;#!/bin/sh&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;That way, the system will know what to use when executing the script.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-5677050962401923450?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/5677050962401923450/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=5677050962401923450' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/5677050962401923450'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/5677050962401923450'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2009/07/exec-format-error-in-cron.html' title='Exec format error (in cron)'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-2206359412382428827</id><published>2009-07-15T23:16:00.000-07:00</published><updated>2009-07-15T23:17:48.815-07:00</updated><title type='text'>An Elegant Matching Algorithm In Ruby</title><content type='html'>Recently, I wanted to sit down a learn ruby (independent of rails), so I grabbed a fairly standard hacking problem and went to town on it.  I now love ruby more than ever.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The Problem:&lt;/b&gt;&lt;br /&gt;Given a set of people and a set of jobs, where each person may take a different amount of time to do each job, optimally match people to jobs (1:1) to minimize the amount of time it will take to complete all jobs.&lt;br /&gt;&lt;br /&gt;Many people will recognize this as a standard matching problem for which the &lt;a href="http://en.wikipedia.org/wiki/Hungarian_algorithm"&gt;Hungarian Algorithm&lt;/a&gt; is a known solution.  But for those that have implemented the Hungarian Algorithm (or seen implementations of it), you know well enough to steer clear.  It is error prone, and a very specific algorithm. So, I sought to implement a more elegant (and generally applicable) solution using graphs.&lt;br /&gt;&lt;br /&gt;I found this article over on topcoder describing &lt;a href="http://www.topcoder.com/tc?module=Static&amp;amp;d1=tutorials&amp;amp;d2=maxFlow"&gt; max-flow&lt;/a&gt; algorithms and the beauty of such.  I fell in love and decided that I needed to solve this with max-flow.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The formulation:&lt;/b&gt;&lt;br /&gt;Lets convert our problem to a &lt;a href="http://en.wikipedia.org/wiki/Bipartite_graph"&gt;bipartite graph&lt;/a&gt;. Let one set of nodes be the people, and the other set of nodes be the jobs.  Create an edge from each person to each job, with a weight (NOT capacity!) equal to the time it will take that person to do that job.&lt;br /&gt;&lt;br /&gt;In our situation, the capacity for each line is one since only one person can do a job. Flow is ofcourse initialized to zero for each edge (no one is doing any of the jobs). Lastly, we connect every job to a SINK node in the graph.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The philosophy and algorithm: (the important part)&lt;/b&gt;&lt;br /&gt;Essentially, we'll be finding shortest paths in the graph, from each person to the SINK (via jobs) iterating through each of the people.  On each iteration, we augment the graph with the path.&lt;br /&gt;&lt;br /&gt;To recap the topcoder article, augmenting the graph consists of incrementing the flow for each edge in the augmenting path and adjusting edges to represent the new flow/capacity.  There is an edge that represents "residual capacity" with capacity == capacity - flow, and there is an edge in the reverse direction that represents "upstream flow" with capacity == flow.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;REMEMBER, in our case:&lt;/b&gt;&lt;br /&gt;Capacity is ALWAYS 1.&lt;br /&gt;Flow is either 1 or 0.&lt;br /&gt;This is ENTIRELY independent of the cost/value/weight of an edge.&lt;br /&gt;&lt;br /&gt;What does that mean to us you say?  Well, in our case there are only two situations, a person is assigned to a job (flow == 1), or a person is not assigned ot a job (flow == 0).  In the first case, where a person is assigned a job, there is an edge from the job to the person. During the algorithm, this edge essentially represents the path to UNDO the assignment.  In the second case, the edge simply represents the&lt;br /&gt;making that assignment.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-2206359412382428827?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/2206359412382428827/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=2206359412382428827' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/2206359412382428827'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/2206359412382428827'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2009/07/elegant-matching-algorithm-in-ruby.html' title='An Elegant Matching Algorithm In Ruby'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-3526531208835111648</id><published>2009-07-15T12:46:00.000-07:00</published><updated>2009-07-15T12:48:09.890-07:00</updated><title type='text'>String Array Initialization in Java</title><content type='html'>Just for all those out there that also find string array initialization in Java counter intuitive (especially if you are also a ruby enthusiast)...&lt;br /&gt;&lt;br /&gt;To initialize an array in Java, the syntax is&lt;br /&gt;&lt;br /&gt;String[] foo = {"bar", "serf", "doodle"};&lt;br /&gt;&lt;br /&gt;The key is the curlies. =)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-3526531208835111648?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/3526531208835111648/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=3526531208835111648' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/3526531208835111648'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/3526531208835111648'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2009/07/string-array-initialization-in-java.html' title='String Array Initialization in Java'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-8121383066302930316</id><published>2009-07-15T08:02:00.000-07:00</published><updated>2009-07-15T08:03:33.615-07:00</updated><title type='text'>initializationError0 in JUNit</title><content type='html'>If you end up with a initializationError0 error coming out of JUnit, it is because the JUnit engine can't invoke your test method.  Most likely this is because the method you annotated as a test takes a parameter.  Simply remove the parameter, and you should be all set.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-8121383066302930316?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/8121383066302930316/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=8121383066302930316' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/8121383066302930316'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/8121383066302930316'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2009/07/initializationerror0-in-junit.html' title='initializationError0 in JUNit'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-4215184111928004930</id><published>2009-07-13T09:23:00.000-07:00</published><updated>2009-07-13T09:28:46.017-07:00</updated><title type='text'>RSync for Backup over SSH using Different Port Number  and Bandwidth Limit</title><content type='html'>Over the years, I've come to love rsync for offsite backups.  It is incredibly flexible and can run over SSH.  Here is the most flexible one-line backup you'll ever see:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;rsync --bwlimit=100 --partial --progress --size-only -av "/Volumes/Shed/stuff/" --rsh='ssh -p 2828' "foo@offsitebackup.com:/home/stuff/"&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;This backups my local stuff (in /Volumes/Shed/stuff) and puts it in /home/stuff on offsitebackup.com.  It also keeps partially transferred files (--partial) and shows progress (--progress).  When comparing two files, it only considers the sizes (--size-only). I do this because dates could be different.  Furthermore, it transfers using ssh, but over a different port (2828 in this case).  Finally, I limit the bandwidth that the rsync consumers (--bwlimit) to 100 kb/s.  &lt;br /&gt;&lt;br /&gt;Very handy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-4215184111928004930?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/4215184111928004930/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=4215184111928004930' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/4215184111928004930'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/4215184111928004930'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2009/07/rsync-for-backup-over-ssh-using.html' title='RSync for Backup over SSH using Different Port Number  and Bandwidth Limit'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-2476125068907564772</id><published>2009-07-01T13:10:00.000-07:00</published><updated>2009-07-01T13:13:12.504-07:00</updated><title type='text'>JDBC to MySQL Datetime (Time truncated)</title><content type='html'>Be careful when accessing Datetime fields in a MySQL database through JDBC.  You might think that the java.sql.Date would work, but that actually truncates the Date back to midnight.  In order to access the actual time, use getTimestamp() instead.  Here is the code:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;        Result rs = ...&lt;br /&gt;        while (rs.next()) {&lt;br /&gt;          return rs.getTimestamp(1).getTime();&lt;br /&gt;        }&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-2476125068907564772?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/2476125068907564772/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=2476125068907564772' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/2476125068907564772'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/2476125068907564772'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2009/07/jdbc-to-mysql-datetime-time-truncated.html' title='JDBC to MySQL Datetime (Time truncated)'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-2763771697477919748</id><published>2009-07-01T08:20:00.000-07:00</published><updated>2009-07-01T08:21:41.580-07:00</updated><title type='text'>Sorting list of FIles in Java (returned from listFiles)</title><content type='html'>Here is some handy code to get files in order...&lt;br /&gt;&lt;code&gt;&lt;br /&gt;        File[] files = dir.listFiles();&lt;br /&gt;        Arrays.sort(files, new Comparator&lt;File&gt;() {&lt;br /&gt;            public int compare(File f1, File f2) {&lt;br /&gt;                return f1.getName().compareTo(f2.getName());&lt;br /&gt;            }&lt;br /&gt;        });&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-2763771697477919748?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/2763771697477919748/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=2763771697477919748' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/2763771697477919748'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/2763771697477919748'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2009/07/sorting-list-of-files-in-java-returned.html' title='Sorting list of FIles in Java (returned from listFiles)'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-6949261660092618275</id><published>2009-06-30T11:32:00.001-07:00</published><updated>2009-06-30T11:35:48.038-07:00</updated><title type='text'>Vim syntax highlighting on Ubuntu</title><content type='html'>To get vim syntax highlighting:&lt;br /&gt;&lt;br /&gt;First, make sure you have vim installed in addition to plain old vi.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;sudo apt-get install vim&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Then, create a vimrc dot file.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;vim ~/.vimrc&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;In that file, add the following:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;:syntax on&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Thats it!  Next time you edit a file in vim, you should have syntax highlighting.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-6949261660092618275?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/6949261660092618275/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=6949261660092618275' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/6949261660092618275'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/6949261660092618275'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2009/06/vim-syntax-highlighting-on-ubuntu.html' title='Vim syntax highlighting on Ubuntu'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-261118509824407011</id><published>2009-06-24T10:48:00.000-07:00</published><updated>2009-06-24T11:07:57.391-07:00</updated><title type='text'>Pidgin (and Adium) not connecting to Yahoo</title><content type='html'>OK, I entered a phase where my yahoo login started failing in Pidgin with Ubuntu.  I first went in through my.yahoo.com and reactivated my account.  It turns out that yahoo turns off your account if you don't login for a few years. =)&lt;br /&gt;&lt;br /&gt;After that, it was a problem with the underlying libraries underneath both Pidgin and Adium.  On Mac, I updated to the latest version of Adium (1.3.5) and that fixed it.&lt;br /&gt;&lt;br /&gt;On ubuntu, it turns out that ubuntu won't update to new versions unless their is a security problem.  In order to get functional enhancements, you need to upgrade using pidgin's instructions here:&lt;br /&gt;&lt;a href="http://www.pidgin.im/download/ubuntu/"&gt;http://www.pidgin.im/download/ubuntu/&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;After you enter those two commands, start update manager and you should be able to upgrade pidgin.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-261118509824407011?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/261118509824407011/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=261118509824407011' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/261118509824407011'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/261118509824407011'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2009/06/piding-and-adium-not-connecting-to.html' title='Pidgin (and Adium) not connecting to Yahoo'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-3575346733118526022</id><published>2009-06-18T19:00:00.000-07:00</published><updated>2009-06-18T19:08:02.484-07:00</updated><title type='text'>attachment_fu: No thumbnail generation (make sure you have a parent_id!)</title><content type='html'>I've been using attachment_fu to upload images in a rails application.  Everything was working well except the thumbnails weren't generating.  I think everyone follow's Mike Clark's excellent blog:&lt;br /&gt;&lt;a href="http://clarkware.com/cgi/blosxom/2007/02/24"&gt;http://clarkware.com/cgi/blosxom/2007/02/24&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;He doesn't mention that the parent_id is required, so I thought it was simply the id of the model to which the photo/upload was attached.&lt;br /&gt;&lt;br /&gt;After some digging, I found a conversation here:&lt;br /&gt;&lt;a href="http://www.ruby-forum.com/topic/104213"&gt;http://www.ruby-forum.com/topic/104213&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Turns out attachment_fu, creates a new entry for each thumbnail, then strings them together with the parent_id.  So, make sure you keep the parent_id column otherwise attachment_fu silently fails to generate the thumbnails.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-3575346733118526022?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/3575346733118526022/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=3575346733118526022' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/3575346733118526022'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/3575346733118526022'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2009/06/attachmentfu-no-thumbnail-generation.html' title='attachment_fu: No thumbnail generation (make sure you have a parent_id!)'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-6742203123349744468</id><published>2009-06-17T07:43:00.000-07:00</published><updated>2009-06-17T08:56:21.768-07:00</updated><title type='text'>LDAP/Active Directory Authentication with Apache</title><content type='html'>Alright, it took a few hours to get all the parameters correct, but we finally achieve centralized authentication by linking apache authentication to our ActiveDirectory.  The critical concept to keep in mind when doing it is that there are two things you need to specify.  First, you need to specify the user that apache will connect as, known as the "BindDN".  Second, you need to specify the query string that allows apache to locate a user in the directory.  This is the LDAP url.&lt;br /&gt;&lt;br /&gt;In the end, this is the element we needed to add to our apache config. On ubuntu, we dropped this into the site-specific configuration file in /etc/apache2/sites-available.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt; &amp;lt;Location /&amp;gt;&lt;br /&gt;        AuthBasicProvider ldap&lt;br /&gt;        AuthType Basic&lt;br /&gt;        AuthzLDAPAuthoritative off&lt;br /&gt;        AuthName "Portal"&lt;br /&gt;        AuthLDAPURL "ldap://actrivedirectorymachine/DC=foo,DC=com?sAMAccountName?sub?" &lt;br /&gt;        AuthLDAPBindDN "CN=apache,CN=Users,DC=foo,DC=com"&lt;br /&gt;        AuthLDAPBindPassword "PASSWORD"&lt;br /&gt;        require valid-user&lt;br /&gt;  &amp;lt;/Location&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;In the above example, I created a user specifically for apache, with password PASSWORD.  I highly recommend using JXplorer to verify your bind credentials.  &lt;br /&gt;&lt;br /&gt;When configuring JXplorer, if you are using ActiveDirectory, most likely you'll need a Base DN as well.  This was "DC=foo,DC=com".  The user name is the exact string from above, same with password.&lt;br /&gt;&lt;br /&gt;The AuthLDAPURL is a query that will be used to grab the entry associated with the username that the user types in when prompted by the browser.  In the example above, it will search within DC=foo,DC=com against the attribute "sAMAccountName".&lt;br /&gt;&lt;br /&gt;I hope this helps people out.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-6742203123349744468?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/6742203123349744468/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=6742203123349744468' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/6742203123349744468'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/6742203123349744468'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2009/06/ldapactive-directory-authentication.html' title='LDAP/Active Directory Authentication with Apache'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-8711930722799604402</id><published>2009-06-14T19:38:00.000-07:00</published><updated>2009-06-14T19:44:12.838-07:00</updated><title type='text'>git installation on Mac OSX (to fix undefined method acts_as_mappable)</title><content type='html'>I recently started playing around with geokit within rails.  I kept getting an "undefined method `acts_as_mappable'" error.  It turns out that the script/plugin command for the installation of the geokit-rails plugin was silently failing.  When I entered the script/plugin install command, the command would run and not output anything to the screen.  I ended up with an empty vendor/plugins directory.&lt;br /&gt;&lt;br /&gt;The root cause ended up being:&lt;br /&gt;&lt;br /&gt;I didn't have git installed and on my path.  So, I installed it first using this:&lt;br /&gt;http://code.google.com/p/git-osx-installer/&lt;br /&gt;&lt;br /&gt;And added /usr/local/git/bin to my path.&lt;br /&gt;&lt;br /&gt;(Then later I installed git via ports.)&lt;br /&gt;&lt;br /&gt;When I returned to the rails app and re-entered:&lt;br /&gt;script/plugin install git://github.com/andre/geokit-rails.git&lt;br /&gt;&lt;br /&gt;All worked properly.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-8711930722799604402?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/8711930722799604402/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=8711930722799604402' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/8711930722799604402'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/8711930722799604402'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2009/06/git-installation-on-mac-osx-to-fix.html' title='git installation on Mac OSX (to fix undefined method acts_as_mappable)'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-5432860776150845182</id><published>2009-06-05T08:55:00.000-07:00</published><updated>2009-06-05T08:57:24.255-07:00</updated><title type='text'>WMV to FLV Conversion and Thumbnail Generation</title><content type='html'>Here are two handy command lines for converting WMV to FLV (which is a better format for hosted video), and generating thumbnails for those videos. Both use ffmpeg.&lt;br /&gt;&lt;br /&gt;To convert from wmv to flv:&lt;br /&gt;ffmpeg -i test_video_clip.wmv -ab 48 -ar 22050 -s 512x384 -g 50 -qblur 1 -pass 1 -b 800 -r 25 -y encodedvideo.flv&lt;br /&gt;&lt;br /&gt;To generate the thumbnail:&lt;br /&gt;ffmpeg -i test_video_clip.flv -an -ss 00:00:03 -an -r 1 -vframes 1 -y %d.jpg&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-5432860776150845182?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/5432860776150845182/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=5432860776150845182' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/5432860776150845182'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/5432860776150845182'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2009/06/wmv-to-flv-conversion-and-thumbnail.html' title='WMV to FLV Conversion and Thumbnail Generation'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-7684569484284430604</id><published>2009-05-12T19:52:00.000-07:00</published><updated>2009-05-12T19:58:16.183-07:00</updated><title type='text'>Eclipse on Mac OS X</title><content type='html'>I don't know why Java support is so bad on Mac OS X.  If you want to run Eclipse on Mac you may need to finagle it a bit.  When I first tried to run Eclipse, I go the following error:&lt;br /&gt;_NSJVMLoadLibrary: NSAddLibrary failed for /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Libraries/libjvm.dylib&lt;br /&gt;&lt;br /&gt;To fix this, I first followed this blog post:&lt;br /&gt;http://blog.kischuk.com/2008/05/08/running-eclipse-on-macbooks-with-java-6/&lt;br /&gt;&lt;br /&gt;But, unfortunately I didn't have 1.5.0 installed.  After a lot of googling, I found that Update 4 (available to registered developers through ADC) includes JDK 1.5.0&lt;br /&gt;&lt;br /&gt;So, if you are having trouble getting Eclipse running, install Java for Mac OS X Update 4.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-7684569484284430604?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/7684569484284430604/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=7684569484284430604' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/7684569484284430604'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/7684569484284430604'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2009/05/eclipse-on-mac-os-x.html' title='Eclipse on Mac OS X'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-7211545709380196161</id><published>2009-04-29T06:49:00.000-07:00</published><updated>2009-04-29T06:51:55.933-07:00</updated><title type='text'>Invalid Arguments 501 5.5.4 Error when sending SMTP email through exchange</title><content type='html'>OK, I recently needed to do a quick and dirty mail send from java using an exchange server.  I kept getting a 501 5.5.4 error back, which is Invalid Arguments to the RSET method.  It turns out, when looking at the example: &lt;br /&gt;http://snippets.dzone.com/posts/show/3328&lt;br /&gt;&lt;br /&gt;I had neglected to set the submitter properly.  When googling, all of the discussions were around trailing dots or spaces.  After wiresharking it, I finally saw the problem.&lt;br /&gt;&lt;br /&gt;Word to the wise, make sure when you are using AUTH with SMTP to set the submitter properly.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-7211545709380196161?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/7211545709380196161/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=7211545709380196161' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/7211545709380196161'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/7211545709380196161'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2009/04/invalid-arguments-501-554-error-when.html' title='Invalid Arguments 501 5.5.4 Error when sending SMTP email through exchange'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-3867669030865117607</id><published>2009-04-21T09:40:00.000-07:00</published><updated>2009-04-21T09:45:12.697-07:00</updated><title type='text'>Vanilla Discussion Forum : Initial Login Problems</title><content type='html'>In the past I've been a big phpBB fan, but recently I've wanted a leaner meaner discussion forum for integration into an existing site/application.  I stumbled upon Vanilla.&lt;br /&gt;&lt;br /&gt;http://getvanilla.com/&lt;br /&gt;&lt;br /&gt;So far, I'm a big fan.  I did have some trouble getting setup though.  When installing, you set the COOKIE_DOMAIN, which php then uses to store your cookie.  This needs to match the url through which you are accessing the site.  If it does not, the authentication will work but you will not be signed in.  In other words, if you type in the wrong password you will be rejected.  If you type in the correct password you will be forwarded to the main page, but you will still see the option to sign in up in the top right hand corner.&lt;br /&gt;&lt;br /&gt;Specifically this will happen if you have it deployed locally and access it using "localhost".  In this case, simply map your deployment domain to your local IP address in your /etc/hosts file.&lt;br /&gt;&lt;br /&gt;Also make sure your conf/settings.php contains the correct domain.  I searched for localhost in that file and made sure all were changed to be the deployment domain.&lt;br /&gt;&lt;br /&gt;I hope this helps anyone trying to get started with Vanilla.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-3867669030865117607?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/3867669030865117607/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=3867669030865117607' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/3867669030865117607'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/3867669030865117607'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2009/04/vanilla-discussion-forum-initial-login.html' title='Vanilla Discussion Forum : Initial Login Problems'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-3451833159057439356</id><published>2009-04-15T08:38:00.000-07:00</published><updated>2009-04-17T08:41:44.197-07:00</updated><title type='text'>Building a REST Service in PHP</title><content type='html'>OK, I'm a big fan of using the right tool for the job.  Daily I switch between Rails, Java and PHP.  Rails is probably the easiest to use for developing a REST Service, but sometimes you don't want the overhead of a rails server and you want that feel good all over sense of stability that LAMP gives you.&lt;br /&gt;&lt;br /&gt;First, I created an alias to send all requests to a single php file (service.php).&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; AliasMatch /Beers/.* /var/www/www.liquidmirth.com/service.php&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This sends all http://www.liquidmirth.com/Beers/* requests to service.php.  Then, I created a generic service class.  This grabs the method, id and the target object from the url, and uses reflection to invoke the appropriate method on a service class. The code for the service.php class is below.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;   include 'beer.php';&lt;br /&gt;   header('Content-Type: text/xml');&lt;br /&gt;   $method = strtolower($_SERVER["REQUEST_METHOD"]);&lt;br /&gt;   $object = $_SERVER["REQUEST_URI"];&lt;br /&gt;   $object = substr($object, 1, strlen($object)-1);&lt;br /&gt;   $vars = explode("/", $object);&lt;br /&gt;   $object = $vars[0];&lt;br /&gt;   $id = $vars[1];&lt;br /&gt;   // echo "method ==&gt; (".$method.")&lt;br/&gt;";&lt;br /&gt;   // echo "object ==&gt; (".$object.")&lt;br/&gt;";&lt;br /&gt;   // echo "id ==&gt; (".$id.")";&lt;br /&gt;   $method = new ReflectionMethod($object, $method);&lt;br /&gt;   echo $method-&gt;invoke(NULL, $id);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In the above code, the request is received, the Beer object is created and the get() method is invoked on that object with the id supplied as a parameter.  So, when http://www.liquidmirth.com/Beer/1234 is requested.  Beer-&gt;get(1234) is invoked.&lt;br /&gt;&lt;br /&gt;Its that simple.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-3451833159057439356?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/3451833159057439356/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=3451833159057439356' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/3451833159057439356'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/3451833159057439356'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2009/04/building-rest-service-in-php.html' title='Building a REST Service in PHP'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-2085175951728220029</id><published>2009-04-08T08:26:00.000-07:00</published><updated>2009-04-08T08:30:11.213-07:00</updated><title type='text'>Fixing Sendmail (dead.letter issue)</title><content type='html'>OK, we have lots of machines that we host out on slicehost.  We want them to be part of our domain (foo.ourdomain.com).  So, we configure their hostname to be that.  Unfortunately, we want them to be able to send mail to people in our domain (john@ourdomain.com).  Since the machine thinks it is part of the domain, it looks for that user, can't find them and consequently fails to send the mail out.&lt;br /&gt;&lt;br /&gt;Testing sendmail, it always drops the mail into dead.letter immediately.&lt;br /&gt;&lt;br /&gt;To fix this, I simply edited /etc/mail/sendmail.cf and uncommented the domain, setting it to some fictitious name (since the machine won't be the destination for any mail.&lt;br /&gt;&lt;br /&gt;I uncommented this line:&lt;br /&gt;Dj$w.Foo.COM&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-2085175951728220029?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/2085175951728220029/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=2085175951728220029' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/2085175951728220029'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/2085175951728220029'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2009/04/fixing-sendmail-deadletter-issue.html' title='Fixing Sendmail (dead.letter issue)'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-2300342238180671613</id><published>2009-01-05T09:03:00.000-08:00</published><updated>2009-01-05T09:04:17.703-08:00</updated><title type='text'>Linux System Information</title><content type='html'>Presently we are building an inhouse compute cloud, which means admining a bunch of machines.  To get quick information on the compute power of a machine look in:&lt;br /&gt;&lt;br /&gt;/proc/meminfo&lt;br /&gt;/proc/cpuinfo&lt;br /&gt;/etc/issue (since these are ubuntu machines)&lt;br /&gt;and a df-k for disk space.&lt;br /&gt;&lt;br /&gt;-brian&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-2300342238180671613?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/2300342238180671613/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=2300342238180671613' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/2300342238180671613'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/2300342238180671613'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2009/01/linux-system-information.html' title='Linux System Information'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-2601239993573478374</id><published>2008-11-03T06:36:00.001-08:00</published><updated>2008-12-16T19:01:07.025-08:00</updated><title type='text'>Installing Rails on Linux (Ubuntu)</title><content type='html'>I intend to start using this blog more for notes that might be useful for other people. &lt;br /&gt;&lt;br /&gt;Recipe for RoR on Ubuntu:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;sudo apt-get install ruby&lt;br /&gt;sudo apt-get install rubygems&lt;br /&gt;sudo apt-get install irb&lt;br /&gt;sudo apt-get install ri rdoc ruby1.8-dev build-essential&lt;br /&gt;sudo gem install rails --include-dependencies --remote&lt;br /&gt;sudo apt-get install libmysql-ruby&lt;br /&gt;sudo gem install activerecord-sqlserver-adapter --source=http://gems.rubyonrails.org &lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-2601239993573478374?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/2601239993573478374/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=2601239993573478374' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/2601239993573478374'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/2601239993573478374'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2008/11/installing-rails-on-linux-ubuntu.html' title='Installing Rails on Linux (Ubuntu)'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-7207260408357087492</id><published>2008-03-03T09:35:00.003-08:00</published><updated>2008-03-03T09:36:31.380-08:00</updated><title type='text'>Is J2EE Dead?</title><content type='html'>I recently presented at the &lt;a href="http://www.phillyjug.org/"&gt; Philly JUG&lt;/a&gt;.  In &lt;a href="http://phillyjug.jsync.com/meetings/2010-an-acronym-odyssey-by-brian-oneill"&gt; my presentation &lt;/a&gt;, I asked the question, "Is J2EE dead?", half-kidding, but mostly serious.&lt;br /&gt;&lt;br /&gt;I've spent the last six months developing in Ruby (some on Rails). It quickly went from just a past time, where I was developing a silly little beer review site called &lt;a href="http://www.liquidmirth.com"&gt;liquidMirth&lt;/a&gt; to serious business applications (at the day job: &lt;a href="http://www.rvooz.org"&gt; rVooz&lt;/a&gt;).  And now I have to admit, the compile, build, deploy cycle of a standard J2EE application seems unbelievably daunting. Combine that with the cumbersome and seemingly never ending twiddling of meta-data and deployment descriptor files required by the libraries and frameworks (e.g. Spring &amp; Hibernate) that are supposedly helping the problem and you have an incredibly unproductive environment for web application development.  &lt;br /&gt;&lt;br /&gt;I'd emphasize that this is unproductive for &lt;b&gt;web applications&lt;/b&gt;, because web applications need to be especially responsive to user requirements.  J2EE simply isn't agile enough.  There is a &lt;a href="http://gforgeek.blogspot.com/2006/03/better-web-application-development.html"&gt;&lt;br /&gt;fantastic video&lt;/a&gt; by someone out at NASA JPL that does a fantastic job comparing the latest web application development frameworks.  He does a great job emphasizing this point.&lt;br /&gt;&lt;br /&gt;Now, all that said, J2EE != Java and Java's present sweet spot is in SOA, and business process integration, where things need to be transactional, and message-oriented/event-driven.  Web frameworks are having trouble in that area, where things don't fit into a nice request/response interaction.  On the "back-end" you need a bit more rigor, and typically you need to integrate with systems that won't conform to convention.&lt;br /&gt;&lt;br /&gt;So, IMHO -- let more flexible languages accommodate the fickle nature of users.  Use Java, with specifications like JBI and SCA,  to implement an ESB on the back-end to do the heavy business process lifting, systems integration, and B2B style interactions.  &lt;br /&gt;&lt;br /&gt;And if you do that, you'll quickly realize that you don't need much (if any) of the J2EE spec to get-r-done. Instead, OpenESB in J2SE, ServiceMix, or Mule fill the bill quite nicely.&lt;br /&gt;&lt;br /&gt;just two cents.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-7207260408357087492?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/7207260408357087492/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=7207260408357087492' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/7207260408357087492'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/7207260408357087492'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2008/03/is-j2ee-dead.html' title='Is J2EE Dead?'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-3179420453755928193</id><published>2007-12-06T07:11:00.000-08:00</published><updated>2007-12-06T07:12:47.876-08:00</updated><title type='text'>Philly Emerging Technologies Event: Call for Papers</title><content type='html'>I'm Philly born and bred.   And aside from cheesesteaks and soft pretzels, the &lt;a href="http://www.phillyemergingtech.com/"&gt;Emerging Technologies Event (ETE)&lt;/a&gt; is one of the best things associated with the city of brotherly love.  &lt;a href="http://www.chariotsolutions.com"&gt; Chariot Solutions&lt;/a&gt; organizes this event annually and this year looks to be better than ever.&lt;br /&gt;&lt;br /&gt;ETE looks to have a block buster lineup covering the latest lightweight/agile development frameworks, web 2.0 concepts, java and ruby/rails. ETE has both business and technical tracks.  So, there is something for everyone.  If you would like to be part of this event, the &lt;a href="http://www.phillyemergingtech.com/call.php"&gt; call for papers&lt;/a&gt; just went out.&lt;br /&gt;&lt;br /&gt;Come hang out and while your here grab a cheesesteak and soft pretzel. ;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-3179420453755928193?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/3179420453755928193/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=3179420453755928193' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/3179420453755928193'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/3179420453755928193'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2007/12/philly-emerging-technologies-event-call.html' title='Philly Emerging Technologies Event: Call for Papers'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-937994490749401294</id><published>2007-09-06T10:24:00.000-07:00</published><updated>2007-09-06T10:27:07.247-07:00</updated><title type='text'>ESBs: the value of indoor plumbing, public water and sewer</title><content type='html'>&lt;p&gt;I just saw &lt;a href="http://blogs.zdnet.com/service-oriented/?p=945"&gt; Joe McKendrick's entry&lt;/a&gt; on the value of an ESB.  Although I appreciate his comments, and even agree with some of his points, I don't come to the same conclusions.&lt;/p&gt;&lt;p&gt;There are two things that drive common understanding: shared experiences, and common problems.  The wide acceptance of ESBs is driven by common experiences trying to implement SOA on a large scale with disparate organizations involved.&lt;/p&gt;Without an ESB, the product of such situations is often a fragile, tightly coupled, tangled web of services that is nearly impossible to change, or even reason about -- this causes a lot of pain that motivates people to consider alternative approaches. (This is often the architectural equivalent of burning your hand on the stove -- something you don't do twice =)&lt;br /&gt;&lt;p&gt;Now, this is not to say that ESBs for the sake of ESBs is a good idea.  Often, organizational boundaries can be used as a good litmus test when deciding whether or not to use an ESB, but consider "organizational boundaries" in the more broad sense of the term.  This is more than just the end-consumers/producers involved (e.g. trading partners). It takes into account the vendors supplying and integrating the functional components (infrastructure) of the system.  For example, if you're authentication &amp; authorization components are coming from a different vendor than your service stack; you have an organizational boundary you probably want to consider.&lt;/p&gt;&lt;p&gt;Thus, if your scope is small enough, and you are getting all of your infrastructure from the same vendor (and plan to continue to do so), ESBs may not be worth it.&lt;/p&gt;&lt;p&gt;Joe was actually just reacting to an &lt;a href="http://www.ibm.com/developerworks/webservices/library/ws-soa-esbarch/index.html?ca=drs-"&gt; article by Bobby Woolf&lt;/a&gt;, which has some good insights in it...&lt;br /&gt;"The problem is this: An ESB by itself produces no business value. An ESB is a means to an end, not the end itself. An ESB is like the electrical wiring or plumbing of an SOA. Plumbing does not produce value; sinks with water coming out of their faucets do."&lt;/p&gt;&lt;p&gt;I completely agree with Bobby's statement and just (IMHO) believe Joe made an incorrect inference.&lt;/p&gt;&lt;p&gt; Faucets and toilets deliver the value, but the pipes are not to be overlooked.  Lets all face it, if it wasn't for plumbing we'd all still be sh*tting in outhouses.  There *is* value in being able to connect a Moen faucet to any well pump, and being able to inject a UV-filter and water softener into the line without disturbing either the faucet or the pump; plumbing enables that.  If we take another step back, there is value in being able to then hook into a public sewer system eliminating the need for everyone to install their own septic system. &lt;/p&gt;&lt;br /&gt;A real world example of this can be found in &lt;a href="http://gallemore.blogspot.com/2007/08/bridging-gap-xmpp-to-sip-group-chat.html"&gt;Chad's SIP to XMPP tutorial&lt;/a&gt;.  He was able to build that capability without coding because he used a JBI-based ESB approach.  In this example, the two networks (SIP &amp;amp; XMPP) had "plumbing interfaces", and BPEL could be used as the manifold to connect them.  Consider that Chad could have quickly and easily also added security "in-line" as well that ask the question "Is Alice authorized to talk to Bob?".  These kinds of things are difficult to do without a standards-based, orchestratable messaging and transformation infrastructure (i.e. an ESB).&lt;br /&gt;&lt;p&gt; So, although plumbing might not be worth it for everyone, I for one don't like having to walk outside to relieve myself -- especially in the dead of winter. =) &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-937994490749401294?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/937994490749401294/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=937994490749401294' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/937994490749401294'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/937994490749401294'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2007/09/esbs-value-of-indoor-plumbing-public.html' title='ESBs: the value of indoor plumbing, public water and sewer'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-7884109759926613430</id><published>2007-08-24T07:57:00.000-07:00</published><updated>2007-08-24T08:00:03.005-07:00</updated><title type='text'>An Open Technology Manifesto</title><content type='html'>&lt;p&gt;Many people have read &lt;a href="http://steve-yegge.blogspot.com/2006/09/good-agile-bad-agile_27.html"&gt; Stevey's post&lt;/a&gt;. where he contrasts agile with Agile.  Stevey does a great job of separating out the important "agile" &lt;a href="http://agilemanifesto.org/"&gt; value system &lt;/a&gt; from the methodologies and processes of "Agile" that were created to help the masses implement it. &lt;/p&gt;Because in fact, it is in the implementation of agile that the values sometimes get lost.  Ive' seen Agile often bundled with Extreme Programming tactics (Test-Driven Development, Paired Programming, etc.). which muddied the waters and resulted in teams claiming "agility" simply because they have junit tests.  When people focus on processes, tools and methodologies too much, they can't see the &lt;a href="http://esl.about.com/library/glossary/bldef_130.htm"&gt;forest for the trees&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Likewise, I believe we need a similar separation between values and implementation in "open development". In the details of the implementation, there are decisions about licensing (GPL or Apache?), and community (Java.Net or Sourceforge?).  These can be argued just like people argue over the details of Scrum vs. Lean Devlopment vs. RUP.  But in the end, "open development" manifests itself more so within the attitudes of the team members, than in the implementation decisions -- just like "agile".&lt;br /&gt;&lt;br /&gt;Thus, humbly, I'd like to propose just such a manifesto:&lt;br /&gt;&lt;br /&gt;We are uncovering better ways of developing software by doing it and helping others do it.&lt;br /&gt;&lt;p&gt;Through this work we have come to value:&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Open discussion over closed "white-paper" analysis. &lt;/li&gt; &lt;li&gt;Collaborative contributions to existing efforts over proprietary (re)invention. &lt;/li&gt; &lt;li&gt;Open sharing of experiences over knowledge hording.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;These combine with an overarching desire to commoditize the lower-level functions of the software stack, allowing all software development (and service-delivery) to focus on ever harder more valuable problems.&lt;/p&gt;&lt;p&gt;Enlightened developers often embrace the above values without knowing it, just like many of the same are inherently agile (in the "move fast and react fast sense of the term"). Others operate with a very closed mentality,  despite the fact that sometimes they've "open sourced" their code.&lt;/p&gt;&lt;p&gt;For example, we often see "white-paper" analysis performed by the evil genius architects that lock themselves in a room with their crystal ball, carefully considering all options, finally emerging with an architecture that accounts for all the requirements, *and* all of the unforeseen changes to come (notice the paradox).  Meanwhile, the enlightened developer has spent the same time discussing the options on a mailing list, effectively forcing some of the "unforeseen" changes forward in time by soliciting input from others and adopting suggestions (even if they don't directly address existing requirements).&lt;/p&gt;&lt;p&gt;Likewise, once an enlightened developer accomplishes a feat, he/she will blog about it to advance the productivity of the community at large, whilst the less enlightened will add this to their little secret bag of tricks enhancing their "job security". (the same developer goes on to prove black is white and gets himself killed in a crosswalk)&lt;/p&gt;I was in diapers when the pioneers were doing the real work on open source. So I feel presumptuous even suggesting such a manifesto and I certainly don't intend to even hint that these are novel thoughts.  I'm sure the likes of Eric Raymond and others have been espousing such values for years.  My only point (if any) is that the Agile Manifesto did a great job of distilling agile into four statements that could be internalized by all.  Open Development might be served well to do the same, separating it away from the "noisy" licensing debates discussing freedoms, and capitalism.&lt;br /&gt;&lt;br /&gt;FWIW.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-7884109759926613430?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/7884109759926613430/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=7884109759926613430' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/7884109759926613430'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/7884109759926613430'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2007/08/open-technology-manifesto.html' title='An Open Technology Manifesto'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-943334144647996643</id><published>2007-08-20T08:49:00.000-07:00</published><updated>2007-08-20T08:50:12.458-07:00</updated><title type='text'>JBI: Catch the second wave...</title><content type='html'>&lt;p&gt;If people remember back to the early days of Java EE (J2EE), there was a lot of promise, but a lot of frustration.  I still have mental scars (and a slight eye twinge) from the countless hours tracking down typos in deployment descriptors.  But, we were willing to endure the pain because there was a lot of power in the platform. &lt;/p&gt;And as a model, J2EE was solid.  Sure, there were squabbles over the value of different parts of the model (e.g. Entity Beans), but the general abstractions and approach were incredibly valuable, as evidenced by its success.  JBI is similarly positioned.&lt;br /&gt;&lt;br /&gt;However, mainstream adoption requires not just a solid design model .  Mainstream demands ease of use, immediate gratification, and passionate community support.  This is the fundamental appeal of Ruby/Rails and why J2EE struggled in the beginning.  In the beginning of J2EE, it was a week long effort to get an EJB deployed.  Meanwhile,  Rails has caught on like wild fire because it takes less than 10 minutes to get an entire n-tier application up and running.&lt;br /&gt;&lt;br /&gt;In an effort to learn from this, independent of the actual implementation communities (Apache - ServiceMix, Java.Net - OpenESB, etc.), we've created a JBI community site &lt;a href="http://www.jbizint.org/"&gt;jBIZint&lt;/a&gt;, where the various implementation communities can come together to discuss common needs that will improve a user's over all experience.  If this sounds like something you would like to be involved in, please join the  &lt;a href="http://www.jbizint.org/mailinglists.php"&gt;mailing lists&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;As an example, there are two movements afoot that will improve JBI adoption and ease of use.  The first is a movement to standardize the diagramming technique for service assemblies, and the communication between them.  Much like SCA has done, a standard diagramming technique will allow system designers to communicate effectively, the components, meta-data and communication paths of the services in the system. (Again, please join the discussion on the &lt;a href="http://www.jbizint.org/mailinglists.php"&gt;mailing lists&lt;/a&gt; to get more info)&lt;br /&gt;&lt;br /&gt;The second movement is to get an "easy-install" package management system in place akin to Debian's apt-get and maven's repositories. (credit &lt;a href="http://www.bruceblog.org/"&gt;Bruce Snyder&lt;/a&gt; for the idea).  This would make it simple to install components through tooling (e.g. Eclipse, NetBeans, or command-line).  The package management system would pull down the component and all of its dependencies (e.g. shared libraries), perhaps even a sample service unit.&lt;br /&gt;&lt;br /&gt;Combining standardized diagramming with an easy-to-use package management system should make it even easier to pick up one of the numerous "10-minute" tutorials on JBI, like &lt;a href="http://gallemore.blogspot.com/2007/06/xmpp-to-rss-demonstration.html"&gt;Chad's XMPP-RSS Demo&lt;/a&gt;, and get it up and running in 2 minutes with an understanding of how and what you did. =)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-943334144647996643?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/943334144647996643/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=943334144647996643' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/943334144647996643'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/943334144647996643'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2007/08/jbi-catch-second-wave.html' title='JBI: Catch the second wave...'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-980483127196662831</id><published>2007-07-12T11:47:00.000-07:00</published><updated>2007-07-12T11:48:37.937-07:00</updated><title type='text'>How JBI can improve your love life. (JBI for Social Networking)</title><content type='html'>&lt;p&gt;Our team just released four JBI Components, a &lt;a href="http://sip-bc.dev.java.net/"&gt; SIP BC&lt;/a&gt;, an &lt;a href="http://xmpp-bc.dev.java.net/"&gt; XMPP BC&lt;/a&gt;, an &lt;a href="http://rss-bc.dev.java.net/"&gt; RSS BC&lt;/a&gt;, and a &lt;a href="http://uddi-bc.dev.java.net/"&gt; UDDI BC &lt;/a&gt;.  Having developed those components, we're now reaping the rewards; we're able to combine these low-level collaboration "services" to produce new and cool collaboration capabilities.  Essentially, the four components together create a collaboration platform. One use for just such a platform might be a social networking application.  hmmmm...&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Lets pretend I'm looking for love (in reality, i'm &lt;a href="http://www.mindrain.com/"&gt;happily married&lt;/a&gt;, but we can pretend).  I've joined an online singles dating site and I want to write a quick application that will let me find a date. Lets call this SaaS app the lovinator.&lt;/p&gt;&lt;p&gt;First, things first --- I don't want to have to continually go to the dating site to get the information.  So, I quickly write a &lt;a href="http://wwwsearch.sourceforge.net/mechanize/"&gt;a python script to crawl the website&lt;/a&gt; looking for profiles of interest.  Once the script finds a profile, it posts the profile to the lovinator.&lt;/p&gt;&lt;p&gt;Fortunately, the lovinator is built on a JBI platform.  An HTTP BC receives the request, which contains a raw XML document that has the profile.  That XML is routed to the RSS BC via a simple BPEL process. On my desktop, I'm subscribed to the lovinator feed, and am able to view new profiles.&lt;/p&gt;&lt;p&gt;I see a particular profile that is interesting.  Now, I want to be able to see when he/she comes online. And since I'm so hip (a.k.a geekish), I have an iPhone with a &lt;a href="http://www.beejive.com/iphone/"&gt; jabber client&lt;/a&gt; installed. Lets assume the prospect's XMPP and SIP addresses are in their profile and I'm headed out of the office.  Leveraging the XMPP BC, the lovinator can subscribe to the prospect's presence information and send me an update when he/she comes online; directly to my iphone. Nice.&lt;/p&gt;&lt;p&gt; OK, so now I can peruse prospectives from my desk via RSS, and stalk them from my iphone using XMPP.  The only thing left to do is call them out of the blue. (believe me -- they love that)  Fortunately, the lovinator can do that for me; automagically.  Using the SIP BC to perform a bit of third-party call control (3PCC), the lovinator can setup a call between us. (saves me the time required to look at their number and dial the phone)&lt;/p&gt;&lt;p&gt; Now we're cooking, but where is the social networking aspect?  Well, as I said -- prospects are disseminated over RSS.  So, there is nothing to prevent others from subscribing to the same feeds.  Additionally, it would be trivial to incorporate a Java EE service engine that would allow me (via a webapp) to submit feedback about prospectives. &lt;/p&gt;&lt;p&gt; Lets say that voice conversation didn't go so well.  (e.g. I found out he/she has a dozen cats and lives with his/her mother at the age of 39... and I'm not feline fan)  I could feed that information back into the prospect's profile feed via the webapp. That would get disseminated to all those subscribed, saving other people time and energy -- or making that "special someone's" day. &lt;/p&gt;&lt;p&gt; One can imagine a ton of extensions to the lovinator.  For example once I do find that special someone, the lovinator could send me messages(via the XMPP BC) when their birthday rolls around. (anniversaries, etc) &lt;/p&gt;&lt;p&gt; A bit contrived? perhaps. But the point is that JBI creates a great, extensible, platform with new loosely coupled capabilities being added everyday that we can "wire in" easily.&lt;/p&gt;&lt;p&gt; So, the point is; we save time. &lt;/p&gt;&lt;p&gt;Estimated time to develop the lovinator? Only a few weeks. I just checked and the domain lovinator.com is available.  Any takers? =)&lt;/p&gt;&lt;p&gt;For some more realistic use cases you can check out &lt;a href="http://www.jbizint.org/wiki/index.php?title=Use_Cases"&gt; jBIZint&lt;/a&gt; where we're trying to outline the "tougher" use cases, that the spec may or may not accommodate.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-980483127196662831?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/980483127196662831/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=980483127196662831' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/980483127196662831'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/980483127196662831'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2007/07/how-jbi-can-improve-your-love-life-jbi.html' title='How JBI can improve your love life. (JBI for Social Networking)'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-381637031294291043</id><published>2007-07-12T11:46:00.001-07:00</published><updated>2007-07-12T11:47:26.272-07:00</updated><title type='text'>JBI: Application Development w/o Coding, are we there yet?</title><content type='html'>&lt;p&gt;Many people, including myself, approached JBI as a standards-based means of achieving ESB capabilities.  That was the big value proposition.  In the early stages of using it, we treated JBI like JMS on steroids.  It wasn't until later in the game, we realized the full potential of JBI.&lt;/p&gt;&lt;p&gt;And, it really boils down to knowing the &lt;a href="http://www.jbizint.org/wiki/index.php?title=Getting_Started"&gt; Fundamentals of JBI&lt;/a&gt;.  For developers like myself that have a tad bit of an attention deficit disorder, it is easy to overlook the implications of those fundamentals.  Specifically, the JBI specification had plans within plans, and &lt;b&gt;containers within containers&lt;/b&gt;.&lt;/p&gt;&lt;p&gt;The JBI run-time acts as the first level container, consuming service assemblies for deployment.  Those service assemblies contain service units which get deployed to service engines and binding components.  So, JBI components themselves act as a second-level containers for the artifacts within service units.&lt;/p&gt;&lt;p&gt;This is often misconstrued by people that believe Service Engines *implement* the business logic in an application.  This is not the case.  Instead, business logic gets *deployed* to Service Engines as part of a service unit (within an assembly).  Service Engines contain and execute the business logic, but they by themselves do not provide it.  This is tremendously important because it allows JBI to deliver, "Application Development without coding".&lt;/p&gt;&lt;p&gt;Lets look at an example, the BPEL Service Engine lets me wire together services mapping the results of one service to the inputs of another.  So, without any coding I can deploy a bpel process to the BPEL Service Engine.  Furthermore, I can connect that process to specific transports, like XMPP and SIP by simply deploying service units to the &lt;a href="http://xmpp-bc.dev.java.net/"&gt;XMPP BC&lt;/a&gt; and &lt;a href="http://sip-bc.dev.java.net/"&gt;SIP BC&lt;/a&gt; respectively.&lt;br /&gt;&lt;/p&gt;&lt;p&gt; In this situation, the BPEL SE, XMPP BC and SIP BC are acting as containers for specific business logic and "instances" of capability that could have been defined graphically in an IDE like &lt;a href="http://www.netbeans.org/"&gt;NetBeans&lt;/a&gt;.&lt;br /&gt;&lt;/p&gt;&lt;p&gt; Thus in our never ending quest to make our lives easier and leave the world of semi-colons, I believe JBI has brought us one step closer.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-381637031294291043?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/381637031294291043/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=381637031294291043' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/381637031294291043'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/381637031294291043'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2007/07/jbi-application-development-wo-coding.html' title='JBI: Application Development w/o Coding, are we there yet?'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-5238526570331300664</id><published>2007-06-27T13:56:00.000-07:00</published><updated>2007-06-27T13:57:35.697-07:00</updated><title type='text'>SCA &amp; JBI: Made for each other. (SOA Gone Wild)</title><content type='html'>&lt;p&gt;I agree with Shaun Connolly's&lt;br /&gt;&lt;a href="http://connollyshaun.blogspot.com/2007/03/sca-oasis-and-jcp.html"&gt; observation &lt;/a&gt; that "While they [JBI and SCI] may share some similar patterns, those who pit SCA vs. JBI only demonstrate their inability to distinguish between the two perspectives".  &lt;/p&gt;&lt;p&gt;In fact, we set out to prove the assertion that:&lt;br /&gt;- JBI and SCA are entirely complementary.&lt;/p&gt;And we've made quite a bit of progress by taking an example &lt;a href="http://www.jbizint.org/wiki/index.php?title=SCA"&gt; SCA composite application / contribution &lt;/a&gt; and figuring out how it &lt;a href="http://www.jbizint.org/wiki/index.php?title=SCA_translation_layer"&gt;  translates&lt;/a&gt; into a JBI runtime environment. But translation is only one example of how JBI &amp;amp; SCA may fit together.   &lt;br /&gt;&lt;br /&gt;There are actually three different relationships that make sense.  First, SCA run-times that already exist (e.g. Tuscany) could be deployed as containers within JBI by packaging them as Service Engines.  JBI would leverage the SCA Service Engine as a means of integrating SCA contributions into a JBI runtime. In this respect, JBI provides an integration backbone that would improve the utility of SCA contributions by making them available to networks, capabilities and systems for which there is no SCA component implementation. (e.g. SIP and XMPP)  Essentially, this would attach an SCA contribution to an bus architecture, with all of the benefits that comes with that.&lt;br /&gt;&lt;br /&gt;Secondly, I don't see any reason why there wouldn't be a JBI Component Implementation added to SCA's &lt;a href="http://www.osoa.org/display/Main/Service+Component+Architecture+Specifications"&gt; list&lt;/a&gt; of implementations.  This would allow an SCA contribution to declare a JBI service unit (or service assembly) as a component implementation within an SCA contribution.&lt;br /&gt;&lt;br /&gt;Lastly and most interesting, JBI can be the run-time for SCA contributions.  In this capacity, a translation layer would translate an SCA contribution into a set of service units deployed to binding components and service engines.  In this &lt;a href="http://www.jbizint.org/wiki/index.php?title=SCA_translation_layer"&gt;  example&lt;/a&gt;, each binding in the SCA composite application the would result in a service unit bound to a binding component. Likewise, for each service implementation in the SCA composite application, a service unit would be deployed to a service engine. (e.g. bpel, pojo, etc.)&lt;br /&gt;&lt;br /&gt;The translation is a tremendously powerful construct. It lets JBI deliver all of the bus-like features, life-cycle management, and administrative controls, while allowing architects to define their composite applications in SCA.&lt;br /&gt;&lt;br /&gt;We are working all of this through on &lt;a href="http://www.jbizint.org/"&gt; jBIZint &lt;/a&gt;.  If all goes well, we hope to deliver a Grand Unified Platform by the end of the year that when combined with Eclipse and/or NetBeans will directly interpret developers brainwaves into SOA. =)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-5238526570331300664?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/5238526570331300664/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=5238526570331300664' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/5238526570331300664'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/5238526570331300664'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2007/06/sca-jbi-made-for-each-other-soa-gone.html' title='SCA &amp; JBI: Made for each other. (SOA Gone Wild)'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-6627999541042326809</id><published>2007-06-27T13:55:00.000-07:00</published><updated>2007-06-27T13:56:38.121-07:00</updated><title type='text'>JBI on your cell phone?</title><content type='html'>&lt;p&gt;Despite the fact that many early JBI implementations are reusing enterprise infrastructure for their implementations (e.g. JMS messaging backbones and J2EE containers), my prediction is that JBI will start invading the mobile market.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Already, people are looking to leverage JBI implementations on small footprint platforms as a means of realizing the benefits of an "enterprise" service bus, but without the overhead of the "enterprise".  In this capacity, JBI is a great means of achieving service re-use , while maintaining loosely coupled composition.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;For example, JBI may be the best means to inject security into a mobile application.  Since JBI focuses on data flow, , a developer can just "drop in" security components, rewire the messages to first pass through an authentication and authorization engines. Without changing the app at all, it would be capable of invoking services that require digital signatures. I go through this use case &lt;a href="http://www.jbizint.org/wiki/index.php?title=Security_Interceptor"&gt; here&lt;/a&gt;.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;It is a common misconception that OpenESB is wed to NetBeans and Glassfish. This isn't the case at all.  In fact, you can follow &lt;a href="http://www.jbizint.org/wiki/index.php?title=Getting_Started-OpenESB"&gt; these instructions&lt;/a&gt; to get OpenESB up and running in a J2SE environment, with XMPP capabilities and RSS feeds!&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Lots of fun. =)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-6627999541042326809?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/6627999541042326809/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=6627999541042326809' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/6627999541042326809'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/6627999541042326809'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2007/06/jbi-on-your-cell-phone.html' title='JBI on your cell phone?'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-3660146025688957100</id><published>2007-06-27T13:51:00.000-07:00</published><updated>2007-06-27T13:52:44.413-07:00</updated><title type='text'>JBI as a Convergent Communication Platform</title><content type='html'>&lt;p&gt;I have a hard enough time keeping my mind straight as it is, maintaining multiple internet persona's only makes my life more difficult: a skype account, IRC, AOL, XMPP, Yahoo, email, PSTN, mobile, etc.  Some clients have been doing a better job of bridging the networks from a user perspective, but this does nothing for capabilities development on the server side -- and the disparity between the networks still causes user headache.&lt;br /&gt;&lt;/p&gt;For example, even using one of the multi-protocol chat clients, to coordinate a chat-room I need to get everyone to agree on a common protocol, everyone needs accounts, and everyone needs to be on the same "type of network". (ie. firewalls need to permit traffic to the agreed upon network)&lt;br /&gt;&lt;p&gt; Why? &lt;/p&gt;Because there isn't a server out there capable of maintaining presence, and location information across the multiple protocols.  Sure, there are lots of gateways being built (e.g. XMPP -&gt; SIP and back), but this results in the need for &lt;em&gt;nxn&lt;/em&gt; gateways.  Any architect will tell you that you need a common normalized schema to reduce the number of necessary conversions.  Then you only need to develop &lt;em&gt;n&lt;/em&gt; gateways, each converting from the protocol specific format into the normalized message format.&lt;br /&gt;&lt;br /&gt;Hmmmm, interesting - this sounds awfully familiar.  Enter JBI.&lt;br /&gt;&lt;br /&gt;The devil is in the details, but if we ignore them for a moment, this is exactly the concept behind binding components (BCs) and the normalized message router (NMR).  Over the past six month, we've developed binding components for &lt;a href="http://xmpp-bc.dev.java.net/"&gt; XMPP &lt;/a&gt;, &lt;a href="http://sip-bc.dev.java.net/"&gt; SIP &lt;/a&gt;, &lt;a href="http://uddi-bc.dev.java.net/"&gt; UDDI &lt;/a&gt;, and &lt;a href="http://rss-bc.dev.java.net/"&gt; RSS &lt;/a&gt;.  The purpose of each of these is to convert between normalized messages and their protocol specific equivalents.&lt;br /&gt;&lt;br /&gt;Since the BCs expose those disparate communications networks over a single "bus", this appears to be the perfect environment for convergent applications development.  Thus, you could implement a single presence service, a single locations repository, etc.  Finally, I'll be able to join a chat-room over SIP, while friends join over XMPP, with the entire conversation broadcast over RSS.&lt;br /&gt;&lt;br /&gt;Now, back to the devilish details.  In a previous life, I spent long hours working on SIP (registrar, presence and proxy) servers.  More specifically a commercial derivative of the NIST &lt;a href="http://jain-sip-presence-proxy.dev.java.net/"&gt; JAIN-SIP-Presence-Proxy &lt;/a&gt; server.  Recently we've formed a new project, &lt;a href="http://marlin.dev.java.net/"&gt; Marlin &lt;/a&gt; to attempt the very idea described in this blog, implementing the same capabilities as the JAIN-SIP-Presence-Proxy project, but independent of the protocol.&lt;br /&gt;&lt;br /&gt;We're putting use cases together &lt;a href="http://www.jbizint.org/wiki/index.php?title=Converged_Chat_Room"&gt; here &lt;/a&gt;, and &lt;a href="http://www.jbizint.org/wiki/index.php?title=June_04%2C_2007"&gt; meeting &lt;/a&gt; to determine how all of this relates to &lt;a href="http://sailfin.dev.java.net/"&gt; Sailfin &lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Its an exciting time to be in communications infrastructure. =)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-3660146025688957100?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/3660146025688957100/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=3660146025688957100' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/3660146025688957100'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/3660146025688957100'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2007/06/jbi-as-convergent-communication.html' title='JBI as a Convergent Communication Platform'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-5465313943945489412</id><published>2007-06-27T13:50:00.002-07:00</published><updated>2007-06-27T13:51:27.858-07:00</updated><title type='text'>SOA, ESB, JBI &amp; SCA: A caveman's perspective</title><content type='html'>&lt;p&gt;Software development techniques and processes are changing at ever faster rates as open collaboration development spreads globally (thanks to the adoption and promotion of open source software).  As the systems we architect and implement become increasingly complex, the mechanisms, infrastructure and patterns with which we build the complex systems constantly improve to keep the problems tractable.&lt;/p&gt;&lt;p&gt;The Java Business Integration (JBI) specification and Service Component Architecture (SCA) are the latest additions to our tool set.&lt;br /&gt;&lt;br /&gt;Now, I'm a simple man, a caveman really.  And for the last three years, I've been working to construct a multi-channel service oriented architecture for the federal government, with pluggable enterprise services (pub/sub, security/encryption, messaging, VoIP, etc.)&lt;/p&gt;As you can imagine, this is a hard problem for a caveman to solve, especially when you layer in a complicated political landscape filled with software infrastructure vendors, and their professional services divisions.  We needed an industry standard on which to hang our hat.&lt;br /&gt;&lt;p&gt;Now, most people would hang their hats on "Web Services". Those same people would probably define web services as WSDL + SOAP + HTTP + (UDDI).  They would then proceed to convert all RMI, RPC, and potentially database communication into web services: then call that a SOA.  Unfortunately, that only results in a rat's nest of invocations and derived dependencies that can bring down an entire enterprise. (we have the battle scars to prove it)&lt;/p&gt;&lt;p&gt;So, we evolved.&lt;/p&gt;&lt;p&gt;We realized that we needed a common communications backbone to unravel the mess.  Enter Enterprise Service Bus (ESB) concepts, but again we were disappointed.  We looked around for one of these new fangled ESBs, but all we found were re-applied messaging systems that required proprietary extensions to achieve a services layer.  (and we knew enough to stay away from those, and the vendor lock-in that came with them)&lt;/p&gt;&lt;p&gt;SO, we looked long and hard at the writing on the (cave) wall; and found a promising acronym: JBI.  We set about downloading JBI implementations.  Immediately, we were hooked.  JBI provided a standard interface through which we could deliver our enterprise service "lollipops".  Literally, we could drop our lollipops into existing JBI containers, rewire the connections and provide service consumers and producers with security, compression, discovery and other capabilities. Wow, nirvana.&lt;/p&gt;&lt;p&gt;In fact, as cavemen - we were more productive than ever.  We could develop applications without writing a single line of code.  Applications development became a matter of drawing pretty pictures.  Using a palette of components, and drawing lines between them, in minutes we could create new convergent capabilities - e.g. take messages from XMPP, and post them to RSS feeds.&lt;/p&gt;&lt;p&gt;But alas, nothing gold can stay.  The political landscape shifted, and SCA came down from the heavens like a meteor crashing into the earth.   We ran for cover, trying to figure out how SCA fit into our new world view.  What we had heard about SCA was promising, but we had trouble putting our fingers on it.  SCA seemed like a great language with which to communicate with other cave people, a common way to describe what we were building, and compose larger services from smaller, recursively.  This was much needed, and completely complimentary to our new found love - JBI.  As cavemen, we couldn't see where SCA dictated a run-time, but we didn't need it to.  We had JBI already.&lt;/p&gt;&lt;p&gt;Us cavemen proceeded forward with a new world understanding - determined to build a bridge demonstrating an SCA composite application, running in a JBI runtime.  &lt;/p&gt;&lt;p&gt;You can follow along at &lt;a href="http://www.jbizint.org/"&gt; jBIZint &lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-5465313943945489412?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/5465313943945489412/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=5465313943945489412' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/5465313943945489412'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/5465313943945489412'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2007/06/soa-esb-jbi-sca-cavemans-perspective.html' title='SOA, ESB, JBI &amp; SCA: A caveman&apos;s perspective'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6872023396647681597.post-7310100960452189528</id><published>2007-06-27T12:15:00.000-07:00</published><updated>2007-06-27T12:18:16.331-07:00</updated><title type='text'>Better than Java.net?</title><content type='html'>I'm just wondering if blogspot is better than java.net.  So, this is my test drive.&lt;br /&gt;Ordinarily, I have a blog over on &lt;a href="http://weblogs.java.net/blog/boneill42/"&gt;java.net&lt;/a&gt;, but I noticed some people had moved over here and wanted to see what all the hubbub was about.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6872023396647681597-7310100960452189528?l=brianoneill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://brianoneill.blogspot.com/feeds/7310100960452189528/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6872023396647681597&amp;postID=7310100960452189528' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/7310100960452189528'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6872023396647681597/posts/default/7310100960452189528'/><link rel='alternate' type='text/html' href='http://brianoneill.blogspot.com/2007/06/better-than-javanet.html' title='Better than Java.net?'/><author><name>Brian O'Neill</name><uri>https://profiles.google.com/113458686957253436912</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-cjM3v7a5sao/AAAAAAAAAAI/AAAAAAAAADc/XoksIfr-ztU/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry></feed>
