Friday, September 25, 2009

Embedding web UI components in Eclipse using e4

The demand for software that can be accessed through a web UI is increasing. We already expect software for occasional use (e.g. online shopping, banking, filling out forms, ...) to be accessible from a browser, without having to install anything locally. Over the last few years, more and more producticity applications (email, documents, spreadsheets, etc.) have become available through browsers as well. It is only a question of time until software development tools (at least for a certain class of uses) will have to have a web UI as well. In fact, a few browser-based IDEs already exist, such as Mozilla's Bespin project, and a very recent example: embed, a special-purpose IDE for embedded development.

At the same time, locally installed "rich client" applications, especially software development tools, aren't going to go away soon - there is a huge investment in the tools we have today, and I don't expect that all of this will be reimplemented using other technology just because web UIs are now the cool new thing to do.

So the obvious question is, how can we, the Eclipse community, prepare ourselves for the trend towards the web, while keeping our desktop users happy?

One approach is to keep the current programming model and just "make the stuff run in a browser". Fundamentally, this is very hard because the existing code we have today is not written with a client-server separation in mind. To a certain extent, it can be made to work though, and we have two examples of this at Eclipse, in form of the RAP project, and the experimental "SWT Browser Edition".

The basic idea behind RAP is to place all application and UI logic on the server, including all widgets and their state, and to render those widgets on the client in a web browser while sending user events back to the server. However, there are a couple of characteristics of RAP that limit its applicability: For example, the "stuff" you run in a browser will be a complete application as opposed to individual UI components, high-latency situations are problematic, and you cannot run application code on the client side. (I hope the RAP team will let me know in the comments if I got any of this wrong.)

The work on SWT BE "browser edition" is another take at the same problem, taking, if you will, the opposite approach: Client code (application and UI logic) makes use of the SWT API and as such can run in a desktop situation just fine. For "making it run in a browser", all the code is cross-compiled - to JavaScript for the Dojo port of SWT, or to ActionScript for the Flex port of SWT. So in a nutshell, instead of placing all application code on the server as with RAP, all application code ends up running on the client, in a browser. The obvious problem with this approach is that you still need code that runs on the server, to at least send data to the client and to receive updated data from the client, and that more often than not, you will end up with too much code on the client for execution. Of course, you could rewrite your existing code and ensure a proper client-server split, but if you are rewriting it anyway, why not go all the way and rewrite it using HTML and JavaScript?

For the e4 0.9 release, we have done the first step of exactly that - we rewrote or "cloned" an existing component using HTML, CSS, JavaScript, and Dojo on the client side. The idea is to gradually move certain components (not complete applications) over to use web technology, while still having these components appear in the desktop Eclipse client as first-class citizens. As a first example, we chose the PDE site.xml editor, because of its relative simplicity but also because it is a good representative of a whole class of form-based UI components in Eclipse. We wanted the end result to run in a regular browser, as well as an editor inside of Eclipse. Here you can see it running stand alone in a browser:

To make the editor work in a regular browser, it had to have a "real" server-side counterpart. Luckily, Eclipse already ships with an embedded servlet container, Jetty. This means that the web UI editor could talk to a servlet running in the same VM as the embedded browser widget rendering the UI. This is not unheard of at all - the Eclipse help system is taking the exact same approach.

However, just presenting the unchanged web UI in an embedded SWT browser widget - backed by IE if you run Windows, Firefox on Linux, and Safari on the Mac - is not enough. The editor would only be a first-class citizen in the Eclipse UI if, for example:
  • you didn't have to authenticate to the web UI every time you open an editor,
  • the editor signaled unsaved changes through the usual "*" in the editor tab, as opposed to an indicator in the editor itself,
  • you can trigger saving your changes using the menu (File>Save ),
  • etc.
In other words, the editor needs to make use of appropriate Eclipse APIs that connect Eclipse UI components such as views and editors to their context: the Eclipse workbench. One of the goals of e4 has always been to simplify the core APIs, and to make them accessible from other programming languages. So in a sense, we have started to make this real by offering JavaScript APIs that can be called by web UI components: to signal that they have unsaved changes, to provide a callback that will save those changes, etc.

Give it a try! After downloading the e4 0.9 SDK, start it up with an empty workspace and create an update site project (Ctrl+3, 'nusp'). Add some features and categories to it using the regular PDE site.xml editor, save, and then right-click on the site.xml file and use "Open With" to open it with the web-based editor. It will look like this:

Please leave comments if you have any questions. I will try to write up more about this in the next couple of days, going into more technical detail.

Thursday, September 24, 2009

API compatibility matters

A few weeks ago, Palm has released an SDK called "Mojo" for their WebOS. They also offer Eclipse plug-ins that have been developed for and tested with Eclipse 3.4.2. I just read a short review of this Eclipse-based tooling and was happy to see the following:
The WebOS plug-in is supposed to officially work with Version 3.4.2 of Eclipse (code-named Ganymede). However, I was able to successfully run it on Version 3.5 of Eclipse (code-named Galileo) without any problems.
It makes me happy to see real-world reports like this. They confirm that you can run plug-ins developed for older versions of Eclipse on more current versions. In the Eclipse community, we almost take this for granted and sometimes tend forget the effort involved in pulling this off. Because when you think about it, compatibility is only achieved when both sides do a good job of enabling compatibility:
  • On the Eclipse SDK side, we tend to think that we are doing good job of ensuring API compatibility between Eclipse releases, so that you can run older plug-ins on newer versions of Eclipse. Since Eclipse 1.0 (2001), we've had excellent rules in places around API compatibility, and if you want to read more I'd recommend you start at our "API Central" wiki page. More recently, we've automated a lot of the necessary compatibility checking in form of API tooling that ships with the Eclipse SDK. I haven't seen anything like it for other languages or environment yet, but would like to hear if similar tooling exists elsewhere. C#? ActionScript? Let me know in the comments!
  • On the Palm Mojo side, the developers must have done a good job of only using documented APIs, and abiding by the contracts for those APIs. Because if you don't, all bets are off.
Here is a quote from the 2001 article "How to use the Eclipse API" by Jim des Rivieres, a recommended read for anyone developing Eclipse plug-ins:
As the Eclipse platform matures and evolves, it will be the API contracts that guide how this evolution happens. Outside of these contracts, everything is unsupported and subject to change, without notice, and at any time [...]. Client code that oversteps the above rules might fail on different versions and patch levels of the platform; or when run on different underlying OSes; or when run with a different mix of co-resident plug-ins; or when run with a different workbench perspective; and so on. [...] To those who choose to ignore the rules, don't say that you weren't warned. And don't expect much more than a sympathetic "Told you so."
Of course, in reality, life is never as easy and black-and-white as software developers would like it to be. Sometimes, the existing API doesn't work for your particular case, or there is no supported API at all. In these cases, however, you need to realize that by calling internals, you are assuming technical debt. The idea behind this metaphor, created by Ward Cunningham, is that you have taken a shortcut and need to pay up later, either in form of interest payments or paying back the principal. In concrete terms: Whenever a new version of the plug-ins you depend on comes out, you have the cost of testing that your code still works, and the cost of adapting to any change that may have broken your code. This is a recurring cost, hence the term "interest". If you want your code to run against both older and newer versions of your dependencies, the interest payments are much greater, because the problem is much harder. Often, you will need to use Java reflection to guard your calls to internals. Alternatively, you can pay back the "principal" at a later point in time, when the necessary API has been added, and get rid of your debt. You did file an enhancement request to get that API added, didn't you? Because if you don't, you'll be bound to pay interest forever!

Every now and then, I encounter people who are hoping to get away without paying either interest or principal. And that's after our collective experience with how schemes based on trading debts can take the whole economy down! :-)