Single sourcing with Eclipse RAP

An introduction to RAP

RAP (Rich Ajax Platform) is the framework that allows you to develop an RCP application an make it available over the network just pointing the browser to a given link.
In this article we will see how you can develop an RCP application and launch it both as a desktop as well as a web application.  Yes, sure, exactly the same source code!
Don’t you believe it? Try it yourself.

 

Setup your IDE for RAP

The fastest way to get RAP working is downloading the Eclipse for RCP and RAP Developers package from page http://www.eclipse.org/downloads


Alternatively, you could add RAP from any other Eclipse Indigo SR2 (a.k.a. version 3.7.2) package, just going to Help -> Install New Software… -> select Indigo update site and install Rich Ajax Platform (RAP) Tooling  1.4.2 under the category Web, XML, Java EE and OSGi Enterprise Development.

Now we have to set up a RAP target plaftorm. Then start Eclipse and go to Window -> Preferences -> Plug-in Development -> Target Platform

and click Add… button and go Next

Give a name to the platform, e.g. RAP_1.4 and press Add… button in the first tab (Locations)

then select Software Site

and go Next. Then add the RAP 1.4 Runtime Update site
http://download.eclipse.org/rt/rap/1.4/runtime

uncheck that radio button Include required software and press Finish.

this may take quite a while. At the end that’s what you should see

click Finish.
Then follow the same procedure now adding, from Indigo update site  http://download.eclipse.org/releases/indigo, the feature EMF RAP Target Components from Category EclipseRT Target Platform Components. You should now see the following

The important point here is that now you have two target platforms: the RCP and RAP ones. Select the RAP one for this workspace and press OK.

Now start another Eclipse instance and choose a different workspace, that will be used for RCP development.
Is it becoming clear what we are going to do? We want to have two different workspaces, one for running the RCP (=Desktop) launch and the other for running the RAP (=Web) launch. But what about the project? The very same source code!

After starting Eclipse with the RCP workspace follow one of the wizard for creating an RCP application: File -> New -> Plug-in Project, give the plug-in a name (e.g. it.rcpvision.rcprap.application) and select Yes at question “Do you want to create a Rich Client Application?“. Then choose the second template “RCP application with a view” and press Finish. Now launch the application; you will see the following

Up to now nothing special, just what you probably do almost every day.

Now let’s do a simple change in the Dependencies of this plug-in. Select the dependency from org.eclipse.ui and make it Optional.

Then go the tab MANIFEST.MF and add a dependency from org.eclipse.rap.ui and make it Optional too.

If you run again the application you’ll get, of course, the same result. We just introduced a double, optional, dependency to both RCP and RAP.

Now go back to the other Eclipse instance, the one pointing to the workspace configured for RAP, and import the same project from the file system.
Then select Run -> Run Configurations… -> RAP Application -> New

In the first tab (Main) click the Browse button for field Entry Point or Application

and select our application

In the second folder (Bundles) press Deselect All and add our application (it.rcpvision.rcprap.application) and the following plug-ins

com.ibm.icu.base
javax.servlet
org.eclipse.core.commands
org.eclipse.core.contenttype
org.eclipse.core.databinding
org.eclipse.core.databinding.beans
org.eclipse.core.databinding.observable
org.eclipse.core.databinding.property
org.eclipse.core.expressions
org.eclipse.core.jobs
org.eclipse.core.runtime
org.eclipse.equinox.app
org.eclipse.equinox.common
org.eclipse.equinox.http.jetty
org.eclipse.equinox.http.registry
org.eclipse.equinox.http.servlet
org.eclipse.equinox.http.servletbridge
org.eclipse.equinox.preferences
org.eclipse.equinox.registry
org.eclipse.equinox.servletbridge
org.eclipse.equinox.servletbridge.extensionbundle
org.eclipse.help
org.eclipse.jdt.junit.runtime
org.eclipse.osgi
org.eclipse.osgi.services
org.eclipse.rap.jface
org.eclipse.rap.jface.databinding
org.eclipse.rap.junit
org.eclipse.rap.junit.runtime
org.eclipse.rap.rwt
org.eclipse.rap.rwt.q07
org.eclipse.rap.rwt.theme.classic
org.eclipse.rap.ui
org.eclipse.rap.ui.cheatsheets
org.eclipse.rap.ui.forms
org.eclipse.rap.ui.views
org.eclipse.rap.ui.workbench
org.junit
org.mortbay.jetty.server
org.mortbay.jetty.util

Note: if you don’t want to add them one by one, you can persist the launch (tab Common -> Save as -> Shared file) then open the launch as text and change the following line

with this content

<stringAttribute key=”target_bundles” value=”com.ibm.icu.base@default:default,javax.servlet@default:default,org.eclipse.core.commands@default:default,org.eclipse.core.contenttype@default:default,org.eclipse.core.databinding.beans@default:default,org.eclipse.core.databinding.observable@default:default,org.eclipse.core.databinding.property@default:default,org.eclipse.core.databinding@default:default,org.eclipse.core.expressions@default:default,org.eclipse.core.jobs@default:default,org.eclipse.core.runtime@default:true,org.eclipse.equinox.app@default:default,org.eclipse.equinox.common@2:true,org.eclipse.equinox.http.jetty@default:default,org.eclipse.equinox.http.registry@default:default,org.eclipse.equinox.http.servlet@default:default,org.eclipse.equinox.http.servletbridge@default:default,org.eclipse.equinox.preferences@default:default,org.eclipse.equinox.registry@default:default,org.eclipse.equinox.servletbridge.extensionbundle@default:false,org.eclipse.equinox.servletbridge@default:default,org.eclipse.help@default:default,org.eclipse.jdt.junit.runtime@default:default,org.eclipse.osgi.services@default:default,org.eclipse.osgi@-1:true,org.eclipse.rap.jface.databinding@default:default,org.eclipse.rap.jface@default:default,org.eclipse.rap.junit.runtime@default:default,org.eclipse.rap.junit@default:default,org.eclipse.rap.rwt.q07@default:false,org.eclipse.rap.rwt.theme.classic@default:default,org.eclipse.rap.rwt@default:default,org.eclipse.rap.ui.cheatsheets@default:default,org.eclipse.rap.ui.forms@default:default,org.eclipse.rap.ui.views@default:default,org.eclipse.rap.ui.workbench@default:default,org.eclipse.rap.ui@default:default,org.junit@default:default,org.mortbay.jetty.server@default:default,org.mortbay.jetty.util@default:default”/>

Well, we are ready: run the launch and you’ll see the internal browser opening your application as a Web application!

You can now copy the same URL on your preferred browser from the same machine, but of course, you can also do the same from another machine, just replace the IP (127.0.0.1) with the one that identifies your machine on the network.

Happy RAP to everyone!

Acknowledgments
Thanks to the RAP Team and to Hendy Irawan for this article
http://eclipsedriven.blogspot.it/2010/12/eclipse-rap-single-sourcing-awesomeness.html, which inspired this tutorial.

 

 

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Application
Bundle-SymbolicName: it.rcpvision.rcprap.application; singleton:=true
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: it.rcpvision.rcprap.application.Activator
Require-Bundle: org.eclipse.ui;resolution:=optional,
org.eclipse.rap.ui;resolution:=optional,
org.eclipse.core.runtime
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
This entry was tagged , , , , . Bookmark the permalink.

7 Responses to Single sourcing with Eclipse RAP

  1. Lars Vogel says:

    AFAIK the Entrypoint is not required that you can re-use your application definition.

  2. David S says:

    Works great! ;-)
    Thanks for the great information.

  3. Claus says:

    The article was very useful, thank you.
    Regarding the workspaces:
    Is it possible do have RAP & RCP in just one workspace?

    AHoi,
    Claus

    • Vincenzo says:

      Claus,
      yes, you can switch between two (or more) Target Platforms (RAP & RCP) while staying in the same workspace.
      Vincenzo

  4. Darren says:

    I have an example on Juno that I cannot get to work at all.
    It is the table of authors example, with CDO, but trying to run as RAP.

    I get the following in my stack trace from the RAP launcher:

    java.lang.NoSuchMethodException: org.eclipse.e4.ui.css.swt.internal.theme.BootstrapTheme3x.(org.eclipse.swt.widgets.Display)
    at java.lang.Class.getConstructor0(Unknown Source)
    at java.lang.Class.getConstructor(Unknown Source)
    at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2568)
    at org.eclipse.ui.internal.Workbench.access$5(Workbench.java:2530)
    at org.eclipse.ui.internal.Workbench$5.run(Workbench.java:702)
    at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
    at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:685)
    at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:157)
    at darren.emf.example.rcp.Application.start(Application.java:20)
    at org.eclipse.rap.ui.internal.application.EntryPointApplicationWrapper.createUI(EntryPointApplicationWrapper.java:38)
    at org.eclipse.rwt.internal.lifecycle.RWTLifeCycle.createUI(RWTLifeCycle.java:177)
    at org.eclipse.rwt.internal.lifecycle.RWTLifeCycle$UIThreadController.run(RWTLifeCycle.java:289)
    at java.lang.Thread.run(Unknown Source)
    at org.eclipse.rwt.internal.lifecycle.UIThread.run(UIThread.java:102)

    The application starts up and shows me a basic Library Manager UI in the browser, with a button for the View Authors (which is supposed to open the view part). When I press the View Authors button, nothing happens ( btw, this does all work when run as RCP).

    Do you have any idea what I might be doing wrong here?

    • Darren says:

      It does register my button press in the web server in that it logs some stuff when I press the button, but the view fails to open…..

      15:01:03.635 [qtp759121585-39] DEBUG org.eclipse.jetty.http.HttpParser – filled 610/610
      15:01:03.635 [qtp759121585-39 - /rap?nocache=1370008863633] DEBUG org.eclipse.jetty.server.Server – REQUEST /rap on AsyncHttpConnection@2fff2784,g=HttpGenerator{s=0,h=-1,b=-1,c=-1},p=HttpParser{s=2,l=65,c=72},r=2
      15:01:03.636 [qtp759121585-39 - /rap?nocache=1370008863633] DEBUG o.e.j.server.handler.ContextHandler – scope null||/rap @ o.e.j.s.ServletContextHandler{/,null}
      15:01:03.636 [qtp759121585-39 - /rap?nocache=1370008863633] DEBUG o.e.j.server.handler.ContextHandler – context=||/rap @ o.e.j.s.ServletContextHandler{/,null}
      15:01:03.636 [qtp759121585-39 - /rap?nocache=1370008863633] DEBUG org.eclipse.jetty.server.session – Got Session ID 560itklghk8ls8o1v7vgrycx from cookie
      15:01:03.636 [qtp759121585-39 - /rap?nocache=1370008863633] DEBUG org.eclipse.jetty.server.session – sessionManager=org.eclipse.jetty.server.session.HashSessionManager@68d93a9e
      15:01:03.636 [qtp759121585-39 - /rap?nocache=1370008863633] DEBUG org.eclipse.jetty.server.session – session=org.eclipse.jetty.server.session.HashedSession:560itklghk8ls8o1v7vgrycx@1281894017
      15:01:03.636 [qtp759121585-39 - /rap?nocache=1370008863633] DEBUG o.e.jetty.servlet.ServletHandler – servlet ||/rap -> org.eclipse.equinox.http.jetty.internal.HttpServerManager$InternalHttpServiceServlet-655028946
      15:01:03.636 [qtp759121585-39 - /rap?nocache=1370008863633] DEBUG o.e.jetty.servlet.ServletHandler – chain=null
      15:01:03.640 [qtp759121585-39 - /rap?nocache=1370008863633] DEBUG org.eclipse.jetty.server.Server – RESPONSE /rap 200
      15:01:03.641 [qtp759121585-39] DEBUG o.e.jetty.server.AsyncHttpConnection – Enabled read interest SCEP@32ee2213{l(/127.0.0.1:53331)r(/127.0.0.1:53001),d=true,open=true,ishut=false,oshut=false,rb=false,wb=false,w=true,i=1r}-{AsyncHttpConnection@2fff2784,g=HttpGenerator{s=4,h=0,b=0,c=-1},p=HttpParser{s=0,l=65,c=72},r=2}
      15:01:03.641 [qtp759121585-39] DEBUG org.eclipse.jetty.http.HttpParser – filled 0/0

      • Vincenzo says:

        Hi Darren,
        from the stacktrace I cannot tell what the problem may be.
        I suggest to follow the article step by step on a brand new workspace and then start putting your code, again step by step, each time checking that all is working.
        In this way you can focus on the single step that (maybe) bring the problem.
        Let me know.
        Vincenzo

Leave a Reply

Your email address will not be published. Required fields are marked *


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>