go to http://oracle.in.th
Showing posts with label plaumkamon. Show all posts
Showing posts with label plaumkamon. Show all posts

Friday, July 16, 2010

แจกโปรแกรม Password Generator แบบเบาๆ

เรื่อง Java ใน blog ห่างหายไปนานเลย... เพราะช่วงนี้จะอัพแต่เรื่อง Oracle ซะส่วนใหญ่
วันนี้มีโอกาส ก็เลยเอาเรื่อง Java แบบเบาๆ มาให้อ่านกันนะครับ


คือเรื่องมันมีอยู่ว่า วันนึงผมบังเอิญต้องคิด Password ขึ้นมาใช้งานโดยที่มันต้องมีทั้งตัวเลขและตัวอักษร โดย Password ที่จะคิดขึ้นมานั้น ต้องเอาไปใช้ในเรื่องที่สำคัญซะด้วยสิ...

ซึ่งจะให้ผมคิดเองก็คิดไม่ออกว่าจะคิดออกมาอย่างไรดี ให้มันดู Secure มากที่สุดเอาแบบที่ว่าให้คนอื่นคิดไม่ถึงหรือไม่สามารถเดาได้เลย พร้อมกันนั้น ต้องให้ Password นั้นดูแล้วเราก็สามารถจำได้ง่ายๆ จะได้ไม่ลืมด้วย ไม่ใช่ว่าคิด Password ซะเลิศหรู ดูดี แต่พอมาใช้งานจริง เรากลับจำไม่ได้เองซะงั้น...

ไปๆ มาๆ ผมก็เลยมี idea ขึ้นมา... สร้างตัว Generate password เลยดีกว่า
ซึ่งแน่นอนเลย ผมก็เขียนขึ้นมาใน java นั่นเอง

หลักการที่ผมเขียนเจ้าตัว Password Generator นี้ก็ไม่ซับซ้อนแถมวิธีใช้ก็ง่ายเช่นเดียวกัน ก็แค่ให้มัน generate password ให้ผมขึ้นมาเลย เช่น

890A1UMQ8B
WPD3AMHU
889EO6Q8
3TEG8439S8
3CE609SK
JIKY661A42
T0M770Z2
7119IG2FJ
45977DII9I
P35D7571

แล้วผมก็เอามาดูว่า ตัวไหนที่มันสวยจำง่าย ก็เอามาใช้เป็น Password ซะเลย เช่น
889EO6Q8 หรือ T0M770Z2
ทั้งสวย จำง่าย แถมคนอื่่นยังคิดไม่ถึงด้วย ;P

เท่านี้ ต่อไป ผมก็ไม่ต้องมานั่งเสียเวลาในการคิด Password อีกต่อไปแล้วละครับ
คุณสามารถ Download Password Generator ตัวนี้ไปทดลองเล่นได้เลยจากที่นี่ครับ
Download Source Code

ขอให้สนุกกับ Password Generator นะครับ ^^

Credit by @plaumkamon
ข้อเขียนนี้ช่วยฉัน:  

Thursday, June 17, 2010

การ set ให้ Web server เราสามารถรองรับคนจำนวนมากได้

วันนี้ผมได้รับคำถามจาก Twitter (@oracleinth) อีกแล้วครับ โดยที่คำถามเค้าได้ถามมาว่า...
"ขอถามหน่อยนะครับว่า ถ้าเราลง apache tomcat 6.x เพื่อรัน jsp เป็น Web server เราต้องเซตอะไรบ้างเพื่อให้มันรองรับคนจำนวนมากๆ ? "

ถ้าจะพูดถึงการ set ให้ Web server ของเราสามารถรองรับคนจำนวนมากนั้น สามารถทำได้หลายวิธี ซึ่งถ้าเป็นวิธีพื้นฐานเลย นั่นคือ การ set session timeout วิธีนี้ก็จะช่วยได้ในระดับนึง แต่ set session timeout นั้นมันไม่ได้ช่วยอะไรได้มากเท่าไร จากประสบการณ์ที่เคยเจอมากับตัวนะครับ แต่อีกเรื่องนึงที่พอเราไป set รับรองว่ารับคนได้เยอะขึ้นชัวร์คือไปเพิ่ม memory ให้กับ java นั่นเอง

การไป set parameter ดังนี้
JVM option passed to Resin Meaning
-Xms initial java heap size
-Xmx maximum java heap size
-Xmn the size of the heap for the young generation

แต่การเพิ่มพวกนี้ Ram ต้องเยอะด้วยนะ

การไป set ต้องไป set ที่ Environment variable ของ OS เช่นที่ Windows

set JAVA_OPTS=-Xms512m -Xmx1024m

นอกจากจะ set ที่ Environment variable ของ OS ยังไป set ที่ Tomcat ตรงๆได้ ไป set ที่ file %TOMCAT_HOME%\bin\catalina.bat
ไป search ที่ parameter JAVA_OPTS แล้วไปแก้ไขตรงนั้น

ที่เห็นผลได้ชัดเจน client รองรับได้เยอะขึ้น

...จะบอกว่าการ config อย่างเดียวมันก็ไม่ได้ช่วยได้ที่จะทำให้ Tomcat รองรับได้เยอะขึ้น
อย่างการเพิ่ม memory ให้กับ java, การ set session timeout เป็นการแก้ปัญหาที่ปลายเหตุทั้งสิ้น ถึงการแก้แบบนี้จะรองรับ client ได้เยอะขึ้นแต่เอาเข้าจริงไม่มีทางเกินหลักพัน (ใช้พร้อมกัน) เคยลองใช้ jmeter ลองจำลอง client พันตัวพร้อมกันก็ไม่ไหวแล้ว

พอดีผมได้ฟังประสบการณ์ที่มาจากรุ่นพี่ ซึ่งเค้าเคยทำงานกับ web ที่ uip เป็นหลักหมื่นต่อวัน
ซึ่ง web นี้ใช้ php เป็นภาษา developer ส่วน database ก็เป็นเพียง mysql หรือง่ายๆก็คือ LAMP

ผมเลยถามเค้าว่าทำยังไงถึงได้รองรับ user ได้เยอะขนาดนี้ ?
เค้าก็ตอบว่าทำ web ยังไงก็ได้อย่าให้มีการติดต่อ database เป็นดีที่สุด อย่าไปดึงมาเด็ดขายไม่งั้น web ล่มแน่
พี่เค้าก็บอกว่า เชื่อหรือไม่ว่าหน้าแรกของ web ดังทั้งหลายในไทยเป็น HTML ล้วนๆ โดยจะมีการ generate หน้าแรกตั้งทิ้งไว้เป็น HTML จากนั้นเวลาที่ใครมาเรียกก็จะเรียกจากหน้าที่ generate นั้น (ตรงนี้การแยก HTTP server กับ Servlet Container ออกจากกันจะช่วยให้ทำงานได้ดีมากขึ้น เพราะ PHP ก็ต้องแยกเหมือนกัน)

แล้วผมก็ถามต่อว่าถ้าเป็นหน้าข่าวที่มีคน comment เรื่อยๆหละจะทำยังไง เค้าบอกว่าใช้เทคโนโลยี Caches เข้ามาช่วย จะทำการติดต่อ database ก็ต่อเมื่อ insert, update, และ delete เท่านั้น ถ้าจะ select จะ select แค่ครั้งเดียวเท่านั้น แต่จะ select ใหม่ถ้ามีการ update โดยข้อมูลทั้งหมดจะถูกเก็บลง cache ทั้งหมด ที่ต้องเก็บลง cache ทั้งหมดนั้นจะดีกว่าการ select ใหม่ทุกครั้ง เพราะจะมี overhead สูงมากในการติดต่อ DB

ซึ่งใน java นั้นก็มีอยู่นะ เยอะด้วยยกตัวอย่าง Coherence Caches ของ oracle http://www.oracle.com/technology/pub/articles/vohra-coherence.html ซึ่งเคยได้ยินมา แต่ไม่เคยทดลองเล่นดู...

นอกจาก database cache แล้วใน java ยังมี lib หลายๆส่วนที่สามารถทำ cache ได้ อย่างเช่น connection cache ของการติดต่อ DB (Connection Pooling), การทำ cache ของ object เป็นต้น

และมีอีกประเด็นที่จะเสริมเกี่ยวกับการใช้งาน tomcat เพื่อรับ load จำนวนมาก ควร config tomcat เข้ากับ apache(http server) เพื่อแยกงานการ render web (html) กับงานประมวลผล Java ออกจากกัน
จะทำให้ประสิทธิภาพโดยรวมดีขึ้น

ดูที่ http://tomcat.apache.org/connectors-doc/webserver_howto/apache.html

Credit by @plaumkamon, Kim
ข้อเขียนนี้ช่วยฉัน:  

Friday, May 7, 2010

Android กับ Java


Android เป็น OS บนมือถือที่มีพื้นฐานจาก Linux โดยใช้ภาษา Java เป็น ภาษาที่ไว้ใช้พัฒนา application บน Android แต่จะบอกว่าใช้ Java ตรงๆก็ไม่ถูกนัก เพราะ android มันใช้ Java เพียงแค่ interface (syntax) เท่านั้น เพราะว่า VM (Visual Machine) ที่ใช้นั้นเป็น VM (Dalvik) ที่ถูกสร้างขึ้นมาโดยเฉพาะ โดย Dalvik นั้นก็เป็น VM คล้าย java ทำหน้าที่ compile source code java และรัน java เช่นเดียวกัน แต่ Dalvik ได้พัฒนาต่อยอดมาจาก Project ของ Apache Harmony โดย Apache Harmony นั้นเป็น JVM ของ java ที่เป็น open source แต่ JVM ตัวนี้ความสามารถยังไม่เทียบเท่ากับ JVM official ของ SUN ดังนั้นจึงต้องมาพัฒนาต่อจนกลายเป็น Dalvik นั่นเอง

Dalvik VM
แต่เมืออ่านถึงตรงนี้คงจะมีคำถามว่าทำไมไม่ใช้ JVM ของ SUN เลยหละ มันมีเหตุผลอยู่เพราะว่าการ interpreter ของแต่ละอันนั้นต่างกัน โดยของ JVM นั้นจะเป็น stack machines และของ Dalvik นั้นเป็น register-based ซึ่งการทำงานทั้งสองต่างกัน โดย stack machines นั้นจะอ่าน byte code (class) ของ java แล้วแปล byte code เหล่านั้นเป็น instructions (คำสั่งต่างๆ) แล้วโหลดไปกองไว้ในหน่วยความจำแบบ stack ส่วน register-based นั้นก็มีการทำงานคล้ายๆกันเพียงแต่จะโหลด instructions เข้าไปในหน่วยความจำแบบ register แทน ซึ่งทั้งสองตัวนี้ดูเหมือนคล้ายๆกันเพียงแต่ว่า stack machines นั้นจะสร้าง instructions ออกมามากกว่า register-based ถึงแม้จะเป็น byte code ตัวเดียว ทำให้ไม่เหมาะกับการนำไปใช้ในอุปกรณ์มือถือที่มี CPU และ RAM น้อยกว่า computer มาก

อีกเหตุผลหนึ่งที่ไม่สามารถนำ JVM ไปใช้ได้เพราะ JVM ของ SUN นั้นไม่ใช่ open source ดังนั้นการไปปรับแต่งหรือการแก้ไขนั้นทำไม่ได้จึงต้องหันไปใช้ Dalvik แทน

โดย Android นั้นถูกผลักดันโดยกลุ่มๆหนึ่งที่มีชื่อว่า Open Handset Alliance โดยที่กลุ่มๆนั้นคล้าย JCP (Java Community Process) ของ java มาก เป็นกลุ่มที่คอยสนับสนุน วางแผน ออกแบบ และทิศทางของ Android ซึ่งสามารถเข้าไปดูกลุ่มผู้สนับสนุนได้ตาม link นี้ ถ้าใครลองเข้าไปดูจะพบว่า นอกจากจะมีกลุ่มของผู้ผลิตมือถือแล้วยังมีกลุ่มของผู้ผลิต processor ของมือถือด้วย โดยเริ่มแรกกลุ่มของผู้ผลิต processor เป็นผู้วางสถาปัตยกรรมต่างๆของ Android ให้

แต่ข้อเสียมันก็คือ มันรันบน VM ทำให้มันช้า ลองนึกจินตนาการดูในสมัยที่ใครๆเค้าว่า java ช้ากัน (ช่วงนั้น CPU ใคร 1 Ghz ถือว่าหรูมาก) เพราะเมื่อเรา compile source code เราจะไม่ได้ native เหมือนภาษาอื่น แต่จะได้เป็น bytecode โดย bytecode จะเป็น code ที่เกือบจะเทียบเคียงกับภาษาเครื่องแล้ว (เกือบคล้ายๆ native) เมื่อเวลานำ bytecode ไปรันต้องเสียเวลาตีความอีก แต่ ณ ตอนนี้ปัญหานี้ได้ถูกแก้โดย JVM ที่มีประสิทธิภาพมากขึ้นและ hardware ที่ก้าวกระโดดไปไกล

แต่การแก้ปัญหาของ Android ณ ตอนนี้เหมือนจะไปแก้ที่ปลายเหตุ ไปแก้ที่ hardware แทน โดยสังเกตุ spec ของมือถือ android รุ่นหลังๆ CPU และ RAM จะสูงขึ้นมาก แต่ใช่ว่าจะไม่ได้แก้ปัญหาที่ต้นเหตุ โดยมีบริษัทที่อยู่ในกลุ่มของ Open Handset Alliance ได้มีการสร้าง Dalvik ตัวใหม่ขึ้นชื่อ Dalvik Turbo ซึ่งถ้าหากเอาไปวางแทนที่ Dalvik ตัวเก่าจะทำให้ Android เร็วขึ้น 2-3 เท่า แต่ Dalvik Turbo จะไม่มีให้โหลดมาใช้ตรงๆ แต่จะขายให้กับผู้ผลิตแทน

หรือถ้าใครไม่อยากรอ Dalvik Turbo ก็มีอีกทางเลือกตอนนี้ Android ยังเปิดตัว Development Kits ตัวใหม่คือ NDK ซึ่ง Google ได้เปิดช่องทางอีกช่องหนึ่งให้นักพัฒนาที่ถนัดภาษา C หรือ C++ สามารถเขียน Android ได้โดย NDK จะได้เปรียบกว่า SDK ตรงที่มันไม่ได้ run ผ่าน VM เลยแต่มัน run ผ่านตัว Linux ตรงๆทำให้มันทำงานได้เร็วกว่าการพัฒนาบน SDK

Android กับ Java
Android กับ java นั้นใช้ VM คนละตัวกันทำให้เราจำเป็นที่จะต้องใช้ SDK ที่เป็นของ Android โดยเฉพาะเท่านั้น ทำให้เราไม่สามารถใช้ library (jar) ที่มีอยู่มากมายใน java มาใช้ในการพัฒนา android ไม่ได้ เพราะว่าเราใช้ SDK กันคนละตัวทำให้ bytecode ที่ได้มาจาก SDK ย่อมแตกต่างกัน ดังนั้น library ต่างๆจากภายนอกจึงไม่สามารถนำเข้ามาใช้ใน Android ได้ ยกตัวอย่าง เช่น jFreeChart หากคิดจะเอามาใช้ทำ chart ใน Android หมดสิทธิครับ

ถึงแม้ว่า Dalvik จะมี tool ที่ชื่อว่า dx ทำหน้าที่ในการ compress class java ให้กลายเป็น .dex แต่ว่ามันไม่สามารถทำได้ทุก class ทำให้จึงไม่สามารถนำ class java มาใช้ได้
โดย Android SDK นั้นมี package ให้ใช้ดังนี้ (อ้างอิงจาก Android SDK 1.5)

Top-Level Package
Purpose
android.*
Android application fundamentals
com.google.android.map
Google Map Interface (requires additional terms of service and an apiKey)
dalvik.*
Dalvik Virtual Machine support for debugging and such
java.*
Core classes and familiar generic utilities for networking, security, math, and such
javax.*
Encryption support
junit.*
Unit testing support
org.apache.http.*
HTTP protocol support
org.json
JSON support
org.w3c.dom
W3C Java bindings for the Document Object Model Core (XML and HTML)
org.xml.sax.*
Simple API for XML (SAX) support for XML
org.xmlpull.*
High-performance XML parsing

Reference: Android Wireless Application Development (ขอบคุณ @neogravity ที่ให้ยืมมาอ่าน)
จะสังเกตว่า package java นั้นมีติดมาด้วย ที่มีติดมาด้วยเพราะ Dalvik นั้นพัฒนาต่อยอดมาจาก Apache Harmony ทำให้ package พื้นฐานของ java ติดมา นอกจากนั้น android ยังรองรับกราฟฟิก 2D และ 3D ผ่าน OpenGL library ที่ติดมากับ kernel ของ Linux ส่วน database ที่รองรับคือ SQLLite

Credit by @pluamkamon
ข้อเขียนนี้ช่วยฉัน:  

Tuesday, March 30, 2010

Jar File...รวม library ทั้งหลาย ให้เป็น file เดียว

บทความคราวนี้ ผมได้พบมาจากประสบการณ์ในการทำงานของผมเลย ก็เลยคิดว่า น่าจะเอามาบอกต่อหน่อย เผื่อจะได้เป็นประโยชน์ให้แก่คนที่พบคำถามแบบนี้จากผมนะครับ...

สาเหตุของปัญหานี้ก็คือ พอดีมีลูกค้ามาถามผมว่า "ปกติเวลาเราเขียน application ของ java ส่วนใหญ่มักจะประกอบไปด้วย library (jar) หลายๆตัว เมื่อเราเขียน application เสร็จแล้วถ้าเราจะเอา application ตัวนี้ไปใช้ก็ต้องยกโขยง library ต่าง ๆ ของเราไปด้วย ไม่งั้นจะทำงานไม่ได้"
จึงเกิดคำถามที่ว่า...จะทำอย่างไรที่จะรวม library ต่าง ๆ เหล่านี้เป็น jar ตัวเดียว??


ซึ่งจริง ๆ แล้ว การที่เราต้องยกโขยง library ต่าง ๆ ของ application ไปทั้งหมด มันเป็นสิ่งที่ไม่สะดวกเลยจริง ๆ ดังนั้น จึงมีวิธีการที่เรียกว่า Jar File หรือ Java ARchive ซึ่งเป็นการรวมหลาย ๆ ไฟล์เป็นเป็นไฟล์เพียงตัวเดียว ซึ่ง Developer มักจะใช้การสร้าง .jar ไฟล์นี้ในการทำ Java applications หรือ libraries ซึ่งจะมีทั้งข้อมูล classes, metadata และข้อมูลที่เป็น text, images, และอื่น ๆ อีกมากมาย

ซึ่งตัว JAR file นี้ จะถูกสร้างออกมาในรูปแบบของ ZIP file เมื่อต้องการจะแตก (extract) JAR file ได้โดยพิมพ์คำสั่ง jar command ที่มากับ JDK นั่นเอง

เรามาดูวิธีการทำ Jar File กันเลยดีกว่า
Step 1:
ให้สร้าง xml file โดยตั้งชื่อเป็น "build.xml" แล้วใส่คำสั่งตามข้างล่างนี้

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project default="create_jar" name="Create Jar for Project TodoListTool">
  <!--this file was created by Eclipse Runnable JAR Export Wizard-->
  <!--ANT 1.7 is required                                        -->
  <target name="create_jar">
<jar destfile="C:/Documents and Settings/com11/Desktop/de.allianz.vpl.VPLTransformer.jar"
         filesetmanifest="mergewithoutmain">
<manifest>
        <!--<attribute name="Main-Class" value="systemtool.guiApplication.GuiApplication" />-->
        <attribute name="Class-Path" value="." />
      </manifest>
     
      <fileset dir="D:/java/jFrame_WorkSpace/de.allianz.vpl.VPLTransformer/bin" />

      <zipfileset excludes="META-INF/*.SF"                                                                    
                 
src="D:/java/jFrame_WorkSpace/de.allianz.vpl.VPLTransformer/lib/jdom.jar" />
      <zipfileset excludes="META-INF/*.SF"
                 
src="D:/java/jFrame_WorkSpace/de.allianz.vpl.VPLTransformer/lib/de.allianz.jFrame.jni.jar" />
      <zipfileset excludes="META-INF/*.SF"
                 
src="D:/java/jFrame_WorkSpace/de.allianz.vpl.VPLTransformer/lib/utility.jar" />
      <zipfileset excludes="META-INF/*.SF"
           
src="D:/java/jFrame_WorkSpace/de.allianz.vpl.VPLTransformer/lib/org.eclipse.swt_3.5.0.v3550b.jar" />
      <zipfileset excludes="META-INF/*.SF"           
     
src="D:/java/jFrame_WorkSpace/de.allianz.vpl.VPLTransformer/lib/org.eclipse.swt.win32.win32.x86_3.5.0.v3550b.jar" />
    </jar>
  </target>
</project>

ผมขออธิบายคำสั่งที่สำคัญ 4 ส่วน ก่อนนะครับ

<jar destfile="C:/Documents and Settings/com11/Desktop/de.allianz.vpl.VPLTransformer.jar"
         filesetmanifest="mergewithoutmain">
destfile: it is destination result of jar file.

<fileset dir="D:/java/jFrame_WorkSpace/de.allianz.vpl.VPLTransformer/bin" />
dir: it is result path of build java class (*.class). In Eclipse \bin.


<zipfileset excludes="META-INF/*.SF"                                                                    
            
src="D:/java/jFrame_WorkSpace/de.allianz.vpl.VPLTransformer/lib/jdom.jar" />
src: it is path of reference jar file.

และ


<!--<attribute name="Main-Class" value="systemtool.guiApplication.GuiApplication" />-->
จริง ๆ แล้วคำสั่งนี้ใช้สำหรับสร้าง execute jar file ถ้าต้องการสร้าง ให้เอาคำสั่ง Comment ออก แล้วใช้คำสั่งนี้แทน (ซึ่งตามตัวอย่าง ไม่ต้องการสร้าง เลยทำเป็น Comment ไว้)
value: This value is main class.

Step 2:
ให้ Copy "build.xml" ที่เรา้เพิ่งสร้างเมื่อกี้ นำไปไว้ที่ root directory ของโปรเจค (ตามรูป)


Step 3:

คลิกขวาที่ "build.xml" เลือก Run As > Ant Build


เท่านี้ก็เรียบร้อยครับ ^^

Credit by @plaumkamon
ข้อเขียนนี้ช่วยฉัน:  

Friday, October 2, 2009

Annotation Part#2

Class Annotation

เราจะมาดูตัวอย่างการใช้กันใน class A
// A.java Class Annotation

import mytag.Author;
import mytag.Version;

@Author( name = "John Rambo" )
@Version( major = 1, minor = 1 )

public class A { }

ซึ่งการประกาศ annotation นั้นจะไปประกาศหน้า class เพื่อบอกว่าใครคือผู้สร้าง class นี้และเป็น version อะไร สังเกตว่า annotation จะประกาศกี่อันก็ได้ จากนั้นเราจะมาดูวิธีเรียกใช้ annotation กันว่า ว่ามีวิธีเรียกยังไงใน class ATest

โดยก่อนที่เราจะเรียกใช้เราลอง compile file A.java ดูก่อน โดยเปิด cmd ขึ้นมาแล้วไปยัง directory anno ดังตัวอย่างรูปด้านล่าง

directory anno

ให้ compile class ใน package mytag ทั้งหมดก่อนโดยใช้คำสั่งดังนี้
javac mytag\*.java

จากนั้นลอง compile A.java โดยคำสั่ง
javac A.java

จากนั้นเราลองดูขนาด file A.class กันว่ามีขนาดเท่าไรโดยใช้คำสั่ง
dir A.class

จะพบว่ามันมีขนาดมาถึง 311 byte ถือว่าเยอะมากสำหรับ class ธรรมดาโดยปกติจะประมาณ 100 กว่า byte ทดสอบได้โดย comment annotation ใน A.java ออกแล้วลอง compile ใหม่ดูจะพบว่าเนื้อที่ของ A.class จะเหลือเพียง 176 byte เท่านั้น ที่เป็นเช่นนี้เพราะมันจะเก็บ element ของ annotation เหล่านี้ไว้ใน A.class

ต่อมาลองเรียกใช้ annotation กันซึ่ง class แรกที่เราจะลองนั้นคือ ATest.java
// ATest.java
import mytag.Author;
import mytag.Version;

class ATest {
public static void main(String args[]) {
Author a = A.class.getAnnotation(Author.class);
System.out.println("Author: " + a.name());
Version v = A.class.getAnnotation(Version.class);
System.out.println("Version: " + v.major() + "." + v.minor());
}
}

การจะเอา annotation ที่ติดอยู่ใน class ออกมา เราจะเรียกใช้ property class ซึ่งติดอยู่ใน class ทุก class ที่เราสร้างขึ้นมา โดย property class จะไปอ้างถึง file A.class ที่เราได้มาจากการ compile A.java จากนั้นเราใช้ method getAnnotation(Author.class) โดยตอน get นั้นต้องใส่ property class ของ annotation ที่เราต้องการจะอ่านด้วยจากนั้นเมื่อได้ annotation แล้วเราจึง get ค่าต่างๆออกมากตามที่เรากำหนดไว้ใน element ( การที่เราสามารถดึงค่า annotation ที่อยู่ใน class ออกมาได้นั้นเป็นเพราะ เราใช้ Refection API เข้ามาช่วย ในตัวอย่างนี้เป็นเพียงแค่ เศษเสี้ยวของความสามารถของ Reflection API เท่านั้น สามารถศึกษาต่อได้ ที่นี่ )
System.out.println("Author: " + a.name());
System.out.println("Version: " + v.major() + "." + v.minor());


Class Member Annotation

จากที่เราลองประกาศ annotation บน class แล้ว เราลองประกาศ annotation บน attribute และ method ดูบ้าง ลองไปดูใน code BTest.java ดู ในนั้นจะมี class B อยู่ โดย class B ใน BTest.java จะมีการประกาศ annotation บน attribute และ method ดัง code ด้านล่าง เพื่อเป็นตัวบอกว่า attribute หรือ method เหล่านี้ใครเป็นผู้สร้าง
// part of BTest.java
class B {
@Author( name = "John Rambo" )
public int x;
@Author( name = "Jack Ripper" )
public static void f() { }
}

จากนั้นเราลองดึงเอา annotation ออกมาใช้ โดยวิธีการดึงและการเรียกออกมา จะมีวิธีการเรียกที่แตกต่างกับวิธีของ Class Annotation ดัง code ด้านล่าง
// part of BTest.java
public static void main(String args[])
throws NoSuchMethodException, NoSuchFieldException {
Field f = B.class.getField("x");
Author fanno = f.getAnnotation(Author.class);
System.out.println(fanno.name());

Method m = B.class.getMethod("f");
Author manno = m.getAnnotation(Author.class);
System.out.println(manno.name());
}

ถ้าลองสังเกตจากตัวอย่างที่แล้ว การดึง annotation ในประเภท Class Annotation เราสามารถดึงออกมาเป็น Object ของ annotation นั้นได้โดยตรงๆ แต่การดึง annotation ในประเภท Class Member Annotation นั้นไม่ใช่ การจะดึงออกมาต้องดึงออกมาเป็น object ของ java.lang.reflect.Field ถ้าหากเราจะดึง annotation ของ attribute แต่ถ้าเป็นการดึง annotation ของ method เราต้องดึงออกมาเป็น object ของ java.lang.reflect.Method
Field f = B.class.getField("x");
Method m = B.class.getMethod("f");

โดยการเรียก object ของ java.lang.reflect.Field และ java.lang.reflect.Method นั้น เราจะเรียกผ่าน method getField() และ getMethod() ตามลำดับโดยต้องระบุชื่อของ attribute หรือ method ที่ต้องการเรียก annotation ของ attribute หรือ method นั้นๆ จากนั้นเราจึงเอา object ของ java.lang.reflect.Field และ java.lang.reflect.Method นั้นมาดึงเอา annotation ออกมาอีกที
Author fanno = f.getAnnotation(Author.class);
Author manno = m.getAnnotation(Author.class);

ซึ่งจากทั้งสองตัวอย่างคงจะเข้าใจ annotation มากขึ้น ซึ่งเราจะมาเล่นของลูกเล่นใน annotation กันต่อ

คราวหน้า เราจะมาต่อกันด้วย Default Value นะครับ

Reference from : dr. Werasak Suengtaworn

Compose by : @plaumkamon
ข้อเขียนนี้ช่วยฉัน:  

Friday, September 25, 2009

Annotation Part#1

จาก EJB 2.1 ถ้าหากใครลองเขียนหรือใช้งานดูจะพบว่ามันยุ่งยากมาก ขนาดแค่ Bean เดียวกว่าจะ implement ออกมาก็เหนื่อยแล้ว เพราะมีการ config มากทำให้การใช้งาน EJB 2.1 ค่อนข้างจุกจิก วุ่นวายและยุ่งยาก ที่เป็นเช่นนี้เพราะ การออกแบบ ejb2 ของ sun นั้นได้แบ่ง programmer ออกตาม ตามหน้าที่โดยจะแบ่งหน้าที่เป็น 3 ฝ่ายโดยคร่าวๆดังนี้
  • Programmer: programmer เป็นผู้เขียน beans ทั้งหลายโดยที่แต่ละ beans นั้นจะทำหน้าที่เพียงแค่อย่างใดอย่างหนึ่งเท่านั้น
  • Assembler: assembler นั้นจะเป็นผู้ที่รู้เกี่ยวกับ business logic ดีมากๆ เป็นผู้นำ beans ต่างๆเหล่านี้มาร้อยเรียงกันใหม่จนหลายเป็น services
  • Deployer: เป็นผู้ที่นำ beans ต่างๆเอาเข้าระบบ รวมทั้งเป็นผู้ที่คอย config xml ต่างๆทั้งหมด
จะเห็นว่าถ้าหากในองค์กรเรามี role ต่างๆเหล่านี้ ภาระการ config จะตกอยู่กับ deployer ส่วน programmer นั้นไม่จำเป็นต้อง config เองและไม่ต้องรู้ business เพราะ assembler จะเป็นผู้นำไปร้อยเรียงเอง ซึ่งถ้าถามว่าในองค์กรขนาดเล็กจะมีคนที่ทำหน้าที่อย่างที่ sun กำหนดไหม คำตอบคือไม่ ยกตัวอย่างเช่น software house ในไทย programmer คนเดียวทำงานตั้งแต่ programmer ยัน SA หรือจนไปถึง PM, Consultant ออกไปหาลูกค้าด้วยยังมีเลย ดังนั้นการที่เราจะใช้ ejb2.1 นั้นต้องยุ่งยากมาก ทำให้การแบ่งหน้าที่ตามที่ sun เป็นผู้ออกแบบไว้เป็นไปไม่ได้

และเนื่องจากว่า beans ที่ programmer เขียนขึ้นมานั้นจะไม่สามารถนำมาทดสอบได้เพราะว่ายังไม่มีการ config ไม่มีการนำไป deploy ดังนั้นถ้าหาก deployer ไม่ deploy ให้ก็จะไม่มีทาง check ได้ว่า beans ที่ programmer เขียนนั้นถูกไหมดังนั้นมันเป็นเรื่องที่ยุ่งยากมากเพราะต้องคอยประสานกับอีกฝ่ายทำให้ระยะเวลาการทำงานมากขึ้น แต่การที่ programmer จะมา config เองนั้น เป็นเรื่องที่ปวดตับ (เน้นว่าปวดตับไม่ใช่ปวดหัว) มากกับ programmer ดังนั้นจึงมีคนเสนอมาว่าการ config ต่างๆนั้น แทบจะไม่ได้มีการเปลี่ยนแปลงอะไรเลย

ทำไมเราต้องมาแยกกันด้วยทำไมเราไม่เอา config เหล่านั้นลงใน code เลย ซึ่งแนวคิดนี้ได้ถูกนำไปพัฒนาจนกลายเป็น meta data ที่ใส่ลงไปใน program แต่จะไม่ถูกทำงานตอนเวลา compile time แต่จะถูกอ่านค่าต่างๆเหล่านี้เวลา runtime เพื่ออ่านค่า config เหล่านี้ออกมา ซึ่ง metadata ตัวนี้เราเรียกว่า XDocLet โดยเราเขียนค่า config เหล่านี้ลงใน code จากนั้น XDoclet จะสร้าง (generate) xml config ต่างๆให้หรือว่าแม้กระทั้ง java source code โดยพื้นฐานนี้มาจาก JavaDoc ซึ่งเราสั่งเกตไหมว่าเราสามารถ generate JavaDoc มาจาก source code ได้เลย เพียงแต่เราต้องใส่ comment เข้าไปเพื่อไว้เป็นรายละเอียดของ JavaDoc เท่านั้น เช่น

/**
* Returns an Image object that can then be painted on the screen.
* The url argument must specify an absolute {@link URL}. The name
* argument is a specifier that is relative to the url argument.
* <>
* This method always returns immediately, whether or not the
* image exists. When this applet attempts to draw the image on
* the screen, the data will be loaded. The graphics primitives
* that draw the image will incrementally paint on the screen.
*
* @param url an absolute URL giving the base location of the image
* @param name the location of the image, relative to the url argument
* @return the image at the specified URL
* @see Image
*/
public Image getImage(URL url, String name) {
try {
return getImage(new URL(url, name));
} catch (MalformedURLException e) {
return null;
}
}

ใช้ @ ไปเพื่อให้ JavaDoc Tool อ่านไปเพื่อนำเอาไปใช้ทำ API Doc แต่สังเกตว่าต้องมีการใส่ comment ด้วยเพราะว่าเครื่องหมาย @ นั้นยังไม่รองรับใน J2SE 1.4 ซึ่งอาจจะยังงงๆอยู่ลองดูดังรูปด้านล่าง
 

Annotation - JavaDoc to API Doc
ต่อมา sun ได้นำแนวคิดนี้ไปผนวกกับ java ใน version 5.0 ซึ่งทำให้ EJB 3.0 พลอยได้รับอานิสงส์นี้ไปด้วย จากที่ต้อง config xml ที่แสนปวดตับกลายมาเป็นประกาศการ config เหล่านั้นลงใน java code แทน ซึ่ง java จะเรียก meta data นี้ว่า annotation
Annotation นั้นคือ meta data ที่แทรกลงไปใน code แต่จะไม่ถูก compile เหมือนปกติแต่จะเป็นตัวบ่งบอก ตัว java runtime (JRE) ว่า ขณะ ณ ตอนนั้นให้ทำอะไรซึ่งจะแบ่ง annotation เป็น 3 ประเภทคือ

  • Information for the compiler : เป็น annotation ที่บอก compile เพื่อไว้ใช้สำหรับ detect error หรือ suppress warnings ยกตัวอย่างเช่น


    • @Override เพื่อบ่งบอกว่า method นี้ถูก override มาจาก class แม่
    • @Deprecated เพื่อบ่งบอกว่า method หรือ class
    นี้นั้นควรที่จะหลีกเลี่ยงหรือว่าไม่ควรจะใช้เพราะว่าเป็นอันตรายหรือว่ามี method ที่ดีกว่านี้ให้เลือกใช้

  • Compiler-time and deployment-time processing : เป็น annotation ที่ให้ Software tools อ่าน annotation เหล่านั้นเพื่อนำไปสร้าง file ต่างๆ เช่น xml, javadoc และอื่นๆ
  • Runtime processing : เป็น annotation ที่บ่งบอกให้ JRE นั้นทำงานตอน runtime
ซึ่งเราก็จะมาดูวิธีการสร้างและวิธีการเรียกใช้กันโดยที่เราจะเน้นที่ annotation แบบ Runtime processing เพียงเท่านั้นเพราะว่าใน EJB3.0 นั้นไม่มีการ config xml และ annotation ใน EJB3.0 จะทำงานต่างกันกับ XDoclet เพราะว่าไม่ใช่ annotation แบบ Compiler-time and deployment-time processing แต่เป็นแบบ Runtime processing เรามาลองดูกันเลยดีกว่า แต่ไม่ได้หมายความว่าเราจะไม่สามารถสร้าง annotation แบบ Information for the compiler ได้ เราทำได้โดยไปกำหนด policy ตอนที่เราสร้าง annotation ซึ่งลองไปดู code กันเลยดีกว่า ซึ่งเราจะสร้าง annotation ไว้ทดลองสองตัวคือ

// mytag.Author.java
package mytag;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface Author {
String name();
}

การสร้าง annotation ใช้ @interface ในการประกาศซึ่งในที่นี้เราตั้งชื่อว่า Author จากนั้นเรากำหนด annotation ของเราให้เป็นแบบ Runtime processing โดยกำหนด policy ดังนี้

@Retention(RetentionPolicy.RUNTIME)

ซึ่งการกำหนด policy นั้นมีด้วยกัน 3 อย่างคือ
  • RetentionPolicy.CLASS: Information for the compiler
  • RetentionPolicy.RUNTIME: Runtime processing
  • RetentionPolicy.SOURCE: Compiler-time and deployment-time processing
จากนั้นก็จะมีการ set element ที่ชื่อว่า name ด้วยซึ่งตรงนี้จะมีกี่อันก็ได้และต้องตั้งตาม syntax นี้

<type> <nameofelement>( );

สังเกตุว่าเหมือนการประกาศ abstract method ธรรมดาเพียงแต่ไม่มีการรับ parameter ใดๆทั้งสิ้นใน method นั้น ใน annotation จะมีแต่การประกาศ element เท่านั้นไม่มีการประกาศ attribute หรือ method ใดๆทั้งสิ้น จากนั้นเราก็มาดู annotation อีกตัวคือ

// mytag.Version.java
package mytag;  
import java.lang.annotation.Retention;  
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface Version {
  int major();
  int minor();
}

annotation Version จะมี element ด้วยกันสองตัว annotation Author เราเอามาใช้ในการเก็บชื่อว่าใครเป็นคนเขียน class, method หรือ attribute นี้ขึ้นมา ส่วน annotation Version จะบ่งบอกว่า class, method หรือ attribute นั้นผ่านการปรับปรุงมาถึง version ไหนแล้ว การใช้ annotation มีลักษณะเป็นแบบ location sensitive คือ เมื่อเราเอา annotation ไปแปะไว้ตรงหน้าอะไร ก็จะเป็นการประกาศ annotation ของ สิ่ง นั้น เช่น เอาไว้หน้า class มันก็จะเป็น annotation ของ class นั้นๆ เป็นต้น ซึ่งการประกาศ annotation นั้นสามารถประกาศได้ 2 ชนิดคือ
  • Class Annotation
  • Class Member Annotation
ตอนหน้าเราจะมาดูกันว่า Class Annotation  และ Class Member Annotation เป็นอย่างไร

Reference from : dr. Werasak Suengtaworn

Compose by : @plaumkamon
ข้อเขียนนี้ช่วยฉัน: