Introduzione a RAP
RAP (Rich Ajax Platform) è un framework che vi permette di sviluppare una applicazione RCP e renderla disponibile in rete semplicemente indirizzando il browser su un dato link.
In questo articolo vedremo come potete sviluppare una applicazione RCP e lanciarla sia come applicazione desktop che come applicazione web . Sì, certo, esattamente lo stesso codice sorgente!
Non ci credete? Provate voi stessi.
Setup dell’IDE per RAP
Il modo pi├╣ veloce per lavorare con RAP è quello di scaricare la versione Eclipse for RCP and RAP Developers dalla pagina http://www.eclipse.org/downloads
Alternativamente potete aggiungere RAP a qualsiasi altra Eclipse Indigo SR2 (ovvero la versione 3.7.2), semplicemente selezionando Help -> Install New Software… -> scegliere l’update sitd di Indigo e installare Rich Ajax Platform (RAP) Tooling 1.4.2 sotto la categoria Web, XML, Java EE and OSGi Enterprise Development.
Ora dobbiamo effettuare il setup di una RAP target plaftorm. Quindi lanciamo Eclipse e selezioniamo Window -> Preferences -> Plug-in Development -> Target Platform
e premiamo il bottone Add… e poi Next
Diamo un nome alla platform, ad es. RAP_1.4 e premiamo Add… nel primo tab (Locations)
poi selezioniamo Software Site
e poi Next. Quindi aggiungiamo l’Update site RAP 1.4 Runtime
http://download.eclipse.org/rt/rap/1.4/runtime
deselezioniamo il radio button Include required software e premiamo Finish.
questa operazione potrebbe richiedere un po’ di tempo. Al termine questo è quello che dovreste vedere
premere Finish.
Quindi seguiamo la stessa procedura aggiungendo, dall’update site di Indigo http://download.eclipse.org/releases/indigo, la feature EMF RAP Target Components dalla Category EclipseRT Target Platform Components. Dovreste ora vedere quanto segue
La cosa importante da tenere presente qui è che ora avete due target platform: quella RCP e quella RAP. Selezionate quella RAP per questo workspace e premete OK.
Ora lanciate un’altra istanza Eclipse e scegliete un nuovo workspace, che sarà usato per lo sviluppo RCP.
Sta diventando chiaro quello che stiamo facendo? Vogliamo avere due differenti workspace, uno per eseguire il lancio RCP (=Desktop) e l’altro per eseguire il lancio RAP (=Web). Ma anche il progetto deve essere diverso? Niente affatto: stessi identici sorgenti!
Dopo aver lanciato Eclipse con il workspace RCP seguiamo uno degli wizard per creare una applicazione RCP: File -> New -> Plug-in Project, diamo un nome al plug-in (es. it.rcpvision.rcprap.application) e selezioniamo Yes alla domanda “Do you want to create a Rich Client Application?“. Poi scegliamo il secondo template “RCP application with a view” e premiamo Finish. Ora lanciamo l’applicazione; vedrete questo
Fin qui niente di nuovo, una cosa che probabilmente fate quasi quotidianamente.
Ora faremo un piccolo cambiamento nelle Dependencies di questo plug-in. Selezioniamo la dependenza da org.eclipse.ui per renderla Opzionale.
Andiamo quindi al tab MANIFEST.MF e aggiungiamo una dipendenza da org.eclipse.rap.ui e rendiamo anch’essa Opzionale.
Se eseguiamo di nuovo l’applicazione otterremo, naturalmente, lo stesso risultato. Abbiamo semplicemente introdotto una doppia dipendenza, alternativa, verso RCP e RAP. A seconda della platform verrà sfruttata l’una o l’altra, dallo stesso medesimo codice sorgente.
Ora torniamo all’altra istanza di Eclipse, quella che punta al workspace configurato per RAP, e importiamo lo stesso progetto dal file system.
Poi selezioniamo Run -> Run Configurations… -> RAP Application -> New
Nel primo tab (Main) premiamo il bottone Browse per il campo Entry Point or Application
e selezioniamo la nostra applicazione
Nel secondo folder (Bundles) premiamo Deselect All e aggiungiamo la nostra applicazione (it.rcpvision.rcprap.application) e i seguenti plug-in
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
Nota: se non avete intenzione di aggiungerli uno ad uno, potete persistere il lancio (tab Common -> Save as -> Shared file) e poi aprire il lancio stesso come testo e cambiare la seguente linea
con il seguente contenuto
<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”/>
Ok, siamo pronti a partire: eseguite il lancio e dovreste vedere il browser interno aprire la vostra applicazione come applicazione Web!
Potete copiare lo stesso URL su vostro browser preferito dallo stesso pc, ma ovviamente anche da un’altro pc sulla stessa rete, semplicemente sostituendo l’IP (127.0.0.1) con quello che identifica il vostro pc sulla rete.
Buon divertimento con RAP a tutti!
Riconoscimenti
Grazie al Team di RAP e a Hendy Irawan per questo suo prezioso articolo
http://eclipsedriven.blogspot.it/2010/12/eclipse-rap-single-sourcing-awesomeness.html, che ha ispirato la creazione di questo 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