Thursday, 14 January 2010

NetBeans, Ruby on Rails, smartGWT and eclipse can work together!

This post is all about RAD on steroids. Combining the awesome power of SmartGWT with Ruby on Rails is a compelling, powerful and extremely fast development approach for real world Web 2.0 applications.

One of the big problems with Ruby on Rails is that that is has limited Web 2.0 support. Yes, there is prototype built in, but the truth is that if you want to build proper Ajax applications, prototype is playing in a different field. It doesn't attempt to provide the sort of Web 2.0 features that YUI, smartGWT or jQuery provide.

In my opinion, the best Web 2.0 development system out there is Google's GWT. There are many frameworks, such as YUI and jQuery that provide exceptional features, however they require you to code in JavaScript and whilst these libraries themselves offer tested and debugged code that is highly portable across browsers, hand-coding JavaScript yourself quickly becomes a quagmire of browser compatibility issues and arcane debugging techniques.

Enter GWT which allows you to not only code and debug in Java, but has an extremely good (and continuously improving) Java to JavaScript translater. This produces browser-portable, optimised JavaScript. Moreover, as browser releases continue, GWT has the added advantage of keeping up to date with the latest releases and a quick recompile of your code is all that you need to ensure that your JavaScript works with the latest browsers in the most optimal manner.

SmartGWT is one of the best (many argue, the best) Web 2.0 frameworks available. It has a vast array of features and capabilities. Not only has it the breadth of service, it also has depth with each component being fully customisable and extensible. Because it's written in Java, you can take full advantage of Java programming techiques. My experience of SmartGWT is that it's the Web equivalent of programming in Swing except in many ways it's more feature rich and powerful than swing. Certainly the components look better designed and stylish!

If you use GWT, although it is possible to use other IDEs such as Sun's NetBeans, the only real player in town is Eclipse. There are many assumptions made in GWT and the supporting documentation that you are using Eclipse and the tide is such that you would be ill-advised to try use another IDE. Why waste the time? So for the Web 2.0 client-side development, your best choice is Eclipse, SmartGWT and GWT. It's stack that works extremely well.

 However, the best player in town for RAD is Rails. The reason is one word: ActiveRecord. Okay, there are many reasons why Rails puts the R in RAD, but ActiveRecord is so powerful, it is so quick to define the way your tables relate to each other and ActiveRecord does so much heavy lifting for you as well as makes your Ruby code so very readable and elegant that it has to be one of the best features in Rails. Not only is ActiveRecord a pleasure to work with, but because it is so well implemented and so quick to set up, marrying ActiveRecord to SmartGWT produces massive coding benefits and saves vast amounts of not just initial development time, but more crucially maintenance and debugging time.

Not only does ActiveRecord make Rails development a dream but bear in mind that few applications online are stand-alone. Most are embedded in web sites and those web sites are fully designed, subject to changes and have active lifecycles. This is what Rails excels at. It was designed to allow developers to work with designers and to minimise the impact of changes as well as to turn around sites very quickly. All these advantages (and many more) Rails delivers with ease. So given the context of Web 2.0 apps sitting in a web site's ecosystem, Rails becomes even more compelling as it handles both sides of the equation with ease. Moreover, it keeps your coding simple, it implements DRY (Don't Repeat Yourself) and it's a joy to work in. You write fewer lines of code and as a result make fewer mistakes and your code is easier to debug.

For a fully fledged IDE for Ruby on Rails that not only provides all the features that you need but also takes the headache out of deployment and will neatly package up your Rails app into a fully fledged, works-out-the-box JRuby WAR file, there is no other choice but Sun's NetBeans. That's not to say that there are other very good alternatives, textmate being the obvious contender. But NetBeans has something very special in the ease with which it allows switching between Ruby and JRuby and the way in which you can package the finished product up and deploy to an app server.

A point of disclosure is needed: I am heavily biased towards JRuby as I see it bringing not just the full catalog of Java libraries to the Ruby table but also implements proper multithreading (a Ruby bane) and tremendous performance advantages. Moreover, a tight integration between Ruby and Java is a very enterprise-ready direction. Given that so few greenfield sites exist in the enterprise, who integrates, wins is the rule of survival and JRuby is the golden goose in this department.

So now we have NetBeans running Rails as the back end and Eclipse running SmartGWT as the front end.

How to get them to talk to each other?

The issue that you will run into is SOP, Same Origin Policy. This is a security restriction that the JavaScript engines place on browsers that means that you cannot have javascript that you loaded from one domain access data from another domain. Given that Eclipse will run GWT (and hence SmartGWT) in development mode on port 8888 and your Ruby on Rails will run under NetBeans on port 3000, this is a problem. Your SmartGWT will not be able to access your ActiveRecord bindings in Rails.

Whilst there are solutions out there that implement various types of HTTP proxy, the veteran Apache server has a fully fledged, easy to implement and easy to maintain proxy server.

What does a proxy server do? It allows your web browser (where your SmartGWT application will be running) to load the SmartGWT application (i.e. the JavaScript that is subject to SOP restrictions) from the same domain as your Rails application (running on Netbeans) will respond to. Even though Eclipse and NerBeans could be running on different development machines as well as usuing different ports, the proxy server (apache) invisibly reroutes these requests. The browser thinks that it is only talking to Apache on the same port. Apache is able to take those requests and, with the aid of mappings that you specify, work out where each request actually routes to. I.e. It will send Rails requsts to NetBeans and GWT requests to Eclipse.

By using Apache as a proxy, you overcome the Same Origin Policy restrictions of JavaScript and your SmartGWT can now talk to Rails and vice versa.

There are only two small problems left in this cunning plan to get SmartGWT working with Rails.

The first is the issue of SmartGWT and REST. To be blunt, it's broken with Rails. SmartGWT doesn't implement dynamic URLs and as such, the Rails method of mapping REST resources simply doesn't work because URLs like /controller/action/id/ simply are not constructed by SmartGWT. Moreover, the action that SmartGWT intends to happen is embedded in a parameter called _operationType and the restrictions caused by SmartGWT's static data URLs are such that Rails will misinterpret the REST calls, mistaking an update, for example, for an insert.

Whilst it is possible to subclass the SmartGWT datasources and manully add URL manipulation to force SmartGWT to confirm to Rails' URL usage, this sits badly with SmartGWT as the parameters that it passes need to be interpreted by Rails in any case. Not only this, but your Rails controllers quickly begin to get bogged down with the extra coding needed to support SmartGWT's parameter passing. It all starts to get messy and complicated rather quickly and the whole point of using Railis is that it's so quick and easy to implement controllers, models and views. I.e. Data bindings.

The solution is to use the flexibility of the Ruby language and the awesome Rails design. We subclass the ApplicationController class to create a new class  for controllers, IscController. In this controller, we add helper methods that will cleanly build model view instances, understand the SmartGWT way of doing things and build SmartGWT-friendly responses.

This will then enable us to create SmartGWT-enabled controllers just as we would "normal" controllers by using:
     class MySmartGWTController < IscController
instead of the usual

     class MySmartGWTController

From then on, our controllers remain as simple and elegant as any other Rails controller, the power of ActiveRecord is at our disposal and the Rails application talks the same flavour of REST as the SmartGWT client code.

The second issue with the Rails <-> SmartGWT integration is Rails' authentication_token parameter. This is an anti-forgery device intended to stop spoofing of REST calls by hackers. It's a code that Rails automatically sets when a browser connects to the application and Rails maintains this code invisibly. However, SmartGWT's AJAX calls do not pass Rail's authentication_token. The solution is to create a JavaScript variable alongside the isomorphicDir variable and to explicity add this into the SmartGWT's DataSource URLs.

We will see how these are implemented in later blogs. For now, we have the principles of how to get the best of both the SmartGWT as well as the Ruby on Rails worlds, without compromise and at full power!

6 comments:

  1. Awesome idea! I'm gonna give it a shot this weekend.

    ReplyDelete
  2. Hope that it worked out for you. I am finding it an incredibly powerful development platform.

    ReplyDelete
  3. Quite a few people seem to have a problem with the apache proxy config. So here is how I do it on Kubuntu.

    I have the standard Kubuntu setup which http2. I also have the proxy module installed (use the Ubuntu/Kubuntu installers for this if you don't have it as a default).

    You will find this directory:
    /etc/apache2/sites-enabled/

    In it, create this file:
    010-proxy

    And in the file, place YOUR version of this (note that my GWT app is called mainApplication and runs on port 8888 and my Ruby on Rails app runs off root on port 3000):


    ServerAdmin spam@kieser.net
    ServerName gwtproxy.kieser.net
    ServerAlias localhost
    ErrorLog /var/log/apache2/gwtproxy.kieser.net-error_log
    CustomLog /var/log/apache2/gwtproxy.kieser.net-access_log common

    ProxyHTMLLogVerbose On
    LogLevel Debug


    ProxyPass /mainApplication.html http://localhost:8888/mainApplication.html
    ProxyPassReverse /mainApplication.html http://localhost:8888/mainApplication.html

    ProxyPass /mainApplication.css http://localhost:8888/mainApplication.css
    ProxyPassReverse /mainApplication.css http://localhost:8888/mainApplication.css

    ProxyPass /MainApplication http://localhost:8888/MainApplication
    ProxyPassReverse /MainApplication http://localhost:8888/MainApplication

    ProxyPass /sc/ http://localhost:8888/MainApplication/sc/
    ProxyPassReverse /sc/ http://localhost:8888/MainApplication/sc/

    ProxyPass / http://localhost:3000/
    ProxyPassReverse / http://localhost:3000/

    DocumentRoot /var/www

    ReplyDelete
  4. I am so glad i came across this post. Have just started a new project and needed some really powerful AJAX to make it work. The thought of making and maintaining all that code in jQuery just wanted to make me moan.
    Any timeframe on when you are going to publish the second part of this post with the actual implementation? It would be of immense help to me.

    ReplyDelete
  5. Is there any updates about this awesome idea?
    I'm also wondering about this RAILS and SmartGWT to work together, though I think, it will be very hard to configure.

    ReplyDelete
  6. Apologies for the very long delay, the volume of work that I have had stopped me writing up. I hope to be updating the second part next week. Thank you for all the many kind words that people have written. It's much appreciated.

    ReplyDelete