I have just decided to upgrade Eclipse, and thought it best to start from scratch. I do a lot of work in Java, PHP as well as Ruby on Rails and so I tried to set up an integrated environment using Eclipse. I have documented the steps here as much as a reminder for myself as a guide for other people trying to something similar.

First, download and unzip the Ecipse + J2EE package from http://www.eclipse.org/downloads/. You do not need to ‘install’ Eclipse as such, just put the uncompressed directory somewhere logical (/Applications on a Mac, for example).

  1. Launch Eclipse :P
  2. Select: Help -> Software Update -> Final and Install.
  3. Select Search for new features to install
  4. Check the Europa Discovery Service
  5. Select Add Remote Site
  1. Type in name: Aptana (For javascript support)
  2. Type in url: http://update.aptana.com/install/3.2/
  3. Select OK
  • Select Add Remote Site (For Ruby on Rails support)

    1. Type in name: RadRails
    2. Type in url: http://update.aptana.com/install/rails/3.2/
    3. Select OK
  • Select Add Remote Site (For SVN integration)
    1. Type in name: Subclipse
    2. Type in url: http://subclipse.tigris.org/update_1.2.x
    3. Select OK
  • Select Add Remote Site (for PHP support)

    1. Type in name: PDT
    2. Type in url: http://download.eclipse.org/tools/pdt/updates/
    3. Select OK
  • Select Add Remove Site (for Hibernate support)
    1. Type in name: Hibernate Tools
    2. Type in url: http://download.jboss.org/jbosside/updates/development
    3. Select OK
  • Select Finish
  • Select your nearest mirror, when prompted
  • Select Eurpoa Discovery Site -> Programming Languages -> Ruby Development Tools
  • Select PDT
  • Select Aptana
  • Select RadRails
  • Select Subclipse
  • Select Hibernate Tools
  • Select Select Required (to resolve dependencies)
  • Select Next
  • Accept the agreement(s) and select Next
  • Select Finish
  • Go for a walk.
  • Phew, so after all that, you should have an Eclipse IDE set up to support PHP, Ruby, Rails, Javascript, Java, Hibernate and Subversion. You can, of course, select many other tools from the Europa discovery site for other development tools, graphical editing and the like.

    Windy Road has a nice article on the use of Javascript And Hidden Applets, what they call JAHA.  This is similar to the technique I have used in Robonobo, however I am having all sorts of issues on Mactel Firefox, possibly due to the Apple MRJ / Firefox integration.

    It would be nice to have a small js library that allowed you to dynamically instantiate and destroy embedded, hidden applets.

    Finally worked this out…

    These pages are rather helpful: Mozilla’s guide to using proxies and XulPlanet’s description of the nsIProxyObjectManager

    This interface defines a proxy manager. An instance of this manager is used to create a proxy for a particular object on which you wish to invoke a method. If you are calling from any other thread that which you initialized xpcom on, you will need to do this, and as far as I am aware, there is no trivial way of doing otherwise.

    Anyway, the code to open a new window would be as follows. Note, this method assumes that there is already a constructed object called windowWatcher, which is an instanceof nsIWindowWatcher, see previous post for details.

     public void openWindow(String chromeUri, String name) {
    nsIEventQueueService eventQueueServive =
    (nsIEventQueueService)serviceManager.getServiceByContractID(
    "@mozilla.org/event-queue-service;1",
    nsIEventQueueService.NS_IEVENTQUEUESERVICE_IID);
    
    nsIEventQueue eventQueue = eventQueueServive.getSpecialEventQueue(
    nsIEventQueueService.UI_THREAD_EVENT_QUEUE);
    
    nsIProxyObjectManager proxy =
    (nsIProxyObjectManager)componentManager.createInstanceByContractID(
    "@mozilla.org/xpcomproxy;1",
    null,
    nsIProxyObjectManager.NS_IPROXYOBJECTMANAGER_IID);
    
    nsIWindowWatcher windowProxy =
    (nsIWindowWatcher)proxy.getProxyForObject(
    eventQueue,
    windowWatcher.NS_IWINDOWWATCHER_IID,
    windowWatcher,
    nsIProxyObjectManager.INVOKE_SYNC );
    
    windowProxy.openWindow(null, chromeUri, name, "centerscreen", null);
    } 

    The code here uses the service manager to get an instance of the event queue manager, which is subsequently used to retreive the main UI event queue. This is then passed to the proxy manager’s getProxyForObject method, along with the IID of the nsIWindowWatcher interface, the actual instance, and flag representing the type of proxy operation (async, sync, etc, see the xulplanet page for more info).

    This method returns an instance of nsIWindowWatcher, which is actually a proxy which will inject events onto the UI thread for you. Then, just use the object as normal, sweet!

    After poking around for some hours (then days) trying to find some useful information on how to use JavaXPCOM (which is a bridge between XPCOM and Java, formally known as Javaconnect) I stumbled across a few things as well as hacking together some understanding myself and through C++ examples of XPCOM usage.

    We decided a while back to adopt an XML based protocol wherever possible, and moreover, RDF where appropriate. When communicating with a central server, this would use HTTP, so it seemed logical to use the same on the localhost. So, XUL uses AJAX, basically, to do asynchronous calls over HTTP to localhost, and retreives XML which is then passed into objects representing the returned resources. This way, we dont need to heavily integrate Java and XUL using XPCOM, and we allow other applications to be able to place nicely with the API over a well-known protocol and format. Anyway, this means that the only work JavaXPCOM needs to do is:

    • Start XPCOM using a XULRunner installation
    • Start an XUL window and pass control over to it
    • Be able to call javascript/xul events from java (to open windows, etc)

    So to start with, we need to find an XULRunner install. As it stands, we will distribute a version with the installer, but JavaXPCOM contains code to easily find installed versions as well (this is actually documented on the JavaXPCOM site).

    1. Set the path the XULRunner directory, here we are doing it explicitly:
      File grePath = new File(new File(".").getAbsolutePath(), "platform/win32/xulrunner");
    2. Next create an instance of the LocationProvider
      LocationProvider locProvider = new LocationProvider(grePath);
    3. Initialize JavaXPCOM embedding:
      Mozilla.getInstance().initEmbedding(grePath, grePath, locProvider);
    4. Now we need to start an XUL application, so we get an instance of the XPCOM service manager
      nsIServiceManager serviceManager = moz.getServiceManager();
    5. Now we need to get the @mozilla.org/toolkit/app-startup;1 service:
      nsIAppStartup appStartup = (nsIAppStartup)serviceManager.getServiceByContractID("@mozilla.org/toolkit/app-startup;1", nsIAppStartup.NS_IAPPSTARTUP_IID);
    6. Get the nsIWindowWatcher interface to the above
      nsIWindowCreator windowCreator = (nsIWindowCreator)appStartup.queryInterface(nsIWindowCreator.NS_IWINDOWCREATOR_IID);
    7. Get the window watcher service
      nsIWindowWatcher windowWatcher = (nsIWindowWatcher)serviceManager.getServiceByContractID("@mozilla.org/embedcomp/window-watcher;1", nsIWindowWatcher.NS_IWINDOWWATCHER_IID);
    8. Set the window creator (from step 6)
      windowWatcher.setWindowCreator(windowCreator);
    9. Create the root XUL window:
      nsIDOMWindow win = windowWatcher.openWindow(null, "chrome://your-app/content/window.xul", "mywindow", "chrome,resizable,centerscreen", null);
    10. Set this as the active window
      windowWatcher.setActiveWindow(win);
    11. Hand over the application to xpcom/xul, this will block:
      appStartup.run();

    Now, the LocationProvider is responsible for providing path(s) and file(s) that XPCOM needs. I have implemented a version that when the ‘ChromeML’ location is asked for returns an array of File’s, the first of which points to my own applications chrome folder, and the second of which is the xulrunner’s own chrome folder. This seems to work, but there are several issues:

    1. I do not seem to be able to open XUL windows (or in anyway interact with xpcom/xul) from another thread. Since this run() method on nsIAppStartup blocks, this is a bit annoying. I presume there is a way to run this loop manually, or hook into it so we can queue up requests from other threads to be invoked on the xpcom thread.

    Ok, thats only one major issue for now, but I’m sure I will think of others.
    If anyone has any ideas how these problems can be solved, or how one may circumvent them, I’m all ears. Also, I know that this area is so bleeding edge it hurts, so it would be nice to talk to some other people doing the same things!

    Ajax, Development @ 22 October 2005, “No Comments”

    Ajax is damn cool.

    I am currently working on a small project using Google Maps which displays properties on a map. There is a central object which manages communication (via googles GXmlHttp) with the servers-side php. Upon response, this same object parses the response XML and then updates its observers.

    Each component then has an object which manages its display, it subscribes to the main object, and upon update will redraw that elements innerHTML, mostly by transfrorming the responseXML with XSLT using googles GXslt class).

    This got me thinking about a component base widget framework implemented in javascript, something that a server side application could easily communicate with. Imagine something like awt/swing being rendered to a javascript/html browser, rather than a normal windowing system. Upon an event, the component would send the event object back to the server, the server would process this, and update all components subscribed to the model, the components would then decide whether they need to be redrawn or not, and the new state of these components would be collected, packaged up in xml, and sent back to the client.

    This would mean that only the components that change would need to be updated and redrawn, and the whole page need not be reloaded.

    A quick poke around found a couple of interesting projects: