Load ZUML in Java
Overview
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 GenericForwardComposer {
private Window main; //assumed wired automatically
public void onClick() {
Executions.createComponentsDirectly(
"<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 approach is to create components from a URI.
Map arg = new HashMap();
arg.put("someName", 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 method can be accessed in the page being created by use of the arg object. For example,
<button label="Submit" if="${arg.someName}"/>
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 wan 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 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.
- ↑ 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) {
return Executions.createComponentsDirectly(
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.
Notices
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].
- 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 directive in a ZUML document loaded in this way.
- On the other hands, when <?function-mapper?>, <?variable-resolver?> and <?component?> work correctly, they decide how a ZUML document is parsed rather than how the current page (Page) shall be.
- The variables, functions and classes defined in zscript will be stored in the interpreter of the current page (Page.getInterpreter(String)).
- If Execution.createComponents(String, Map), Executions.createComponents(WebApp, String, Map) or similar is used to create components not attached to any page, the variables, functions and classes defined in the ZUML document will be lost. Thus, it is a not a good idea to use zscript in this case.
- ↑ Don't confuse a ZUML page with Page. The former refers to a file containing a ZUML document. The later is a Java object of Page represents a portion of a desktop.
Version History
Version | Date | Content |
---|---|---|