Twitter Logo Follow us on Twitter
Project Information About this project

RAP 2.0 - New and Noteworthy

Here's a list of the most noteworthy things in the RAP 2.0 release which is available for download since February 11, 2013.

Network / Communication

In 1.5 we replaced the communication between server and client with a new, JSON-based format. In 2.0, the client uses the same format to report changes to the server. With this change, the entire communication uses the JSON protocol. No HTTP request parameters are involved anymore. All widgets LCAs have been reworked to handle the new JSON-based message.

The exact format is described in the RAP Protocol wiki page.

New Java API for Custom Widgets

With RAP 2.0, it's becoming a lot easier to write custom widgets or other add-ons for RAP. We've published a new Java API to synchronize server-side objects with their related objects on the client. This API is built on the new RAP protocol and it lets you send updates directly to the client (and receive updates from the client in turn) without diving too deep into RAP's internals. In particular, you don't have to write any so-called LifeCycleAdapters (LCAs) anymore.

RemoteObject

The central interface, called RemoteObject, is used to communicate with the client-side counterpart of an object, the remote object. First you need to create this object, then you can start sending updates to it by simply calling the remote object's set, call, etc. methods.

The following snippet shows how to create a remote object of the type example.CoffeeMachine and set the property sugar to the value false. That's all there is to do to send a create operation to the client with the initial property included.

Connection connection = RWT.getUISession().getConnection();
RemoteObject remoteObject = connection.createRemoteObject( "example.CoffeeMachine" );
remoteObject.set( "sugar", false );

OperationHandler

To receive updates from the client, you have to add an operation handler to the remote object. This operation handler has handle… methods for all relevant protocol operations.

remoteObject.setHandler( new AbstractOperationHandler() {

  @Override
  public void handleNotify( String event, Map<String, Object> properties ) {
    // react on the event, notify listeners ...
  }
} );

The new API lives in the package org.eclipse.rap.rwt.remote. It's still considered provisional, but already used by a couple of widgets and services in RAP itself. It's expected to evolve over the next release, but we don't expect big changes.

New JavaScript API for Custom Widgets

For the first time ever, RAP provides public JavaScript API. There's now an object named rap in the global namespace of the JavaScript client. All methods contained in this object are documented in the RAP API reference together with their return types. The most important methods are registerTypeHandler and getRemoteObject.

This API can also be used in JavaScript code added by the JavaScriptLoader, the JavaScriptExecutor, or the ClientScripting add-on.

Registering type handler

A type handler defines how protocol messages for a specific type should be handled. At minimum it defines a factory function that is used to create an object of this type when the server sends a create operation. It can also define the name of a destructor function, and a list of supported properties, events and methods. A typical type handler might look like this:

rap.registerTypeHandler( "example.CoffeeMachine", {

  factory : function( properties ) {
    return new CoffeeMachine( properties );
  },

  destructor : "dispose",

  properties : [ "sugar", "power" ],

  events : [ "Ready" ]

} );

The created object is stored by the framework under its object id. This object has to implement setter methods that match the properties defined in the handler, which will then be called when the server sends a set operation for a given property.

Remote Object (client)

Just like the server, the client provides a RemoteObject that represents the server-side counterpart of a client object. It has a very similar API, with set, call and notify methods. If, for example, the custom widget wishes to inform the server that the value of the property text changed, it could look like this:

var remoteObject = rap.getRemoteObject( this );
remoteObject.set( "text", this.getText() );
remoteObject.notify( "Modify" );

New Client API

Now that alternative clients can be connected to a RAP server, applications will need to distinguish between different clients, e.g. to render parts differently on certain clients.

To support those cases, we added a service provider interface Client that can be acquired using the new method RWT.getClient(). Unless you have a custom client implementation installed, RWT.getClient() will always return an instance of WebClient.

Client implementations can provide client-specific services, which can be obtained using the method getService( Class<T> type ). Some existing API has been transformed into services of the WebClient.

JavaScriptExecutor service

This service can be used to execute a piece of JavaScript code on the client. It replaces the internal class JSExecutor. Example:

JavaScriptExecutor executor = RWT.getClient().getService( JavaScriptExecutor.class );
executor.execute( "alert( \"Hello World!\" );" );

JavaScriptLoader service

If a custom component requires additional JavaScript code on the client, the JavaScriptLoader can be used to load a JavaScript file just before the component uses it. The JavaScriptLoader will ensure that the file is loaded only once, even if require() is called subsequently.

JavaScriptLoader loader = RWT.getClient().getService( JavaScriptLoader.class );
loader.require( "rwt-resources/myComponent/MyFile.js" );

ClientInfo service

The ClientInfo service provides additional information about the client that is connected to the current UI session. In this version, the service provides the client's locale and its timezone offset in minutes. Unfortunately, it's not possible to obtain the actual timezone region from the browser.

ClientInfo clientInfo = RWT.getClient().getService( ClientInfo.class );
int timezoneOffset = clientInfo.getTimezoneOffset();
Locale clientLocale = clientInfo.getLocale();

UrlLauncher service

The UrlLauncher service allows to open any URL (websites, files, "mailto", etc.) without influencing or leaving the application. Popup blocker may ask the user for permission before a new window is opened.

UrlLauncher launcher = RWT.getClient().getService( UrlLauncher.class );
launcher.openURL( "http://www.eclipse.org/" );
launcher.openURL( "mailto:someone@nowhere.org" );

Please use this new client service instead of the deprecated ExternalBrowser.

BrowserNavigation service

The BrowserNavigation service provides support for the browser's back/forward buttons and deep linking. It's a complete replacement for the removed class BrowserHistory.

BrowserNavigation navigation = RWT.getClient().getService( BrowserNavigation.class );
navigation.pushState( "main", "Main View" );

ExitConfirmation service

Used to configure the confirmation dialog that can be shown before the user leaves the application. It is no longer possible to do this in a branding. Example:

ExitConfirmation confirmation = RWT.getClient().getService( ExitConfirmation.class );
confirmation.setMessage( "Where do you think you're going?!" );

Widget Set

Touch-Scrolling for Tree and Table

Tree and Table widgets can now be scrolled on mobile devices (iOS and Android) by dragging a row with one finger. However, Tree and Table can only scroll item-by-item, not smooth like the List.

SWT.ICON_SEARCH and SWT.ICON_CANCEL support for Text widget

Text widget now have full support for SWT.ICON_SEARCH and SWT.ICON_CANCEL style flags.

Theming enhancements

The themeablity of some widgets has been improved. The following properties and states have been added:

  • box-shadow property for DateTime
  • hover state and text-decoration property for List-Hyperlink
  • text-decoration property for Button
  • disabled state for Combo-Button-Icon

New Event System

The event system in RWT has been completely re-written. For historical reasons, the implementation was based on typed events like SelectionEvent with untyped events built on top. This caused several problems that are now fixed (see bug 334028).

This also allowed us to provide some missing API: All typed events have a time field that reflects the time an event has occurred. MouseEvent has a field count that allows to distinguish single and double clicks. Custom widgets can now use the protected method Widget #removeListener( int, SWTEventListener ).

API Changes

With the move to RAP 2.0, we are cleaning up our APIs. This will lead to breaking changes. Existing RAP 1.x applications will therefore need minor adjustments to work with RAP 2.0. See the RAP 2.0 Migration Guide for instructions on updating your code to RAP 2.0.

Package org.eclipse.rwt renamed

We renamed this package to org.eclipse.rap.rwt in order to comply with Eclipse naming convention that packages should be prefixed with the project that creates it.

Constant WidgetUtil.CUSTOM_VARIANT moved

This constant has been moved to the class RWT.

Prefix “I” removed from interfaces

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're removing the prefix from all interfaces.

Deprecated public classes and methods removed

JSWriter, JSVar, JSListenerType, JSListenerInfo
removed together with the corresponding methods in WidgetLCAUtil and ControlLCAUtil. These classes were used for rendering JavaScript are now obsolete.
AdapterFactory
removed without a replacement together with the extension point, see bug 344541
ResourceManagerFactory
remove without a replacement, see bug 348476

Graphics deprecated

The class Graphics had been used to create shared instances of resources like Color and Font before resource constructors were introduced in 1.3. This practice is problematic because instances created using these methods throw an exception when trying to dispose them. Moreover, they cannot be garbage collected. In RAP 2.0, resources should only be created using the constructors of Color, Font, Cursor, and Image.

Graphics also provided methods for test size measurement. We expect that these methods are hardly used by application code and can be replaced by SWT's GC API. To measure a string in a given font, create a GC, set the font, and call the GC methods stringExtent or textExtent. Don't forget to dispose of the GC afterwards.

Service store deprecated

The service store is used internally by the framework to store data in the scope of a request. Application developers shouldn't really need this store anymore. If an application needs to store any information in the request scope, it should use the request object directly, i.e. RWT.getRequest().setAttribute(...).

Session store replaced by UI session

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. Here's some background:

The HTTP session is managed by the servlet container which recognizes the user with the help of a Cookie or URL rewriting. It has a configurable timeout, after which a user has to sign in again. The HTTP session is the place to store user-specific information.

The UI session is built on top of the HTTP session, but has a shorter lifetime. A new UI session is started every time a user accesses an entrypoint and it lives as long this UI is being used. When the user accesses another entrypoint, this results in a new UISession, but the HttpSession will be the same. The UI session is the place to store information that is related to the current instance of an application's UI. It can now also be used to access UI-session-scoped instances such as the Client and the locale.

The interface ISessionStore has been renamed to UISession. The types SessionStoreListener and SessionStoreEvent have been renamed accordingly.

In addition to the get/setAttribute methods, UISession also provides access to the Client instance and the Locale. Actually, RWT.getClient() is now a shortcut for RWT.getUISession().getClient(). The same is true for RWT.getLocale() and RWT.setLocale( locale ).

New Server Push API to replace UICallBack

The class UICallBack represents RAP's mechanism to “push” UI updates to the client when these updates occur outside of a request. It can be activated and deactivated using an ID, in order to allow different parties to activate the the push independently. We noticed that users had trouble to understand the idea behind these IDs, so we tried to come up with a new API.

We chose to call the system server push, which is the common name for technologies that simulate a push update from an HTTP server to a client. To activate the server push, you can create a new ServerPushSession and start it. The push session can be stopped when it is no longer needed (in contrast to UICallBack, this can now be done from any thread). As long as there are any push sessions running, the framework will keep the server push system active.

BrowserHistory replaced by BrowserNavigation service

The BrowserHistory and related classes have been replaced by the more general BrowserNavigation client service. The new name will allow us to add more navigation features to this service that are not directly related to history. All features of BrowerHistory are retained, see the migration guide for a code example.

Application store replaced by Application context

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

In addition to the get/setAttribute methods, ApplicationContext has accessor methods for the resource manager and the service manager. Actually, RWT.getResourceManager() is now simply a shortcut for RWT.getApplicationContext().getResourceManager().

Service handlers

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 response objects from static methods anymore.

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.

Resource Manager Rework

The resource manager (IResourceManager) is used to register static resources like images or JavaScript files in RAP applications. We reduced its interface to this purpose and simplified the implementation.

  • For resources that are registered in an ApplicationConfiguration, the method Application.addResource(…) now accepts a ResourceLoader instead of IResource.
  • 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 encoding of a resource is not taken into account anymore, getCharset() has been removed from the IResource interface. If you used to register text files with a charset other than UTF-8, you should make sure that your client code reads the resources with the correct charset.
  • The Method getOptions() has been removed from the IResouce interface. This means:
    • The resource manager can not minify JavaScript anymore. It is recommend that custom component developers minify their JavaScript files with a tool such as YUI Compressor, Google Closure Compiler, or JSMin.
    • The resource manager can not add version hashes to file names anymore. If there is a need to add version hashes to URLs, applications can simply add a URL parameter like "?nocache=4711" when requesting the resource.

Moreover, the resource manager does not close input streams anymore after registering a resource, as it did in 1.5 (bug 347615). Double check that you're closing your input streams correctly.

Dropped Support for entrypoints by name

Until now, entrypoints could be registered with a name in an entrypoint extension. Those entrypoints had been available at a URL with the default servlet name “rap” and a URL parameter “startup” pointing to this name. This approach had a number of drawbacks, thus we decided to remove the support for it completely in RAP 2.0. Now entrypoints can only be registered by path, which was introduced in RAP 1.5. For example, an entrypoint that is registered with the path /foo will be available at:

http://hostname/webapp/foo

Branding

Entrypoint mapping

Since entrypoints are now always registered by path, there is no need for an entrypoint-to-path mapping in a branding anymore. Therefore, we removed the attributes servletName, defaultEntrypointId, and the element associatedEntrypoints from the branding extension point. A branding can now be bound to an entrypoint by setting the new attribute brandingId.

<extension point="org.eclipse.rap.ui.entrypoint">
  <entrypoint id="example.entrypoint"
      class="example.MyEntryPoint"
      path="/example"
      brandingId="example.branding" />
  </entrypoint>
</extension>

Exit confirmation

For exit confirmations, the new client service ExitConfirmation should be used as explained above. The attribute exitConfirmationClass is no longer supported by the branding extension point.

Branding API removed from RWT

With these changes, we also removed the branding API from RWT, namely the classes AbstractBranding and Header. We don't expect that anyone was using these classes. In plain RWT applications, entrypoint properties can be used for branding.

IApplication

If you use the interface IApplication as entrypoint to your application, you now have to add an entrypoint extension to your plugin.xml in order to bind the application to a path. To do so, create a new entrypoint extension and, instead of providing an EntryPoint class, specify the id of the application extension in the new parameter applicationId:

<extension point="org.eclipse.rap.ui.entrypoint">
  <entrypoint id="example.application.entrypoint"
      path="/example"
      brandingId="example.branding"
      applicationId="example.application" />
  </entrypoint>
</extension>

Settings

Development Mode

During development, it's recommended to start RAP in development mode. In this mode, the JavaScript for the web client is not compressed and potential client-side errors will not be caught. This new setting replaces the old clientLibraryVersion, which has been used for this purpose before. In the RAP Launcher, you'll find a new option to enable the development mode:

In OSGi launch configurations, please replace the VM parameter -Dorg.eclipse.rwt.clientLibraryVersion=DEBUG with -Dorg.eclipse.rap.rwt.developmentMode=true.

Tools

RAP Launcher always terminates previous launch

The RAP launcher has an option to terminate an already running application before starting a new one. This turned out to be a valuable feature, particularly when working with fixed ports. We couldn't find a good reason to ever disable this functionality, so we decided to remove the option from the launcher while keeping the default behavior.

RWT Launcher

The RWT Launcher has got new options to configure the session timeout and the context path, just like the RAP Launcher.

New Basic Template

For lightweight RAP applications, we recommend to implement an EntryPoint and an ApplicationConfiguration instead of using the Workbench and its extension points. To get you started quickly with a minimal application, we added a new very basic Hello World template to the RAP Tools. This template uses declarative services to register an ApplicationConfiguration. It replaces two old Eclipse Workbench-based templates.

The popular Mail template remains as an example for an application that uses the Workbench stack, IApplication, advisors, views and a perspective, etc.

Bugfixes

This list shows all bugs that have been fixed for this release.

RAP 2.0 Migration Guide

After 6+ years of development in the 1.x stream, we're cleaned up some API in RAP 2.0. To assist you with the migration from 1.x to 2.0, we maintain a migration guide.