Frequently Asked Questions

General Questions

  • What are the benefits of ULC? >>
  • On what platforms does ULC run? >>
  • Which IDEs support ULC? Can I use Eclipse / WebSphere Studio to develop ULC applications? >>
  • How do I access the bug database for ULC? How do I report a problem? >>
  • How do I keep in touch with ULC developers and developments in ULC? >>

Deployment

  • What are the components of a ULC application and how are they deployed? >>
  • How do I deploy and test a ULC application as an applet? >>
  • How do I deploy a ULC application in an EJB container? What does the client code accessing the ULC EJB look like? >>
  • What protocol is used for communication between the ULC client (UI Engine) and the ULC application (on the server)? >>
  • How do I secure my ULC applications? >>
  • How do I test my ULC applications for performance, scalability, and stress with multiple clients? >>
  • Is the entire GUI of an application instantiated at once on the client? >>
  • What really happens internally when the UI Engine initiates a connection to a ULC application? >>
  • Can the ULC client be synchronized with the server in case of loss of connection? >>

Development

  • What are the best coding practices for ULC applications? >>
  • How do I extend ULC with a new widget? >>
  • Can ULC applications be created using screen painting/drag&drop of widgets from a palette? Is there GUI Builder support? >>
  • Do I have to write or understand client/server communication methods in order to write ULC applications? >>
  • Where and how are the events on the widgets handled? How do I speed up the display of data? What are the benefits of synchronous and asynchronous modes of event processing? >>
  • How can a ULC application handle server-side database connection pooling? >>
  • How can I access the client environment? >>
  • Is it possible to call native code synchronously/asynchronously from the UI Engine? >>
  • Is it possible to manipulate ULC objects or fire events from another thread? Is there an equivalent of Swing's invokeLater in ULC? >>
  • How do I implement server push functionality? >>
  • How can I save on server round trips? >>
  • How do I change the look and feel of my ULC application? >>
  • How do I set up the sorting of table columns? >>
  • How do I change the icon or the rendering of a tree node? >>

What are the benefits of ULC?

In a nutshell, ULC will save you time and resources because it is based on a standard and mature user interface technology, and is not restricted by browser limitations.
For more information see Business Value.

On what platforms does ULC run?

ULC requires Java 2 (JRE or JDK 1.4 or later), i.e., J2SE for the UI Engine on the client and J2EE for the ULC application on the server.

Generally, ULC is J2EE-compliant and can therefore be deployed in any J2EE-compliant application server that supports either at least the Servlet 2.4 specification or at least the EJB 2.1 specification.


Which IDEs support ULC? Can I use Eclipse / WebSphere Studio to develop ULC applications?

ULC is a Java library that can be used in any IDE which provides support for the Java 2 platform (JDK 1.4 or later). For a description how to set up your IDE, see Section 3.3, Setting up your Java IDE for ULC, in the ULC Installation Guide.

How do I access the bug database for ULC? How do I report a problem?

Use the UltraLightClient Issue Tracking tool to track problem reports and feature requests.

Issue Tracking provides a Jira-based tool to track the status of ULC problem reports and feature requests. Search and browse through all public problem reports and feature requests.

To submit problem reports and feature requests, please send a detailled description to the ULC mailing lists.


How do I keep in touch with ULC developers and developments in ULC?

To stay up-to-date with the latest news about our ULC technology, subscribe to our ULC mailing lists:

  • General ULC News mailing list:
    Get the latest news about ULC releases, new add-ons, documentation and training. To subscribe, please visit the ULC news list.
  • ULC Developer mailing list:
    Take part in the latest ULC technology discussions about development issues, questions, bug reports and workarounds. To subscribe, please visit the ULC developer list.

  • ULC Premium Support mailing list:
    Premium Support offers guaranteed response times for your support queries within 1 working day (per email only, Swiss office hours from 9am to 5pm CET), free access to Premium Support mailing list archive and free upgrades within one year.
    For further information see ULC Premium Support.

What are the components of a ULC application and how are they deployed?

A ULC application has two components: an application-independent presentation component called the UI Engine on the client, and the ULC application running on the server. The UI Engine does not contain any application-specific code.

Client-Side Deployment:

The UI Engine is small: approximately 500KB of Java code, packaged in various Java archives (jar files). It consists of two components: the UI Engine launcher and the UI Engine core. Both components are customizable and extensible. The launcher creates an execution environment and starts the UI Engine. The UI Engine can be deployed and started in either of the following modes:

  • The launcher can be a standalone Java application creating a secure sandbox for the UI Engine. This mode requires explicit installation of the UI Engine on the client. The installation process might be supported by an installation program such as InstallAnywhere.
  • The launcher can be an applet, running the UI Engine within a browser.
  • Java Web Start is a lean way to both deploy the UI Engine and start ULC applications.

Server-Side Deployment:

A ULC application may be deployed as a servlet in a servlet container or as a stateful session bean in an EJB container.

The required protocol for the servlet container is HTTP(S). This is the standard deployment scenario for applications with users in the Internet since HTTP(S) is accepted by most firewalls.

An EJB container offers more sophisticated application management features, such as support for activation/passivation. For Intranet scenarios, this may be a valuable alternative to servlet container deployment.

How do I deploy and test a ULC application as an applet?

The UI Engine can be deployed and executed as an applet running in the Java Plug-in of a web browser. When the user clicks on a ULC application link in an HTML page, the UI Engine applet is started. The UI Engine connects to the ULC application running on the server to present the application's GUI. The URL of the ULC application is provided as an applet parameter to the UI Engine applet.

To run ULC applications as applets inside a web browser, you need to deploy them in a supported server container, such as an EJB container or a servlet container. There are two ways to deploy the applet: either embedded in an HTML page or outside the HTML page in a separate frame.

The suggested style of ULC development is writing application code and testing it on-the-fly with the DevelopmentRunner or AppletDevelopmentRunner, and eventually deploying it in a J2EE-compliant container and performing final tests such as testing the applet behavior in a web browser.

Described below is the procedure to run the Hello World sample application as an applet from within the Tomcat servlet engine:

  • Copy the hello.war file from the ulc-6.0/sample/hello/webapp directory to <tomcat-root>/webapps.
  • Start Tomcat.
  • Point your web browser to: http://localhost/hello/index.html.
  • Click on the applet link to start the Hello World application.

Please refer to ULC Deployment Guide for more details.



How do I deploy a ULC application in an EJB container? What does the client code accessing the ULC EJB look like?

A ULC application can be deployed as a stateful session bean in an EJB container. The transport protocol used by the UI Engine to connect to applications deployed in this way depends on the EJB container implementation. This deployment mode can be used to leverage the advanced management facilities of EJB containers (e.g., passivation/activation). ULC supports EJB containers that implement EJB specification 2.1 or higher.

For more details refer to the ULC Deployment Guide.

What protocol is used for communication between the ULC client (UI Engine) and the ULC application (on the server)?

ULC is (almost) independent of any protocol. During development you don't need to worry what protocol is going to be used in the production environment. The protocol is mainly determined by the container in which a ULC application is deployed. With a ULC application running inside a servlet container, the protocol is HTTP(S). With an EJB container it might be RMI, IIOP or T3, for example.

If you need to get through a firewall, deploy your ULC application in a servlet container, otherwise an EJB container may be an alternative.

How do I secure my ULC applications?

Similar to a web browser, ULC offers a variety of measures to meet stringent security requirements. Basically, it is recommended that the UI Engine is run in a sandbox. A sandbox is provided automatically when you run the UI Engine as an applet or through Java Web Start. In addition, protocols like HTTP(S) or IIOPS provide encryption and authentication.

The UI Engine can also be adapted to different security environments. In a trusted environment it may run outside the sandbox if it is restricted to connect to trusted hosts only. The UI Engine can also be signed by a trusted entity and restricted to connect to specific hosts only. Finally, using the Java Security Architecture, restricted access to security-sensitive functionality (e.g., access to portions of the file system) can be enabled.

How do I test my ULC applications for performance, scalability, and stress with multiple clients?

In addition to the ULC Framework, Canoo offers ULC Load, a tool to simulate multiple client connections and to measure the performance, scalability, and robustness of ULC applications. Since these characteristics depend on the underlying infrastructure components such as the Java VM, or the platform operating system, ULC Load can also be used to quantify the impact of these components.

ULC Load enables testers to record scenarios of user interactions with the ULC applications and then play these scenarios with an arbitrary number of players, thus loading the ULC application with simultaneous connections and requests. The testers can then measure statistics like number of requests, roundtrips, and size of requests.

Another way to observe performance of a ULC applications is by using the GUI console provided by ULC DevelopmentRunner. The DevelopmentRunner enables simulation of various network bandwidth scenarios for client/server communication. Moreover, it allows the users to set logging levels to be able to view the request data and size. Further details are available at ULC Reference Guide.

Is the entire GUI of an application instantiated at once on the client?

No. The GUI of the ULC application on the server side is instantiated on the client side (in the UI Engine) on demand. Instantiating a widget ina ULC application does not automatically upload it and instantiate in the UI Engine. It is instantiated in the UI Engine only when it or its becomes visible (setVisible(true)).

What really happens internally when the UI Engine initiates a connection to a ULC application?

When users connect to a ULC application, they start the UI Engine with the URL of the application as an argument. The UI Engine is started from the main method of a launcher class, which creates a connector object (responsible for the communication with the server) and a new UISession object, passing the connector to it. The connector encapsulates the transport protocol used (HTTP(S), EJB). UISession now sends, via the configured connector, an init request to the server (the 'server' in this case might be a servlet or an EJB). The init request also transmits client-specific information, such as display size, available fonts, widget specific LAF properties, etc. In response to the init request, the server creates a ULCSession which then creates an instance of the application class (the one implementing IApplication). The user's application class is wrapped by the ULCSession class, which is the server half-object. Next, the start method of the IApplication class is called, where the developer composes the user interface using ULC widgets. These widgets are then marshalled and sent to the UISession in response to the init request. The UI Engine interprets this description of the UI and renders it by instantiating client-side half objects with unique IDs and the underlying Swing widgets. This means that for a ULCButton in a ULC application on the server, a UIButton and a Swing JButton are created on the client within the UI Engine.

To understand what happens when the user starts interacting with the GUI, let's consider the example of a button widget. For a ULCButton widget, a UIButton half-object is registered as a listener of the actual Swing JButton. When a click occurs, the UI half sends a request to the server containing the ID of the button and event type, in this case actionEvent. On the server side, the registry is looked up with this ID, a corresponding server half-object is found (an instance of ULCButton) and the protected method ULCButton.handleRequest is executed, which will call actionPerformed() for all actionListeners added to this ULCButton by the ULC application developer. Therefore, developers using the ULC framework do not have to worry about the client/server split, they just add listeners to the ULC widgets and the framework takes care of all communication and notification.

More information about the internal architecture can be found in the ULC Architecture Guide.

Can the ULC application be synchronized with the updates made on the client in case of loss of connection?

At present, ULC does not provide any infrastructure to automatically synchronize client-side offline updates. Offline updates are highly application-specific and have to be implemented accordingly. Simply put, ULC provides an optional partitioning at the presentation level, i.e., the partitioning can be used in a client/server scenario or dropped in a standalone scenario without changes to the presentation code.

What are the best coding practices for ULC applications?

While coding ULC applications you need to keep in mind certain constraints that my be imposed by the performance requirements, or by the container in which the ULC application is running, etc. Please refer to ULC Essentials Guide for the best coding practices.

How do I extend ULC with a new widget?

ULC comes with a standard set of widgets. However, there may be a requirement to customize existing widgets or to add new widgets to the library. ULC Extension Guide describes how to extend ULC.

Can ULC applications be created using screen painting/drag&drop of widgets? Is there GUI Builder support?

Yes. In addition to the ULC Framework, Canoo offers ULC Visual Editor, an Eclipse plug-in that enables ULC applications to be created using screen painting or drag&drop of widgets from a palette.

For IDEs other than Eclipse, to create ULC applications, developers have to import the ULC framework classes into their IDE and build the GUI manually.

Do I have to write or understand client/server communication in order to write ULC applications?

The client/server communication mechanism, protocol, and distribution are handled completely by the ULC framework. Therefore, developers using the ULC framework do not have to worry about the client/server split and the communication between client and server. They can concentrate completely on GUI building using ULC widgets, by adding listeners and event handlers to the widgets. The framework takes care of all communication and notification. However, some knowledge of communication and notification is useful in order to improve performance, avoid unnecessary traffic, and make extensions to the framework.

During development a developer need not worry about the protocol to be used in production. The container in which the ULC application is deployed mainly determines the protocol used for communication between the ULC client (UI Engine) and the ULC application. With a ULC application running inside a servlet container, the protocol is HTTP(S). With a ULC application running inside an EJB container, it might be RMI, IIOP or T3, for example.

Deployment in a servlet container is recommended if you need to get through a firewall, otherwise an EJB container may be an alternative.

Where and how are the events on the widgets handled? How do I speed up the display of data? What are the benefits of synchronous and asynchronous modes in event processing?

ULC's event model is based on the same principles as the standard Java (AWT and Swing) event model. Action events, such as button click, scrolling, focus change, selection, defined by widgets are handled in the ULC application on the server. The ULC application framework does not give access to low level events (e.g., mouse events). Instead, low level events are either handled locally on the client side (to avoid a server roundtrip) or converted to a semantic event (e.g., action events), and then sent to the application on the server. Events are sent from the client to the server only if there is a registered listener for this event on the server side.

Event dispatching (i.e., sending an event to the server and calling the corresponding listeners) is handled synchronously by default in order to ensure data and user interface consistency. To increase the usability and responsiveness of a user interface, application developers can configure specific event listeners to be called asynchronously. However, developers must be aware that users might continue to interact with the user interface on the client while the event is dispatched to the server. Using the ClientContext.setEventDeliveryMode() method, events of a specific type and for a specific component can be configured to be delivered synchronously (i.e., the user interface is blocked) or asynchronously (i.e., the user can continue to interact with the user interface). By default, events are delivered synchronously.

When loading data (e.g., table rows), ULC uses asynchronous communication between the UI Engine and the ULC application. This allows ULC applications to stay responsive even in a wide area network where response times and network latency vary greatly.

How can a ULC application handle server-side database connection pooling?

ULC is basically a GUI library, which takes care of client/server partitioning. Developers define the application GUI using ULC widgets and implement the application logic in the event handlers of the widgets. The connection from the application to services, databases, etc. depends on the developer's preferences and to some extent on the container in which the ULC application is deployed. The code related to connections to databases and services can either be implemented in the container initialization-related code or in the application logic.

As far as database connection pooling is concerned, one solution would be to model the pool as a singleton. The connections will be established when the first client session gets the singleton. On the other hand, if you would like to do the initialization before starting the first client session then you need to look into container facilities. ULC requires the Servlet 2.4 specification.

How can I access the client environment?

ULC provides APIs in the ClientContext class which the UI Engine can use to access client functionality like reading and writing local files, showing a given URL in a web browser, accessing information about the client environment and most important UI defaults (like default colors, fonts, insets, and integer-valued properties). Client-side printing functionality can be implemented by uploading a PDF file from the server.

Is it possible to call native code synchronously/asynchronously from the UI Engine?

The UI Engine is a standard Java application and can be adapted and extended to specific needs. Therefore native calls via JNI are possible as well. The native code DLL or library, if not available on the client, can be distributed using JNLP.

ULC provides hooks to exchange custom messages between client and server. For example, using the ClientContext.sendMessage() API, a ULC application may send messages to the client which may delegate it to the native library. To react to such messages a client must have an IMessageService installed. This can be done by calling ClientEnvironmentAdapter.setMessageService(IMessageService messageService). This custom messaging mechanism could be used for notification of the completion of an asynchronous call.

Is it possible to manipulate ULC objects or fire events from another thread? Is there an equivalent of Swing's invokeLater in ULC?

It is not possible to perform operations on ULC objects from another thread and there is no equivalent of the Swing method SwingUtilities.invokeLater() in ULC. All the code must be executed as part of processing a client request in the widget's event handlers.

To simulate invokeLater-like behavior, use the ULCPollingTimer class. Using this class, the UI Engine can poll the ULC application at a specified polling interval. The non-ULC code can then be given access to the ULC objects in the IActionListener for the polling event. However, the appropriate fire methods should be called in the actionPerformed() method of the registered listener to initiate a server roundtrip.

How do I implement server push functionality?

The UI Engine and the ULC application communicate using the request-response model wherein the client initiates all the requests. This means there is no direct support for server-side push. However, push functionality can be simulated using client-side polling. This can be achieved by using the ULCPollingTimer class.

ULCPollingTimer creates a Swing timer on the client side, which will generate requests at specified time intervals. Then in the registered IActionListener code, check the global state and update each client session. Each time an action event is fired on the client side, a server roundtrip will be initiated. Hence, the ULCPollingTimer class can be used to poll the server for data updates. Please see the ULC Reference Guide for a details.

ULC polling scales much better than refreshing an HTML page, since ULC only sends changed data from the server to the client. In addition, the user interface remains stable, whereas with HTML the user interface is completely rebuilt.

How can I save on server roundtrips?

ULC widgets come with lots of built-in optimizations to reduce server roundtrips.

ULC offers formatting and input validation on the client side by means of configurable formatters and validators. So called "data types" allow widgets (e.g., text fields) to validate and format input data directly in the UI Engine, without any server roundtrips.

Some ULC components and models can act as "enabler sources" of other components. Enablers allow widgets to be enabled or disabled based on the state of another widget without a server roundtrip. In addition, enablers can be concatenated in order to realize simple boolean logic (e.g., by using AND and OR enablers).

Using the above mentioned features, application developers can achieve highly optimized validation and enabling behavior without any effort (compare this to HTML application development).

Moreover, to save on data transfers, developers can share ULC models across different widgets. When sharing ULC models, the actual data is transferred to the client only once, and cached on the client side thereafter. Also, loading of data on the client is done in a lazy mode, i.e., data is only requested from the server when it is needed for display on the client. In addition, to increase responsiveness, prefetch of data can be specified to save on future server roundtrips.

Uploading the GUI to the client side is also done in a lazy mode, i.e.,only when widgets become visible. In addition, network traffic can also be reduced by sharing ULC resource objects, ULCIcons and ULCFonts. The actual data of a resource (e.g., an image) is only transferred the first time the resource is referenced. For all subsequent references, only a symbolic reference is transferred; this dramatically reduces network traffic.

How do I change the look and feel of my ULC application?

There are several possibilities to set the L&F in ULC depending on how the application is executed on the client:

  • Write your own launcher:

    For applets, standalone and jnlp applications, default launchers are provided. You can extend these default launcher classes and set the look and feel (and any other UIManager oder UIDefaults settings) in the main method just as you would in a Swing application.

    public class LAFAppletLauncher extends DefaultAppletLauncher {
        public void init() {
            try {
                UIManager.setLookAndFeel(new MyLookAndFeel());
            } catch (Exception e) {
                e.printStackTrace();
            }
            super.init();
        }
    }
    
    public class LAFStandaloneLauncher
                extends DefaultStandaloneLauncher {
        public static void main(String[] args) {
            try {
                UIManager.setLookAndFeel(
                "com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
            } catch (Exception e) {
                e.printStackTrace();
            }
           DefaultStandaloneLauncher.main(args);
        }
    }
    
    public class LAFJnlpLauncher extends DefaultJnlpLauncher {
        public static void main(String[] args) {
            try {
                UIManager.setLookAndFeel(
                    "com.sun.java.swing.motif.MotifLookAndFeel");
            } catch (Exception e) {
                e.printStackTrace();
            }
            DefaultJnlpLauncher.main(args);
        }
    }
    
  • For standalone applications, configure the settings of the client VM:
    Set the Swing property when starting the application to:

    java -Dswing.defaultlaf=com.sun. ... .WindowsLookAndFeel MainClass
    
  • For JNLP applications:

    Unfortunately there is no way to set the look and feel only in the JNLP file because:

    1. The default permission only allows the read and write of properties that look like jnlp.xxx. To set the swing.defaultlaf property, you have to set the security to all-permissions and sign your application.

    2. Even with the security set to all-permissions and a signed application, it looks like version 1.2 of Java Web Start sets the property too late, that is after the UI is initialized.

    Therefore, you will need to write your own JnlpLauncher and call UIManager.setLookAndFeel() in any case. However, if you want to keep the flexibility to set the look and feel in the JNLP file, you can use a launcher similar to the example listed below. Do not forget to sign the application.

    add in the jnlp-file:
    <security>
    	<all-permissions/>
    </security>
    
    <property name="swing.defaultlaf"
         value="com.sun.java.swing.motif.MotifLookAndFeel" />
    
    
    public class FlexibleLAFJnlpLauncher extends DefaultJnlpLauncher {
        public static void main(String[] args) {
    	try {
                UIManager.setLookAndFeel(
                    System.getProperty("swing.defaultlaf"));
            } catch (Exception e) {
                e.printStackTrace();
            }
            DefaultJnlpLauncher.main(args);
        }
    }
    


How do I set up the sorting of table columns?

Sorting of table columns has to be implemented by developers where such functionality is required. This is illustrated in the TeamMembers application, the source code of which is available as part of the ULC distribution. An outline of the implementation is given below:

    1. Create a class SortedTableModel derived from an AbstractTableModel class. This class decorates an ITableModel thus adding sorting functionality to the decorated ITableModel.

    2. Use this SortedTableModel class for the table to be sortable.

    3. Sorting is controlled via the following methods of SortedTableModel: setSortedColumn() and setAscending().

    4. The Comparator to be used by the sort() method is also specified in the SortedTableModel.

    5. In the SortedTableModel, all methods of the ITableModel interface are delegated to the decorated ITableModel, e.g., getRowCount(), getColumnCount(), getColumnName(), setValueAt(), getValueAt(), etc. In all the delegated methods the SortedTableModel must consider the sorting, as the row indices need to be converted according to the current sorting. The events on the decorated ITableModel, such as tableChanged(), handleRowInserted(), etc., must be converted by the SortedTableModel according to the current sorting since they contain the row index.

    6. A SortAction listener is registered with the ULCTableHeader of the ULCTable. Every click on the TableHeader invokes the actionPerformed() method of the SortAction. This method sets the column to be sorted on the SortedTableModel (setSortedColumn()) and the sorting order (setAscending()), which carries out the sorting using the Comparator.


Further details can be obtained by refering to Sorted Table Model contribution of the ULC community.

How do I change the icon or the rendering of a tree node?

To change the icons used in a tree, set a custom ITreeCellRenderer. By implementing the method getTreeCellRendererComponent(), a component to be used for any node can be returned. For instance, the component could be a label with an icon. This mechanism can be used to customize the appearance of the root node as well as all other nodes.

As an example, the following code defines a custom tree cell renderer that renders non-leaf nodes in bold and uses cyan as the selection color:

tree.setCellRenderer(new CustomTreeCellRenderer());

private class CustomTreeCellRenderer extends ULCLabel
                                    implements ITreeCellRenderer {
    public IRendererComponent getTreeCellRendererComponent(
            ULCTree tree, Object value, boolean selected,
            boolean expanded, boolean leaf, boolean hasFocus) {
        Font treeFont = tree.getFont();
        int fontStyle = treeFont.getStyle();
        if (!leaf) {
            fontStyle = Font.BOLD;
        }
        setFont(new Font(
                treeFont.getName(),
                fontStyle,
                treeFont.getSize()));
        Color background = tree.getBackground();
        if (selected) {
            background = Color.cyan;
        }
        setBackground(background);
        return this;
    }
}