Thursday, February 23, 2012

Creating a headless application

There are times when you might want to run your RCP application in headless mode. While this is typically not the default mode for applications it might still be useful as an alternative launch option. Eclipse comes with a wizard for this. let' see how it works.

Source code for this tutorial is available on github as a single zip archive, as a Team Project Set or you can browse the files online. 


Step 1: Create the Application

Create a new Plug-in Project called com.codeandme.headless. Eclipse allows to register applications, classes that implement IApplication. At startup eclipse allows to launch exactly one of these classes which is the main entry point to your application.

Lets build such an application: first lets create the extension point for it.
Therefore open the MANIFEST.MF file and switch to the Extensions tab. Add a new org.eclipse.core.runtime.applications extension. Create a new run subnode and set the class name to com.codeandme.headless.Application. The ID of our application will be comprised of the plugin name followed by the ID of the root node of the extension. So lets set the ID to application. The final plugin.xml should look like this:
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<plugin>

   <extension
         id="application"
         point="org.eclipse.core.runtime.applications">
      <application
            cardinality="singleton-global"
            thread="main"
            visible="true">
         <run
               class="com.codeandme.headless.Application">
         </run>
      </application>
   </extension>
</plugin>
Clicking on the class link creates the java class:
package com.codeandme.headless;

import java.util.Map;

import org.eclipse.equinox.app.IApplication;
import org.eclipse.equinox.app.IApplicationContext;

/**
 * This class controls all aspects of the application's execution
 */
public class Application implements IApplication {

 @Override
 public Object start(final IApplicationContext context) throws Exception {
  System.out.println("Hello RCP World!");
  final Map<?,?> args = context.getArguments();
  final String[] appArgs = (String[]) args.get("application.args");
  for (final String arg : appArgs) {
   System.out.println(arg);
  }

  return IApplication.EXIT_OK;
 }

 @Override
 public void stop() {
  // nothing to do
 }
}

Instead of a java main() we now have to implement start() and stop(). We are not interested in UI here, so we simply print some messages to the console and finish.

Step 2: A simple test run

Open the Launch Configurations and add a new Eclipse Application launch. On the main tab activate Run an application and select com.codeandme.headless.application. Make sure all required plug-ins are selected and give it a try. You should get some print outputs on the console.


Step 3: Create a Product Configuration

We will create a very basic product configuration here just to get a working runnable.

Select our Plug-in com.codeandme.headless, and select New -> Product Configuration from the context menu. Set the File name to "Headless" and select "Create a configuration file with basic settings".



On the Overview tab find the section Product Definition and hit the New... button on the righthand side of the Product line.

Enter a nice Product Name and a unique Product ID. Make sure the Application is set to com.codeandme.headless.application. The Defining Plug-in needs to be part of your exported RCP, in our case we will simply use com.codeandme.headless for this purpose.


Switch over to the Contents tab and add com.codeandme.headless. Further add the plugin org.eclipse.core.runtime, then select Add Required Plug-ins to automatically resolve all dependencies. Save your Product Configuration and test it by selecting Launch an Eclipse application on the Overview tab. Again you should see the output on the Console view.

Step 4: Exporting the RCP Product

Start the Eclipse Product export wizard from the Overview tab of the Product Configuration. Just select an appropriate destination Directory and let the wizard do the rest. In case you do this multiple times it might help to manually wipe the destination directory before starting a new export.

This way of building products is fine for a test run, if you are interested in a more  professional way of building products, have a look at my tycho tutorials.

Step 5: Running the Application

To run the application just double click eclipse.exe in the destination directory. Still this won't give you any output. So fire up a console and enter

eclipse -application com.codeandme.headless.application -consoleLog -noExit first second last
  • -application
    will tell eclipse which application to start. You might omit this if you want to run the default application you exported. It makes sense for RCPs with multiple applications though.
  • -consoleLog
    opens a dedicated eclipse console and should be well known already.
  • -noExit
    will keep eclipse running even if our application finished. It keeps the console open to examine output 
The other parameters are passed to our application and therefore will be parsed and printed.

Monday, February 6, 2012

Eclipse integrated JavaScript Interpreter

I am working on an integration of Rhino (a Java based JavaScript interpreter) into the Eclipse IDE. Target is to execute JavaScript code directly within the running Eclipse environment. Such an interpreter might be used to script Eclipse itself. Wouldn't it be nice to have macro support?

Therefore I raised bug 365133. As I finally was able to post some code I'd like to give a short overview of what can be done.

Run Plug-ins

You need at least Eclipse 3.7 with JSDT tools installed (get them from the Indigo repository).

Import all four projects from the archive to your workspace. Right click one one of them in Package Explorer and select Run As -> Eclipse Application.

JavaScript Shell

Before we have a look at the integrated JS shell we will quickly adjust some settings: open menu Window -> Preferences and navigate to JavaScript -> Shell. Set all output values to "Shell".

Now open the shell view: select menu Window -> Show View -> Other... Then open view JavaScript -> JavaScript Shell.

The shell consists of a big output pane and an input line at the bottom. Start entering your first JS code there:
i = 2+2;
You will see the result right in the output pane. There is a print command available that will dump text to the Console view.
print("Hello world!");


An integrated help is available when hitting the help toolbar button.

JavaScript Run target

To execute JavaScript files there exists a new run target that allows to right click any JS source file and select Run As -> JavaScript. This will create a new interpreter (so it will not run in the same context as the shell) and execute the file.

Loadable Modules

For developers there exists an interesting Plug-in: com.example.javascript.modules.tools. It is an example how to extend JS functionality. Every method within this class augmented with @WrapToJavaScript
will be available as JS function automagically. This way JS functionality can be easily extended while using the benefits of Java.


Due to Rhino and the used ClassLoader it is possible to mix JavaScript code and pure Java classes. Eg the following JS code will create an instance of java.io.File and call a method upon it:
var myFile = new Packages.java.io.File("~/.bashrc");
print(myFile.exists());


Wrap up

Having a native JS interpreter within Eclipse will provide great new ways to build applications. It might give us macro support, rapid testing facilities for programmers (just load your Plug-in and access it with the Script Shell) and maybe a lot more things I can currently not think of.

If you want to support this idea please vote on bug 365133 or help in finding ways to make this part of Eclipse.