Dynamic loading in Rich UI
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.
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 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
- 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 property 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.
For a sample use of the dynamic loader, see EGL Dojo widgets; and, in particular, the GalleryDynamicLoading.egl file there.
DynamicLoader functions
- 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 how to be in greater control of memory management: Rich UI memory management.
- 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
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 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- DynamicLoader.loadDoneListenersThis 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.loadFailListenersThis 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.loadInfoListenersThis 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 - Parts:
Handler instances
function createPage1() returns (Secondary)
anotherPage1 Secondary = new Secondary{};
return(anotherPage1);
end handler MainHandler type RUIhandler {onConstructionFunction = start }
// error!
anotherPage1 Page1 = new Secondary{};
endConsiderations 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.
- 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
- 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.
- The CSS and include files that are specified in the dynamically loaded handlers are not available to the Preview pane. You must reference those files from the handler being edited or from a handler that is directly or indirectly loaded by type reference from the handler that you are editing.
- You need to handle JavaScript™ runtime
files, even if you would not otherwise reference them. For example,
if Handler A does not use EGL Dojo widgets and refers to Handler B
only by string, and if Handler B uses EGL Dojo widgets, you must set
the includeFile property of Handler A to
reference the Dojo runtime code, as shown here:
{ includeFile = "config/includeDojo.html" }