Ralf is a software engineer with a history as Eclipse committer and project lead.
In recent years, he devoted himself to JavaScript technologies and helped pulling off …
RAP 2.0 is approaching and I want to explain the most important changes in this short blog series. The key innovation of RAP 2.0 is its support for alternative clients. Today I’d like to introduce you to the new Client API that lets you find out which client is currently connected. This interface can also be used to access some of the client’s specific features.
[ Get insight from Eclipse experts: polish up your coding in Eclipse Training. | More on RAP from our blog: RAP technology overview ]
When developing a RAP application, you normally don’t have to know which client is connected. SWT screens written for a native client can be accessed with the default web client just as well. You can check the Display for the client’s display resolution and adapt your SWT layout to the available screen estate (the client area).
However, in some cases you may want to make certain adjustments to your application, depending on the client. In this case, you can find out what client is connected to the current UI session by calling UISession.getClient() (you can also use the shortcut RWT.getClient()). The result is an instance of the interface Client. When accessed with the web client, it will be an instance of WebClient, for Tabris, it will be a TabrisClient.
Most clients can provide information about their timezone and locale, some can also provide their geo position. Accessing this information can help to supply the user with more appropriate information. To make this information available, we could have added methods like getTimeZone() or getGeoPosition() to the Client interface. However, mobile clients can offer a lot more services, such as scanning bar codes, taking photos, or making phone calls. Moreover, some services are not specific to one client but can be provided by different clients. Adding methods for every possible feature to the Client interface was clearly not an option but we also wanted to avoid code that looks like this:
if( client instance of ThisClient ) {
((ThisClient) client).doThis();
} else if( client instance of ThatClient ) {
((ThatClient) client).doThat();
} else if( client instance of SomeOtherClient ) {
((SomeOtherClient) client).doSomethingElse();
…
Using the Service Locator pattern allowed us to come up with an extensible API. Every client implements the method getService( ClientService ):
GeoLocation location = client.getService( GeoLocation.class );
if( location != null ) {
location.getLatitude();
}
Using this method is like going to a hardware store to buy a tool that you need. If you’re lucky, the item is in stock, otherwise you walk out with empty hands. If the client cannot provide the requested service, there’s nothing we can do. Whether a service is available or not depends on the client implementation, and it may even depend on the client device (does it have a camera?). The RAP API contains only the hardware store (the Client) and those tools that the default web client can provide. Alternative clients may implement these services, but they can also provide their own specific service interfaces.
Employing a service locator started as an experiment. There is some controversy about this pattern and I’m sure there are plenty of ways to misuse it. However, since we introduced the client services, we found much more use cases than we initially expected. The WebClient already supports six different services (ClientInfo, JavaScriptExecutor, JavaScriptLoader, just to name a few), and more will follow. In Tabris, there are plenty of client services, such as AppLauncher, GeoLocation, Camera, etc. (some of them are not implemented as client services yet as they predate this API).
So it feels like a good choice. I can’t wait to see more stores opening along that road!
[ This post belongs to the RAP 2.0 Countdown series. Continue with part 4 or go back to part 2. ]
Ralf is a software engineer with a history as Eclipse committer and project lead.
In recent years, he devoted himself to JavaScript technologies and helped pulling off …