Embed ZK Component in Foreign Framework

From Documentation


Embed ZK Component in Foreign Framework


Employment/Purpose

Here we describe how to embed ZK component(s) as a native element of a foreign framework. For example, how ZK components can be embedded as a native JSF component. It allows application developers to use the native element without knowing the existence of ZK.

For the sake of description, we call it the embedded component.


Note: If it is OK for your developers to work on ZUL directly, it is more convenient and powerful to use the inclusion (such as <jsp:include>) or ZK JSP Tags, and you don't have to wrap them into a native element.

Prerequisite

DOCTYPE

To use ZK components correctly, the pages generated by the foreign framework (JSP, JSF...) must generate the doc type as follows.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

Browser Cache

Though optional, it is suggested to disable the browser to cache the result page. It can be done as follows.

<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Pragma" content="no-cache" />
    <meta http-equiv="Expires" content="-1" />

Embed a component directly

The simplest way to embed is to invoke Renders.render(ServletContext, HttpServletRequest, HttpServletResponse, Component, String, Writer) when it is time to output the content of the native element.

For example, if you are implementing a JSP tag, then you can invoke the render method in doTag() as follows.

 1 public void doTag() throws JspException, IOException {
 2     //prepare variables
 3     final JspContext jspctx = getJspContext();
 4     final PageContext pgctx = Jsps.getPageContext(jspctx);
 5     final ServletContext svlctx = pgctx.getServletContext();
 6     final HttpServletRequest request = (HttpServletRequest)pgctx.getRequest();
 7     final HttpServletResponse response = (HttpServletResponse)pgctx.getResponse();
 8 
 9     //create components
10     Listbox listbox = new Listbox();
11     listbox.appendChild(new Listitem("Item 1"));
12     listbox.appendChild(new Listitem("Item 2"));
13 
14     //render the result
15     final StringWriter out = new StringWriter();
16     Renders.render(svlctx, request, response, listbox, null, out);
17     getJspBody().invoke(out);
18 }

Embed by implementing a richlet

If you want to have more control, such as applying a composer provided by users or creating components from a ZUL page, you could implement a richlet (Richlet) and then invoke Renders.render(ServletContext, HttpServletRequest, HttpServletResponse, Richlet, String, Writer) instead.

 1 Renders.render(svlctx, request, response,
 2   new GenericRichlet() {
 3     public void service(Page page) throws Exception {
 4         //execution is ready
 5         //... do whatever you want
 6         Window main = new Window();
 7         main.setPage(page); //associate to the page
 8         Executions.createComponents("/WEB-INF/template/foo.zul", main, null);
 9         composer.doAfterCompose(main); //assume user assigned a composer
10     }
11   }, null, out);

where we use GenericRichlet to simplify the implementation of a richlet.

Example

Embed as a native JSF component

ZK Component as a native JSF component can be easily achieved by wrapping it as a custom JSF component [1] and rendering it in Render Response Phase of JSF lifecycle by invoking Renders.render(ServletContext, HttpServletRequest, HttpServletResponse, Richlet, String, Writer)

 1 @FacesComponent(value = "window")
 2 public class WindowTag extends UIComponentBase {
 3 	private static final Log log = Log.lookup(WindowTag.class);
 4 	private Window window;
 5 	
 6 	public void encodeBegin(FacesContext context) throws IOException {
 7 		ServletContext svlctx = (ServletContext)context.getExternalContext().getContext();
 8 		HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
 9 		HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();
10 		ResponseWriter responseWriter = context.getResponseWriter();
11 
12 		try {
13 			Renders.render(svlctx, request,response, 
14 					new GenericRichlet() {	
15 						public void service(Page page) throws Exception {
16 							window = new Window();
17 							window.setPage(page);
18 							applyProperties();
19 							doAfterCompose();
20 						}
21 					}, null, responseWriter);
22 		} catch (ServletException e) {
23 			throw new IOException(e.getMessage());
24 		} 
25 	}
26 
27 	/** apply ZK component properties as retrieved from JSF custom component tag */
28 	private void applyProperties() {
29 		Map<String, Object> attrs = getAttributes();
30 		Set<String> attrNames = attrs.keySet();
31 		
32 		for (Iterator iterator = attrNames.iterator(); iterator.hasNext();) {
33 			String attrName = (String) iterator.next();
34 			if(!"apply".equals(attrName)) {
35 				try {
36 					Property.assign(window, attrName, attrs.get(attrName).toString());
37 				} catch(PropertyNotFoundException pnfe) {
38 					log.debug(pnfe.getMessage());
39 				}
40 			}
41 		}
42 	}
43 	/** apply composer by calling doAfterCompose after ZK component is composed */
44 	private void doAfterCompose() throws Exception {
45 		Object o = getAttributes().get("apply");
46 		if(o instanceof String) {
47 			o = Classes.newInstanceByThread(o.toString());
48 		}
49 		if(o instanceof Composer) {
50 			((Composer)o).doAfterCompose(window);
51 		}
52 	}
53 
54 ....
55 }

Version History

Version Date Content
5.0.5 September 2010 Renders was introduced to simplify the making of a native element for a foreign framework.



Last Update : 2024/02/01

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