Load ZUML in Java

From Documentation


Execution provides a collection of methods to allow you to create components based on a ZUML document, such as Execution.createComponents(String, Component, Map), Execution.createComponentsDirectly(String, String, Component, Map) and many others. In addition, Executions provides a similar collection of shortcuts so that you do not have to retrieve the current execution first.

For example,

public class Controller extends SelectorComposer {
    private Window main; //assumed wired automatically
    @Listen(onClick = #main)
    public void createListbox() {
           "<listbox><listitem label=\"foo\"/></listbox>", "zul", this, null);

Create from URI

There are several ways to create components based on a ZUML document. One of the most common approaches is to create components from a URI.

Map arg = new HashMap();
arg.put("myKey", someValue);
Executions.createComponents("/foo/my.zul", parent, arg); //attach to page as root if parent is null

where parent (an instance of Component) will become the parent of the components specified in the ZUML document. If parent is null, the components specified in the ZUML documents will become the root components of the current page. In other words, the components created by Execution.createComponents(String, Component, Map) will be attached to the current page.

The arg Object

The Map passed to the createComponents() can be accessed on the page being created by use of the arg object. For example,

<button label="Submit" if="${arg.myKey}"/>



Create Components Not Attached to Any Pages

If you want to create components that will not be attached to a page, you could use Execution.createComponents(String, Map). It is useful if you want to maintain a cache of components or implement a utility.

For example:

Map arg = new HashMap();
arg.put("someName", someValue);
Component[] comps = Executions.getCurrent().createComponents("/foo/my.zul", arg); //won't be attached to a page
cache.put("pool", comps); //you can store and use them later since they are not (yet) attached to any pages

Create Components in Working Thread

With Executions.createComponents(WebApp, String, Map), you could create components in a working thread without execution[1], though it is rare.

Of course, the components being created by Executions.createComponents(WebApp, String, Map) will not be attached to any pages. You have to attach them manually, if you want to show them to the client.

  1. It means Executions.getCurrent() returns null. For example, it happens when the application starts, or in a working thread.

Create from Content Directly

If the ZUML document is a resource of Web application (i.e., not accessible through ServletContext), you could use one of the createComponentsDirectly methods. For example, you could read the content into a string from database and pass it to Execution.createComponentsDirectly(String, String, Component, Map). Or, you could represent the content as a reader (say, representing BLOB in database) and then pass it to Execution.createComponentsDirectly(Reader, String, Component, Map)

For example, suppose we want to create a component from a remote site. Then, we could represent the resource as a URL and do as follows.

public void loadFromWeb(java.net.URL src, Component parent) {
        new java.io.InputStreamReader(src.openStream(), "UTF-8"), parent, null);

Create from Page Definition

When creating components from the URI (such as Execution.createComponents(String, Component, Map)), ZK Loader will cache the parsed result and reuse it to speed up the rendering.

However, if you create components from the content directly (such as Execution.createComponentsDirectly(String, String, Component, Map)), there is no way to cache the parsed result. In other words, the ZUML content will be parsed each time createComponentsDirectly is called.

It is OK if the invocation does not happen frequently. However, if you want to improve the performance, you could parse the content into PageDefinition by using Executions.getPageDefinitionDirectly(WebApp, String, String), cache it, and then invoke Executions.createComponents(PageDefinition, Component, Map) to create them repeatedly.

PageDefinition is a Java object representing a ZUML document. It is designed to allow ZK Loader to interpret even more efficiently. Unfortunately, it is not serializable, so you can not store it into database or other persistent storage. You could serialize or marshal the original content (i.e., ZUML document) if required.


There are a few notices worth to know.

No Page Created

When creating components from a ZUML document as described above, no page (Page) is created. Components are attached to the current page, to a component, or simply standalone. Since no page is created, there are a few differences than visiting a ZUML document directly[1].

  1. The <?page?>, <?script?>, <?link?>, <?header?> and other directives controlling a page (Page) have no function. It means that you could not change the page's title, add JavaScript code, or add CSS with these directives in a ZUML document loaded in this way.
  2. On the other hand, when <?function-mapper?>, <?variable-resolver?> and <?component?> work correctly, they decide how a ZUML document is parsed rather than how the current page (Page) should be.
  3. The variables, functions and classes defined in zscript will be stored in the interpreter of the current page (Page.getInterpreter(String)).

  1. Don't confuse a ZUML page with Page. The former refers to a file containing a ZUML document. The latter is a Java object of Page that represents a portion of a desktop.

Last Update : 2024/02/06

Copyright © Potix Corporation. This article is licensed under GNU Free Documentation License.