Wednesday, 12 September 2012

ZK Liferay Integration First Step for creating ZK Liferay Portlet


ZK Liferay Integration First Step for creating ZK Liferay Portlet


Hello Friends,

Welcome to CAPITAL CODE.

As per current IT market trends Liferay is world’s leading enterprise-class open source portal. At the same time ZK is a very popular framework for RIA Applications. ZK is a highly productive open source Java framework for building amazing enterprise web and mobile applications. One can develop the AJAX based RIA without knowing AJAX, Javascript and jQuery.




Steps for ZK + Liferay Integrtion to develop the RIA Portlets
I have used Liferay 6.1 CE  and ZK 6.0.1 CE for this demo portlet.

1) You can refer this WIKI Link to setup Liferay IDE with Eclipse.

2) For installing ZK Studio for Eclipse ZK you can refer this link.

3) Create Liferay Portlet

  •   Create new Liferay project




  • Select Liferay MVC portlet option and click on finish.



 

3) ZK related configurations
  • Edit \WEB-INF\web.xml file.
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>ZK-Sample-portlet</display-name>
      <listener>
        <description> Used to cleanup when a session is destroyed</description>
        <display-name>ZK Session cleaner</display-name>
        <listener-class>org.zkoss.zk.ui.http.HttpSessionListener</listener-class>
    </listener>
    <servlet>
        <description>The ZK loader for ZUML pages</description>
        <servlet-name>zkLoader</servlet-name>
        <servlet-class>org.zkoss.zk.ui.http.DHtmlLayoutServlet</servlet-class>
        <init-param>
            <param-name>update-uri</param-name>
            <param-value>/zkau</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet>
        <description>The asynchronous update engine for ZK</description>
        <servlet-name>auEngine</servlet-name>
        <servlet-class>org.zkoss.zk.au.http.DHtmlUpdateServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>zkLoader</servlet-name>
        <url-pattern>*.zul</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>zkLoader</servlet-name>
        <url-pattern>*.zhtml</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>zkLoader</servlet-name>
        <url-pattern>*.svg</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>zkLoader</servlet-name>
        <url-pattern>*.xml2html</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>auEngine</servlet-name>
        <url-pattern>/zkau/*</url-pattern>
    </servlet-mapping>
    <session-config>
      <session-timeout>30</session-timeout>
    </session-config>
  <jsp-config>
      <taglib>
          <taglib-uri>http://java.sun.com/portlet_2_0</taglib-uri>
          <taglib-location>
              /WEB-INF/tld/liferay-portlet.tld
          </taglib-location>
      </taglib>
  </jsp-config>
</web-app>


  • Add below zk.xml file to /WEB-INF dir

<?xml version="1.0" encoding="UTF-8"?>
<zk>
 <library-property>
        <name>org.zkoss.zul.progressbox.position</name>
        <value>center,center</value>
    </library-property>
    <library-property>
        <name>org.zkoss.zk.portlet.PageRenderPatch.class</name>
        <value>org.zkoss.zkplus.liferay.NonRootContextJQueryRenderPatch</value>
    </library-property>
    <library-property>
        <name>org.zkoss.zkplus.liferary.jQueryPatch</name>
        <value>1500</value>
    </library-property>
    <error-page>
     <exception-type>java.lang.Throwable</exception-type>   
     <location>/zul/error.zul</location>   
 </error-page>
    <session-config>
     <device-type>ajax</device-type>
     <timeout-message>Session timeout. Please reload the page.</timeout-message>
 </session-config>
</zk>

  • Update /WEB-INF/liferay-portlet.xml file as per given below

<?xml version="1.0"?>
<!DOCTYPE liferay-portlet-app PUBLIC "-//Liferay//DTD Portlet Application 6.0.0//EN" "http://www.liferay.com/dtd/liferay-portlet-app_6_0_0.dtd">

<liferay-portlet-app>
    <portlet>
        <portlet-name>zk-sample</portlet-name>
        <icon>/icon.png</icon>
        <instanceable>true</instanceable>
        <header-portlet-css>/css/main.css</header-portlet-css>
        <header-portlet-javascript>/zkau/web/js/zk.wpd</header-portlet-javascript>
        <footer-portlet-javascript>/js/main.js</footer-portlet-javascript>
        <css-class-wrapper>zk-sample-portlet</css-class-wrapper>
    </portlet>
    <role-mapper>
        <role-name>administrator</role-name>
        <role-link>Administrator</role-link>
    </role-mapper>
    <role-mapper>
        <role-name>guest</role-name>
        <role-link>Guest</role-link>
    </role-mapper>
    <role-mapper>
        <role-name>power-user</role-name>
        <role-link>Power User</role-link>
    </role-mapper>
    <role-mapper>
        <role-name>user</role-name>
        <role-link>User</role-link>
    </role-mapper>
</liferay-portlet-app>
  • Update /WEB-INF/portlet.xml as per given below

<?xml version="1.0"?>
<portlet-app
    version="2.0"
    xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd">
    <portlet>
        <portlet-name>zk-sample</portlet-name>
        <display-name>Zk Sample</display-name>
        <portlet-class>com.liferay.zk.ZKPortlet</portlet-class>
        <init-param>
            <name>zk_page_view</name>
            <value>/zul/view.zul</value>
        </init-param>
        <init-param>
            <name>zk_page_edit</name>
            <value>/zul/edit.zul</value>
        </init-param>
        <expiration-cache>0</expiration-cache>
        <supports>
            <mime-type>text/html</mime-type>
            <portlet-mode>VIEW</portlet-mode>
            <portlet-mode>EDIT</portlet-mode>
        </supports>
        <supported-locale>en</supported-locale>
        <portlet-info>
            <title>ZK Sample</title>
            <short-title>ZK Sample</short-title>
            <keywords>ZK Sample</keywords>
        </portlet-info>
        <security-role-ref>
            <role-name>administrator</role-name>
        </security-role-ref>
        <security-role-ref>
            <role-name>guest</role-name>
        </security-role-ref>
        <security-role-ref>
            <role-name>power-user</role-name>
        </security-role-ref>
        <security-role-ref>
            <role-name>user</role-name>
        </security-role-ref>
    </portlet>
</portlet-app>

4) Add below ZK libraries in /WEB-INF/lib directory
  • zcommon.jar
  • zel.jar
  • zhtml.jar
  • zk.jar
  • zkbind.jar
  • zkplus.jar
  • zul.jar
  • zweb.jar
  • bsh.jar
  • commons-fileupload.jar
  • commons-io.jar
5) Create com.liferay.zk.ZKPortlet.java file as mentioned below


package com.liferay.zk;

import java.io.IOException;

import javax.portlet.PortletException;
import javax.portlet.PortletPreferences;
import javax.portlet.PortletRequestDispatcher;
import javax.portlet.PortletSession;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;

import org.zkoss.zk.ui.Session;
import org.zkoss.zk.ui.http.DHtmlLayoutPortlet;

import com.liferay.portal.kernel.util.WebKeys;
import com.liferay.portal.theme.ThemeDisplay;

/**
 * The Class ZKPortlet.
 */
public class ZKPortlet extends DHtmlLayoutPortlet{
 
 public static final String ZK_EDIT_PAGE = "zk_page_edit";
 public static final String ZK_VIEW_PAGE = "zk_page_view";
 
 private String strViewModePage;
 private String strEditModePage;
 
 public void init() {
  this.strViewModePage = getInitParameter(ZK_VIEW_PAGE);
  this.strEditModePage = getInitParameter(ZK_EDIT_PAGE);
 }
  
 @Override
    protected boolean process(Session sess, RenderRequest request, RenderResponse response, String path, boolean bRichlet) throws PortletException, IOException {
        setupSessionParameters(sess, request);
        return super.process(sess, request, response, path, bRichlet);
    }

    protected void setupSessionParameters(Session sess, RenderRequest request)
    {

     ThemeDisplay themeDisplay = (ThemeDisplay) request.getAttribute(WebKeys.THEME_DISPLAY);
        PortletSession portletSession = request.getPortletSession();
        PortletPreferences prefs = request.getPreferences();
        
        sess.setAttribute("SESSION_ID", portletSession.getId());
  sess.setAttribute("THEME_DISPLAY", themeDisplay);
  sess.setAttribute("GROUP_ID", themeDisplay.getScopeGroupId());
  sess.setAttribute("PORTLET_PREFERENCES", prefs);
  sess.setAttribute("PORTLET_ID",themeDisplay.getPortletDisplay().getId());
        sess.setAttribute("currentUser",themeDisplay.getUser().getScreenName());
    }
    
    @Override
 protected void doEdit(RenderRequest request, RenderResponse response) throws PortletException {
  try{
   if (this.strEditModePage != null) {
    this.dispatch(this.strEditModePage, request, response);
   } else {
    this.doView(request, response);
   }
   
  } catch (IOException ex){
   //Exception Handling Code
  }
 }
    
    @Override
 protected void doView(RenderRequest request, RenderResponse response) throws PortletException {
  try{
   if (this.strViewModePage != null) {
    this.dispatch(this.strViewModePage, request, response);
   } 
  } catch (IOException ex){
   //Exception Handling Code
  }
 }
 
 protected void include(String path, RenderRequest renderRequest,
            RenderResponse renderResponse) throws IOException, PortletException {
  try{
         PortletRequestDispatcher portletRequestDispatcher = getPortletContext().getRequestDispatcher(path);
         if (portletRequestDispatcher != null) {
          portletRequestDispatcher.include(renderRequest, renderResponse);
         }
  } catch (IOException ex){
   //Exception Handling Code
  }
 
 }
 
 private void dispatch(String page, RenderRequest request, RenderResponse response)
  throws IOException, PortletException {

  PortletRequestDispatcher objDisp = this.getPortletContext().getRequestDispatcher(page);
  if (objDisp != null){
   objDisp.include(request, response);
  }
 }
}

6) Create /docroot/zul folder and place below zul files in it.
  • view.zul
  • edit.zul
  • error.zul
view.zul

<?page id="viewPage" title="ZK Sample View Page" cacheable="false" language="xul/html" zscriptLanguage="Java" contentType="text/html;charset=UTF-8"?>
<zk xmlns="http://www.zkoss.org/2005/zul"
    xmlns:zk="http://www.zkoss.org/2005/zk">
 <window id="winView" width="100%">
    <caption label="CAPITAL CODE"/>
    <grid>
     <auxhead>
         <auxheader label="ZK Liferay Portlet Window" colspan="2"/>
        </auxhead>
     <columns>
         <column label="Component Type" width="150px" />
            <column label="Component"/>
        </columns>
        <rows>
         <row>
             <label value="Textbox Field" width="150px" />
                <textbox width="150px" tabindex="1" constraint="no empty" />
            </row>
            <row>
             <label value="Password Field" width="150px" />
                <textbox type="password" width="150px" tabindex="2" />
            </row>
            <row>
             <label value="Intbox Field" width="150px" />
                <intbox width="150px"  tabindex="3" />
            </row>
            <row>
             <label value="Decimalbox Field" width="150px" />
             <decimalbox format="###.##" width="150px"  tabindex="4" />
            </row>
            <row>
             <label value="Datebox Field" width="150px" />
             <datebox  format="yyyy/MM/dd" width="150px" tabindex="5"/>
            </row>
            <row>
             <label value="Listbox Field" width="150px" />
             <listbox mold="select" tabindex="6">
              <listitem label="Default" value="" />
              <listitem label="CAPITAL CODE Java" value="java" />
              <listitem label="CAPITAL CODE ZK" value="zk" />
              <listitem label="CAPITAL CODE Liferay" value="liferay" />
             </listbox>
            </row>
            <row>
             <label value="Spinner Field" width="150px" />
          <spinner constraint="no negative,no zero" value="10" tabindex="7" />
      </row>
            <row>
             <cell colspan="2" style="text-align:center">
             <button mold="os" label="Submit" width="100px" height="30px" />
             </cell>
            </row>
       </rows>
    </grid>
    </window>
</zk>
edit.zul

<?page id="editPage" title="ZK Sample Edit Page" cacheable="false" language="xul/html" zscriptLanguage="Java" contentType="text/html;charset=UTF-8"?>
<zk xmlns="http://www.zkoss.org/2005/zul"
    xmlns:zk="http://www.zkoss.org/2005/zk">
 <window id="winEdit" width="100%" height="100px">
     <caption label="CAPITAL CODE"/>
     <grid>
      <columns>
          <column label="ZK Liferay Portlet Window (EDIT)"/>
         </columns>
         <rows/>
        </grid>
    </window>
</zk>
error.zul

<?page id="errorPage" title="ZK Sample Error Page" cacheable="false" language="xul/html" zscriptLanguage="Java" contentType="text/html;charset=UTF-8"?>
<zk xmlns="http://www.zkoss.org/2005/zul"
    xmlns:zk="http://www.zkoss.org/2005/zk">
 <window id="winError" width="100%" height="100px">
     <caption label="CAPITAL CODE"/>
     <grid>
      <columns>
          <column label=" ZK Liferay Portlet Window (Error)"/>
         </columns>
         <rows/>
        </grid>
    </window>
</zk>


Finally our Liferay Portlet will look like below,


After completing all above steps,
  • Start the tomcat server in liferay.
  • Deploy the portlet using ant deploy command.
  • Login to the liferay and add the zk sample portlet in any page.
That's it. We are done with the demo of Liferay ZK Portlet. :)


7 comments:

  1. Very nice blog and good help for setting up environment to develop portlet using zk.

    ReplyDelete
  2. what is mean by Deploy the portlet using ant deploy command.

    ReplyDelete
  3. I followed this tutorial and it worked nicely. Thanks and keep up the good work.

    MJ

    ReplyDelete
  4. Awesome, this topic is very useful for me


    mysql services

    ReplyDelete
  5. informative post.it is very useful post i really like this post.
    php

    ReplyDelete
  6. Nice and help full post.....
    i have getting one error when i try to deploy the zk project in liferay 6.2..... error log is given below please suggest me how to resolve this one

    SEVERE: Exception thrown by attributes event listener
    java.lang.NoClassDefFoundError: org/zkoss/util/resource/XMLResourcesLocator
    at org.zkoss.zk.ui.http.HttpSessionListener23.attributeRemoved(HttpSessionListener23.java:96)
    at org.apache.catalina.core.ApplicationContext.removeAttribute(ApplicationContext.java:782)
    at org.apache.catalina.core.ApplicationContextFacade.removeAttribute(ApplicationContextFacade.java:410)
    at com.liferay.portal.kernel.deploy.hot.BaseHotDeployListener.unregisterClpMessageListeners(BaseHotDeployListener.java:155)
    at com.liferay.portal.deploy.hot.PortletHotDeployListener.doInvokeUndeploy(PortletHotDeployListener.java:550)
    at com.liferay.portal.deploy.hot.PortletHotDeployListener.invokeUndeploy(PortletHotDeployListener.java:140)
    at com.liferay.portal.deploy.hot.HotDeployImpl.fireUndeployEvent(HotDeployImpl.java:111)
    at com.liferay.portal.kernel.deploy.hot.HotDeployUtil.fireUndeployEvent(HotDeployUtil.java:31)
    at com.liferay.portal.kernel.servlet.PluginContextListener.fireUndeployEvent(PluginContextListener.java:169)
    at com.liferay.portal.kernel.servlet.SecurePluginContextListener.fireUndeployEvent(SecurePluginContextListener.java:294)
    at com.liferay.portal.kernel.servlet.PluginContextListener.doPortalDestroy(PluginContextListener.java:132)
    at com.liferay.portal.kernel.util.BasePortalLifecycle.portalDestroy(BasePortalLifecycle.java:31)
    at com.liferay.portal.kernel.servlet.PluginContextListener.contextDestroyed(PluginContextListener.java:97)
    at org.apache.catalina.core.StandardContext.listenerStop(StandardContext.java:4980)
    at org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5626)
    at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:232)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:160)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:633)
    at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1113)
    at org.apache.catalina.startup.HostConfig$DeployDirectory.run(HostConfig.java:1671)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
    at java.util.concurrent.FutureTask.run(FutureTask.java:166)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
    at java.lang.Thread.run(Thread.java:722)
    Caused by: java.lang.ClassNotFoundException: org.zkoss.util.resource.XMLResourcesLocator
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1714)
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1559)
    ... 28 more

    11:45:26,783 INFO [localhost-startStop-6][PortletHotDeployListener:558] 1 portlet for ZK-Demo-portlet was unregistered
    Jun 05, 2014 11:45:26 AM org.apache.catalina.core.ApplicationContext log
    INFO: Closing Spring root WebApplicationContext
    11:45:26,788 INFO [localhost-startStop-6][PluginPackageUtil:1016] Reading plugin package for ZK-Demo-portlet

    ReplyDelete