With the move to RAP 2.0, we've cleaned up our APIs and had to introduce some breaking changes. Existing RAP 1.x applications will therefore need some adjustments to work with RAP 2.x. This guide explains the steps to be taken to update existing applications.
Meanwhile, RAP 2.1 has been released. Except for changes to the Remote API (which did not exist prior to RAP 2.0) there are no breaking changes between 2.0 and 2.1.
The package org.eclipse.rwt has been renamed to org.eclipse.rap.rwt. You need to update your bundle manifest files and your Java code to this change. A brute-force search for “org.eclipse.rwt” may be helpful to discover all occurrences in your workspace.
The interface EntryPoint moved to the package org.eclipse.rap.rwt.application.
If you use Import-Package
in your bundle manifests
(META-INF/MANIFEST.MF
files), you have to replace all imports of packages named
org.eclipse.rwt*
with the corresponding packages from
org.eclipse.rap.rwt*
, i.e. you have to insert an “.rap
” before the
“.rwt
”.
Compile errors in your code can be fixed by using Eclipse's Organize Imports feature.
To do so, select a single class or an entire project and select
Source > Organize Imports from the main menu.
If you find it easier, you can also replace all textual occurrences of
org.eclipse.rwt
with org.eclipse.rap.rwt
.
Note that this change also affects service interfaces. If you're using declarative services, please also adjust your component definition files.
The prefix “I” in interface names like IEntryPoint is a heritage from the Eclipse platform. This deviates from the naming pattern used in SWT and other libraries, and also from the Java class library. Since it is not even used consistently in RAP, we plan to remove the prefix from all interfaces.
Where public interfaces have been renamed, we left the old name in place where possible to ease the migration and to leave a clue when adapting your application to RAP 2.0.
RWT.getRequest().setAttribute(...)
.
The resource manager (IResourceManager) has undergone a rework and has been reduced in its functionality (See the New and Noteworthy). These changes affect the following API:
The class RegisterOptions has been removed. If you used RegisterOptions other than RegisterOptions.NONE, your application will continue to work without these options, but your JavaScript code will no longer be compressed and the name of the registered resource will not contain a version hash anymore.
You may consider to minify JavaScript yourself and register a minified version.
There are many free tools out there, such as
YUI Compressor,
Google Closure Compiler,
or JSMin.
If you need a version hash to prevent caching, you can add a URL parameter like
“?nocache=4711
” when requesting the resource.
The resource manager now registers the bytes from a given input stream as is. If you used to register resources using a method with a charset parameter, please make sure that textual resources are read with the correct encoding by the client. If all your resources are UTF-8 encoded there will be no change to RAP 1.5.
If you used a method that accepted or used a ClassLoader to register resources, please change your code to use the method register( String, inputStream ). You may have to call ClassLoader.getResourceAsStream( resourceName ) to open an input stream.
The resource manager does not close input streams anymore after registering a resource, (bug 347615). Please double check that you're closing your input streams correctly.
The IResource interface is now only used in the extension point org.eclipse.rap.ui.resources and has therefore been moved to the bundle org.eclipse.rap.ui.workbench. The methods getCharset() and getOptions() have been removed because of the changes described above.
For resources that are registered in an ApplicationConfiguration, the method Application.addResource(…) now accepts a ResourceLoader instead of IResource.
When working with RAP, you have to deal with two different types of sessions: the servlet container's HttpSession and RAP's UISession (formerly known as session store). Both sessions have a different scope and a different purpose. In recent projects we've noticed that the relationship between the HTTP session and RAP's “session store” led to confusion. By renaming the session store to UI session we hope to make it more clear that both are sessions with a different scope and meaning.
The interface ISessionStore has been renamed to UISession.
An instance can be acquired from RWT.getUISession()
which replaces
RWT.getSessionStore()
.
The types SessionStoreListener and SessionStoreEvent have been renamed
accordingly.
The new ApplicationContext represents the running instance of a RAP application, it is shared by all UI sessions. This interface replaces IApplicationStore, it can be used to store shared data, and also to obtain application-scoped services such as the resource manager. Just like the UISession is built on the servlet container's HttpSession, the ApplicationContext is built on the ServletContext, and its life cycle is also bound to lifetime of the servlet context. We chose the name ApplicationContext to highlight this analogy.
The interface IApplicationStore has been renamed to ApplicationContext.
An instance can be acquired from RWT.getApplicationContext()
which replaces
the old method RWT.getApplicationStore()
.
The ApplicationContext can also be used to get a reference of the resource manager and the
service manager, e.g. applicationContext.getResourceManager()
.
The interface ServiceHandler has been changed. The service method now provides two parameters request and response to the implementation. Developers don't have to obtain the request and reponse objects from static methods anymore.
public class MyServiceHandler implements ServiceHandler { public void service( HttpServletRequest request, HttpServletResponse response ) {HttpServletRequest request = RWT.getRequest();HttpServletResponse response = RWT.getResponse();response.setContentType( "text/plain" ); response.getWriter().write( "Hello!" ); } }
The ServiceManager has got a new method getServiceHandlerUrl( String ). Developers should use this new method to obtain the URL to access a service handler instead of assembling the URL manually.
ServiceManager manager = RWT.getServiceManager(); manager.registerServiceHandler( "download", new DownloadServiceHandler() ); String url = manager.getServiceHandlerUrl( "download" );
The class UICallBack is going to be replaced by a new API for server push.
Instead of calling UICallBack.activate( id )
to activate the server push,
you now have to create a new ServerPushSession and start()
it.
To deactivate the server push, you call stop()
on the same ServerPushSession
instance.
In contrast to the UICallBack, this can be done directly from the background thread without
a UISession context.
final ServerPushSession pushSession = new ServerPushSession(); Runnable runnable = new Runnable() { public void run() { // do some background work ... // schedule the UI update display.asyncExec( new Runnable() { public void run() { if( !widget.isDisposed() ) { label.setText( "updated" ); } } } ); // close push session when finishedUICallBack.runNonUIThreadWithFakeContext( display, new Runnable() {public void run() {UICallBack.deactivate( "someUniqueID" );}} );pushSession.stop(); } ); };UICallBack.activate( "someUniqueID" );pushSession.start(); new Thread( runnable ).start();
To run code in the context of a UISession, e.g. in order to access a session singleton from a background thread, you can use the new method exec(Runnable) on the UISession instead of the infamous UICallBack.runNonUIThreadWithFakeContext(Display, Runnable).
The class BrowserHistory
has been replaced by a more general client service
BrowserNavigation that provides the same features with slightly different API.
Here's an example how to change your code:
// OBSOLETE BrowserHistory history =RWT.getBrowserHistory();history.addBrowserHistoryListener( new BrowserHistoryListener() { public void navigated( BrowserHistoryEvent event ) { String state =event.entryId;// restore the application state } } ); history.createEntry( "main", "Main View" );
// NEW CODE BrowserNavigation navigation = RWT.getClient().getService( BrowserNavigation.class ); navigation.addBrowserNavigationListener( new BrowserNavigationListener() { public void navigated( BrowserNavigationEvent event ) { String state = event.getState(); // restore the application state } } ); navigation.pushState( "main", "Main View" );
RAP applications can not be accessed by startup parameter anymore:
http://hostname/webapp/rap?startup=example(OBSOLETE)
Instead of this, every entrypoint must have a dedicated path (servlet name):
http://hostname/webapp/example
If you used to register entrypoints by parameter in your extensions, you have to use the attibute path instead:
<extension point="org.eclipse.rap.ui.entrypoint"> <entrypoint id="example.entrypoint" class="example.MyEntryPoint"parameter="example"path="/example" /> </entrypoint> </extension>
To make an IApplication available at a certain path, you have to create a separate entrypoint extension and specify the id of the application extension in the new parameter applicationId.
<extension point="org.eclipse.rap.ui.entrypoint"> <entrypoint id="example.application.entrypoint" applicationId="example.application" path="/example" /> </entrypoint> </extension>
The attributes servletName, defaultEntrypointId, and the element associatedEntrypoints have been removed from the brandings extension point. Instead of adding entrypoints to a branding, a branding can now be bound to an entrypoint by setting the new attribute brandingId in the entrypoint extension:
<extension point="org.eclipse.rap.ui.entrypoint"> <entrypoint id="example.entrypoint" class="example.MyEntryPoint" path="/example" brandingId="example.branding" /> </entrypoint> </extension>
The attribute exitConfirmationClass is no longer supported by the branding extension point. The new client service ExitConfirmation should be used instead.
Custom widgets and other components must now read and write JSON protocol messages using the new RemoteObject APIs on client and server. Components that read parameters from the request or write JavaScript directly, e.g. using JSWriter, will not work anymore.
Please check the RAP Developer's Guide and the RAP 2.0 New and Noteworthy for more information about these new APIs. The CkEditor for RAP is a good example for a custom widget that uses these new APIs.
Please note that the Remote API has changed again in RAP 2.1.
To start a RAP application in development mode, please replace the VM parameter
-Dorg.eclipse.rwt.clientLibraryVersion=DEBUG
with
-Dorg.eclipse.rap.rwt.developmentMode=true
.
The IDs of the features have been changed in order to follow the naming conventions that we use throughout all RAP components.
org.eclipse.rap.feature
org.eclipse.rap.runtime
.
org.eclipse.rap.equinox.target.feature
org.eclipse.rap.runtime.requirements
.
org.eclipse.rap.examples.feature
org.eclipse.rap.tools.feature
org.eclipse.rap.tools
.