Ruby-in-XPages is Inching Towards Practicality

Apr 4, 2012, 9:20 PM

Tags: ruby xpages

I've made some more encouraging progress today in my quest to be able to actually use Ruby when doing XPages development. I implemented method binding (as opposed to just value binding) and found a way to shim in the interpreter so that Ruby can be used for early events like beforePageLoad. The revised code is up on my GitHub profile:

That last part was kind of tough - I found structures for custom Application objects in the XSP Starter Kit, but I couldn't for the life of me get the faces-config.xml directives to work, like the runtime was ignoring the /faces-config/factory/application-factory node entirely. I set that aside for now and instead picked up on ViewHandlers, which can fire at the start of each page request, which works for this purpose. I wrote a custom handler that adds the RubyBindingFactory if it's not present and then otherwise hands control off to the standard Domino variant.

Another big hurdle I encountered was variable resolution. When making my proof-of-concept servlet, I inserted a couple standard variables, but that wouldn't cut it here - beyond the usual suspects like session and view, I had to make sure that Ruby could find local xp:repeat variables and other non-globals. After trying to find a way to either get a list of available variables in the current Faces context or write a proper variable resolver to attach to the Ruby runtime, I decided to just go the Ruby route for now: method_missing. When instantiating a Ruby runtime, I add facesContext as a global variable and run a bit of hard-coded Ruby to create a method_missing method to act as a variable resolver. Good enough!

So what's next? A couple things I can think of:

  1. Efficiency and doing it the right way. The whole thing is still a bit too hacky for my tastes. It may end up being the best way to do it, but I haven't given up on refining it. Additionally, I currently create a new Ruby runtime for each value and method binding, which is overkill - I think there should be one per page.
  2. Designer. Though Designer rarely outright complains about Ruby code (it doesn't like Ruby's #{} string-interpolation syntax for understandable reasons), I'd love to get it to stop throwing warnings around, but that's not a high priority.
  3. Edge cases. xp:repeat controls appear to do their own syntax-check pass that doesn't like Ruby, so I'd like to figure out how to work around that.
  4. Ruby "Script Libraries". If nothing else, I'd like to add the ability to bring in .rb file resources in a similar way to you reference Server JavaScript. Presumably, I could do this by checking, at initial page load, for controls with certain properties and then fetching the script content like I did for servlets.

I also remembered another potential related use for JRuby: writing Java classes in JRuby and having Designer translate them to Java design elements. I did a little bit with this a while ago, adding a custom builder that would fire for .rb files, use JRuby's API to translate it to Java code, and then store it. If I recall correctly, Designer's built-in builders even automatically took the Java and compiled it. If that would actually work smoothly, it should result in code performance somewhere in between pure Java and Server JavaScript.

I'll turn Domino into a developer-friendly environment if it kills me!

Commenter Photo

Nathan T Freeman - Apr 5, 2012, 1:28 AM

"...I couldn't for the life of me get the faces-config.xml directives to work..."

I don't have the code available in front of me, but go to the StarterLibrary that extends AbstractXspLibrary, and change isGlobal() to return true. It has a rather dramatic effect on any server that it's installed on, but it should then cause the ApplicationFactory to be recognized.

Commenter Photo

Nathan T Freeman - Apr 5, 2012, 1:32 AM

"I'd like to add the ability to bring in .rb file resources in a similar way to you reference Server JavaScript"

You should be able to load any .rb file resources in the NSF at runtime through the normal Eclipse plugin resource file model as long as they are in the WEB-INF folder of the NSF. Technically, you can also retrieve them as plain ol' NSF file resources, but you have to use the runtime VFS to do so. There is a very subtle example of using the runtime VFS in the Starter Kit, but we really should get something more robust in there.

I have to be honest, you're doing something I really really wanted to do myself, but haven't had time. :-) So if you can get on the Bleedyellow Sametime server or find me on Skype, I would love to collaborate on this.

Commenter Photo

Maureen Leland - Apr 5, 2012, 11:17 AM

Assuming this is at least 8.5.3, you should be able to create your own design element for ruby files, and they would be loaded at runtime. My Lotusphere presentation has the details, but that would be a prettier way of bringing the files in.

New Comment