22
Behind-the-scenes look at ZK Spreadsheet for IBM Lotus Domino Designer XPages Dennis Chen ([email protected] ), Potix Corporation Nancy Lin ([email protected] g), Potix Corporation Sachin Mahajan ([email protected] ), IBM May 2012 © Copyright International Business Machines Corporation 2012. All rights reserved. Summary: Learn how ZK and ZK Spreadsheet are integrated into IBM Lotus Domino Designer XPages. This white paper explains the concepts and implementation of ZK, ZK Spreadsheet, and XPages. Table of Contents 1 Introduction...................................................................................................................................1 2 Integrating ZK with other frameworks.........................................................................................3 3 Bridge component – ZulBridgeBase.............................................................................................7 4 Renderer – ZulRendererBase........................................................................................................9 5 ZK asynchronous update (AU) in XPages..................................................................................13 6 Configuration of XPages extension............................................................................................16 7 ZK Spreadsheet for XPages........................................................................................................17 8 Configurations.............................................................................................................................19 9 Usage...........................................................................................................................................20 10 Conclusion................................................................................................................................21 11 Resources..................................................................................................................................21 12 About the authors......................................................................................................................22 1 Introduction ZK SpreadSheet is a powerful Microsoft® Excel-like ZK mega component that has been offering users many unique features since its first release in 2009. For example, it is able to be embedded into Web- based applications, and is programmable and is easily integrated with current application data. XPages is a front-end, presentation-layer technology hosted by OpenNTF that runs in IBM® Lotus® Domino®. It not only follows Java TM Server Faces (JSF) 1.1 specification but also provides JSF 2.0 features so as to have Ajax-related functions as well. 1

Behind-the-scenes look at ZK Spreadsheet for IBM Lotus Domino Designer XPagespublic.dhe.ibm.com/software/dw/lotus/ZK_XPages_Final.pdf · 2012. 5. 15. · XPages, discussing the concepts

  • Upload
    others

  • View
    0

  • Download
    0

Embed Size (px)

Citation preview

  • Behind-the-scenes look at ZK Spreadsheet for IBM Lotus Domino Designer XPages

    Dennis Chen ([email protected]), Potix Corporation Nancy Lin ([email protected]), Potix CorporationSachin Mahajan ([email protected]), IBM

    May 2012

    © Copyright International Business Machines Corporation 2012. All rights reserved.

    Summary: Learn how ZK and ZK Spreadsheet are integrated into IBM Lotus Domino Designer XPages. This white paper explains the concepts and implementation of ZK, ZK Spreadsheet, and XPages.

    Table of Contents1 Introduction...................................................................................................................................12 Integrating ZK with other frameworks.........................................................................................33 Bridge component – ZulBridgeBase.............................................................................................74 Renderer – ZulRendererBase........................................................................................................95 ZK asynchronous update (AU) in XPages..................................................................................136 Configuration of XPages extension............................................................................................167 ZK Spreadsheet for XPages........................................................................................................178 Configurations.............................................................................................................................199 Usage...........................................................................................................................................2010 Conclusion................................................................................................................................2111 Resources..................................................................................................................................2112 About the authors......................................................................................................................22

    1 IntroductionZK SpreadSheet is a powerful Microsoft® Excel-like ZK mega component that has been offering users many unique features since its first release in 2009. For example, it is able to be embedded into Web- based applications, and is programmable and is easily integrated with current application data.

    XPages is a front-end, presentation-layer technology hosted by OpenNTF that runs in IBM® Lotus® Domino®. It not only follows JavaTMServer Faces (JSF) 1.1 specification but also provides JSF 2.0 features so as to have Ajax-related functions as well.

    1

    mailto:[email protected]

  • Currently ZK Components can be integrated with JSF under certain conditions. If we could deploy a similar concept to provide an integrated XPages plug-in, ZK Spreadsheet would be able to reach the XPages community, delivering to developers the convenience of embedding a complex Excel-like component into an application by using ZK Spreadsheet integrated within XPages.

    In this white paper we provide an overview of how ZK and ZK Spreadsheet are integrated into XPages, discussing the concepts and implementation of ZK, ZK Spreadsheet, and XPages.

    To get the most from this paper, it is recommended that you first understand the entire background of ZK Spreadsheet for XPages, including the concepts of the executing mechanism of JSF components and the executing mechanism of ZK components, and that you have general knowledge of developing an XPages plug-in.

    1.1 Defining the terminologyPlug-in: Following OSGi and XPages API standards, able to be installed in the Lotus Domino Server and Designer package.

    JSF Component: Components following JSF specifications; runs only within JSF Context.

    JSF Renderer: Renderer following JSF specifications; runs only within JSF Context.

    ZK Component: ZK server-side components, runs only within ZK Context.

    ZK Widget: ZK client-side components, produced from server side to client side; usable only within browsers.

    ZK Renders: org.zkoss.zkplus.embed.Renders; utility provided by ZK for generating the creation JavaScript of ZK Widgets in other UI frameworks.

    ZK Bridge: org.zkoss.zkplus.embed.Bridge; utility provided by ZK for generating the update JavaScript of ZK Widgets in other UI frameworks.

    ZulBridgeBase: Provides cross-operations of JSF and ZK components by implementing JSF Renderer and integrating ZK components.

    ZulRendererBase: Provides cross-framework build and update of JSF and ZK widgets by implementing JSF components and integrating ZK components.

    NOTE: To avoid redundant code, we only present simplified and shortened code in this document. For the complete source code, refer to http://code.google.com/p/zkxpage/

    1.2 What is XPages?XPages is a rapid Web-application-development platform and a presentation-layer technology

    2

    http://code.google.com/p/zkxpage/

  • enabling fast development of Web applications on an existing Domino server. On the browser side, it integrates the Dojo framework, providing convenient UI components and Ajax functionality. On the server side, it follows JSF specifications and leverages existing functionalities of Lotus Domino such as Document-Oriented databases.

    Moreover, when XPages applications are developed by use of Domino Designer, XPages also offers a drag-and-drop component and a What You See Is What You Get (WYSIWYG) design application screen-editing gadget.

    The development of XPages plug-ins follows the OSGi Plug-in specifications (like that of Eclipse plug-ins) while providing an extensibility API, allowing developers to customize their own plug-ins.

    2 Integrating ZK with other frameworksZK is a highly productive Java Web Framework known for its “Ajax without JavaScript” approach since its debut in 2005. Besides the continual endeavor in upgrading core functions and creating new components, the ZK Team is also committed to system integration with other frameworks, to enhance cross-community compatibility.

    At the presentation level, it is able to be integrated with frameworks following Java Enterprise Edition (JEE) specifications such as JSF and JavaServer Pages (JSP) while, at the backend, it can be integrated with middleware-layer technologies such as Spring, Grails and Contexts and Dependency Injection (CDI). For database accesses, ZK can also be integrated with persistence layers such as Hibernate and Java Persistence API (JPA).

    2.1 Integrate ZK & JSFAs the lifecycle of JSF is different than that of ZK, there are three main points when integrating them using the Render and Bridge concepts in ZK (see figure 1):

    1. Renders ZK Component in JSF Render phase: done by ZK Render.2. Provides ZK Component accessibility in JSF Action phase: done by ZK Bridge.3. Renders ZK Update by JSF Partial Response Writer: implementation depends on the version

    of JSF specification applied. With JSF 2.0, “PartialResponseWriter” can be used.

    3

  • Figure 1. JSF Lifecycle

    Listings 1 and 2 show partial code on how the JSF phases were implemented. For more detailed information, refer to the document, “ZK Developer's Reference/Integration/Embed ZK Component in Foreign Framework.”

    Listing 1. Rendering ZK in JSF Render phasepublic class WindowTag extends UIComponentBase { .... 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(); }

    4

    http://books.zkoss.org/wiki/ZK_Developer's_Reference/Integration/Embed_ZK_Component_in_Foreign_Frameworkhttp://books.zkoss.org/wiki/ZK_Developer's_Reference/Integration/Embed_ZK_Component_in_Foreign_Framework

  • }, null, responseWriter); } catch (ServletException e) { throw new IOException(e.getMessage()); } } .... }

    Listing 2. Rendering ZK in JSF Render phasepublic class MyBean { public void saveDetails(ActionEvent e) throws IOException { ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext(); ServletContext svlctx = (ServletContext) ec.getContext(); HttpServletRequest request = (HttpServletRequest) ec.getRequest(); HttpServletResponse response = (HttpServletResponse) ec.getResponse(); Component comp = getComponent(); Bridge bridge = Bridge.start(svlctx, request, response,comp.getDesktop()); try { // update ZK component(s) state here //comp.appendChild(new SomethingElse()); ... //Send back bridge.getResult() with the response writer (eval) PartialResponseWriter responseWriter = FacesContext.getCurrentInstance().getPartialViewContext().getPartialResponseWriter(); responseWriter.startDocument(); responseWriter.startEval(); responseWriter.write(bridge.getResult()); responseWriter.endEval(); responseWriter.endDocument(); responseWriter.flush(); responseWriter.close(); } finally { bridge.close(); } } }

    2.2 Integrate ZK with XPagesThe plug-in was divided into two parts, the first being the ZK Core plug-in, which takes charge of common related core and library functionalities, and the second part being the actual integration process of ZK Spreadsheet and XPages (see figure 2).

    This independence provides an architecture with great extensibility in that it's easily integrable with any ZK components. To add another ZK component plug-in to the scope, simply extend the ZK Core plug-in, which can be shared among multiple ZK component plug-ins.

    5

  • Figure 2. ZK Core plug-in components

    2.3 Integrate ZK Core Plug-inTo integrate this plug-in, we must first consider how to:

    • Render a ZK Component and a ZK Widget to Web pages.• Provide accessibility of ZK Components in the Action phase of JSF.• Update ZK Components, (JavaScript for updating ZK Widget) to Web pages.• Mount ZK Servlets to XPages context, enabling ZK Components to self-control and update.

    Considering that ZK Renders and ZK Builder provide more complex utilities at the base layer, which may become a concern for this project, an integration between JSF and ZK’s Components and Renderers was performed to form a common class for the extension. Figure 3 depicts this design spectrum.

    6

  • Figure 3. Integrating ZK and JSF components

    3 Bridge component – ZulBridgeBase“ZulBridgeBase extends UIComponentBase” is a standard JSF component mainly responsible for providing:

    • Getter/Setter attribute interfaces that follow values specified by JSF tags.• An attribute reference for “ZulRenderBase” when building a ZK component.• A ZK component (component filed) defined as transient for JSF Action phase or Renderer

    phase (see listing 3).

    Listing 3. Setters and Getterspublic abstract class ZulBridgeBase extends UIComponentBase implements Serializable {

    /* the root zk component instance, will be assign by renderer */ private transient Component component;

    .... /** get root ZK Component of this bridge**/ public Component getComponent() {

    return component; } /** get ZK Desktop that related to component **/ public Desktop getDesktop() {

    return component == null ? null : component.getDesktop();}

    7

  • /** zk properties from JSF tag **/ public String getStyle() {

    return states.getString("style",getFacesContext(),this); } public void setStyle(String style) {

    states.set("style", style); }

    ….

    It also implements “saveState(FacesContext)” and “restoreState”(FacesContext, Object state), integrates JSF and ZK context, saves the desktop-id and component-id, and uses this information to retrieve existing ZK components that were lost after “JSFpostback” due to rebuilding of components (see listing 4).

    Listing 4. State informationpublic void restoreState(FacesContext context, Object state) { ....

    String uuid = (String) values[2]; String dtid = (String) values[3]; ServletContext servletContext = (ServletContext) context

    .getExternalContext().getContext(); HttpServletRequest req = (HttpServletRequest) context

    .getExternalContext().getRequest(); Desktop desktop = ZkUtil.findDesktop(servletContext, req, dtid); if (desktop != null) {

    component = ZkUtil.findComponent(desktop, uuid); if (component == null) {

    throw new IllegalStateException("component " + uuid + " not in desktop " + desktop);

    } }

    .... }

    public Object saveState(FacesContext context) { ....

    Desktop desktop = component.getDesktop(); Object state[] = new Object[5];

    .... state[2] = component.getUuid(); state[3] = desktop.getId();

    .... return state;

    }

    ZulBridgeBase also provides the execution (Action) interface. By implementing this “Action” interface, when accessing ZK Components from the JSF Action Phase, it will automatically wrap ZK Renders and record the updated results of the ZK Widget that was produced.

    This will then be passed on to “ZulRenderBase” for the JSF Render Phase to use at a later step. Listing 5 shows the implementation of the Action interface.

    8

  • Listing 5. Executionpublic void execute(Action action) {

    ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();

    ServletContext svlctx = (ServletContext) ec.getContext(); HttpServletRequest request = (HttpServletRequest)

    ec.getRequest(); HttpServletResponse response = (HttpServletResponse)

    ec.getResponse();

    Desktop dt = getDesktop(); Bridge bridge = null; try{

    bridge = Bridge.start(svlctx, request, response,dt); action.doAction(this); addAuScript(bridge.getResult());

    } finally { if(bridge!=null){

    bridge.close(); }

    } }

    Action is a simple interface providing access to ZK components during the JSF Action phase:

    public interface Action {public void doAction(ZulBridgeBase bridge);

    }

    4 Renderer – ZulRendererBaseZulRendererBase is mainly responsible for turning a ZK component into a ZK Widget, or into updated JavaScript produced during the JSF Render phase, and then sending the response JavaScript to the browser. When turning a ZK component into a ZK Widget or into updated JavaScript, we must consider four types of conditions and come up with a solution for each one:

    • Not a post back. When users first link to this page, ZK Renders is used to create a ZK component, load its attributes, produce a ZK widget, and then finally output it to the page.

    • Post-back and full refresh. There will be a previous version of the Web page before it has been refreshed that will contain the ZK component in its state before the refresh. However, as the entire page will be fully refreshed, the existing ZK component must be re-attached to the new page, made into a new ZK Widget, and then output to the page.

    • Post-back and partial refresh, component is in update area. There will be a previous version of the Web page before it has been refreshed that will contain the ZK component in its state before the refresh. However, the partial refresh contains a ZK widget, which means that when part of the Web page is being refreshed, old contents (DOM) will be replaced by new contents and the ZK Widget will disappear.

    9

  • • Since we do not want to keep repeating the process of creating a new ZK Widget, we use the API provided by XPages update, save the ZK Widget temporarily, and then reattach it to the new content once it has been updated.

    • Post-back and partial refresh, component is not in update area. There will be a previous version of the Web page before it has been refreshed that will contain the ZK component in its state before the refresh. ZK Widget is not included in the partial refresh this time; therefore, simply use the API provided by XPages to update ZK Widget.

    A “JsfContext” class was created to help determine each of the four conditions (render cases), in which “FaceListener” is used to identify “Postback”, and “FacesContextEx” is used to identify partial refresh. Listing 6 demonstrates this class.

    Listing 6. JSF Context classpublic class JsfContext { ....

    /** * is current request a postback request */ public boolean isPostback(){

    FacesContext fc = check(); if(fc.getExternalContext().getRequestMap().get(Constants.POSTBACK_KEY)!

    =null){ return true;

    } return false;

    } /** * is current request a partial refresh request */ public boolean isAjaxPartialRefresh(){

    FacesContextEx fc = (FacesContextEx)check(); boolean r = fc.isAjaxPartialRefresh(); return r;

    } /** * is comp in the partial refresh list (include descendant). */ public boolean isAjaxRendered(UIComponent comp){

    FacesContextEx fc = (FacesContextEx)check(); boolean r = fc.isAjaxRendered(comp); while(!r){

    comp = comp.getParent(); if(comp!=null){

    r = fc.isAjaxRendered(comp); }else{

    break; }

    } return r;

    10

  • } }

    In “encodeEnd” under the “ZulRendererBase” class, every case is treated differently with different methods. Listing 7 shows the ZulRendererBase class.

    Listing 7. Zul Renderer base classpublic abstract class ZulRendererBase extends javax.faces.render.Renderer {….

    public void encodeEnd(FacesContext context, UIComponent component) throws IOException {

    ZulBridgeBase bridge = (ZulBridgeBase) component; ResponseWriter writer = context.getResponseWriter();

    JsfContext jsfc = JsfContext.instance(); if(!jsfc.isPostback()){

    // not a post back, a direct link//create a new zk component and attach it to new page newZKComponent(bridge, context);

    }else if(!jsfc.isAjaxPartialRefresh()){

    //postback, not a partial refresh //reuse old zk component and attach it to new page reattachZKComponent(bridge, context);

    }else if(jsfc.isAjaxRendered(component)){ //postback, in partial refresh //update client that added in ZulBridgeBase.execute outXspUpdateJs(bridge.getAuScripts());

    //reattach client widget to new dom (old one was replaced

    by new one with sam id) outXspUpdateJs("zkXPage.reattach('$" +

    bridge.getComponent().getId() + "','#"+bridge.getClientId(context)+"');"); }else if(bridge.hasAuScript()){

    //postback, not in partial refresh and has au update //update client that added in ZulBridgeBase.execute outXspUpdateJs(bridge.getAuScripts());

    } }

    ….

    In the construction of “newZKComponent()”, ZK Renders is used to create a new ZK Widget and output it to the Web page. Listing 8 shows the newZKComponent method, within which an abstract method “createRootComponent()” is also provided because an extended class can be easily inherited to build the actual ZK Component.

    Other methods such as “applyAttributes”, “applyComposer”, and “afterComposer” are also provided for the convenience of extending and/or customizing inherited classes.

    11

  • Listing 8. newZKComponent methodabstract protected HtmlBasedComponent createRootComponent(Page page, ZulBridgeBase bridge);

    protected void newZKComponent(final ZulBridgeBase bridge, final FacesContext context) throws IOException {

    final HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();

    final HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();

    final ServletContext svlctx = (ServletContext) context.getExternalContext().getContext();

    final ResponseWriter writer = context.getResponseWriter(); Renders.render(svlctx, request, response, new GenericRichlet() {

    public void service(Page page) throws Exception { applyVariableResolver(page);

    HtmlBasedComponent comp = createRootComponent(page, bridge);

    comp.setId(bridge.getId()); comp.setPage(page); bridge.setComponent(comp);

    applyAttributes(bridge,comp); applyComposer(bridge,comp,context); afterComposer(bridge,comp,context);

    } }, null, writer);

    }

    In the “reattachZKComponent” method (see listing 9), ZK Component must be detached before adding it to the new page after which ZK Renders is used to create a new ZK Widget and output it to the Web page.

    Since the page is fully refreshed, we do not need to care about changes made when the component was detached from the old page because these changes are also simultaneously recorded in the new ZK Widget.

    Listing 9. reattachZKComponent methodprotected void reattachZKComponent(final ZulBridgeBase bridge,

    FacesContext context) throws IOException {

    Desktop dt = bridge.getDesktop(); final HttpServletRequest request = (HttpServletRequest)

    context.getExternalContext().getRequest(); final HttpServletResponse response = (HttpServletResponse)

    context.getExternalContext().getResponse(); final ServletContext svlctx = (ServletContext)

    context.getExternalContext().getContext(); final ResponseWriter writer = context.getResponseWriter();

    Bridge zbridge = Bridge.start(svlctx, request, response,dt);

    12

  • try { //detach bridge.getComponent().detach(); //don't need to out au, all page is reloaded

    } finally { zbridge.close();

    } //re-attach Renders.render(svlctx, request, response, new GenericRichlet() {

    public void service(Page page) throws Exception { Component comp = bridge.getComponent(); comp.setPage(page); bridge.setComponent(comp);

    } }, null, writer);

    }

    In the “outXspUpdateJs” method (see listing 10), the API provided by XPages is used to output the JavaScript that's responsible for updating ZK Widget to the Web page.

    Listing 10. outXspUpdateJs methodprotected void outXspUpdateJs(List scripts){

    FacesContext ctx = FacesContext.getCurrentInstance(); UIViewRootEx vrex = ((UIViewRootEx)ctx.getViewRoot()); Iterator iter = scripts.iterator();

    while(iter.hasNext()){ String script = (String)iter.next(); ScriptResource r = new ScriptResource(); r.setClientSide(true); r.setContents(script); vrex.addEncodeResource(r);

    } }

    5 ZK asynchronous update (AU) in XPages The previous section established how a ZK Component can be rendered/updated and accessed in the JSF Context. We are addressing ZK component’s action and update issues and, to implement this, ZK’s “DynamicHtmlUpdateServlet” needs to be added into XPages. This section explains how to do this.

    5.1 Servlets in XPagesIn XPages, there are two methods by which a customized servlet can be added into the system, both of which use plugin.xml to configure. The first method is to add the servlet into the application by using “extensionorg.eclipse.equinox.http.registry.servlets”. Listing 11 shows an example.

    Listing 11. Example of adding servlet into the application

  • class="org.zkoss.xpage.core.web.AuServlet" load-on-startup="true">

    With this method, the servlet can be directly accessed in the application, for example, via http://localhost/myapp/zkau.

    This makes the method simple and independent while also following the standards of the lifecycle of a servlet. However, this method is not adopted in this project because the servlet created via this method is not able to share “Session” with XPages.

    The second method is to use “extension com.ibm.commons.Extension” and implement the “IServletFactory” interface (see listing 12).

    Listing 12. IServletFactory configuration

    In “IServletFactory”, the “init” and “getServletMatch” methods must fulfil the contract as shown in listing 13.

    Listing 13. IServletFactory interfacepublic abstract interface IServletFactory{ public abstract void init(ComponentModule paramComponentModule);

    public abstract ServletMatch getServletMatch(String paramString1, String paramString2) throws ServletException;}

    By doing so, the servlet can be accessed within the application itself via an XPages path, for example, via http://localhost/myapp/xsp/zkau (/xsp is a fixed path for saving “com.ibm.xsp.adapter.servletFactory”). Although this method does not follow standards of the servlet lifecycle, it can share “Session” with XPages and therefore is adopted for this project.

    5.2 XspServletFactoryAs with the “IServletFactory” interface, which does not follow the servlet lifecycle standards used to add the ZK Servlet into XPages, every servlet request sent to the ServletMatch is interpreted as a newly created servlet.

    This means that the “init()” method of the servlet is called out every time, resulting in ZK Servlet being repeatedly initialized in the same application context. Therefore we need to create a

    14

    http://localhost/myapp/zkau

  • mechanism to avoid this. Here a delegator class is used to forward the requests to ZK Servlet and employ a flag to avoid ZK Servlet from being called out by the init() method repeatedly, as outlined in listing 14.

    Listing 14. XspServletFactory classpublic class XspServletFactory implements IServletFactory { private Servlet servlet;

    static final String XSP_AU = "/xsp/zkau";static final String AU = "/zkau";

    private AuServlet auServlet;private boolean zk_initialed = false;...public ServletMatch getServletMatch(String contextPath, String

    path)throws ServletException {

    if(path.startsWith(XSP_AU)){initialServelts();ServletMatch sm = new

    ServletMatch(servlet,AU,path.substring(XSP_AU.length()));return sm;

    }//not a zk ajax updatereturn null;

    }

    /** initial zk servlets, NOTE no way to destroy for now **/private void initialServelts() throws ServletException {

    if(servlet!=null) return;auServlet = new AuServlet();servlet = module.createServlet(new XspAuServlet(),

    "xspAuServlet", config);}…public class XspAuServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;public void init(ServletConfig config) throws

    ServletException {//since initial will be called by every request , so

    I need to control it per ServletFactory scope.super.init(config);if(zk_initialed) return;auServlet.init(config);zk_initialed = true;

    }….

    public void doGet(HttpServletRequest req, HttpServletResponse res)

    throws ServletException, IOException {auServlet.service(req,res);

    }}

    }

    15

  • 6 Configuration of XPages extensionAt this point, most of the main coding process has been done. Now we must provide the correct configuration files for each separate plug-in. There are three main files:

    • Configuration file for the plug-in• JSF configuration file• XPages configuration file

    For “plug-in.xml”, the configuration file for the plug-in, “extension com.ibm.commons.Extension” is used to load the “com.ibm.xsp.Library” service, to provide XPages with basic information needed for the ZK Core Plug-in.

    com.ibm.xsp.Library defines an Xsp library that can be used by XPages to find information about ZK Core Plug-in. At the same time, ZK Servlet is also configured via this file. Listing 15 shows an extract from this file.

    Listing 15. plug-in.xml

    ....

    General information about ZK Core Plug-in are provided by XspLibrary, including the plug-in id, version, JSF configuration files, and XPages configuration files. This class is outlined in listing 16.

    Listing 16. XSP Librarypublic class XspLibrary extends AbstractXspLibrary {

    public String getLibraryId() { return "org.zkoss.xpage.core.library";

    }

    public String getTagVersion() { return "0.9.0";

    }

    public String getPlug-inId() { return "org.zkoss.xpage.core";

    }

    public String[] getFacesConfigFiles() { return new String[] { "META-INF/zk-xpage-core-faces-

    config.xml"}; }

    16

  • public String[] getXspConfigFiles() { return new String[] { "META-INF/zk-xpage-core.xsp-config"};

    } }

    The second file is a standard JSF configuration file, provided by “getFacesConfigFields” of “XspLibrary”.

    The third file is an XPages configuration file provided by “getXspConfigFiles” of “XspLibrary”. When dealing with JSF components, apart from setting the JSF configuration file, this file also must be set up with related information, the details of which are included in the next section.

    7 ZK Spreadsheet for XPagesNext, we discuss ZK Spreadsheet for XPages. You have probably noticed that the most vital point of the whole integration lies in ZK Core Plug-in. The actual implementation of integrating ZK Spreadsheet into XPages relies on ZK Core Plug-in and requires little coding.

    7.1 ZK Spreadsheet Plug-inWith ZK Core Plug-in readily at hand, the coding of ZK Spreadsheet Plug-in is now much simpler. All you need to do is to create a new plug-in that depends on ZK Core Plug-in, perform a small-scale implementation on inherited “ZulComponentBase” and “ZulRenderBase”, and provide Spreadsheet-related attributes.

    7.2 SpreadsheetBridgeThis class is inherited from “ZulBridgeBase”, providing Getter/Setter attribute methods related to ZK Spreadsheet as well as a convenient method that directly casts ZK Component to ZK Spreadsheet (see figure 17).

    Listing 17. SpreadSheet Bridgepublic class SpreadsheetBridge extends ZulBridgeBase {

    public String getSrc() {return states.getString("src",getFacesContext(),this);

    }

    public void setSrc(String src) {states.set("src", src);

    }

    ....public Spreadsheet getSpreadsheet(){

    Component comp = getComponent();return (Spreadsheet)comp;

    }}

    7.3 SpreadsheetRendererThis class inherits “ZulRendererBase” and provides the method of building a ZK Spreadsheet

    17

  • instance, setting attributes provided by SpreadsheetBridge to the ZK Spreadsheet instance (see listing 18). Other, more-complex logics are handled by its super class “ZulRendererBase”.

    Listing 18. SpreadSheet Runnerpublic class SpreadsheetRenderer extends ZulRendererBase {

    protected HtmlBasedComponent createRootComponent(Page page,ZulBridgeBase bridge){

    return new Spreadsheet();}

    protected void applyAttributes(ZulBridgeBase bridge, HtmlBasedComponent comp) throws Exception {

    super.applyAttributes(bridge, comp);SpreadsheetBridge zss = (SpreadsheetBridge) bridge;Spreadsheet ss = (Spreadsheet) comp;Integer in = zss.getMaxrows();if (in != null) {

    ss.setMaxrows(in.intValue());}in = zss.getMaxcolumns();if (in != null) {

    ss.setMaxcolumns(in.intValue());}

    ....}

    ...}

    7.4 XspLibraryThis class provides information needed for the ZK Spreadsheet plug-in, including plug-in ID, and version and configuration files needed for JSF. This class must be specifically set up in the plug-in.xml file.

    Listing 19. XSP Librarypublic class XspLibrary extends AbstractXspLibrary {

    public String getLibraryId() {return "org.zkoss.xpage.zss.library";

    }public String[] getFacesConfigFiles() {

    return new String[] { "META-INF/zk-xpage-zss-faces-config.xml" };

    }public String getPlug-inId() {

    return "org.zkoss.xpage.zss";}public String[] getXspConfigFiles() {

    return new String[] { "META-INF/zk-xpage-zss.xsp-config" };}public String getTagVersion() {

    return "0.9.0";}

    }

    18

  • 8 ConfigurationsWe must offer a plug-in configuration file (plug-in.xml) for OSGi as well as one JSF and one XPages configuration file required for XspLibrary.

    plug-in.xml. This configuration file must load the “com.ibm.xsp.Library” service via “extension com.ibm.commons.Extension” in order for XPages to provide the necessary information about ZK Core Plug-in (see listing 20).

    Listing 20. Plug-in xml config

    zk-xpage-zss-faces-config.xml. In this configuration file, information on JSF components for ZK Spreadsheet must be configured, for example, rendered-type and renderer-class of JSF components (see listing 21).

    Listing 21. zk-xpage-zss-faces xml config

    org.zkoss.xpage org.zkoss.xpage.spreadsheet org.zkoss.xpage.zss.renderkit.zul.SpreadsheetRenderer

    zk-xpage-zss.xsp-config. In this configuration file, component information on XPages for ZK Spreadsheet must be configured, for example, name-space, component group/property, component/component-extension/tag-bane, and component/property (see listing 22).

    Listing 22. zk-xpage-zss.xsp-config

    http://www.zkoss.org/xpagezk

    org.zkoss.xpage.xul....

    style

    19

  • java.lang.String

    ....

    A zk spreadsheet componentSpreadsheetorg.zkoss.xpage.spreadsheetorg.zkoss.xpage.zss.component.SpreadsheetBridgeorg.zkoss.xpage.xul

    spreadsheetorg.zkoss.xpageorg.zkoss.xpage.spreadsheet

    ....

    maxcolumnsint

    ....

    9 UsageWhen using ZK Spreadsheet in XPages, you must add ZK Spreadsheet tag and related properties, such as “src” or “maxrows”, to XPages. In order to access ZK Spreadsheet from XPages Action, you must first retrieve “SpreadsheetBridge”, then call out “execute(action:Action)”, and finally access ZK Spreadsheet during implementation of Action.

    In terms of how “SpreadsheetBridge” can be retrieved in the first place, a convenient request scope bean, “ComponentBindingBean” (named “zkComponentBinding” classified as “Map”) is provided for this purpose. The bean can be used to bind the component and the pages, as follows:

    To access ZK Spreadsheet in XPages Action, this simple utility bean can be used to retrieve “ZulBridgeBase” (see listing 23).

    Listing 23. Accessing ZK Spreadsheet in XPages actionComponentBinding.getBridge("sheet").execute(new Action(){

    public void doAction(ZulBridgeBase bridge) { Spreadsheet ss = ((SpreadsheetBridge)bridge).getSpreadsheet(); //manipulate spreadsheet here

    }});

    For more detailed information on the use of ZK Spreadsheet for XPages, refer to “ZK_Spreadsheet_for_XPage_HowToUse” and “ZK Spreadsheet Essentials.”

    20

    http://books.zkoss.org/wiki/ZK_Spreadsheet_Essentials%20http://code.google.com/p/zkxpage/wiki/ZK_Spreadsheet_for_XPage_HowToUse

  • 10 ConclusionThere are three main points to remember from this project:

    ZK Core Plug-in is the key plug-in. Although the main focus of this paper has been on ZK Spreadsheet for XPages, 90% of the code is related to ZK Core Plug-in, including “ZulBridgebase”, “ZulRendersBase”, and adding the ZK Servlet into XPages. Using the compatibility and extensibility provided by the design and implementations in ZK Core Plug-in makes it quite easy to create a ZK Spreadsheet Plug-in.

    ZK Spreadsheet is the key component. ZK Spreadsheet is the most suited ZK Component to be integrated with commonly adopted enterprise-level applications such as Lotus Domino. It can be easily embedded into an application, bringing Excel-like functionality to the Web, and it interacts with application data and executes logic integration.

    Any ZK Component is possible. The architecture of this integration is designed to be easily extensible such that any ZK Component (that is, to mega, independent components such as ZK Pivotable and ZK Calendar, not small components like a Button) can be integrated as an XPages Plug-in. This makes it extremely convenient for future integration and, in turn, the greatest value coming out of this project.

    11 Resources• Domino Designer Information Center topic, Introduction to the JavaScript and XPages

    reference:http://publib.boulder.ibm.com/infocenter/domhelp/v8r0/index.jsp?topic=%2Fcom.ibm.designer.domino.api.doc%2Fr_wpdr_intro_c.html

    • IBM Support Techdoc #7014929, “Knowledge Collection: XPages”:http://www-01.ibm.com/support/docview.wss?uid=swg27014929

    • XPages information:http://xpages.info/XPagesHome.nsf/Home.xsp

    • Notes and Domino Application Development wiki article, “XPages Extensibility API Developers Guide”:http://www-10.lotus.com/ldd/ddwiki.nsf/dx/Master_Table_of_Contents_for_XPages_Extensibility_APIs_Developer_Guide

    • developerWorks® article, “Rich Internet applications using ZK”: http://www.ibm.com/developerworks/web/library/wa-aj-open/?S_TACT=105AGX08&S_CMP=HP

    • ZK Open source Ajax:http://www.zkoss.org/

    21

    http://www.zkoss.org/http://www.ibm.com/developerworks/web/library/wa-aj-open/?S_TACT=105AGX08&S_CMP=HPhttp://www.ibm.com/developerworks/web/library/wa-aj-open/?S_TACT=105AGX08&S_CMP=HPhttp://www-10.lotus.com/ldd/ddwiki.nsf/dx/Master_Table_of_Contents_for_XPages_Extensibility_APIs_Developer_Guidehttp://www-10.lotus.com/ldd/ddwiki.nsf/dx/Master_Table_of_Contents_for_XPages_Extensibility_APIs_Developer_Guidehttp://www-10.lotus.com/ldd/ddwiki.nsf/dx/Master_Table_of_Contents_for_XPages_Extensibility_APIs_Developer_Guidehttp://www-01.ibm.com/support/docview.wss?uid=swg27014929http://publib.boulder.ibm.com/infocenter/domhelp/v8r0/index.jsp?topic=%2Fcom.ibm.designer.domino.api.doc%2Fr_wpdr_intro_c.htmlhttp://publib.boulder.ibm.com/infocenter/domhelp/v8r0/index.jsp?topic=%2Fcom.ibm.designer.domino.api.doc%2Fr_wpdr_intro_c.html

  • • ZK Live demos:http://www.zkoss.org/demo/

    • ZK Developer's Reference: http://books.zkoss.org/wiki/ZK_Developer%27s_Reference

    • ZK Studio documentation:http://docs.zkoss.org/wiki/ZK_Studio_Docs

    12 About the authors

    Dennis Chen is the Manager of Tools & Integration at Potix Corporation, which produces the ZK framework. He has been a Java developer for more than 11 years, with experience in Java/J2EE solutions, BPM/SOA systems, and Ajax/Web2.0 applications.

    Nancy Lin is currently the Marketing Specialist at Potix Corporation and is a recent graduate from the University of Queensland.

    Sachin Mahajan is currently working in the Enterprise Marketing Management group of IBM Software Group. He graduated with a Masters degree from University of Utah, USA.

    Trademarks• developerWorks, Domino, IBM, and Lotus are trademarks or registered trademarks of IBM

    Corporation in the United States, other countries, or both.

    • Java and all Java-based trademarks are trademarks of Sun Microsystems, Inc. in the United States, other countries, or both.

    • Microsoft and Windows are trademarks of Microsoft Corporation in the United States, other countries, or both.

    • Other company, product, or service names may be trademarks or service marks of others.

    22

    http://docs.zkoss.org/wiki/ZK_Studio_Docshttp://books.zkoss.org/wiki/ZK_Developer's_Referencehttp://www.zkoss.org/demo/

    1 Introduction2 Integrating ZK with other frameworks3 Bridge component – ZulBridgeBase4 Renderer – ZulRendererBase5 ZK asynchronous update (AU) in XPages 6 Configuration of XPages extension7 ZK Spreadsheet for XPages8 Configurations9 Usage10 Conclusion11 Resources12 About the authors