Wednesday, October 24, 2007

Debugging a JRuby on Rails app with jruby-debug and NetBeans

We've been working on the java port of ruby-debug for awhile and it's getting perilously close to usable. And with the latest builds of NetBeans, you can actually use the NB ruby debugger with it. If you're very brave, you can try it for your yourself. Be warned, it's still a work in progress, but here's how to get started:

  1. Check out jruby from trunk and build it. You'll need java and ant, but if you're interested in jruby chances are good you have those already. It's super easy to build, check it out from http://svn.codehaus.org/jruby/trunk and do ant dist and you're good to go.
  2. Check out jruby-debug from http://debug-commons.rubyforge.org/svn/jruby-debug/trunk. In this directory, do rake install_gem. This will compile and build a jruby version ruby-debug-base, which ruby-debug (command line rdebug debugger) and ruby-debug-ide (which NetBeans and Eclipse use) both depend on.
  3. Check out ruby-debug-ide from http://debug-commons.rubyforge.org/svn/trunk/ruby-debug-ide. Then do a rake gem to build the gem and gem install pkg/ruby-debug-ide-0.1.8.gem to install it.
  4. Grab a copy of NetBeans daily builds ruby ide from here: http://deadlock.netbeans.org/hudson/job/ruby/
  5. Fire up NetBeans like with some extra command line switches: ./netbeans -J-Dorg.netbeans.modules.ruby.debugger.force.rdebug=true -J-Dorg.netbeans.modules.ruby.debugger.fast.not.required=true
    The first tells NetBeans to always use the fast debugger even tho the classic debugger is what appears selected in the UI. The second tells NB to ignore the fact that the classic debugger is selected and allow us to debug a rails app anways. These flags were just added to allow us to play with jruby-debug in NetBeans for now, they won't be necessary once jruby-debug matures a little and full support for it comes into NB.
  6. In NetBeans Tools | Options be sure and have your ruby interpreter pointing at the jruby you built from trunk in Step 1.
You should now be able to debug Ruby and ROR apps using the fast ruby debugger inside of jruby. Like I said, this is all very experimental. All these steps will go away in the next few weeks or months and jruby-debug, jruby, NetBeans, ruby-debug-ide do releases.

Things which seem to work ok:
  • setting breakpoints
  • looking at variables (global and local)
  • watches
A little flaky (tho it may already be fixed by the time you read this):
  • Stepping over some code in Rails
  • Stepping out of a method
Finally, big time kudos to Martin for kicking this whole thing off and Peter for knocking out bugs and implementing more features every hour just about. It's definitely looking close now.

Sunday, October 21, 2007

Avoiding Helpful Tools Considered Stupid

Rarely does a blog post get me all fired up like Giles Bowketts here. As part of the team working on improving debugging support for JRuby, it probably struck a particularly personal chord. Nothing like having your hard work publicly ridiculed to get you exicted. I might have ignored it, and maybe I probably should, but the post contains some truly exceptional BS that needs to be addressed.

First off, it claims to inspired by a good friend of mine. So Giles, to quote from that famous vice presedential debate: I know Jim Weirich, and you sir, are no Jim Weirich! Ok, so maybe Giles didn't actually claim to be Jim Weirich, but the fact that he even attributed Jim in any way while spouting such blatent poppycock just shouldn't be.

As part of my job I have the incredible good fortune to pair with Jim on a Rails project. At the risk of pointing out what should be obvious, we do write test cases. And, it's true, when we first started working together, we did not use a debugger. Most of the time, we didn't need one. But every so often, we would have a situation where we couldn't understand what some code was doing. More embarrassing still, sometimes it was even code that we wrote.

So, when confronted with such a situation, when we couldn't think of any more test cases to write, we would add statements like this to our code "puts DBG: #{some_value_we_want_to_see}". Wow, perty high tech, eh? And it worked. We could always solve our problem this way. Jim even had a little rake task that would comb thru the code to find DBG: in our code so we could easily remove these when we were done.

Then one day I got tired of us typing DBG: in our code and I said something like "Let's try using rdebug". And guess what: rdebug was often handier than adding puts statements to our code. We could inspect all kinds of stuff. Sometimes it helped us learn more about how Rails works, especially when it did things that were, umm, a little unexpected. It was a good thing. So much so, in fact, Jim spent some time working on getting it working better with emacs so it was even easier to use.

And, hard to believe tho it may be, it did not cause us to write less test cases. Every time we learned something while debugging, we could go back and write a test case which documented our learning. In the end it helped us to write more and better test cases because we were actively trying to do so.

So it should be obvious, but since it didn't seem to be I'll state it: debuggers are tools. Like any tool, if it helps you do your work better, you might want to use it. If it doesn't you probably shouldn't. Using a tool does not lead to bad habits, bad habits lead to using a tool incorrectly. And it's worth pointing out, the technique of classifying a technology or tool as bad because it can be used incorrectly is exactly the argument that I hear made against metaprogramming and run time type checking. Kind of ironic.

Wednesday, August 8, 2007

Geeky Fatherhood Moment

Some dads live for moments like when their son can beat them at basketball or throw a touchdown pass at a high school football game. Since my family seems to share my, ahem, lack of athletic prowess, I mostly get my "dad pride" fixes in different ways. For example, today my 10 yr old son asked me a question that nearly brought a tear to his old man's eye:

"Dad is there a job you can have when you grow up where you use Gimp?"

:)

Thursday, August 2, 2007

Spring Rails Plugin 0.1

Well, I finally checked in my code for a Spring Rails plugin. Consider it pre-alpha at this point. It's unit tested, and I made a simple example app to prove that it works. But that's about it. So if you find it useful, try it out and let me know so I can decide where to go with it next.

To install the plugin:

script/plugin install svn://rubyforge.org/var/svn/jruby-extras/trunk/rails-integration/plugins/spring


You'll need to get a basic Rails application working with the goldspike plugin in order for the Spring plugin to be of use. Currently it loads the Spring ApplicationContext by getting it from the ServletContext (which assumes you are using the Spring context listener to put it there). So if you're not running Rails in a servlet engine it doesn't work. If there is real interest in having the plugin be able to get an app context from somewhere else I'll look at supporting that down the road.

For an example of how to use it in a controller, see my previous post.

Why you shouldn't use it

If you're a Java programmer new to (J)Ruby and are thinking: "Awesome, I'll use Spring in all my Rails apps because Spring is awesome!" you need to hold up a second. Spring is awesome -- when you are developing Java applications. But in Ruby, dependency injection turns out to be unnecessary a whole lot of the time. This is because the Ruby language allows you to change things in a more straightforward way. And even if there were cases where you needed DI in Ruby there are probably better choices. I see the Spring plugin being useful where you have existing J2EE code wired together with Spring and want to front end it in JRuby on Rails. So use this plugin if you need it, but if you don't, then don't.

Don't take my word for DI and Ruby, my friend Jim had this blog post about it after our IM conversation. See the comments where other Ruby heavyweights weigh in on the subject.

Saturday, July 28, 2007

eRubyCon was awesome

Just wanted to get in a blog, albeit a week and a half late, about eRubyCon. It was an awesome conference; I felt honored being involved as a speaker doing a presentation on JRuby. Being among such incredible speakers as Jim Weirich, Glen Vandenburg, Stuart Holloway, and many others made me a little like the scene in Wayne's World where Wayne and Garth meet Alice Cooper: I'm not worthy!

As far as I know, this is the first conference specifically devoted to Ruby in the Enterprise. If all you've gotten is the 30 second soundbytes about Ruby and Rails this may sound like an oxymoron, but it's not. The other speakers, particularly Glen in his "Enterprise Schmenterprise" keynote made this point eloquently. Ruby, because of it's excellence at producing easily understood and therefore much more maintainable code, is the perfect language to develop the kind of applications thought of as "enterprisey". Glen: "Enterprises aren't ready for Ruby, they're desperate for it".

Stuart made a point in his blog about this too. His series on Ruby vs Java myths made the point that Ruby is actually better for large applications than for small ones. Definitely worth a read.

Finally a big Thanks! to Joe at Edgecase for putting this together. Joe, I know it was a lot of effort time and finance wise but I hope the community can grow enough to make this a viable yearly conference: the word about Ruby really needs to get out in the enterprise development area. For their sake and ours.

Thursday, June 21, 2007

include Spring

I've gotten a little farther with my JRuby on Rails Spring integration code. I think I have what may make the beginning of a Spring plugin for JRuby on Rails. Here's the code for the Spring module. This is my first foray into metaprogramming in Ruby, I'd welcome any feedback.

# spring.rb
# June 20, 2007
#


module Spring
include Java
import javax.servlet.ServletContext
import org.springframework.web.context.WebApplicationContext
import org.springframework.web.context.support.WebApplicationContextUtils

def spring_bean (bean)
class_eval "def #{bean.to_s}; application_context.get_bean(\"#{bean.to_s}\"); end;"
end

# dunno if there is a better way to do this. I need the spring_bean method
# to become a class method on the includee, but application_context needs to be
# a normal instance method
def self.append_features(includee)
includee.extend(Spring)
includee.class_eval do
def application_context
WebApplicationContextUtils.getWebApplicationContext($servlet_context)
end
end
end
end

This gives you a handy spring_bean method in any class where you've included Spring. The spring_bean method will then dynamically add an accessor to the class you use it in. This is what it looks like in a controller:

class TestSpringController < ApplicationController
include Spring
spring_bean :descriptor1
def showcontext
render_text descriptor1.displayName
end

end


Obviously to have this working you need several things. You need to have the goldspike plugin (from SVN trunk as per my earlier post). You also need to have Spring and its dependent jars in your WEB-INF/lib. I just copied em in for playing around purposes, with a little tweaking of my conf/war.rb file I could probably make goldspike fetch them. And lastly, it assumes you have an applicationContext.xml in WEB-INF, and that you have the Spring ContextLoaderListener declared in your web.xml.

Wow, that's a lot of trouble, why the heck would I want to do all that? What's this all for anyways? First of all, if you need this you probably don't need to ask, you know who you are. No, I'm not even trying to suggest using Spring for greenfield JRuby on Rails applications. But if you need to do heavy Java integration or you have an existing Spring application you want to front end in Rails, this kind of thing could end up being quite handy. This is my situation: I have a pretty large Spring/Hibernate/Tapestry app and I'd like to make moving to JRuby on Rails a viable option. Rather than replace everything whole hog, I'd like to be able to leverage working Spring services easily from Rails. As you can see, doing this should be a piece of cake.

Monday, June 18, 2007

Spring + JRuby on Rails

I've only been threatening to do this for a year, but I finally added the necessary stuff to have JRuby on Rails talking to Spring. There's a lot more to come here, but this controller code demonstrates being able to get ahold of a Spring WebApplicationContext in a Ruby on Rails controller.

class TestservletController < ApplicationController
include Java
import javax.servlet.ServletContext
import org.springframework.web.context.WebApplicationContext
import org.springframework.web.context.support.WebApplicationContextUtils

def showcontext
app_context = WebApplicationContextUtils.getWebApplicationContext($servlet_context)
render_text app_context.display_name
end
end


In order for this to work, you'll have to use the very latest goldspike-snapshot plugin from SVN trunk. I just checked in the code to expose $servlet_context earlier today. Obviously this code will only work using a servlet container, and you'll need to have Spring and necessary deps in WEB-INF/lib and have the Spring context loader listener in your web.xml. From here, my next step is some metaprogramming to allow you to add spring bean accessors into your controllers.