Interaction between web and desktop application

Browser component in Eclipse RCP application offers the possibility to mix web and desktop applications. There’s a lot of advantages of this technic, in particular when it concern a reuse of an existing web application. One of the interest is to never be dependant of the browser but you’re application is the browser.
To make this working it’s necessary to communicate between web and desktop. This article suggest 6 solutions…

Browser component in Eclipse RCP application offers the possibility to mix web and desktop applications. There’s a lot of advantages of this, in particular when it concern reuse of an existing web application. One of the interest is to never be dependant of the browser but to make your application become the browser.
To make this working it’s necessary to communicate between web and desktop, it’s relatively easy to send data to browser by using (setURL()) or by executing Javascript (execute()). But for sending data to the desktop it’s more difficult. I suggest 6 solutions to do that :
1. via the status bar : like it show on the SWT snippets site (Snippet160)
2. via the address bar: like Peter Nehrer say
3. directly request HTML DOM : by using Mozilla Browser (new in 3.3) with the XPCOM library. A little example using the Snippet267 and modify it to use XPath and catch a title of an input field. There’s a lot of possibility with this API like ATF do (maybe i have to take time to make an article about the possibility offers by XPCOM).

static Browser browser;
public static void main(String[] args) {
    Display display = new Display();
    Shell shell = new Shell(display);
    shell.setLayout(new GridLayout(2, true));
    shell.setText("Use Mozilla's Design Mode");
    try {
        browser = new Browser(shell, SWT.MOZILLA);
    } catch (SWTError e) {
        System.out.println("Could not instantiate Browser: " + e.getMessage());
        return;
    }
    browser.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true, 2, 1));
    Button searchButton = new Button(shell, SWT.PUSH);
    searchButton.setText("Search");
    searchButton.addListener(SWT.Selection, new Listener() {
        public void handleEvent(Event event) {
            search();
        }
    });
    browser.setUrl("http://www.google.com");
    shell.setSize(400, 400);
    shell.open();
    while (!shell.isDisposed()) {
        if (!display.readAndDispatch())
             display.sleep();
    }
    display.dispose();
}

public static boolean search() {
    nsIWebBrowser webBrowser = (nsIWebBrowser) browser.getWebBrowser();
    if (webBrowser == null) {
        System.out.println("Could not get the nsIWebBrowser from the Browser widget");
        return false;
    }
    nsIDOMWindow window = webBrowser.getContentDOMWindow();
    nsIDOMDocument document = window.getDocument();
    nsIDOMXPathEvaluator xpath = (nsIDOMXPathEvaluator) document.queryInterface(nsIDOMXPathEvaluator.NS_IDOMXPATHEVALUATOR_IID);
    nsIDOMXPathNSResolver res = xpath.createNSResolver(document);
    nsISupports obj = xpath.evaluate("//input[@name='q']/@title",
                                                 document,
                                                 res,
                                                 nsIDOMXPathResult.STRING_TYPE,
                                                 null);
    nsIDOMXPathResult result = (nsIDOMXPathResult) obj.queryInterface(nsIDOMXPathResult.NS_IDOMXPATHRESULT_IID);
    System.out.println(result.getStringValue());
    return true;
}


4. via a socket : by executing an XMLHTTPRequest with execute() method which call a socket and get the content.

private String getDataFromBrowser() {
	String javascript = "try {";
	javascript += "xhr_object = new ActiveXObject(\"Microsoft.XMLHTTP\"); ";
	javascript += "xhr_object.open(\"POST\", \"http://localhost:9091\", false);";
	javascript += "xhr_object.setRequestHeader(\"Content-type\", \"application/x-www-form-urlencoded\");";
	javascript += "xhr_param = generateXML();"; // appel d'une fonction retournant un contenu
	javascript += "xhr_object.send(xhr_param);";
	javascript += "} catch (ex) { alert(\"Failed to save document\"); }";

	String xml = null;
	XMLPicker e = new XMLPicker();
	Thread t = new Thread(e);
	t.start();

	// wait threa run
	try {
		Thread.sleep(10);
	} catch (InterruptedException eee) {
	}
	// ask browser
	boolean ok = browser.execute(javascript);

	int wait = 0;
	while (xml == null && wait < 10)
		try {
			Thread.sleep(10);
			wait++;
			xml = e.getXML();
		} catch (InterruptedException eeee) {
		}
	System.out.println(xml);
	return xml;
}

private class XMLPicker implements Runnable {
	private String xml;
	public String getXML() {
		return xml;
	}

	public void run() {
		ServerSocket server = null;
		try {
			server = new ServerSocket(9091);
			server.setSoTimeout(5000);
			System.out.println("Waiting for response");
			Socket socket = server.accept();
			// stream treatment, i can give the HTTPServer class if you want
			xml = HttpServer.getXMLString(socket, "UTF-8"); 
			socket.close();
		} catch (IOException ee) {
			System.err.println(ee);
		} finally {
			if (server != null) {
				try {
					server.close();
				} catch (Exception e) {
				// Ignore.
				}
			}
		}
	}
}

5. running an HTTP server inside the Eclipse JVM : with Tomcat embedded for example or with WebObjects (Application.primeApplication()). The objects in the same JVM can be shared but be carreful of classloaders.
6. via terracota : a JVM cluster offer an easy way to synchronize objects between JVM.