Scopes in RAP

While RAP inherits many traits of a desktop application framework from SWT/RCP, it is in fact a multi-user, client-server based web framework. This means there are some significant architectural differences that need to be considered when building RAP applications.

In a desktop environment, an instance of an application normally serves only a single user, runs in its own Java VM instance, and the operating system usually provides a user-specific storage on the file system. The UI is rendered on the same machine as the application runs on, and when the user exits, the application is terminated. For RAP applications, these things work differently.

A RAP application does not own the VM. It runs on a server and shares the VM with the servlet container, other applications, maybe even other RAP applications. There are multiple users accessing an application, each one with a separate UI connected via HTTP, but all sharing the same classes. Moreover, a RAP application runs for a very long time. When a user logs in, the application is already running, and it will continue to run when the user leaves.

For these reasons, it is necessary to distinguish various scopes and threads in RAP.

ApplicationContext

There can be more than one RAP application running at the same time, e.g. in different web applications, or even on different servlet containers listening on different network ports. Every application has it's own set of entry points, registered resources and service handlers. All these things have application scope and are kept in the ApplicationContext. The current instance of the application context can be obtained via RWT.getApplicationContext().

The ApplicationContext can be used to acquire application-scoped instances of framework services such as the ResourceManager. An application can also use the ApplicationContext to store any data as attributes. Objects stored in the application context have application scope, i.e. they are accessible from everywhere in the application, but not from another application.

The application context lives as long as the application runs on the server, even if there are currently no clients connected. When the application is stopped (e.g. when the servlet context is destroyed), all data in this scope is lost. The application context is thread safe, it can be accessed concurrently from different threads. However, an instance of the application context can only be acquired from the context of a UI Session (see Threads).

UISession

A UI session in RAP spans exactly one execution of an EntryPoint. It is created when the user connects to the server, and usually ends with a refresh or timeout. While UI sessions are built on top of the servlet container's session management, they are not identical to the underlying HTTP session. For example, when the browser is refreshed (usually by hitting F5) to start over, the user still has the same HTTP session, but a fresh UI session.

A UI session is represented by an UISession instance that can be obtained by calling RWT.getUISession(). It provides access to session details such as the client object, and also to the underlying HTTP session. Similar to the ApplicationContext, the UISession it can be used to store session-scoped data as attributes. Often, what would be a singleton or static field in a desktop application, requires UI Session scope in RAP.

Session Timeout

A UI session ends when the execution of an entry point is finished (display is disposed) or when the underlying HTTP session times out. The timeout interval must be be configured with the servlet container. For web applications, this can be done in the web application's deployment descriptor (web.xml):

<session-config>
  <session-timeout>30</session-timeout>
</session-config>

The timeout value can also be changed programmatically on a per session basis:

RWT.getUISession().getHttpSession().setMaxInactiveInterval(<timeout in Seconds>);

Note that when using the RAP launcher, sessions never expire by default. To change this, adjust the timeout setting on the Main tab.

Session Cleanup

To cleanup UI session-scoped objects, a UISessionListener can be registered with the UI session:

RWT.getUISession().addUISessionListener( new UISessionListener() {
  public void beforeDestroy( UISessionEvent event ) {
    // Perform cleanup
  }
} );

Another way to run cleanup code is to register a dispose runnable with the Display using its method disposeExec(). This method also works in SWT.