Thursday, October 18, 2007

Getting ruby-openid OpenID gem to work with JRuby on Rails

As you may know a few native methods aren't yet implemented in JRuby and a few ones aren't even possible to implement due to the POSIX native calls.

I really don't know where odes FileTest#chardev? method fits in, but JRuby doesn't have it right now.

So if ever you want to use the 'ruby-openid' gem in your JRuby on Rails using for instance the official wrapper, there is a workaround.
Indeed if you do nothing, either at the rake setup, either at startup, you'll get something like:

=> Booting WEBrick...
/home/rvalyi/DEV/jruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27: FileTest#chardev? not yet implemented (NotImplementedError)
from /home/rvalyi/DEV/jruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27
from /home/rvalyi/DEV/jruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27
from /home/rvalyi/DEV/jruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `require'
from /home/rvalyi/DEV/jruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `require'
from /home/rvalyi/DEV/livetribune/vendor/rails/activesupport/lib/active_support/dependencies.rb:496:in `require'
from /home/rvalyi/DEV/jruby/lib/ruby/gems/1.8/gems/ruby-openid-1.1.4/lib/openid.rb:1:in `new_constants_in'
from /home/rvalyi/DEV/livetribune/vendor/rails/activesupport/lib/active_support/dependencies.rb:496:in `require'
from /home/rvalyi/DEV/jruby/lib/ruby/gems/1.8/gems/ruby-openid-1.1.4/lib/openid.rb:1:in `require'
from /home/rvalyi/DEV/jruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:32:in `require'
from /home/rvalyi/DEV/jruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:32:in `require'
from /home/rvalyi/DEV/livetribune/vendor/rails/activesupport/lib/active_support/dependencies.rb:496:in `require'
from /home/rvalyi/DEV/livetribune/vendor/plugins/open_id_authentication/init.rb:120:in `new_constants_in'
from /home/rvalyi/DEV/livetribune/vendor/rails/activesupport/lib/active_support/dependencies.rb:496:in `require'
from /home/rvalyi/DEV/livetribune/vendor/plugins/open_id_authentication/init.rb:120:in `binding'


The workaround is to override the FileTest module and define a stub value for the chardev? method. That method is to return true or false. Returning always true for that useage seems to work well.

So at the VERY BEGINNING of your environment.rb, just write:

module FileTest
def self.chardev?(file_name); return true; end
def chardev?(file_name); return true; end
end


Then Open Id is going to play nice with your JRuby on Rails app. At the time I'm speaking, I'm on JRuby SVN head trunk and the String#split method is having a little bug that'll ouput a stack trace but fortunately this has no consequence on the functionality.

JRuby rocks!

Saturday, October 06, 2007

migrating Livetribune.com on JRuby on Rails2.0

update: I'm here talking about problems I encountered migrating from Rails 1.2.3/1.2.4 to Rails2.0. My app has been on JRuby since almost the beginning and I had no issue with JRuby (this time at least). Being on JRuby motivated me even more to try Rails2.0 as the routing is said to be optimized by caching as I'll explain there.

The current state of JRuby (trunk) is that low level tests tend to be faster than C-Ruby but Rails is still a bit slower. Some people, included me, tend to think this might be due to the request routing of Rails being slow in JRuby. Indeed Rails routing extensively uses regexps and regexps in JRuby are still a lot slower than in C-Ruby. In fact this is because Java regex engines work with char[] whereas Ruby (including JRuby) represents strings as byte[]. So in JRuby we have to translate byte into char[] and back all the time for regexps untill somebody ports on Java a byte based regexp engine (namely the oniguruma lib).

So for a JRuby dev, it's always nice the hear Rails2.0 made some caching optimization on routing. So I wanted to try it. I didn't finish yet to port the Livetribune application (not yet in prod BTW) but I made great progress. In order to help other people in their migration I'll relate here a few tricks I had to do to make it working.

* url_for don't accept anymore symbols to point controllers. You have to write strings instead. So for instance:
map.connect ':locale/topics/:year/:month/:day/:id', :controller => :topics, :action => 'show'
became
map.connect ':locale/topics/:year/:month/:day/:id', :controller => 'topics', :action => 'show'
else rails will complain symbol :topics have no method [].

* the usefull routing_navigator plugin doesn't work anymore out of the box in Rails2.0 . This seems to be due to the self.template_root method call in the RoutingNavigatorController that doesn't exist anymore in Rails2.0. I didn't fin the work arround so I simply dropped the plugin.

* replace @base_path by ActionController::Base.view_paths whenever its used (in the AuthGenerator plugin for instance) as suggested here:
http://dev.rubyonrails.org/ticket/9689
(still I didn't get AuthGenerator fully working yet. Rails still miss its view templates)

* Since by default Rails2.0 sessions are based on a cookie store, either set it back to file store, either explicitly define a secrete that'll be share between the client browser and your server, like:
config.action_controller.session = { :session_key => "_myapp_session", :secret => '449fe2e7daee471bffae2fd8dc02313a' }
in your environment.rb


After this I had almost everything working again. Still some trouble with AuthGenerator, please provide feedback if you get this one fixed.

Also I installed that Rails 1.2.4 version before hoping it would shout for all the potential issues. It never shouted for those I just wrote about, so may be that could have done it better (or may be it's not too late to include those pointers).

Rails is very cool and Ruby is too. But it's in those kind of migration situations you'll think Java was just safer. I mean, I think half those problems would have been statically highlighted by the compiler. For the other half, let's face it you would have used some IOC injection like Spring so you wouldn't have detected it either (that the big hypocrisy of the today's J2EE world).

I still think nothing is approaching Rails in its niche, but that was just to highlight Ruby will never replace Java fully, even as a language. Rails is OK because the compiler safety is being replaced by the community checking quite effectively, but that wouldn't be true in an enterprise world for instance.

Finally I think JRuby really is the expected silver bullet, because it will allow you to closely choose where things get dynamic but unsafe (Ruby) and where thing get static and safe (Java). Moreover, the new optional Ruby type signature that's being imagined for the new JRuby compiler ( http://headius.blogspot.com/2007/09/compiler-is-complete.html )will just allow you to compile your great Ruby lib in Java and then use it from Java (as a jar bytecode) calling it through normal Java typed methods. It means you'll use safely Ruby libs whenever their author would have decided some part of its API deserves more security (and yes, a bit less agility). I mean JRuby will let you have the choice and that's great.

Also I forgot: I had no issue due to the use of JRuby (trunk) with Rails2.0.
Have fun with JRuby and Rails2.0.

Raphaël Valyi.

Thursday, October 04, 2007

JRuby IT survey using Yahoo pipes

Suppose you are all convinced JRuby is the next big thing that will bring an incredible productivity to the enterprise world. What matters from now one is to track the new JRuby experiments popping all arround the world. Every day more and more people are throwing specialized Java libs into brand new web2.0 Rails applications. And there are also of course the JRuby implementation to track. Indeed great expectations, such as speed boost, optional typing, Java/Ruby tight integration, can be put into the recent compiler advances.

So what I did is a simple Yahoo pipe that will crawl the web and gather very recent stories about JRuby usage and progress. You would think you could simply use Google blog search and see the same. Well, that would be a little bit less pertinent. Indeed, contrary to Google, this pipe filters out SVN commits as well as bug reports which tend to pollute Google blog searches. By aggregating lots of sources including the JRuby core developer blogs, you are also sure you won't miss anything important.

So the pipe is there:
http://pipes.yahoo.com/pipes/pipe.info?_id=oCCxOv9w3BGq_aM_1vC6Jw



And here is the output of that pipe (truncated to the 4 last entries only) thanks to Google AJAX Feed API:

Loading



An important thing you could notice is that Technorati and Delicious aren't used. Well actually the problem with those is that they provide feeds ordered by tagging history, not by publication history. So an old story could seem recent in Delicious just because somebody just tagged it.

Anyway, Yahoo pipes looks like a terrific tool for IT survey in general. Analyzing how people build pipes might also provide good semantic information to Yahoo, just like Delicious.

Have fun and feel free to provide feedback or build better clones.

Raphaël Valyi.