I.T. aware

Sébastien Letélié and Cyril Balit weblog
  • English
  • Français
  • en
  • fr
  • Blog
  • A propos
  • Présentations
  • Publications

Interaction between web and desktop application

Sébastien Letélié | 15 juillet 2007

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.

1 Star2 Stars3 Stars4 Stars5 Stars (1 votes, average: 4,00 out of 5)
Loading ... Loading ...
Commentaires
Pas de Commentaires »
Catégories
Eclipse, RIA-RDA-RWA
Flux rss des commentaires Flux rss des commentaires
Trackback Trackback
1 791 views
Print This Post

Interaction entre desktop et web

Sébastien Letélié |

Dans une application Eclipse RCP le composant Browser permet de mixer web et desktop. Les avantages de cette technique sont nombreux, notamment quand il s’agit de réutiliser un existant Web pour l’encapsuler dans une application desktop. L’interêt est de ne plus être dépendant d’un navigateur mais d’être son propre navigateur. Cependant pour que cela fonctonne il faut faire communiquer web et desktop. Lorsqu’il s’agit d’envoyer des données à l’application Web cela reste simple en modifiant l’URL (setURL()) ou en executant du Javascript (execute()). Mais lorsqu’il s’agit de récupérer des données depuis le web c’est plus fastidieux. Je vous propose ici 6 techniques :
1. via la barre de statut: c’est le code que l’on trouve sur les snippets SWT (Snippet160)
2. via la barre d’adresse: comme le propose Peter Nehrer
3. en requetant directement le DOM : depuis la 3.3 il est possible d’utiliser Mozilla et l’API XPCOM fournie la possibilité d’accèder au DOM de la page HTML. Ci-dessous un petit exemple reprenant le Snippet267 mais en requetant en XPath pour récupérer le titre d’un champ. Les possibilités sont multiples à l’image de l’utilisation qu’en fait ATF (faudrait que j’y consacre un article complet pour explorer toutes les possibilités qu’offre 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 un socket : en executant une XMLHTTPRequest via la méthode execute() qui fait appel à un socket ouvert pour l’occasion et permet de récupérer un contenu.

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();

	// Attend que le thread démarre.
	try {
		Thread.sleep(10);
	} catch (InterruptedException eee) {
	}
	// Demande au browser un contenu.
	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();
			// Traitement du flux, la classe HTTPServer est disponible pour ceux que ca intéresse
			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. en démarrant un serveur http dans la meme JVM que Eclipse RCP : tomcat peut être embarqué et demarré depuis une application Java, c’est aussi le cas de WebObjects (Application.primeApplication()). Les objets étant issus de la même JVM leur statut est partagée par les deux application mais attention toutefois aux classloaders.
6. via terracota : ce cluster de JVM permet de synchroniser les objets de 2 JVM et de répercuter en temps réel les états des objets.

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading ... Loading ...
Commentaires
1 Commentaire »
Catégories
Eclipse, RIA-RDA-RWA
Flux rss des commentaires Flux rss des commentaires
Trackback Trackback
1 444 views
Print This Post

Recherche

Twitter

  • Implementing DCI in Qi4j | Javalobby: http://bit.ly/d65u5M 2 days ago
  • Google Reader Play http://bit.ly/aMIPRM 6 days ago
  • BIRT is Mobile! - BIRT Exchange: http://www.birt-exchange.org/blog/2010-03-10/birt-is-mobile/ 1 week ago
  • Zenika lance les ZenLabs http://tinyurl.com/yfwq3j3 1 week ago
  • Microsoft Courier = Microsoft Tablet : looks great !http://bit.ly/d7EZgL 1 week ago
  • More updates...

Powered by Twitter Tools.

Profils

  • Viadeo
  • LinkedIn
  • Twitter
  • FriendFeed
  • Blogs

    • Damien Viel
    • David J Orme
    • Didier Girard
    • Improve Technologies
    • Java Desktop
    • Jerôme Denanot
    • Joshua Marinacci
    • Le touilleur
    • Planet Eclipse
    • The coder’s breakfast
    • Tom Schindl
    • Wiki Improve
  • Open-Source

    • Monoi
    • Rialto
    • Tom’s Quest
    • XDI
  • English Feed French Feed rss Flux rss des commentaires valid xhtml 1.1 design by jide powered by Wordpress get firefox