Nick Sieger: Tag warbler tag:blog.nicksieger.com,2005:Typo Typo 2007-09-04T02:48:40+00:00 Nick Sieger urn:uuid:a88e00d4-56b6-4b75-95e9-4e21e6b0387a 2007-09-04T02:48:40+00:00 2007-09-04T02:48:40+00:00 Warbler, A Little Birdie To Introduce Your Rails App To Java <p>This week I was working on integrating the latest <a href="http://www.bloglines.com/blog/ThomasEEnebo?id=35">JRuby 1.0.1</a> and <a href="http://rubyforge.org/frs/shownotes.php?release_id=14048">Goldspike 1.3</a> releases into our environment, when my frustration hit a fever pitch.</p> <p>See, I had always thought that the .war packaging side of Goldspike was a little clunky and un-ruby-like, but I didn&#8217;t see a clear path to fixing it. I had heard little complaints about it here and there: the little configuration DSL didn&#8217;t give you enough control or wasn&#8217;t documented well enough; the fact that it downloads libraries from the internet during assembly (convenient, but not safe or reproducible for production deployments).</p> <p>Also, in my own opinion it took the wrong approach to packaging Rails in a .war file. It puts the Rails application directory structure into the root of the .war file where any web server or Java application server might mistakenly serve up your code as static content. The Java .war file spec has this special directory called <code>WEB-INF</code> expressly for the purpose of hiding that stuff away, so why not use it?</p> <p>And then, suddenly Goldspike was packaging up my entire Rails application directory, .svn directories and everything. So I set out to fix this once and for all.</p> <p>And so I present <a href="http://caldersphere.rubyforge.org/warbler/">Warbler</a>. A little bird who chirpily steps up to the task of assembling your Rails application into a Java Web Archive (.war). Here, get it:</p> <pre><code>gem install warbler </code></pre> <p>And then, in the top directory of your Rails application,</p> <pre><code>warble </code></pre> <p>Those two steps are all it takes to make a .war file, including your application and recent versions of JRuby and Goldspike, that&#8217;s deployable to your <a href="https://glassfish.dev.java.net/">favorite Java application server</a>.</p> <p>There are a number of points about Warbler worth mentioning.</p> <h3>Does one thing, well</h3> <p>Warbler only packages, and doesn&#8217;t care about anything else, like how to dispatch servlet requests to Rails. This will allow for more runtime servlet binding mechanisms to take advantage of Warbler in the future.</p> <h3>Fast and lightweight</h3> <p>50% less code than the Goldspike packaging plugin, yet does the job quickly and efficiently.</p> <h3>Sane defaults</h3> <p>Warbler only packages code that you need to run the application, omitting database migrations and tests. If your application is self-sufficient (no external dependencies), then the out-of-the-box configuration will probably work for you. Public HTML/images/javascript/stylesheets go in the root of the webapp, where Java webservers expect them to be.</p> <h3>Documented, flexible configuration</h3> <p>Need to customize your configuration? Run <code>warble config</code> and edit <code>config/warble.rb</code>. All the options are there, commented and documented.</p> <p>Need to change out the bundled JRuby/Goldspike versions? <code>warble pluginize</code> makes a copy of Warbler in the <code>vendor/plugins</code> area of your application, allowing you to change the .jar files in the <code>vendor/plugins/warbler-0.9/lib</code> directory. Warbler then makes his nest in your project&#8217;s list of rake tasks (as <code>rake -T | grep war</code> shows)</p> <pre><code>rake war # Create trunk.war rake war:app # Copy all application files into the .war rake war:clean # Clean up the .war file and the staging area rake war:gems # Unpack all gems into WEB-INF/gems rake war:jar # Run the jar command to create the .war rake war:java_libs # Copy all java libraries into the .war rake war:public # Copy all public HTML files to the root of the .war rake war:webxml # Generate a web.xml file for the webapp </code></pre> <p>Warbler even omits himself in the .war file produced when running in plugin mode, since you won&#8217;t need him at runtime. It&#8217;s the little details that matter.</p> <p>Give him a try and let me know if it makes your life deploying Rails applications to JRuby on Java appservers easier!</p> Nick Sieger urn:uuid:e7399075-a1ca-4af7-b122-ede5647c4fcc 2008-07-10T05:10:27+00:00 2008-07-10T05:10:27+00:00 Blog Setup <p>The other day <a href="http://blog.nicksieger.com/articles/2008/07/06/this-blog-powered-by-glassfish-jruby-and-jruby-rack#comments">several people chimed in</a> wondering how I set up this blog with JRuby and Glassfish&#46; One of the reasons I didn&#8217;t include the details in the post is that it&#8217;s not really much different than any JRuby/Glassfish/Warbler deployment, but in case you don&#8217;t know what that looks like, here are the basics&#46;</p> <h3>Preconditions (Java)</h3> <p>I&#8217;m running on a <a href="http://joyent.com/accelerator">Joyent Accelerator</a>, which runs <a href="http://opensolaris.org/">OpenSolaris</a>, which has JDK 6 installed by default&#46; If you&#8217;re running on some flavor of Linux, hopefully <a href="https://jdk-distros.dev.java.net/">there&#8217;s a package available for you to install</a>, otherwise you may have to <a href="http://www.java.com/en/download/help/5000010500.xml">download a self&#45;extracting binary</a>&#46;</p> <h3><a href="https://glassfish.dev.java.net/downloads/v2ur2-b04.html">Install Glassfish</a></h3> <p>This step is actually straightforward; not at all as problematic as you might expect of a piece of Java technology! In the parent directory where you want Glassfish to be installed (substituting the name of the Glassfish jar you downloaded as appropriate):</p> <pre><code>java -Xmx256m -jar glassfish-installer-v2ur2-b04-sunos_x86.jar cd glassfish chmod -R +x lib/ant/bin ./lib/ant/bin/ant -f setup.xml </code></pre> <p>Start Glassfish&#46;</p> <pre><code>./bin/asadmin start-domain </code></pre> <p>You may want to add <code>GLASSFISH/bin</code> to your path so that you can run the Glassfish <code>asadmin</code> command from anywhere&#46;</p> <p>On Solaris, <a href="http://www.sun.com/bigadmin/content/selfheal/smf-quickstart.jsp">SMF</a> is the subsystem that is used to ensure services are started at boot time (among other things)&#46; Glassfish <a href="http://blogs.sun.com/bloggerkedar/entry/app_server_and_solaris_10">works nicely with SMF</a>&#46; On other systems, there may be <code>/etc/rc.d</code> init scripts out there, or you can roll your own (<code>asadmin start-domain</code> and <code>asadmin stop-domain</code>)&#46;</p> <h3>Install JRuby</h3> <p><a href="http://dist.codehaus.org/jruby/jruby-bin-1.1.2.tar.gz">Download JRuby</a> and <a href="http://wiki.jruby.org/wiki/Getting_Started">unpack it somewhere</a>&#46; I recommend adding <code>JRUBY_HOME/bin</code> to the end of your path, so it doesn&#8217;t clash with Matz&#45;Ruby&#46;</p> <h3>Install Warbler and activerecord&#45;jdbcmysql&#45;adapter</h3> <p>In addition to Warbler, I&#8217;m using the activerecord&#45;jdbcmysql&#45;adapter to connect to the blog&#8217;s database&#46; Both can be installed with Rubygems:</p> <pre><code>jruby -S gem install warbler activerecord-jdbcmysql-adapter </code></pre> <p>With Rails 2 and up, the application&#8217;s <code>config/database.yml</code> file should be updated for <code>adapter: jdbcmysql</code>:</p> <pre><code>&lt;% jdbc = defined?(JRUBY_VERSION) ? 'jdbc' : '' %&gt; development: adapter: &lt;%= jdbc %&gt;mysql encoding: utf8 database: testapp_development username: root password: socket: /tmp/mysql.sock # same for test/production... </code></pre> <p>Otherwise, you need to <a href="http://wiki.jruby.org/wiki/Running_Rails_with_ActiveRecord-JDBC">jump through some extra environment&#46;rb configuration hoops</a>&#46;</p> <h3>Configure Warbler</h3> <p>Warbler needs to be told about any gems that your application uses&#46; To generate a Warbler configuration file:</p> <pre><code>jruby -S warble config </code></pre> <p>The file is generated at <code>config/warble.rb</code>&#46; In it, modify the following sections:</p> <pre><code>config.gems = ["activerecord-jdbcmysql-adapter"] ... config.webxml.jruby.min.runtimes = 2 config.webxml.jruby.max.runtimes = 4 </code></pre> <h3>Build and deploy the &#46;war</h3> <pre><code>jruby -S warble asadmin deploy --contextroot / blog.war </code></pre> <p>(<code>--contextroot /</code> makes the application rooted at <code>/</code> in the server, rather than at <code>/blog</code> which would be the default&#46;)</p> <p>At this point, the blog application is up and running on port 8080&#46; I had previously been running the blog with an Apache/&#46;htaccess&#45;based setup reverse&#45;proxying to mongrel, so all I had to do was change the port&#46; I haven&#8217;t touched it since&#46;</p> <h3>But is this right for you?</h3> <p>Chances are, this setup is overkill for a simple blog&#46; If you&#8217;re going to try it, I&#8217;d recommend at minimum running on a VPS with at least 1G of memory&#46; But once you get the core pieces in place, updating and re&#45;deploying the application is really just as simple as the last two commands&#46; It&#8217;s mundane and boring in its simplicity&#46; But boring is good when you don&#8217;t want to worry about having to keep Mongrel running, or max out the memory in your server and make it unstable&#46;</p>