Announcement: TorqueBox

18 May 2009

java jboss rails ruby

I announced the TorqueBox project today.

It's the coolest platform for your Ruby applications, ever. Really.

Trip Report: Raleigh RubyCamp

20 October 2008

37signals camp cobbler donuts genome raleigh redhat ruby

I did the round-trip from the land of cows to Raleigh to attend the Raleigh RubyCamp over the weekend.

I think I heard about 80 folks showed up, but I'm not certain on that.

Mark (root@37s) and James did a very nice job of organizing it. They provided good coffee and donuts to start the morning right. Krispy Kreme is never a bad idea.

We gathered, and a handful of folks presented introductions about what they wanted to do a session on. We then figured out the slots, and got started.

Brenton Leanhardt talked about Genome and Cobbler, two emerging technologies at Red Hat. Cobbler helps to stitch together distributions, Kickstarts and repositories, while Genome helps manage the inventory of virtualization hardware and the guest instances running on them.

His use-case for the technologies is the fact that we've got Xen hosts running on machines scattered under desks and in closets, which have been donated to a virtual pool.

Where did you launch that instance last month? Where can you launch a new instance today? Genome helps answer those questions. Many of the Genome bits are Camping apps.

I presented my short slide-deck about JBoss-Rails.

Mark Imbriaco led an open discussion about Rails deployments. It ended up mostly being us asking how 37signals did things. He described their hosting environment, their occasional frustrations with Mongrel, along with some stories about running migrations against a 100gig database.

Sean Cribbs talked about his experience in joining and then leading open-source projects, particularly Radiant CMS. He discussed breaking up the core into many plugins and modules, and the uptick in community participation that followed.

Overall it was a great weekend, and I even got some nice t-shirts out of it. Not bad.

Preliminary slides for JBoss-Rails at RubyCamp

18 October 2008

java jboss ruby rubycamp slides

Thanks to the typical demo demons, I've been unable to get everything functioning perfect for instantaneous clustering on EC2 by tomorrow.

Oh well.

But here's the first draft of some slides I'm taking with me to the Raleigh RubyCamp.

It's a BarCamp style event, so I anticipate the slides probably changing throughout the day. I'll published updates if needed.

Reminder: RaleighRubyCamp

30 September 2008

barcamp java jruby raleigh ruby

Don't forget, in a few weeks at the Red Hat offices in Raleigh, there will be an unconference-style Ruby BarCamp on October 18th.

My plan is to put together a few clumps of slides, prepare a cluster on EC2, and see if anyone wants to hear about JBoss Rails. I'll of course put them online sometimes before/during/after the camp, since that's part of the rules.

JBoss on Rails

22 September 2008

java jboss jbossas rails ruby

Tomorrow is my first real status update call with my boss, Sacha Labourey. I've been anxious to deliver something, to prove I hadn't gone completely pudding-brained during my tenure as management.

This morning, it all finally came together in a pleasing fashion, causing me to hoot and holler loud enough to scare the cats and probably some cows.

I've just pushed an ugly-but-working deployer targeting JBoss-AS 5.0.0.CR2 (the latest and greatest!)

It's not very consumable at this point, as it's just a deployer, not a nice Rails plugin with a set of Rake tasks. Heck, it doesn't even undeploy yet.

But adding the deployer to your server's deployers/ directory allows you symlink live RAILS_ROOTs into your deploy/ directory, and be running on JBoss.

Live. In-situ. Edit your controllers or views as you like, and your changes are immediately reflected in the running instance. Just like with ./script/server. It does not even have to redeploy your app. The rails framework is handling the magic reloading.

It's taken me some time to dig through the innards of JBoss-Microcontainer, and a few false starts, but I finally figured out a super simple deployment process.

I'd previously been trying to manipulate a RAILS_ROOT into a synthetic Java WAR archive, and shoe-horn things around that. But I have the freedom to go lower than that, so the jboss-rails deployer just sets up a Catalina context appropriately, without regard to WEB-INF or other non-Rails stuff. There's no need for that cruft. Likewise, I can directly control and manipulate the classpath, so the RAILS_ROOT does not even have to have any JRuby bits in it.

The example application (src/test/ballast) is a virgin rails app with ActiveRecord disabled so I don't have to deal with database-driver gems just yet.

Once deployed, a Rails app looks like pretty much any other web-app. The jboss.rails.deployment domain contains deployment objects for each rails app. And jboss.web contains all the webby bits floating around.

I need to go back and remove the dead-end code I've left in my wake, and update the tests I'd disabled while in a coding flury (bad Bob!) I plan to put together an easy-to-consume plugin gem which contains an nicely-configured AS along with the jboss-rails deployer pre-installed, along with rake tasks to start/stop AS, and deploy your app. I'd also like to give clustering a whirl, and see what we can do.

It's been an excellent 3 weeks back as an engineer.

And now, something slightly different

28 August 2008

java jboss jbossorg job jruby ruby

Back in May, I was a manager.

I feebly attempted to direct 8 great guys and gals to further the goals of JBoss.org. After the Codehaus, you'd think I'd be able to help build an opensource community with fun and flair. But I came to realize that it's hard to build a community as an active effort. Instead, I think community develops as a by-product of a useful and well-run project. And that's under the control of the project leaders and contributors, not necessarily some external third party.

Back in May, I gave up being a manger.

Now, the day after Labor Day, fittingly enough, I'll be jumping back into the world of JBoss. But not as a manager. When I was burned out and felt like resigning, Mark Proctor and Sacha Labourey instead talked me into taking a sabbatical. And I'm truly grateful to them. Now, after unwinding for a few months, I asked to rejoin the team as an engineer. Through Sacha's patience and budget manipulation, I'm once again excited to go to work. I think JBoss should definitely be held up as a company that takes care of its people. They could've easily given me the boot, but instead they've been extremely kind and accommodating.

So, what will I be doing?

After talking to Java developers and Rubyists alike, my first goals are to look at Rails as just-another-way to write J2EE apps (or "JEE" I reckon, these days...). Yes, I know about (and plan to use) things like Warbler and JRuby-Rack. Both are good things.

But I also have full control of the deployment environment, to build a stack to make it happier than "build and deploy a WAR".

Through the miracle of AS5 built on JBossMicrocontainer, along with the awesome VFS bits, it should be possible to deploy a Rails app in-situ, right from your working directory. There should be no reason to have to build a WAR while you're hacking a rails app. And deployment to a server should still involve capistrano (in my opinion). Stick to the Rails way of doing things, but make it Java under the covers.

Various blog posts have shown Rails apps on Glassfish in 12, 10, or 5 steps. My goal is to get it down to 1 step. And you should magically be able to pick up and use all the wonderful JEE bits that maps to the Rails functionality the Railers of the world enjoy, without having to be aware of the JEE bits.

Speaking with Mark Newton (the guy who runs JBoss.org now), it seems sensible to view Rails as simply yet-another-programming-model for writing Java apps. The idea is to avoid leaky abstractions, so we're not having to write some psuedo RubyJava application.

Once we've got that base covered, then we can make fun and exciting Ruby bindings to all the powerful JBoss tools, such as Drools, ESB, Cache or MQ.

I expect to have a bit of fun with this. More fun than being a manager, certainly.

Raleigh RubyCamp

25 August 2008

redhat ruby unconference

Oh, fortuna!

I'm rejoining the Red Hat/JBoss mothership, doing rubyish things, and what do you know, but there's a RubyCamp at the RHT HQ in Raleigh on October 18th.

37signals and Ruby Row are sponsoring the event.

Space is limited to 200, but at the time of this posting only 57 have signed up. It's an unconference, so bring your own good ideas, and you can lead a session

Be a smarter patch monkey

25 August 2008

git metaprogramming ruby

A project I'm working on requires some hard-core monkey-patching of Rails internals.

Monkey-patching is a dangerous occupation, and liable to cause new and intriguing bugs into previously-tested sane code.

I've been working on a smarter patch-monkey, known as Lemur.

The goal is to allow monkey-patched methods (currently only instance methods are supported) to be written in modules that are mixed in (as modules are) but allowing redefinition of methods in the patchee by the patcher module.

I may be ignorant of some Ruby to make it happen, but I've resorted to alias_method and remove_method, along with a handful of Ruby's reflection methods to swap methods in a reasonable, clean, and auditable fashion.

The specs demonstrate how it works. Assume a basic class:

  
class BasicClass
  def some_instance_method()
    # ...
  end
end

And a module to monkey-patch it

  
module PatchModule
  def some_instance_method()
    # ...
  end
end

Normally, Ruby will prefer a locally-defined method over a module mix-in, so you can't just include your patch module in, even using class_eval.

So, invite in the Lemur.

  
Lemur.patch_class(BasicClass, PatchModule)

And voila! Your class is monkey-patched by the nicely self-contained module, plus, it's tracked.

  
Lemur.patched_classes # [ BasicClass ]

And even more cool, you can get some patch-audit information for each patched class:

  
Lemur.patch_records( BasicClass ) # [ array of PatchRecords ]

Each PatchRecord keeps up with the patched class, the patched method name, the actual replaced Method object, along with the patch module and the patch method.

A total of 40min has been spent writing the code so far. The idea is to add better auditability, unpatching, and dealing with class methods, not just instance methods.

Now, when you encounter a weird bug, you can ask the Lemur where the oddness might've originated.

Want to pitch in and do some meta-programming to make future meta-programming less scary, fork my git repository and send me some pull requests.

Point of Use

22 December 2007

dsl java languages ruby

When we moved from C to C++, we were overjoyed that we no longer had to declare all of our variables at the top of the function.

do_something() {
  int num = 0;
  int another_num = 0;
  num = get_a_num();
  another_num = get_a_num();
}

We could instead declare them near the point of use, when needed.

do_something() {
  int num = 0;
  num = get_a_num();
  int another_num = 0;
  another_num = get_a_num();
}

Ultimately, the rule intends to make things visible to the smallest necessary scope. While technically "scope" is an entire block, actual scope for a given statement consists only of that statement and those that follow. Defining variables at the top of a block unnecessarily extends their scope beyond the actual needs.

That's great for variables. What about expressions or statements or blocks of statements?

When we hack out straight code, perhaps a one-time chunk of Perl or Ruby or bash, we declare a statement exactly at its point of use. If we don't name it, it's lost in the ether, immediately out of scope again.

rm -Rf path/to/stuff
mkdir other/path/to/stuff
cc -o google google.c

We climb up into the world of "engineering" and we start to create functions, or classes and methods. We give names to a chunk of statements and increase the visible scope of this code.

def turn_on_sprinkler()
  call_sprinkler_webservice( :on )
end

But have we just moved our declarations too high, like our variable declarations in C at the top of the block?

We follow a rule that if you use the result of an expression more than once, you should stuff it into a variable. A local variable. Not a global variable. More than likely not an instance variable.

How about if you use a statement more than once, you stuff it into a named block. A local named block. Not a global named block. More than likely not a method on a class.

notify = Proc.new{|person,message|
  person.email.send( message )
  person.sms.send( message )
}

notify.call( person.wife, "I'll be home late" )
notify.call( person.mistress, "Motel 6 in 10" )

Unless the functionality is required at any higher scope, declaring and defining named blocks locally prevents pollution of the namespaces.

With languages such as Ruby, instance methods can be defined upon instances that need them, instead of upon every instance of a given class.

def ship_via_cargo_container(item={})
  class << item
    def cube
      (self[:height]||1) * (self[:width]||1) * (self[:length]||1)
    end
  end

  freight_cost  = item.cube * 100.dollars
  handling_cost = item.cube * 10.dollars * 2
end

In effect, this view is one of macros. When it's convenient to create a short-hand notation, or a micro-DSL, do it where it has minimal impact on the rest of the system.

It could be argued that interpreters and compilers are not prepared to see and optimize for these types of blocks. The Java world surely keeps debating closures. I have no idea the impact on Ruby interpretation when you're constantly defining new methods on individual objects. But then again, there was a time we feared the overhead of managing objects instead of simply free functions and structs.

Unwind with Subversion

16 October 2007

codehaus jbossorg opensource ruby subversion tools

At the Codehaus and at JBoss.org, I've continually come across Subversion repositories that needed to be split apart or merged, perhaps after converting from CVS. One problem you continually hit, particularly if you're merging repositories, is the "date order of revisions" bug. Simply stated, if you create a new repository loaded from two other repositories, you can end up with a situation where revision N does not necessarily occur before revision N+1, in terms of the commit time-stamp.

When you do a date-based operation using Subversion, it does a binary search through the revision sequence to find the revisions matching the specified dates. This binary search assumes the revisions are indeed date-ordered.

With the acquisition of Mobicents by JBoss, we're in the situation of having to merge about a dozen repositories. Some are CVS, some are SVN. Good ol' cvs2svn works well for the first step, of converting a CVS repository into a SVN repository. But now we have either oddly disjoint repositories, or conflicting paths overlaid one another.

I've always been a fan of mod_rewrite for Apache-httpd, and a SVN dumpfile has a lot of paths just ripe for rewriting. 1000 lines of Ruby code later, I'm able to announce Unwind. Unwind is a Ruby library, along with a command-line tool, for performing mind-numbing feats of repository surgery.

Since a massive conversion and rewriting is something that requires a bit of trial-and-error, the command-line utility is ultimately driven by a configuration file. Of course, with Ruby, it's just a DSL created using instance_eval and blocks.

Picture 5.png

This configuration file will ultimate produce a single file (merged-repo.svndump) from multiple input dump files. Each source file can include()/exclude paths (based upon the original paths in that particular dumpfile). Each source can also use Rails-ish URL rewriting. The :something syntax matches 1 segment of a path, and is available as a substitution value in the output path for the rule.

The rewrite engine tracks all existing paths, and creates parent directories when necessary. SVN copy operations are fully adjusted both for the source and the destination paths.

Unwind automatically interleaves revisions to achieve total monotonically increasing time-ordering for the final repository.

Finally, before a revision is emitted to the output repository, addition include()/exclude() rules can be applied. For repositories converted from CVS, you may end up with a bundle of CVSROOT directories attempting to live in the same location. No reason to rewrite them to unique locations, as you can just exclude them before they get figured into the final output repository.

Unwind uses SQLite for organizing the meta-information about each repository and revision, while performing random-access seeks on the source dumpfiles to produce the final repository. While merging may be the common use-case, Unwind's rewriting also makes it useful just for extracting bits out of a repository.

At this point, this blog entry is the complete documentation for Unwind. But feel free to browse the SVN repository.