Instead of deploying all the Rich UI handlers into a single
HTML file, you can control the downloading of Rich UI handler code
at run time. For large applications, you gain significant advantage
in scalability and performance. Dynamic loading is not supported
in version .7.
Each dynamic load is asynchronous. You code listener functions
to respond when the load completes, and until the load completes,
the user continues to interact with the web page.
By way of background, consider that one handler can refer to another
handler in either of two ways:
- By a type reference, as in the following examples:
// a simple declaration
mySecondary Secondary{};
// the as keyword, in a usage described later in this topic
mySecondary Secondary = theHandler as Secondary;
- By a quoted string that is resolved only at run time, as in the
following example:
handler MainHandler type RUIhandler {onConstructionFunction = start }
function start()
// Load the first page
DynamicLoader.loadHandler("myPkg.Secondary");
end
If you want to ensure that a handler is loaded from the application
server only at run time, do as follows:
- Invoke the DynamicLoader.loadHandler function.
- Configure the EGL deployment descriptor. Your purpose is twofold:
- To identify the handler that is named in the invocation of DynamicLoader.loadHandler.
The string used as an argument is meaningful only at run time. By
identifying the same handler in the EGL deployment descriptor, you
ensure that the handler is available for runtime load.
- To prevent the handler from being included in the immediately
downloaded code, which is the logic that is downloaded at one
time; for example, in the initially downloaded HTML file. If one handler
dynamically loads a second handler that dynamically loads a third,
only the parts and widgets for the second handler are downloaded with
the second handler. The third handler is not in the immediately downloaded
code.
If you specify a type reference and do not configure the EGL deployment
descriptor for dynamic loading, the type reference causes the referenced
handler to be included in the immediately downloaded code.
As noted in a later code example, a type reference is necessary
if your code directly accesses fields or functions in the dynamically
loaded handler. However, a type reference is not necessary if your
code accesses only the widget array assigned to the initialUI field
of the dynamically loaded handler.
Dynamic loads are handled at run time by an EGL dedicated service
named ModuleLoaderService. Do not change this service, which deals
with internal details that might change in future versions of the
product.
Additional details are in the following sections:
For a sample use of the dynamic loader, see “EGL Dojo widgets”;
and, in particular, the GalleryDynamicLoading.egl file
there.
DynamicLoader functions
The
DynamicLoader library
has the following functions, along with listener functions (described
later) that respond to your invocation:
- loadHandler (handlerName String
in)
This function loads a handler.
- handlerName
- Fully qualified name of the handler to load dynamically, as in
the example shown earlier.
- loadHandlerNoInstantiation (handlerName String
in)
This function loads the handler type definition but not a handler
instance. You might use this function for better runtime performance.
For example, you might want a handler type to be available in your
application but to create the handler itself only if the user clicks
a menu item that requires the handler.
- handlerName
- Fully qualified name of the handler to load dynamically.
- unloadHandler (handlerName String
in)
This function unloads a handler but does not destroy the instances
of that handler. You cannot unload EGL libraries, which are available
until an application ends.
A handler instance cannot be removed
from memory if either of the following statements is true:
- The handler is referenced by type in another handler that is not
being removed from memory.
- The handler is subscribed to the Infobus, as described in “Rich
UI Infobus.”
In most cases, memory is freed by the EGL runtime code.
However, the following topic describes a case in which you are in
greater control of memory management: “Rich UI memory management for Microsoft™ Internet Explorer.”
- handlerName
- Fully qualified name of the handler to unload.
- showDebugView()
This function ensures
that details are displayed to show what is happening inside the dynamic
loader. You might set this in the on-construction function of your
main handler.
DynamicLoader listener arrays
The
DynamicLoader library
provides a mechanism by which you code listeners in accordance with
a Delegate part and then assign those listeners to an array and in
this way respond to events at run time. Here is an example use:
function start()
// Set handler for the event that the page has been loaded
DynamicLoader.loadDoneListeners ::= processLoadDone;
DynamicLoader.loadHandler("myPkg.Secondary");
end
function processLoadDone (event HandlerLoadedEvent in)
// attach the initialUI widgets to the current page.
// this step does not require use of a type reference.
div.children = event.initialUI;
// access a function in the loaded handler
theHandler any = event.theHandler;
// the use of a handler (or other container) of type any requires
// a type reference so that your code can directly access a field
// or function that is embedded in that container
if (theHandler isa Secondary)
p1 Page1 = theHandler as Secondary;
p1.doTask();
end
end
Here is the
HandlerLoadedEvent Record
part, which identifies what is available from the
event parameter
for
processLoadDone:
record HandlerLoadedEvent
// The name of the handler
name String;
// The widgets defined by the Rich UI handler.
initialUI Widget[];
// A reference to the Rich UI handler
theHandler any;
end
Here are the listeners and related Delegate
parts that are provided by the
DynamicLoader library:
- DynamicLoader.loadDoneListeners
This
array specifies a set of listeners that are invoked after the handler
is loaded. The delegate part is here:
delegate
LoadDoneListener (event HandlerLoadedEvent in)
end
- event
- As shown earlier. However, if a listener is running in response
to your having invoked the loadHandlerNoInstantiation function,
the initialUI parameter receives an empty
array, and the theHandler parameter receives
a null.
- DynamicLoader.loadFailListeners
This
array specifies a set of listeners that are invoked if the load fails.
The delegate part is here:
delegate
LoadFailListener (handlerName string in, msg string in)
end
- handlerName
- The fully qualified name of the handler that failed to load.
- msg
- An error message.
Here is an example:
function start()
DynamicLoader.loadFailListeners ::= processLoadFail;
DynamicLoader.loadHandler("myPkg.Secondary");
end
Function processLoadFail (handlerName string in, msg string in)
Syslib.writeStdErr(handlerName + “ failed to load. ” + msg);
end
- DynamicLoader.loadInfoListeners
This
array specifies a set of listeners that are invoked from the dynamic
loader and are used for tracing download and unload behavior at run
time. The set is invoked once for every downloaded or unloaded
resource,
which might be any of the following units:
- Parts:
- Rich UI handlers
- Basic handlers
- Widgets
- Libraries, including Rich UI properties libraries
- Records
- Other resources:
- JavaScript™ include
files, whether globally defined or referenced in an external type
- Properties files related to a Rich UI properties library
- Service-binding files related to an EGL deployment descriptor
The delegate part is here:
delegate
LoadInfoListener (handlerName string, resourceName string,
code string, msg string)
end
- handlerName
- The fully qualified name of the handler that was passed to a load
or unload function.
- resourceName
- The name of a downloaded or unloaded resource.
- code
- One of the following codes, each of which identifies a type of
information:
- DynamicLoader.INFO_LOAD indicates that the resource was loaded.
- DynamicLoader.INFO_UNLOAD indicates that the resource was unloaded.
- DynamicLoader.INFO_UNLOAD_SKIP indicates that the resource was
not unloaded; for example, because the resource was a library.
- DynamicLoader.INFO_DEBUG is a generic message from the dynamic
loader.
- msg
- A message.
Here is an example:
function start()
DynamicLoader.loadInfoListeners ::= processLoadInfo;
DynamicLoader.loadHandler("myPkg.Secondary");
end
function processLoadInfo (handlerName string,
resourceName string, code string, msg string)
if (code == DynamicLoader.INFO_UNLOAD)
Syslib.writeStdErr(resourceName + “ unloaded.”);
end
end
Handler instances
You can create new instances
of a handler after the handler is loaded, as shown here:
function createPage1() returns (Secondary)
anotherPage1 Secondary = new Secondary{};
return(anotherPage1);
end
Do not try to create a new instance before
the handler is loaded. Here is an example:
handler MainHandler type RUIhandler {onConstructionFunction = start }
// error!
anotherPage1 Page1 = new Secondary{};
end
Considerations for using CSS files at
run time
When the EGL deployer creates the HTML file for
a handler, the file includes a list of all the CSS files that are
used in the Rich UI application. CSS files are not loaded dynamically.
The
order of priority for the CSS definitions is as follows:
- At the highest level are the definitions in the topmost handler.
- Next are the definitions in the other handlers that are in the
HTML file.
- At the lowest level are the definitions in the handlers that are
loaded dynamically.
Considerations for using the Preview pane
of the Rich UI editor
When you run a handler in the Preview
pane of the Rich UI editor, the following rules apply:
- The workbench builds an HTML file that includes all resources
that are referenced by type in the handler being edited, or are referenced
by type in a handler that is referenced by one of those second-level
handlers, and so forth, to any level of reference.
- The only handlers that are loaded dynamically are those that are
identified by string and not by type reference.
For the handlers that are loaded dynamically in the Preview
pane, the following considerations apply: