Nick Sieger: Tag jruby tag:blog.nicksieger.com,2005:Typo Typo 2010-11-22T18:03:42+00:00 Nick Sieger urn:uuid:8f70150f-ec57-4646-afaa-c3e07b6df7c3 2010-10-14T15:25:51+00:00 2010-11-22T18:03:42+00:00 activerecord-jdbc-adapter 1.0.0 <p>Just a quick note that <code>activerecord-jdbc-adapter</code> has finally hit 1&#46;0&#46;0&#46; Install it today:</p> <pre><code>gem install activerecord-jdbc-adapter </code></pre> <p>Included are adapters for <a href="http://www.mysql.com/" title="MySQL :: The world's most popular open source database">MySQL</a>, <a href="http://www.postgresql.org/" title="PostgreSQL: The world's most advanced open source database">PostgreSQL</a>, <a href="http://www.sqlite.org/" title="SQLite Home Page">SQLite3</a>, <a href="http://db.apache.org/derby/" title="Apache Derby">Derby</a>, <a href="http://hsqldb.org/" title="HSQLDB">HSQLDB</a>, <a href="http://www.h2database.com/" title="H2 Database Engine">H2</a>, and <a href="http://www.microsoft.com/sqlserver/2008/en/us/" title="SQL Server 2008 Overview, data platform, store data | Microsoft">Microsoft SQL Server</a>&#46;</p> <pre><code>gem install activerecord-jdbcmysql-adapter gem install activerecord-jdbcpostgresql-adapter gem install activerecord-jdbcsqlite3-adapter gem install activerecord-jdbcderby-adapter gem install activerecord-jdbchsqldb-adapter gem install activerecord-jdbch2-adapter gem install activerecord-jdbcmssql-adapter </code></pre> <p>You can also use <code>activerecord-jdbc-adapter</code> with Oracle, DB2, Sybase, and Informix&#46; Just ensure that the database JDBC driver jar files are mentioned in <code>$CLASSPATH</code> or <code>require</code> them directly in your script or application&#46; Then, configure <code>database.yml</code> with <code>adapter:</code> set to one of <code>oracle</code>, <code>db2</code>, <code>sybase</code>, or <code>informix</code>&#46;</p> <p>This release promises superb compatibility with Rails 3&#46; We now have the ActiveRecord test suite <a href="http://ci.jruby.org/view/Rails">running in CI</a> and the 1&#46;0&#46;0 release is 100% green when run on MySQL&#46; (SQLite3 is right behind with just 13 failures, and we hope to fix those soon&#46;)</p> <p>As <a href="/articles/2010/02/24/jruby-and-rails-3-sitting-in-a-tree">mentioned before</a>, to get started with Rails 3, JRuby and <code>activerecord-jdbc-adapter</code>, simply run:</p> <pre><code>$ rails new app --database mysql --template http://jruby.org ... apply http://jruby.org apply http://jruby.org/templates/default.rb gsub Gemfile gsub config/database.yml $ cd app &amp;&amp; bundle install ... Using activerecord-jdbc-adapter (1.0.0) ... Using jdbc-mysql (5.0.4) ... Using rails (3.0.0) Your bundle is complete! Use `bundle show [gemname]` ... </code></pre> <p>One new feature in 1&#46;0&#46;0 is the ability to define an extension adapter for your proprietary JDBC database without needing to hack the <code>activerecord-jdbc-adapter</code> source code&#46; To get you started we extracted the <code>activerecord-cachedb-adapter</code> and <a href="http://github.com/nicksieger/activerecord-cachedb-adapter">put it on Github</a> for you to use as a template&#46;</p> <p>The 1&#46;0&#46;0 release had over 200 commits poured into it and lots of great help from the community&#46; Thanks to David Kellum, Dmitry Denisov, Dwayne Litzenberger, Gregor Schmidt, James Walker, John Duff, Joshua Suggs, Nicholas J Kreucher, Peter Donald, Geoff Longman, Uwe Kubosch, Youhei Kondou, Michael Pitman, Alex B, and Ryan Bell for their contributions to this release&#46;</p> <p>Enjoy!</p> Nick Sieger urn:uuid:4c6d6645-1832-4ed6-b947-51f55231f41f 2010-08-30T17:12:07+00:00 2010-11-22T18:03:42+00:00 JRuby at JavaZone 2010 <p>I&#8217;m pleased to be able to return to Oslo for JavaZone 2010&#46; Whether you&#8217;re checking out JRuby for the first time or a veteran JRuby user, I&#8217;ll have something for you! And if I don&#8217;t, I encourage you to come badger me after the talk is finished&#46;</p> <h3><a href="http://javazone.no/incogito10/events/JavaZone%202010/sessions/JRuby:%20Now%20With%20More%20J!">JRuby: Now With More J!</a></h3> <p>Additionally, if you&#8217;re interested in meeting up for some JRuby discussion next week in Oslo, do drop me a note at the address in the upper right&#46;</p> Nick Sieger urn:uuid:055dd055-5fd2-4b4b-ab36-41f806396627 2010-08-30T17:06:52+00:00 2010-11-22T18:03:43+00:00 Deploying, Monitoring and Troubleshooting Rails on JRuby <p>I am pleased that my Engine Yard webinar on JRuby and deployment is available for general viewing&#46; While the JRuby deployment story is still evolving and maturing, and the 60 minute time frame is too short to cover the issues in depth, I hope you&#8217;ll find the content at least gives you some ideas or directions to look&#46;</p> <p>As always, feel free to contact me with any questions!</p> <p><iframe src="http://player.vimeo.com/video/14435288" width="400" height="300" frameborder="0"></iframe><p><a href="http://vimeo.com/14435288">Deploying, Monitoring and Troubleshooting Rails on the JVM with JRuby</a> from <a href="http://vimeo.com/engineyard">Engine Yard</a> on <a href="http://vimeo.com">Vimeo</a>&#46;</p></p> Nick Sieger urn:uuid:a2ff03a8-5c6c-4bf0-b000-8a169b441be8 2010-04-06T17:11:17+00:00 2010-11-22T18:03:43+00:00 Warbler 1.0 <p>It&#8217;s past due time to &#8220;carry the 1&#8221; over and roll over to a 1&#46;0 version of <a href="http://caldersphere.rubyforge.org/warbler/">Warbler</a>&#46; This time around, the changes in the codebase are significant enough that I hope you&#8217;ll find many past usability issues resolved&#46;</p> <h2>Assemble in&#45;place</h2> <p>The biggest change is that Warbler now creates a war file in place, without an intermediate copy&#45;to&#45;assemble step&#46; Warbler does this using the <code>rubyzip</code> gem, or alternatively using a small Java extension when run under JRuby 1&#46;5 or greater&#46; This should reduce processing and confusion due to the extra copy, which can sometimes get out of sync&#46; The downside is that Warbler cannot be used easily for exploded directory development, though you can always create the war file and unpack it to a staging area&#46; </p> <h2>Simpler extension</h2> <p>Warbler also underwent an internal refactoring that should make extending it much easier&#46; Here&#8217;s how you add Warbler tasks to your <code>Rakefile</code>:</p> <div class="typocode"><pre><code class="typocode_ruby "><span class="ident">require</span> <span class="punct">'</span><span class="string">warbler</span><span class="punct">'</span> <span class="constant">Warbler</span><span class="punct">::</span><span class="constant">Task</span><span class="punct">.</span><span class="ident">new</span></code></pre></div> <p>In versions prior to 1&#46;0, if there were deploy steps that created new files that didn&#8217;t exist at the time the <code>Rakefile</code> was loaded (such as what the <code>asset:packager:build_all</code> task does in the <a href="http://synthesis.sbecker.net/pages/asset_packager">asset_packager</a> plugin), it was tricky to get Warbler to recognize them&#46; No longer &#45;&#45; now the expected Rake configuration should do the trick&#46;</p> <div class="typocode"><pre><code class="typocode_ruby "><span class="ident">require</span> <span class="punct">'</span><span class="string">warbler</span><span class="punct">'</span> <span class="constant">Warbler</span><span class="punct">::</span><span class="constant">Task</span><span class="punct">.</span><span class="ident">new</span> <span class="ident">task</span> <span class="symbol">:war</span> <span class="punct">=&gt;</span> <span class="punct">&quot;</span><span class="string">asset:packager:build_all</span><span class="punct">&quot;</span></code></pre></div> <h2>Bundler support</h2> <p>Another exciting development in the Ruby development world is <a href="http://gembundler.com/">Bundler</a>, and Warbler 1&#46;0 supports packaging your bundled gems with it&#46; Warbler even creates a <code>.bundle/environment.rb</code> file inside the war file that loads the gems from relative paths to where Warbler puts the gems in the war file&#46;</p> <h2>More configuration</h2> <p>There are a number of new configuration options, so <a href="http://github.com/nicksieger/warbler/blob/master/warble.rb">check out the new configuration</a> and see if any are useful to you&#46;</p> <ul> <li><code>config.gem_home</code> allows you to control the path inside the war file where Warbler will pack your application&#8217;s gems&#46; For use with older versions of Bundler or other custom gem vendoring schemes&#46;</li> <li><code>config.webinf_files</code> is a file list that can contain multiple files, XML or otherwise&#46; If the files named in this list have <code>.erb</code> extensions, they will be expanded in the same manner as <code>web.xml</code>&#46;</li> </ul> <h2>Rails 3 support</h2> <p><a href="http://jruby-rack.kenai.com/">JRuby&#45;Rack</a>, the servlet adapter component bundled by Warbler, also received a version bump, and there are no longer any Java libraries included in the Warbler gem, so the two components can be versioned independently&#46; With the release of both Warbler 1&#46;0 and JRuby&#45;Rack 0&#46;9&#46;7, Rails 3 applications can be warbled and deployed seamlessly, often without any additional configuration&#46;</p> <p>Please continue to send feedback to the <a href="http://xircles.codehaus.org/lists/user@jruby.codehaus.org">JRuby mailing list</a> or the <a href="http://kenai.com/jira/browse/WARBLER">Warbler bug tracker</a>&#46; Enjoy!</p> Nick Sieger urn:uuid:603837d6-55bf-4e03-8fec-4d2db26c002e 2010-02-24T03:58:00+00:00 2010-11-22T18:03:45+00:00 JRuby and Rails 3, Sitting in a Tree <h2>Synopsis</h2> <pre><code>jruby -S rails new myapp -m http://jruby.org/rails3.rb </code></pre> <p>When creating your Rails 3 application, just add the JRuby&#45;specific template (<code>-m http://jruby.org/rails3.rb</code>)&#46;</p> <h2>Details</h2> <pre><code>$ jruby -S gem install rails --pre --no-rdoc --no-ri Due to a rubygems bug, you must uninstall all older versions of bundler for 0.9 to work Successfully installed i18n-0.3.3 Successfully installed tzinfo-0.3.16 Successfully installed builder-2.1.2 Successfully installed memcache-client-1.7.8 Successfully installed activesupport-3.0.0.beta Successfully installed activemodel-3.0.0.beta Successfully installed rack-1.1.0 Successfully installed rack-test-0.5.3 Successfully installed rack-mount-0.4.7 Successfully installed abstract-1.0.0 Successfully installed erubis-2.6.5 Successfully installed actionpack-3.0.0.beta Successfully installed arel-0.2.1 Successfully installed activerecord-3.0.0.beta Successfully installed activeresource-3.0.0.beta Successfully installed mime-types-1.16 Successfully installed mail-2.1.3 Successfully installed text-hyphen-1.0.0 Successfully installed text-format-1.0.0 Successfully installed actionmailer-3.0.0.beta Successfully installed thor-0.13.3 Successfully installed railties-3.0.0.beta Successfully installed bundler-0.9.7 Successfully installed rails-3.0.0.beta 24 gems installed </code></pre> <h3>And:</h3> <pre><code>$ jruby -S gem install activerecord-jdbcsqlite3-adapter --no-rdoc --no-ri Successfully installed activerecord-jdbc-adapter-0.9.3-java Successfully installed jdbc-sqlite3-3.6.3.054 Successfully installed activerecord-jdbcsqlite3-adapter-0.9.3-java 3 gems installed </code></pre> <h3>Finally:</h3> <pre><code>$ jruby -S rails new myapp -m http://jruby.org/rails3.rb create ...(app creation)... apply http://jruby.org/rails3.rb apply http://jruby.org/templates/default.rb gsub Gemfile run jruby script/rails generate jdbc from "." ...(warnings omitted)... exist create config/initializers/jdbc.rb create lib/tasks/jdbc.rake $ cd myapp $ jruby script/rails server ...(warnings omitted)... =&gt; Booting WEBrick =&gt; Rails 3.0.0.beta application starting in development on http://0.0.0.0:3000 =&gt; Call with -d to detach =&gt; Ctrl-C to shutdown server [2010-02-23 19:44:26] INFO WEBrick 1.3.1 [2010-02-23 19:44:26] INFO ruby 1.8.7 (2010-02-23) [java] [2010-02-23 19:44:26] INFO WEBrick::HTTPServer#start: pid=16449 port=3000 </code></pre> <p><img src="http://img.skitch.com/20100224-eik9e957x7uu8k5x8y4xgt9jes.jpg" alt="rails-welcome"/></p> <h2>Recap</h2> <p>You&#8217;ll have best results with <a href="http://ci.jruby.org/snapshots">JRuby 1&#46;5 snapshots</a>, which include RubyGems 1&#46;3&#46;6&#46; JRuby 1&#46;5 final is coming soon&#46; Also, <a href="http://rubyforge.org/forum/forum.php?forum_id=36489">the new <code>activerecord-jdbc-adapter</code> 0&#46;9&#46;3 release</a> is required for Rails 3 compatibility&#46;</p> <p>The Rails experience on JRuby continues to get better&#46;</p> Nick Sieger urn:uuid:32ea8753-bf86-4fe8-bec2-4b2f432512fe 2009-04-11T04:10:51+00:00 2010-11-22T18:06:58+00:00 JRuby on Google AppEngine: First Impressions <p>I was surprised by <a href="http://googleappengine.blogspot.com/2009/04/seriously-this-time-new-language-on-app.html">Tuesday&#8217;s announcements</a> as much as anyone else&#46; <a href="http://olabini.com/blog/2009/04/jruby-on-rails-on-google-app-engine/">Ola keeps secrets well</a>&#46; He sent me a pull request for <a href="http://jruby-rack.kenai.com/pages/Home">jruby&#45;rack</a> just last week mentioning &#8220;some restrictive environments where you can&#8217;t start threads&#8221;&#46; I didn&#8217;t blink, and instead just merged his patch&#46;</p> <p><img src="http://rubyonrails.org/images/rails.png" alt="rails"/> <img src="http://2.bp.blogspot.com/_dLfQMJsmsaI/SdvwPx8hz5I/AAAAAAAAACY/I_DEfn6nQjc/s320/ae_gwt_java.png" alt="java-gae"/></p> <p>Despite the surprise news, it turns out my timing wasn&#8217;t bad&#46; <a href="http://twitter.com/nicksieger/status/1189629742">Just a couple of weeks ago I was experimenting</a> with the Python version of AppEngine, just to see what the fuss is all about&#46; Even though Google&#8217;s had its <a href="http://radar.oreilly.com/archives/2008/04/is-google-app-engine-a-lockin.html">share</a> of <a href="http://www.tbray.org/ongoing/When/200x/2008/04/09/Google-Users-API">criticism</a> for building a platform that is difficult for developers to leave, the lock&#45;in aspect didn&#8217;t bother me&#46; I&#8217;m a pragmatist first, and I believe that we as developers are the only ones locking ourselves to a platform&#46; We have a choice, after all&#46; And look at <a href="http://www.nytimes.com/2009/04/05/fashion/05iphone.html">all the developers willfully rushing</a> to develop Cocoa applications for the iPhone&#46; The fact that their code is not useful on any other device isn&#8217;t stopping them&#46;</p> <p>The thing with AppEngine is that it&#8217;s a unique platform all unto itself&#46; That may seem brutally obvious, but the point seems to be lost in all the frenzy surrounding the Run&#45;Rails&#45;Struts&#45;Spring&#45;Groovy&#45;Grails&#45;Lift&#45;You&#45;Name&#45;It&#45;Framework on AppEngine this week&#46; I&#8217;m not saying it&#8217;s a bad idea to try to run Rails on AppEngine; quite the contrary&#46; I&#8217;m saying you need to be honest about the trade&#45;offs and constraints&#46; And in the case of Ruby and Rails, boy are there a bunch of them:</p> <ul> <li>No regular <code>net/http</code>, <code>restclient</code>, <code>ActiveResource</code> usage&#46; Google has a URL fetch library, and has hooked up Java&#8217;s <code>HttpURLConnection</code> to it, but none of the Ruby URL&#45;fetching libraries use it&#46;</li> <li>No ActiveRecord&#46; &#8216;Nuff said&#46; For some folks, that&#8217;s a welcome change, but wrapping your head around AppEngine&#8217;s BigTable&#45;backed data store takes some thought&#46; You just can&#8217;t view it like a SQL engine&#46;</li> <li>No RMagick/ImageScience/attachment_fu&#46; No <a href="/articles/2008/03/27/imagevoodoo-0-1-released">ImageVoodoo</a> even (no javax&#46;image APIs)&#46; Google has it&#8217;s own image manipulation API&#46;</li> <li>Startup/first request processing time is currently an issue&#46; It&#8217;s not clear yet how long Google keeps JVMs warm, so if your application is idle, the first few hits to it return 500 errors&#46; I can only assume Google has a plan to address this&#46;</li> <li>Crypto&#46; Although java&#46;security and javax&#46;crypto APIs are apparently <a href="http://code.google.com/appengine/docs/java/jrewhitelist.html">whitelisted</a>, I haven&#8217;t had time to figure out how to leverage them&#46; JRuby&#8217;s jruby&#45;openssl gem does not work, which means things like <code>digest</code> aren&#8217;t available&#46; That&#8217;s currently a blocker for Rails&#8217; cookie session store&#46;</li> <li>1000&#45;files limit per application&#46; In order to work around this, I ended up <a href="/articles/2009/01/10/jruby-1-1-6-gems-in-a-jar">jarring up all the Rails gems</a> when deploying a Rails application&#46;</li> </ul> <p>These are just a sampling of some of the problems you&#8217;re dealing with on the AppEngine frontier&#46; They&#8217;re all solvable; it will take a little time and BST (blood, sweat and tears)&#46; The point is you can&#8217;t expect a Rails application on AppEngine to behave like all the Rails applications you&#8217;ve written previously&#46;</p> <p>In return for your troubles, you get the AppEngine value proposition, which is actually attractive in a lot of ways: Google runs the platform&#46; You don&#8217;t have to worry about it&#46; Transparent scaling, monitoring, logging, everything below your application code is taken care of&#46; Single&#45;step deployment, with application versioning and rollback&#46; Scalable services: BigTable storage, memcached, scheduled tasks&#46; My friend <a href="http://googleappengine.blogspot.com/2009/02/best-buys-giftag-on-app-engine.html">Curt Thompson of Best Buy&#8217;s Giftag&#46;com</a> talks about how they leverage AppEngine for a non&#45;toy application&#46; (Curt also helped me get my <a href="http://nicksieger-notes.appspot.com/">Python AppEngine experiment</a> up and running&#46;)</p> <p>In the end, I&#8217;m still extremely excited about the prospect of using JRuby and Rails on AppEngine, and can&#8217;t wait to see what people build with these tools&#46; If you want a little head start, you can check out the first Rails application I deployed, <a href="http://jruby-rack.appspot.com/">jruby&#45;rack&#46;appspot&#46;com</a>&#46; The &#8220;application environment&#8221; page is the main dynamic action in the app, which just enumerates a bunch of request and system environment properties so you can get a feel for how things are set up in the AppEngine Java environment&#46; The source code for the application is linked from the front page&#46; Note that the app was deployed with JRuby trunk and <a href="http://kenai.com/projects/jruby-rack/lists/talk/archive/2009-04/message/0">JRuby&#45;Rack 0&#46;9&#46;4</a>; Warbler is not yet using these components but you can build them yourself, drop them in and try them&#46; We&#8217;ll be updating JRuby, Warbler and other tools soon to make this process more seamless soon&#46; Stay tuned!</p> Nick Sieger urn:uuid:9fe84534-3a40-40e8-8626-a15bb05d74b4 2007-03-16T16:55:00+00:00 2010-11-22T18:06:59+00:00 JRuby on Rails: Integration Plugin Goes 1.0 <p>On the heels of my last post, Robert <a href="http://rubyforge.org/pipermail/jruby-extras-devel/2007-March/000432.html">announced the 1&#46;0 release of Rails Integration</a>, the bits that allow JRuby on Rails to be run out of a Java web archive (war)&#46; If you have any interest at all in trying out JRuby on Rails, do yourself a favor and <a href="http://www.headius.com/jrubywiki/index.php/Rails_Integration">try out the integration bits</a>&#46; Even though this is 1&#46;0, we&#8217;re still moving rapidly and would appreciate any and all feedback&#46; (And Robert is doing his best to keep up with changes in core&#46;)</p> <p>Related to this, Stuart Halloway <a href="http://www.relevancellc.com/2007/3/14/the-j-plugin-existing-rails-apps-on-jruby">recently announced his J plugin</a> which is a drop&#45;in collection of Rake tasks that bridge the inherent differences between Rails running on C Ruby vs&#46; JRuby&#46; We still have some work to do in some areas, such as database driver configuration, test database bootstrapping and launching unit tests&#46; For example, instead of the <a href="http://dev.rubyonrails.org/svn/rails/branches/1-2-stable/railties/lib/tasks/databases.rake">big, ugly, database&#45;specific case statement that&#8217;s in Rails&#8217; databases&#46;rake today</a>:</p> <div class="typocode"><pre><code class="typocode_ruby "><span class="ident">desc</span> <span class="punct">&quot;</span><span class="string">Recreate the test databases from the development structure</span><span class="punct">&quot;</span> <span class="ident">task</span> <span class="symbol">:clone_structure</span> <span class="punct">=&gt;</span> <span class="punct">[</span> <span class="punct">&quot;</span><span class="string">db:structure:dump</span><span class="punct">&quot;,</span> <span class="punct">&quot;</span><span class="string">db:test:purge</span><span class="punct">&quot;</span> <span class="punct">]</span> <span class="keyword">do</span> <span class="ident">abcs</span> <span class="punct">=</span> <span class="constant">ActiveRecord</span><span class="punct">::</span><span class="constant">Base</span><span class="punct">.</span><span class="ident">configurations</span> <span class="keyword">case</span> <span class="ident">abcs</span><span class="punct">[&quot;</span><span class="string">test</span><span class="punct">&quot;][&quot;</span><span class="string">adapter</span><span class="punct">&quot;]</span> <span class="keyword">when</span> <span class="punct">&quot;</span><span class="string">mysql</span><span class="punct">&quot;</span> <span class="constant">ActiveRecord</span><span class="punct">::</span><span class="constant">Base</span><span class="punct">.</span><span class="ident">establish_connection</span><span class="punct">(</span><span class="symbol">:test</span><span class="punct">)</span> <span class="constant">ActiveRecord</span><span class="punct">::</span><span class="constant">Base</span><span class="punct">.</span><span class="ident">connection</span><span class="punct">.</span><span class="ident">execute</span><span class="punct">('</span><span class="string">SET foreign_key_checks = 0</span><span class="punct">')</span> <span class="constant">IO</span><span class="punct">.</span><span class="ident">readlines</span><span class="punct">(&quot;</span><span class="string">db/<span class="expr">#{RAILS_ENV}</span>_structure.sql</span><span class="punct">&quot;).</span><span class="ident">join</span><span class="punct">.</span><span class="ident">split</span><span class="punct">(&quot;</span><span class="string"> </span><span class="punct">&quot;).</span><span class="ident">each</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">table</span><span class="punct">|</span> <span class="constant">ActiveRecord</span><span class="punct">::</span><span class="constant">Base</span><span class="punct">.</span><span class="ident">connection</span><span class="punct">.</span><span class="ident">execute</span><span class="punct">(</span><span class="ident">table</span><span class="punct">)</span> <span class="keyword">end</span> <span class="keyword">when</span> <span class="punct">&quot;</span><span class="string">postgresql</span><span class="punct">&quot;</span> <span class="constant">ENV</span><span class="punct">['</span><span class="string">PGHOST</span><span class="punct">']</span> <span class="punct">=</span> <span class="ident">abcs</span><span class="punct">[&quot;</span><span class="string">test</span><span class="punct">&quot;][&quot;</span><span class="string">host</span><span class="punct">&quot;]</span> <span class="keyword">if</span> <span class="ident">abcs</span><span class="punct">[&quot;</span><span class="string">test</span><span class="punct">&quot;][&quot;</span><span class="string">host</span><span class="punct">&quot;]</span> <span class="constant">ENV</span><span class="punct">['</span><span class="string">PGPORT</span><span class="punct">']</span> <span class="punct">=</span> <span class="ident">abcs</span><span class="punct">[&quot;</span><span class="string">test</span><span class="punct">&quot;][&quot;</span><span class="string">port</span><span class="punct">&quot;].</span><span class="ident">to_s</span> <span class="keyword">if</span> <span class="ident">abcs</span><span class="punct">[&quot;</span><span class="string">test</span><span class="punct">&quot;][&quot;</span><span class="string">port</span><span class="punct">&quot;]</span> <span class="constant">ENV</span><span class="punct">['</span><span class="string">PGPASSWORD</span><span class="punct">']</span> <span class="punct">=</span> <span class="ident">abcs</span><span class="punct">[&quot;</span><span class="string">test</span><span class="punct">&quot;][&quot;</span><span class="string">password</span><span class="punct">&quot;].</span><span class="ident">to_s</span> <span class="keyword">if</span> <span class="ident">abcs</span><span class="punct">[&quot;</span><span class="string">test</span><span class="punct">&quot;][&quot;</span><span class="string">password</span><span class="punct">&quot;]</span> `<span class="ident">psql</span> <span class="punct">-</span><span class="constant">U</span> <span class="punct">&quot;</span><span class="string"><span class="expr">#{abcs[&quot;test&quot;][&quot;username&quot;]}</span></span><span class="punct">&quot;</span> <span class="punct">-</span><span class="ident">f</span> <span class="ident">db</span><span class="punct">/</span><span class="comment">#{RAILS_ENV}_structure.sql #{abcs[&quot;test&quot;][&quot;database&quot;]}`</span> <span class="keyword">when</span> <span class="punct">&quot;</span><span class="string">sqlite</span><span class="punct">&quot;,</span> <span class="punct">&quot;</span><span class="string">sqlite3</span><span class="punct">&quot;</span> <span class="ident">dbfile</span> <span class="punct">=</span> <span class="ident">abcs</span><span class="punct">[&quot;</span><span class="string">test</span><span class="punct">&quot;][&quot;</span><span class="string">database</span><span class="punct">&quot;]</span> <span class="punct">||</span> <span class="ident">abcs</span><span class="punct">[&quot;</span><span class="string">test</span><span class="punct">&quot;][&quot;</span><span class="string">dbfile</span><span class="punct">&quot;]</span> `<span class="comment">#{abcs[&quot;test&quot;][&quot;adapter&quot;]} #{dbfile} &lt; db/#{RAILS_ENV}_structure.sql`</span> <span class="keyword">when</span> <span class="punct">&quot;</span><span class="string">sqlserver</span><span class="punct">&quot;</span> `<span class="ident">osql</span> <span class="punct">-</span><span class="constant">E</span> <span class="punct">-</span><span class="constant">S</span> <span class="comment">#{abcs[&quot;test&quot;][&quot;host&quot;]} -d #{abcs[&quot;test&quot;][&quot;database&quot;]} -i db\#{RAILS_ENV}_structure.sql`</span> <span class="keyword">when</span> <span class="punct">&quot;</span><span class="string">oci</span><span class="punct">&quot;,</span> <span class="punct">&quot;</span><span class="string">oracle</span><span class="punct">&quot;</span> <span class="constant">ActiveRecord</span><span class="punct">::</span><span class="constant">Base</span><span class="punct">.</span><span class="ident">establish_connection</span><span class="punct">(</span><span class="symbol">:test</span><span class="punct">)</span> <span class="constant">IO</span><span class="punct">.</span><span class="ident">readlines</span><span class="punct">(&quot;</span><span class="string">db/<span class="expr">#{RAILS_ENV}</span>_structure.sql</span><span class="punct">&quot;).</span><span class="ident">join</span><span class="punct">.</span><span class="ident">split</span><span class="punct">(&quot;</span><span class="string">; </span><span class="punct">&quot;).</span><span class="ident">each</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">ddl</span><span class="punct">|</span> <span class="constant">ActiveRecord</span><span class="punct">::</span><span class="constant">Base</span><span class="punct">.</span><span class="ident">connection</span><span class="punct">.</span><span class="ident">execute</span><span class="punct">(</span><span class="ident">ddl</span><span class="punct">)</span> <span class="keyword">end</span> <span class="keyword">when</span> <span class="punct">&quot;</span><span class="string">firebird</span><span class="punct">&quot;</span> <span class="ident">set_firebird_env</span><span class="punct">(</span><span class="ident">abcs</span><span class="punct">[&quot;</span><span class="string">test</span><span class="punct">&quot;])</span> <span class="ident">db_string</span> <span class="punct">=</span> <span class="ident">firebird_db_string</span><span class="punct">(</span><span class="ident">abcs</span><span class="punct">[&quot;</span><span class="string">test</span><span class="punct">&quot;])</span> <span class="ident">sh</span> <span class="punct">&quot;</span><span class="string">isql -i db/<span class="expr">#{RAILS_ENV}</span>_structure.sql <span class="expr">#{db_string}</span></span><span class="punct">&quot;</span> <span class="keyword">else</span> <span class="keyword">raise</span> <span class="punct">&quot;</span><span class="string">Task not supported by '<span class="expr">#{abcs[&quot;test&quot;][&quot;adapter&quot;]}</span>'</span><span class="punct">&quot;</span> <span class="keyword">end</span> <span class="keyword">end</span></code></pre></div> <p>we can use migrations to create the test database:</p> <div class="typocode"><pre><code class="typocode_ruby "><span class="ident">desc</span> <span class="punct">&quot;</span><span class="string">Recreate the test databases from migrations</span><span class="punct">&quot;</span> <span class="ident">task</span> <span class="symbol">:migrate_test_db</span> <span class="keyword">do</span> <span class="constant">ActiveRecord</span><span class="punct">::</span><span class="constant">Base</span><span class="punct">.</span><span class="ident">establish_connection</span><span class="punct">(</span><span class="constant">ActiveRecord</span><span class="punct">::</span><span class="constant">Base</span><span class="punct">.</span><span class="ident">configurations</span><span class="punct">['</span><span class="string">test</span><span class="punct">'])</span> <span class="constant">ActiveRecord</span><span class="punct">::</span><span class="constant">Schema</span><span class="punct">.</span><span class="ident">verbose</span> <span class="punct">=</span> <span class="ident">t</span><span class="punct">.</span><span class="ident">application</span><span class="punct">.</span><span class="ident">options</span><span class="punct">.</span><span class="ident">trace</span> <span class="constant">ActiveRecord</span><span class="punct">::</span><span class="constant">Migrator</span><span class="punct">.</span><span class="ident">migrate</span><span class="punct">(&quot;</span><span class="string">db/migrate/</span><span class="punct">&quot;)</span> <span class="keyword">end</span></code></pre></div> <p>Over time, I hope to see all these efforts coalesce and make the Rails developer experience virtually identical on either interpreter&#46; What would be most excellent is to eventually push some of these improvements back to the Rails core&#46;</p> Nick Sieger urn:uuid:091b1464-16fe-49ee-9d4b-ce18ddf2da0d 2006-05-15T03:12:00+00:00 2010-11-22T18:06:59+00:00 JRuby on Rails and ActiveRecord on JDBC <p><a href="http://www.bloglines.com/blog/ThomasEEnebo?id=16">Tom</a> and <a href="http://headius.blogspot.com/2006/05/and-they-said-jruby-was-dead.html">Charlie</a> have just experienced what can only be described as a watershed moment in the grand scheme of dynamic languages on the JVM&#46; The Rails experience may soon be visiting a Java application server near you! Even though JRuby will be in perpetual catch&#45;up mode with C Ruby, Tom and Charlie and the rest of the JRuby contributors have shown incredible perseverance in tracking the Ruby language despite <em>the lack of any formal specification</em>&#46; Maybe Rails will never be mainstream, but the possibilities just got a whole lot more interesting&#46; I agree with <a href="http://jroller.com/page/obie?entry=jruby_on_rails_is_born">Obie</a> that this could be a game&#45;changer&#46;</p> <p>Now, a few comments about the ActiveRecord JDBC adapter&#46; This code can still be considered alpha quality at best&#46; It&#8217;s awesome that Tom and Charlie will be able to demo a top&#45;to&#45;bottom, working Rails app on JRuby, but don&#8217;t jump to conclusions yet that this will be anything like a write&#45;once, deploy&#45;to&#45;any&#45;database kind of experience&#46; But you didn&#8217;t think it would, did you? We all learned that about Java a long time ago, right?</p> <p>You can <a href="http://svn.caldersphere.net/svn/main/activerecord-jdbc/trunk/">check out the code here</a>&#46; At the moment, I&#8217;ve only tried it with MySQL&#46; Most of the problems with it come from the lossy mapping from ActiveRecord&#8217;s abstraction of the database to JDBC&#8217;s&#46; (Although I suspect as more JDBC drivers are tried that there will eventually be compatibility issues with different implementations of the JDBC spec&#46;)</p> <p>Probably the thorniest issue is the one of type conversion&#46; ActiveRecord has a fairly simple notion of types: <code>:string, :text, :integer, :float, :datetime</code> etc&#46; Compare this to <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/sql/Types.html">JDBC&#8217;s</a>&#46; What a mess! Right now there are arrays of <code>proc</code>s for each AR type that try to guess the best JDBC type to use&#46; This will certainly need improvement to become a more robust solution&#46;</p> <p>Probably the most promising approach may be to create a patch that refactors much of the AR adapters&#8217; type conversion methods into separate modules that could be included into instances of the JDBC adapter depending on the underlying database&#46; Then the JDBC types wouldn&#8217;t be needed at all &#45;&#45; the existing AR database metadata could be reused&#46; Presumably this would require some petitioning of the Rails core team to accept the changes even though the changes don&#8217;t buy AR itself any additional flexibility&#46;</p> <p>If you have a chance to try out the code or can think of any additional tricks that would help the ActiveRecord JDBC implementation along, let me know!</p> Nick Sieger urn:uuid:a88e00d4-56b6-4b75-95e9-4e21e6b0387a 2007-09-04T02:48:40+00:00 2010-11-22T18:06:59+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&#46;0&#46;1</a> and <a href="http://rubyforge.org/frs/shownotes.php?release_id=14048">Goldspike 1&#46;3</a> releases into our environment, when my frustration hit a fever pitch&#46;</p> <p>See, I had always thought that the &#46;war packaging side of Goldspike was a little clunky and un&#45;ruby&#45;like, but I didn&#8217;t see a clear path to fixing it&#46; 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)&#46;</p> <p>Also, in my own opinion it took the wrong approach to packaging Rails in a &#46;war file&#46; It puts the Rails application directory structure into the root of the &#46;war file where any web server or Java application server might mistakenly serve up your code as static content&#46; The Java &#46;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, &#46;svn directories and everything&#46; So I set out to fix this once and for all&#46;</p> <p>And so I present <a href="http://caldersphere.rubyforge.org/warbler/">Warbler</a>&#46; A little bird who chirpily steps up to the task of assembling your Rails application into a Java Web Archive (&#46;war)&#46; 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 &#46;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>&#46;</p> <p>There are a number of points about Warbler worth mentioning&#46;</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&#46; This will allow for more runtime servlet binding mechanisms to take advantage of Warbler in the future&#46;</p> <h3>Fast and lightweight</h3> <p>50% less code than the Goldspike packaging plugin, yet does the job quickly and efficiently&#46;</p> <h3>Sane defaults</h3> <p>Warbler only packages code that you need to run the application, omitting database migrations and tests&#46; If your application is self&#45;sufficient (no external dependencies), then the out&#45;of&#45;the&#45;box configuration will probably work for you&#46; Public HTML/images/javascript/stylesheets go in the root of the webapp, where Java webservers expect them to be&#46;</p> <h3>Documented, flexible configuration</h3> <p>Need to customize your configuration? Run <code>warble config</code> and edit <code>config/warble.rb</code>&#46; All the options are there, commented and documented&#46;</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 &#46;jar files in the <code>vendor/plugins/warbler-0.9/lib</code> directory&#46; 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 &#46;war file produced when running in plugin mode, since you won&#8217;t need him at runtime&#46; It&#8217;s the little details that matter&#46;</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:bfda082f-fa26-41d8-aa16-fc07b41aba35 2007-10-25T03:36:00+00:00 2010-11-22T18:07:00+00:00 JRuby on Rails: Fast Enough <p>People have been asking for a while how fast JRuby runs Rails&#46; (Of course, &#8220;fast&#8221; has always been a <a href="http://www.joelonsoftware.com/items/2006/09/12.html">relative term</a>&#46;) We haven&#8217;t been quick to answer the question, because frankly we didn&#8217;t know&#46; We hadn&#8217;t been building real Rails applications on JRuby ourselves yet, and there was no definitive word from the crowd either&#46;</p> <p>Recently, several guys from <a href="http://studios.thoughtworks.com/rubyworks">ThoughtWorks</a> have been working on a <a href="http://tw-commons.rubyforge.org/svn/petstore/trunk/">Rails petstore</a> application and benchmark to get to the heart of the matter&#46; <a href="http://www.nabble.com/forum/Search.jtp?forum=14106&amp;local=y&amp;query=petstore">Discussion has been heated</a> on the JRuby mailing list, but results have not been conclusive yet&#46;</p> <p>In the project I&#8217;m working on, we&#8217;ve <a href="http://blog.nicksieger.com/articles/2007/10/06/railsconf-europe-hydra">committed to using and deploying on JRuby</a>&#46; Eventually we were going to reach the point where we&#8217;d need to find out how well our application runs&#46; So today I began running a simple single request benchmark on a relatively busy page&#46; The numbers turned out to be rather surprising:</p> <p><img src="/files/jr-requests.png" alt="Requests" title="Requests"/></p> <p><img src="/files/jr-average.png" alt="Average" title="Average"/></p> <p>(The <a href="http://spreadsheets.google.com/pub?key=pGobleZnKsdI1zW38xpNaaw">raw data is available here</a>&#46;)</p> <p>Now, MRI (C Ruby) will always run about the same speed no matter how many runs you give it, but it&#8217;s well known that the JVM <a href="http://www.javaworld.com/javaworld/javaqa/2003-04/01-qa-0411-hotspot.html">needs time to warm up</a>&#46; And indeed it does; after 250 iterations, Mongrel running on JRuby finally surpasses MRI&#46; The JRuby/Goldspike/Glassfish combo comes close as well&#46;</p> <p>Some details about the setup:</p> <ul> <li>I ran the tests on my MacBook Pro Core 2 Duo 2&#46;4 GHz&#46; I didn&#8217;t disable one of the cores for the tests, which means that JRuby has an advantage over MRI because it can use both (native threads at work)&#46; However, the test script ran the requests serially, which means that the advantage was minimal&#46;</li> <li>The application is indeed of the <a href="http://blog.nicksieger.com/articles/2007/10/06/railsconf-europe-hydra">&#8220;hydra&#8221;</a> variety; the setup is nearly identical to the second diagram on that page&#46; So a single request is passing through <strong>not one, but two</strong> Rails applications in addition to touching the database&#46; It rendered an HTML ERb view with data from an ActiveResource&#45;accessed RESTful service&#46; The applications are based on Rails 1&#46;2&#46;3&#46;</li> <li>MRI version is using Ruby 1&#46;8&#46;6 and Mongrel 1&#46;0&#46;1&#46;</li> <li>JRuby Mongrel is also version 1&#46;0&#46;1 (<a href="http://jxh.bingodisk.com/bingo/public/Hackdays/JRuby/">details on installing it here</a>)</li> <li>JRuby on Glassfish used Glassfish 2 and Goldspike 1&#46;4, deployed in war files via <a href="http://caldersphere.rubyforge.org/warbler">Warbler</a>&#46;</li> <li>The two JRuby setups used JDK 1&#46;5 and were tweaked to <a href="http://ola-bini.blogspot.com/2007/07/objectspace-to-have-or-not-to-have.html">disable ObjectSpace</a> and use the &#8220;server&#8221; VM (&#45;server argument to the JVM)&#46;</li> </ul> <p>The main point I wish to make with these numbers is that JRuby performance is there today, and still has room to grow&#46; There&#8217;s no longer any doubt in my mind&#46; Yes, this is a simplistic application benchmark run on a developer&#8217;s machine, but it&#8217;s a real application&#46; The test may not be exacting in precision, but I see enough in the numbers to believe that this will be replicable to production environments&#46; The plot thickens!</p>