Embed ZK Component in Foreign Framework"
Line 11: | Line 11: | ||
</blockquote> | </blockquote> | ||
− | =DOCTYPE= | + | =Prerequisite= |
+ | ==DOCTYPE== | ||
To use ZK components correctly, the pages generated by the foreign framework (JSP, JSF...) must generate the doc type as follows. | To use ZK components correctly, the pages generated by the foreign framework (JSP, JSF...) must generate the doc type as follows. | ||
Line 18: | Line 19: | ||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" | ||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> | "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> | ||
+ | </source> | ||
+ | |||
+ | ==Browser Cache== | ||
+ | |||
+ | Though optional, it is suggested to disable the browser to cache the result page. It can be done as follows. | ||
+ | |||
+ | <source lang="xml"> | ||
+ | <html xmlns="http://www.w3.org/1999/xhtml"> | ||
+ | <head> | ||
+ | <meta http-equiv="Pragma" content="no-cache" /> | ||
+ | <meta http-equiv="Expires" content="-1" /> | ||
</source> | </source> | ||
Revision as of 08:32, 15 October 2010
Employment/Purpose
Here describes how to embed ZK component(s) as a native element of a foreign framework. For example, how to embed ZK components as a native JSF component. It allows application developers to use the native element without knowing the existence of ZK.
For 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.
<syntax lang="java" high="16"> public void doTag() throws JspException, IOException {
//prepare variables final JspContext jspctx = getJspContext(); final PageContext pgctx = Jsps.getPageContext(jspctx); final ServletContext svlctx = pgctx.getServletContext(); final HttpServletRequest request = (HttpServletRequest)pgctx.getRequest(); final HttpServletResponse response = (HttpServletResponse)pgctx.getResponse();
//create components Listbox listbox = new Listbox(); listbox.appendChild(new Listitem("Item 1")); listbox.appendChild(new Listitem("Item 2"));
//render the result final StringWriter out = new StringWriter(); Renders.render(svlctx, request, response, listbox, null, out); getJspBody().invoke(out);
} </syntax>
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.
<syntax lang="java"> Renders.render(svlctx, request, response,
new GenericRichlet() { public void service(Page page) throws Exception { //execution is ready //... do whatever you want Window main = new Window(); main.setPage(page); //associate to the page Executions.createComponents("/WEB-INF/template/foo.zul", main, null); composer.doAfterCompose(main); //assume user assigned a composer } }, null, out);
</syntax>
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)
<syntax lang="java" high="13"> @FacesComponent(value = "window") public class WindowTag extends UIComponentBase { private static final Log log = Log.lookup(WindowTag.class); private Window window;
public void encodeBegin(FacesContext context) throws IOException { ServletContext svlctx = (ServletContext)context.getExternalContext().getContext(); HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest(); HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse(); ResponseWriter responseWriter = context.getResponseWriter();
try { Renders.render(svlctx, request,response, new GenericRichlet() { public void service(Page page) throws Exception { window = new Window(); window.setPage(page); applyProperties(); doAfterCompose(); } }, null, responseWriter); } catch (ServletException e) { throw new IOException(e.getMessage()); } }
/** apply ZK component properties as retrieved from JSF custom component tag */ private void applyProperties() { Map<String, Object> attrs = getAttributes(); Set<String> attrNames = attrs.keySet();
for (Iterator iterator = attrNames.iterator(); iterator.hasNext();) { String attrName = (String) iterator.next(); if(!"apply".equals(attrName)) { try { Property.assign(window, attrName, attrs.get(attrName).toString()); } catch(PropertyNotFoundException pnfe) { log.debug(pnfe.getMessage()); } } } } /** apply composer by calling doAfterCompose after ZK component is composed */ private void doAfterCompose() throws Exception { Object o = getAttributes().get("apply"); if(o instanceof String) { o = Classes.newInstanceByThread(o.toString()); } if(o instanceof Composer) { ((Composer)o).doAfterCompose(window); } }
.... } </syntax>
Environment setup for using an embedded component
To use an embedded component, ZK Update Engine (DHtmlUpdateServlet) is required, while ZK Loader (DHtmlLayoutServlet) is not (though it is safe to install it too. If ZK Loader is not installed, it assumes the udpate URI is /zkau
, which can be overriden by setting a library property called org.zkoss.zkplus.embed.updateURI
.
<syntax lang="xml"> <servlet> <servlet-name>auEngine</servlet-name> <servlet-class>org.zkoss.zk.au.http.DHtmlUpdateServlet</servlet-class> </servlet>
<servlet-mapping> <servlet-name>auEngine</servlet-name> <url-pattern>/zkau/*</url-pattern> </servlet-mapping> </syntax>
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. |