Plugin for Rich Internet Application development with Canoo's UltraLightClient (ULC) library.
The ULC Plugin provides advanced support for developing UltraLightClient
applications with Intellij IDEA. It contains the following features:
ULC provides a server-side API to Swing and allows for developing Rich Internet Applications (RIA) that run on the
server side in either a Servlet or an EJB container, but still provide a highly-usable, responsive and convenient
user interface based on Swing on the client side. More information on ULC can be found on the
UltraLightClient website from Canoo
The ULC facet provides convenient support for configuring the ULC version for a specific module. ULC itself consists
of a number of different jar files, each containing classes for one specific aspect, such as server-side component
API, client-side UI delegates, support for different server- and client-side deployment scenarios (Servlet, EJB,
Applet, JNLP, command line) or functional testing.
The ULC plugin organizes these aspects in "scopes" and "modules".
These are orthogonal in such a way that each module may be present in different scopes. For example, the "base"
module contains both classes for the "client" and the "server" scope, as there is both a "ulc-base-client.jar" and a
"ulc-base-server.jar". Using the ULC facet, the ULC scopes and modules can be specified for each module of the
The ULC facet supports multiple ULC versions starting from ULC 6.1.x. ULC versions are managed as installations (a
specific ULC version installed at a specific location on the computer). ULC Installations are added to the ULC facet
in a very similar way as JDKs are. ULC installations are stored globally one IDEA installation. For each module
configured using the ULC facet, one specific version is selected from the list of available ULC installations.
Depending on the ULC version related to that installation, the scopes and modules can be selected on demand. The ULC
facet automatically manages the jar files, source stubs and JavaDoc entries. Behind the scenes, ULC creates a module
libary called "ULC" for each ULC-enabled module. This "ULC" library can also be exported to other dependent modules
when using a multi-module project.
When creating a new project or module in IDEA, the ULC facet can already get configured during the new project / new
The ULC application class template provides support for creating a new ULC application class that already extends
from the corresponding ULC framework class and implements the required callback method for starting the application.
The ULC application class template can get customized using "IDE Settings" -> "File Templates". The template is
available in the "J2EE" tab under "UltraLightClient".
The ULC application class template can selected using "New" -> "ULC Application Class"
Using the ULC run configuration, a ULC application class can get started without the need for a main method or the
so-called "DevelopmentRunner" (CTRL + SHIFT + F10). The ULC run configuration automatically configures the ULC
environment that allows for executing the client- and server part of a ULC application in a single Java VM. This
way, ULC applications can also get debugged using the same debugging infrastructure known for standalone Java
applications (SHIFT + F9).
The ULC run configuration also supports configuration of advanced, ULC-specific parameters, such as carrier stream
provider, data stream provider, client- and server-side coder registry providers, ULC log level, connection type for
bandwidth and latency simulation, user parameter and init parameters.
Various ULC code inspections further simplifies the development of ULC applications and reduces the likelihood of
hard-to-find bugs. Currently, the following inspections are provided:
ULCProxy instances represent the server-side half of a distributed GUI component (according to the Half-Object
Protocol Pattern). Each proxy belongs to exactly one ULC session. Proxies have distributed state that automatically
gets managed by the ULC session. When proxies get shared between different ULC sessions, the state handling fails to
work properly. This may lead to hard-to-track exceptions. The most common error that lead to such exceptions is the
use of static references to instances of ULCProxy. This inspection is able to detect static references to proxies.
In ULC, each server-side proxy has an inner class called "dispatcher". This dispatcher represents the API the
server-side proxy exposes to it client-side counterpart for state synchronization and event dispatching. Dispatchers
build up a class hierarchy parallel to the ULCProxy class hierarchy in the sense that, if a proxy A extends proxy B,
then the dispatcher of proxy A also extends the dispatcher of proxy B. Doing so, it is ensured that the API exposed
to the client-side counterpart of proxy B is also available to the client-side counterpart of proxy A. In addition,
added a correct dispatcher to a ULCProxy extension allows for later extenions (e.g. by application projects using a
extension). This inspection detects missing dispatchers on ULCProxy subclasses and provides support for adding the
As a Rich Internet Application framework, ULC provides a number of widgets that display that from potentially large
models. Such widgets are tables, tree, table trees, lists or text areas. Instances of these widgets are normally
surrounded with a component that allows for scrolling through the large amount of data, a so-called scroll pane.
Adding such a widget directly into a container (a panel) often leads to non-usable applications with less appealing
layouts. This inspection checks for model-based widgets that are directly added to a container (using a method
called "add") and provides convenient support for surrounding the widget with a scroll pane.
Using the ULC plugin, it is very convenient to create and run a small "hello world" ULC application:
ULCFrame frame = new ULCFrame("Hello World Application"); frame.setDefaultCloseOperation(ULCFrame.TERMINATE_ON_CLOSE); frame.getContentPane().add(new ULCLabel("Hello World!")); frame.setLocationRelativeTo(null); frame.setVisible(true);