Saturday, December 8, 2012

Init/Cleanup Session/Desktop in ZK


Introduction

This post talking about how to prepare some data for each session or each desktop and clear them while session/desktop invalidated.

The Program

index.zul

Link to this page to see init of desktop of this page and init while session created.

Click button to see init of another.zul and cleanup of this page, or wait 10 seconds to see cleanup of session and desktop(s).

<zk>
    <!-- Tested with ZK 6.0.2 -->
    <div>test desktop cleanup and session cleanup</div>
    <div>click 'to another.zul' button than you will see the cleanup message for desktop in console</div>
    <div>or wait 10 secondes than you will see cleanup message for session and all desktops in console</div>
    
    <button label="to another.zul">
        <attribute name="onClick"><![CDATA[
            Executions.getCurrent().sendRedirect("/another.zul");
        ]]></attribute>
    </button>
</zk>


another.zul

Click button to see init of index.zul and cleanup of this page, or wait 10 seconds to see cleanup of session and desktop(s).

<zk>
    <!-- Tested with ZK 6.0.2 -->
    <div>test desktop cleanup and session cleanup</div>
    <div>click 'to index.zul' button than you will see the cleanup message for desktop in console</div>
    <div>or wait 10 secondes than you will see cleanup message for session desktop(s) in console</div>
    
    <button label="to index.zul">
        <attribute name="onClick"><![CDATA[
            Executions.getCurrent().sendRedirect("/index.zul");
        ]]></attribute>
    </button>
</zk>


web.xml

We specify a TestSessionCleaner here to do some init while session created and do cleanup while session destroyed

<?xml version="1.0" encoding="UTF-8"?>

<!-- web.xml
    Purpose:
        
    Description:
        
    History:
        Wed Dec 29 12:13:00     2004, Created by tomyeh

Copyright (C) 2004 Potix Corporation. All Rights Reserved.
-->

<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> 

    <description><![CDATA[My ZK Application]]></description>
    <display-name>MyApp</display-name>

    <!-- //// -->
    <!-- ZK -->
    <!-- listener for session cleanup, use it to do init and
        cleanup of session

        used to be org.zkoss.zk.ui.http.HttpSessionListener,
        we use another class (TestSessionCleaner) which extends from
        org.zkoss.zk.ui.http.HttpSessionListener
        and so some customize here
     -->
    <listener>
        <description>
            ZK listener for session cleanup
        </description>
        <listener-class>test.TestSessionCleaner</listener-class>
    </listener>
    <servlet>
        <description>ZK loader for ZUML pages</description>
        <servlet-name>zkLoader</servlet-name>
        <servlet-class>org.zkoss.zk.ui.http.DHtmlLayoutServlet</servlet-class>

        <!-- Must. Specifies URI of the update engine (DHtmlUpdateServlet).
        It must be the same as <url-pattern> for the update engine.
        -->
        <init-param>
            <param-name>update-uri</param-name>
            <param-value>/zkau</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup><!-- Must -->
    </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>
        <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>auEngine</servlet-name>
        <url-pattern>/zkau/*</url-pattern>
    </servlet-mapping>

    <welcome-file-list>
        <welcome-file>index.zul</welcome-file>
        <welcome-file>index.zhtml</welcome-file>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
    </welcome-file-list>
</web-app>


zk.xml

We specify a TestDesktopInit to do init for desktops and a TestDesktopCleanup to do cleanup for desktops here.

<zk>
    <!-- Tested with ZK 6.0.2 -->
    <!-- specifies the time, in seconds, between client requests before
        a session is invalidated. A negative time indicates the session
        should never timeout. The default zero means to use the system
        default (which is usually specified in web.xml).
     -->
    <session-config>
        <session-timeout>10</session-timeout>
    </session-config>
    <!-- specifies the time, in seconds, between client requests before
        a desktop is invalidated. A negative time indicates the
        desktop should never timeout.
     -->
    <desktop-config>
        <desktop-timeout>5</desktop-timeout>
    </desktop-config>
    <!-- Classes that implement DesktopCleanup and DesktopInit,

        From official site:
        Notice that ZK will instantiate an object from the class you
        registered for each callback. For example, an object is
        instantiated to invoke DesktopInit.init(Desktop, Object), and
        another object instantiated to invoke DesktopCleanup.cleanup(Desktop),
        even if you register a class that implements both DesktopInit and DesktopCleanup.
     -->
    <listener>
        <listener-class>test.TestDesktopCleanup</listener-class>
    </listener>
    <listener>
        <listener-class>test.TestDesktopInit</listener-class>
    </listener>
</zk>


TestSessionCleaner.java

Extends org.zkoss.zk.ui.http.HttpSessionListener and do some customize in sessionCreated and sessionDestroyed methods.

package test;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;

import org.zkoss.zk.ui.http.HttpSessionListener;

/**
 * Tested with ZK 6.0.2
 * @author benbai
 *
 */
public class TestSessionCleaner extends HttpSessionListener {

    private static Map<String, Object> MapOfVeryBigDataPerSession = new HashMap<String, Object>();
    // called while session created
    public void sessionCreated(HttpSessionEvent evt) {
        super.sessionCreated(evt);
        HttpSession session = evt.getSession();
        System.out.println(" session created " + session.getId());
        MapOfVeryBigDataPerSession.put(session.getId(), session.getId());
        System.out.println(" put data into MapOfVeryBigDataPerSession, size = " + MapOfVeryBigDataPerSession.size());
        System.out.println();
    }
    // called while session destroy
    public void sessionDestroyed(HttpSessionEvent evt) {
        super.sessionDestroyed(evt);
        HttpSession session = evt.getSession();
        System.out.println(" session destroyed " + session.getId());
        MapOfVeryBigDataPerSession.remove(session.getId());
        System.out.println(" remove data from MapOfVeryBigDataPerSession, size = " + MapOfVeryBigDataPerSession.size());
        System.out.println();
    }
}


TestDesktopInit.java

Implements org.zkoss.zk.ui.util.DesktopInit, the init method will be called while desktop initiated, you can also do different actions based on the request path as needed.

package test;

import java.util.HashMap;
import java.util.Map;

import org.zkoss.zk.ui.util.DesktopInit;
import org.zkoss.zk.ui.Desktop;

/**
 * Tested with ZK 6.0.2
 * @author benbai
 *
 */
public class TestDesktopInit implements DesktopInit {
    private static Map<String, Object> MapOfVeryBigDataPerDesktop = new HashMap<String, Object>();
    // the init function that will be called by ZK
    // while desktop initiated
    public void init(Desktop desktop, java.lang.Object request) {
        System.out.println(" desktop init, id = " + desktop.getId() + ", path = " + desktop.getRequestPath());
        MapOfVeryBigDataPerDesktop.put(desktop.getId(), desktop.getId());
        System.out.println(" put data into MapOfVeryBigDataPerDesktop, size = " + MapOfVeryBigDataPerDesktop.size());
        System.out.println();
    }
    public static void removeDataFromMapOfVeryBigDataPerDesktop (String key) {
        MapOfVeryBigDataPerDesktop.remove(key);
    }
    public static int getSizeOfMapOfVeryBigDataPerDesktop () {
        return MapOfVeryBigDataPerDesktop.size();
    }
}


TestDesktopCleanup.java

Implements org.zkoss.zk.ui.util.DesktopCleanup, the cleanup method will be called while desktop destroy, you can also do different actions based on the request path as needed.

package test;

import org.zkoss.zk.ui.util.DesktopCleanup;
import org.zkoss.zk.ui.Desktop;

/**
 * Tested with ZK 6.0.2
 * @author benbai
 *
 */
public class TestDesktopCleanup implements DesktopCleanup {
    // the cleanup function that will be called by ZK
    // while desktop destroy
    public void cleanup (Desktop desktop) {
        System.out.println(" desktop cleanup " + desktop.getId() + ", path = " + desktop.getRequestPath());
        TestDesktopInit.removeDataFromMapOfVeryBigDataPerDesktop(desktop.getId());
        System.out.println(" remove data from MapOfVeryBigDataPerDesktop, size = "
                    + TestDesktopInit.getSizeOfMapOfVeryBigDataPerDesktop());
        System.out.println();
    }
}



The Result

Please run this project and see the message in your console as needed.

Reference

http://books.zkoss.org/wiki/ZK_Configuration_Reference/zk.xml/The_session-config_Element

http://books.zkoss.org/wiki/ZK%20Configuration%20Reference/zk.xml/The%20desktop-config%20Element

http://books.zkoss.org/wiki/ZK_Configuration_Reference/web.xml/ZK_Session_Cleaner

http://www.zkoss.org/forum/listComment/17031-ZK-Session-Desktop-won-t-get-invalidated-after-actual-session-timeout

Download

Full project at github
https://github.com/benbai123/ZK_Practice/tree/master/Flow/CleanupDesktopAndSession

1 comment: