Running an Eclipse RCP app as a service




public class MyRCPApplication implements IPlatformRunnable {

    private boolean shouldStop = false;

    private Object returnCode = IPlatformRunnable.EXIT_OK;

    public Object run(Object args) throws Exception {

        // start any necessary non-UI plugins
        //  for example, a plugin that starts up a JMS or Tomcat server...

        MyServicePlugin.getDefault();

        // keep the application running until we're ready to close

        while (!shouldStop) {

            // get the display
            final Display display = PlatformUI.createDisplay();

            // create a shell and the System Tray
            final Shell shell = new Shell(display);
            Image image = new Image(display, 16, 16);
            final Tray tray = display.getSystemTray();


            if (tray == null) {
                System.out.println("The system tray is not available");
            } else {

                final TrayItem item = new TrayItem(tray, SWT.NONE);
                item.setToolTipText("My Application");

                final Menu menu = new Menu(shell, SWT.POP_UP);

                MenuItem open = new MenuItem(menu, SWT.PUSH);
                open.setText("Open");
                open.addSelectionListener(new SelectionListener() {

                    public void widgetSelected(SelectionEvent e) {

                        createWorkbench(display);

                    }

                    public void widgetDefaultSelected(SelectionEvent e) {

                    }
                });


                MenuItem restart = new MenuItem(menu, SWT.PUSH);
                restart.setText("Restart");
                restart.addSelectionListener(new SelectionListener() {

                    public void widgetSelected(SelectionEvent e) {

                        returnCode = IPlatformRunnable.EXIT_RESTART;
                        shouldStop = true;

                    }

                    public void widgetDefaultSelected(SelectionEvent e) {

                    }
                });

                MenuItem stop = new MenuItem(menu, SWT.PUSH);
                stop.setText("Close");
                stop.addSelectionListener(new SelectionListener() {

                    public void widgetSelected(SelectionEvent e) {

                        shouldStop = true;

                    }

                    public void widgetDefaultSelected(SelectionEvent e) {

                    }
                });

                item.addListener(SWT.MenuDetect, new Listener() {
                    public void handleEvent(Event event) {
                        menu.setVisible(true);
                    }
                });
                item.setImage(image);
            }

            while (!shell.isDisposed() && !shouldStop) {
                if (!display.readAndDispatch())
                    display.sleep();
            }

            image.dispose();
            shell.dispose();
        }

        return returnCode;
    }

    private Object createWorkbench(Display display) {

        if (PlatformUI.isWorkbenchRunning() == false) {

            int returnCode = 0;

            WorkbenchAdvisor advisor = new MyAdvisor();

            try {
                returnCode = PlatformUI.createAndRunWorkbench(display, advisor);
                if (returnCode == PlatformUI.RETURN_RESTART) {
                    return IPlatformRunnable.EXIT_RESTART;
                } else {
                    return IPlatformRunnable.EXIT_OK;
                }
            } finally {
                if (display != null)
                    display.dispose();
            }
        } else
            return IPlatformRunnable.EXIT_OK;

    }

}

You can run this application as an NT service via the Java Service Wrapper rather easily and it will all work correctly with the exception of the restart function. Instead of restarting you'll just close the application. This is because the restart exit code is handled by the eclipse.exe launcher not by any Java class. Since we're using the wrapper.exe to run as an NT service instead of eclipse.exe we lose the restart functionality. The same occurs if you start your Eclipse application via a 'java' command instead of the supplied launcher.

To restore the restart functionality I would either need to use some other service wrapper (such as srvany) to launch the eclipse.exe as a service directly or hack either the wrapper.exe or eclipse.exe source code to add the missing functionality. Again, if anyone has any better ideas, please let me know!

Anyway, I hope this at least gives everyone the basic idea behind writing this sort of Eclipse RCP application. I'm certain there may be some tricks or better practices that I've missed. I'll try and get the source code and an example app up on SourceForge later this weekend. I should note that some of the code above is taken pretty much directly from various examples on the Eclipse site. Feel free to reuse it as necessary.