วันจันทร์ที่ 15 กันยายน พ.ศ. 2551

Basic ZK Framework ตอนที่ 5 วิธี Add EventListener บน Java

การ Add EventListener ก็เหมือนกับว่าเราร้อยสายจาก Java ไปที่หน้าจอน่ะครับ เช่น เราบอกว่า onClick จะให้ไปทำอะไรเราสามารถมาเขียนที่ Java ได้เลย ว่าถ้ามี onclick แล้วจะให้ไปทำอะไรต่อ โดยที่เราไม่ได้ไปทำที่ ZUL File น่ะครับ (ถ้าไม่ เข้าใจโทษทีครับ ลองทำดูจะเข้าใจมากขึ้น) 

ที่ผมจะสอนคือวิธีแบบธรรมดาที่เราใช้กับพวก onClick, onChange, etc... วิธีีดังนี้
1. เราจะทำการใช้ method ที่ชื่อ  addEventListener ซึ่งจะมีอยู่แล้วในพวก class ใน package org.zkoss.zul เช่น Label, Image
2. ซึ่งใน Method นี้จะมีการใส่ 2 ค่า โดยค่าแรกจะเป็น Event ที่เราต้องการจะดักจับ เช่น onClick เป็นต้น --> ใส่คำนี้ลงไปเลยครับ เพราะรับค่า็เป็น String อยู่แล้ว
3. ต่อไปค่าอีกค่าจะใส่ Class EventListener เราจำต้อง สร้าง Class นี้ขึ้นมาเพื่อรับ ซึ่งจะมี Method บังคับคือ onEvent ซึ่งส่วนนี้นี่ล่ะ เราจะเอาไว้สำหรับว่าจะทำอะไรที่เราต้องการ

ตัวอย่่างที่ทำไว้นะครับ

อันแรกตัว EventListener

private EventListener selectItemListener = new EventListener() {

public void onEvent(Event evt) {

Image img = (Image)evt.getTarget(); เราจะทำการดึงค่าออกมาจากที่เรา addEventListener ไว้ครับ

UserM userM = (UserM)img.getAttribute("sampleUserM"); ดึงค่า attribute ที่เรา set ลงเราสร้าง Image ขึ้นมา

Executions.getCurrent().sendRedirect("zk/sample/userEdit.zul");

}

public boolean isAsap() {
return true;
}
};


ส่วนวิธีเรียกใช้งาน อันนี้ผมทำแบบ Add ใส่ตารางไว้แล้วถ้าเรามา Click จะไปทำงานที่ Event นะครับ

Listcell listCell = new Listcell();
listCell.setStyle("cursor: default");
listCell.appendChild(image);
Image image = new Image("images/edit.gif");
image.setAttribute("sampleUserM", userM); ทำการ set Attribute ชื่อ SampleUserM ขึ้นมา เราสามารถไปเรียกค่าขึ้นมาได้ที่ onEvent ใน EventListener เลยครับ
image.setWidth("23px");
image.setHeight("21px");
image.setStyle("cursor: pointer;");

image.addEventListener("onClick",selectItemListener); ทำการ Add EventListener ในกรณีที่เรา Click ที่รูปนี้


Reference
http://www.zkoss.org/smalltalks/mvc3/ จาก @chanwit  อันนี้จะมีวิธีอื่นด้วยน่ะครับ

วันอังคารที่ 9 กันยายน พ.ศ. 2551

Basick ZK Framework ตอนที่ 4 Config ZK ให้เรียก EJB [On Java File]

เหมือนกับตอนก่อนหน้านี้น่ะครับ แต่อันนี้จะเรียกผ่าน Java เลย ซึ่งที่ผมลอง มีได้ตามนี้ครับ
  1. ถ้าเรียกแบบ Remote EJB สามารถเรียกได้อยู๋แล้วนะครับ คือเรียกอบบบอก IP ไปเลยว่าจะไปที่ไหน สามารถเรียกได้ไม่มีปัญหาครับ
  2. เรียก Local EJB ผมใช้วิธีนี้นะ่ัครับ มีสองวิธี แต่การทำงานคล้ายๆ กัน (โดย Load ใน Servlet ก่อน หรือ บน ZUL File ครับ)
    1. ไป Lookup EJB เสร็จแล้วเก็บค่าไว้ที่ static class สักตัวนึง เช่น Map
    2. ไป Lookup EJB เหมือกนั แต่เก็บไว้ที่ ServletContext เลยครับ
ตัวอย่างการเขียนแบบง่ายๆ ครับ ผมเขียนตอนเรียกไว้ที่ init ใน Servlet แล้วสั่งให้มัน Load on start up

แบบแรกเก็บค่าไว้ที่ static class

public class SampleContext {
private static Map contextJNDI;

เรียกตอน init ใน servlet แล้วสั่งให้ทำตอน load on startup
public void initContext(String jndiName) throws NamingException, CreateException {
Context context = new InitialContext();

ZKServiceEJBLocalHome home = (ZKServiceEJBLocalHome) context.lookup(jndiName);

ZKServiceEJBLocal localObject = home.create();

if(contextJNDI == null) {
contextJNDI = new HashMap();
}

if(contextJNDI.get(jndiName) == null) {
contextJNDI.put(jndiName,localObject);
}
}

อันนี้จะไปเรียกตอนทำงานใน Java ครับ
public ZKServiceEJBLocal getEJB(String jndiName) {

return (ZKServiceEJBLocal)contextJNDI.get(jndiName);

}
}


แบบที่สอง เก็บไว้ที่ ServletContext

เขียนไว้ที่ init ใน Servlet แ ล้ว Config ให้ Load on startup
servletConfig.getServletContext().setAttribute(jndiName, EJBLocalObject); --> jndiName ให้ตอนเวลาจะดึงข้อมูลมาใช้ให้ดึงด้วย jndiName ส่วน EJBLocalObject คือตัว EJBLocal ที่เรา Lookup ใน Context เรียบร้อยแล้ว ล้วเอามาเก็บไว้ที่นี่แทนครับ

ตอนเรียกใช้
ServletContext servletContext = (ServletContext)this.getDesktop().getWebApp().getNativeContext();
servletContext.getAttribute(jndiName);

วันจันทร์ที่ 8 กันยายน พ.ศ. 2551

Basick ZK Framework ตอนที่ 3 Config ZK ให้เรียก EJB [On ZUL File]

สามารถใช้เรียกได้หมดเลยนะครับ ที่เรียกโดยใช้ JNDI แต่เรียกบน ZUL File นะครับ 
โดยเราเพิ่มว่าโหลด JNDIResolver เข้าไปน่ะครับ

<?variable-resolver class="org.zkoss.zkplus.jndi.JndiVariableResolver"
arg0="ZKSampleEAR" --> ใช้สำหรับบอกว่า Application Name ของ Ear File
arg1="sampleEJB=java:comp/env/ejb/sample/zkservice"  --> บอกว่าใช้ EJB Name ชื่ออะไรน่ะครับ แล้วเวลาตอนเรียกใช้จะใช้ sampleEJB ครับ
?>


โดยวิธีการเรียกใช้งานจะเป็นดังนี้


<zscript>
import sample.zk.SampleServiceLocal; <--- Import Class ที่เราใช้เข้ามา
SampleServiceLocal sampleBean = (SampleServiceLocal)sampleEJB; <-- Cast Class ให้เป็นตัวที่เราต้องใช้งานครับ
SampleServiceLocal.doService(); <--- เรียกการทำงาน
</zscript>

*สำหรับคนที่ใช้ Rad deploy บน Websphere ครับ
อันที่จริง Application Server ก็ต้องทำเหมือนกันครับ แต่ผมจะบอกวิธีสำรับคนที่ใช้บน Rad ครับ โดยไป double click ที่ web.xml แล้วไปที่ Tab Reference แล้ว Add EJB Reference เข้าไป โดยชื่อที่เราใช้เรียกจะเป็น อันบนด้านขวา แต่อันล่างด้านขวาจะไป mapping กับ ที่ไปเรียกที่ EJB Project น่ะครับ


Reference

วันพฤหัสบดีที่ 4 กันยายน พ.ศ. 2551

Basick ZK Framework ตอนที่ 2 มาลองใช้ Zk

มาต่อตอนที่ 2 กันครับ ตอนที่ 1 ดู ที่นี่
ตอนนี้มาลองเล่นกันเลยว่ามันทำงานอย่างไรบ้าง


ตัวอย่าง index.zul

<?xml version="1.0" encoding="UTF-8"?>
<?page title="Welcome to ZK Web"?> <-- กำหนดว่า title ของหน้าใช้ชื่ออะไร
<window title="Welcome to ZK Web" 
border="normal" id="login" use="com.zk.LoginView" onOK="login.onOk()">
use ใช้สำหรับว่าจะไปใช้ Java Class ไหน ส่วน id จะเป็น Reference ไว้สำหรับใน window ตัวนี้ โดยเวลาใช้จะใช้ id.method ที่จะใช้น่ะครับ
<textbox id="username"/> <--  กำหนดว่าเป็น input แบบข้อความ โดยกำหนดชื่อเป็น username
และ onOK หมายถึงถ้าเรากด Enter ที่หน้านี้จะเข้าไปทำงานที่ login.onOk()
<button label="OK" onClick="login.onOk()"/> <-- เป็นการบอกว่าถ้ากดปุ่มนี้จะไปที่ Method ชื่อ onOk() ใน Class com.zk.LoginView
<button label="Cancel" onClick="login.onCancel()"/> <-- จะเหมือนกับ ข้างบนครับ
</window>


ต่อไปตัวอย่างของ Java Class นะครับ

package com.zk.service;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

import org.apache.log4j.Logger;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zul.Messagebox;
import org.zkoss.zul.Textbox;
import org.zkoss.zul.Window;


public class LoginView extends Window { <-- ทำเพื่อให้เพื่อเราสามารถดึงค่าได้

private static final long serialVersionUID = -8725354218872079732L;
private static Logger log = Logger.getLogger(LoginView.class);

public void onCreate(Window main) { //does initialization
log.debug("..... init(Window main)");
}

public void onOk() {  <-- พอเรากด Ok ที่หน้าจอจะมาเข้า Method นี้
log.debug("..... save(Window main)");
String userName = ((Textbox)getFellow("username")).setValue(""); <-- ดึงค่าจาก textbox เมื่อกี้ที่ใช้ id เป็น username
Messagebox.show("Username correct.", "Ok", Messagebox.OK, Messagebox.OK); <-- โชว์ Popup บอกว่า Username correct. 

}

public void onCancel() { //cancel any changes
log.debug("..... cancel(Window main)");

((Textbox)getFellow("username")).setValue(""); <-- เป็นการกำหนดค่าให้ username เป็นค่าว่าง

}
}

วันอังคารที่ 2 กันยายน พ.ศ. 2551

Basick ZK Framework ตอนที่ 1 Config ZK

สามารถ Download ได้ ที่นี่
เป็น Ajax Framework ที่ไม่ต้องมานั่งเขียน Java script น่ะครับ หาข้อมูลเพิ่มเติมได่ที่หน้าเวบ

* สามารถใช้บน Websphere 6.x ได้ครับ ลองมาแล้ว Config เหมือนกันเลย

ตอนนี้จะบอกว่าเราต้อง Config อะไรเพิ่มใน web.xml บ้างนะ่ครับ ที่จริงก็อ่านได้ตามเวบเหมือนกัน ผมรวบรวมไว้จะได้ค้นง่ายๆ

เพิ่มส่วนของ Listener ด้วย

<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

<servlet>
<description>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> สำหรับตรงนี้ ถ้า Config บน Websphere อาจจะต้องลองเปลี่ยนเลขดูน่ะครับ ถ้ามันยังไม่ได้
</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-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>auEngine</servlet-name>
<url-pattern>/zkau/*</url-pattern>
</servlet-mapping>


เป็นอันเสร็จครับ ก็จะทำให้ใช้ Zk Framework ได้ล่ะ


ลองเทสโดยการเขียน index.zul แบบนี้ดูครับ ว่ามันขึ้นหน้าจอหรือเปล่า

<window title="My First window" border="normal" width="200px">
Hello, World!
</window>

วันอังคารที่ 29 กรกฎาคม พ.ศ. 2551

Config Servlet Cache Instances [On Websphere 6.0-6.1]

จะสอนวิธี Config Servlet Cache ของ Websphere ซึ่งมีวิธี 3 แบบครับ

ฮธิบายก่อน Servlet Cache คือ การเก็บค่าไว้โดยที่ไม่ต้องทำการประมวณผลใหม่ในกรณีที่เราเข้ามาด้วย parameter เดิมนะครับ (ที่จริงมีกำหนดหลายแบบ ผมขอบอกเฉพาะที่เป็น Parameter นะครับ) เช่น สมมตผมกำหนด ว่าให้ Servlet SampleCache ไว้เป็น Servlet Cache แล้วกำหนด Parameter ให้ productId เป็นไว้ เมื่อเราเข้าหน้าเวบด้วย productId=1 ครั้งแรกจะยังเข้า Servlet อยู่ แล้วครั้งต่อๆ ไปพอเราลอง Refresh หน้าดูแล้วจะไม่มีการเข้าไปใน Process ของ Servlet อีกครับ จะใช้ค่าเดิมที่เราเข้าไปครั้งแรกเลย (สามารถกำหนด Timeout ได้ครับ)

เราต้อง Config ให้ Websphere ใช้งาน Servlet Cache ก่อนโดย

  1. ไปที่ Servers --> Application Servers
  2. แล้วเลือก Server ที่เราต้องการจะ Config Servlet Cache
  3. ดูที่ทางขวา จะมี Container Settings ให้เลือกที่ Web Container Settings --> Web Container
  4. พอกดเข้าไปจะเห็น Enable Servlet Caching แล้วติ๊ก
  5. พอทำเสร็จก็ Restart Server ครับ เป็นอัน Config Servlet Cache ให้ใช้งานได้ล่ะ

ต่อไปเรามา Config Servlet Cache ที่เครื่องเราต่อ (ผมใช้ Config จาก cachespec.xml) ตอนแรกเราจะต้องไปเอา cachespec.xml, cachespec.dtd มาก่อน โดยจะอยู่ที่ xxx\base_v6\properties ครับ แล้ว Copy มาไว้ที่ Project ของเรา ที่ Path --> WEB-INF


แบบที่ 1 จะเป็นการ Config ให้ดูที่ Path

<cache-entry>
<class>servlet</class> --> กำนหดให้เป็นชนิด Servlet
<name>/ProductDisplay</name> --> Servlet Path ชื่อนี้
<cache-id>
<component id="productId" type="parameter"> --> กำหนดให้ Parameter ที่ส่งมาถ้ามีตัวนี้ ซ้ำ จะไม่ทำงานซ้ำ
<required>true</required> --> จำเป็นจะต้องมี Parameter ตัวนี้ส่งมาหรือเปล่า
</component>
<timeout>180</timeout> --> กำหนด Timeout ของ Servlet Cache
</cache-id>
</cache-entry>

แบบที่ 2 กำหนดที่ตัว Class เลย

<cache-entry>
<class>servlet</class>
<name>com.webpage.servlet.ProductDisplay2.class</name> --> บอกว่าเป็น Servlet Class ไหน
<cache-id>
<component id="productId" type="parameter">
<required>true</required>
</component>
<timeout>300</timeout>
</cache-id>
</cache-entry>


แบบที่ 3 จะคล้ายๆ กับแบบแรก แต่จะใช้ Servlet Cache ของ Application Server เลย

<cache-instance name="cache/servlet/sample"> --> กำหนด JNDI Name ของ Servlet Cache
<cache-entry>
<class>servlet</class>
<name>/ProductDisplay3</name>
<cache-id>
<component id="productId" type="parameter">
<required>true</required>
</component>
<timeout>180</timeout>
</cache-id>
</cache-entry>
</cache-instance>


วิธี Config Servlet Cache ของ Application Server

  1. ให้ไปที่ Resources --> Cache instances --> Servlet cache instances
  2. คลิกเข้ามาเสร็จ ก็เลือก New
  3. แล้วกำหนดชื่อ JNDI Name ให้เป็นชื่อเดียวกับ ที่เรากำหนดใน cachespec.xml
  4. Save แล้วก็ Restart Server เป็นอันเสร็จ


Reference
http://www.webagesolutions.com/knowledgebase/waskb/waskb008/index.html

วันศุกร์ที่ 4 กรกฎาคม พ.ศ. 2551

Data store tables
























Table namePurpose
SIBOWNEREnsure exclusive access to the data store by an active messaging engine
SIBCLASSMAPCatalogs the different object types in the data store
SIBLISTINGCatalogs the SIBnnn tables
SIBXACTSMaintain the status of active two-phase commit transactions
SIBKEYSAssign unique identifiers to objects in the messaging engine
SIBnnn, where nnn is a numberContain persisted objects such as messages and subscription information

These
tables hold both persistent and nonpersistent objects, using separate tables
for the different types of data, according to the following convention:


  • SIB000 contains information about the structure of the data in the other
    two tables

  • SIB001 contains persistent objects

  • SIB002 contains nonpersistent objects that have been saved to the data store to reduce the messaging engine memory
    requirement





Reference

Data store tables