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.
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
AFAIK the Entrypoint is not required that you can re-use your application definition.
Works great! 😉
Thanks for the great information.
The article was very useful, thank you.
Regarding the workspaces:
Is it possible do have RAP & RCP in just one workspace?
AHoi,
Claus
Claus,
yes, you can switch between two (or more) Target Platforms (RAP & RCP) while staying in the same workspace.
Vincenzo
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?
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
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