6 สิ่งที่ควรเข้าใจเบื้องต้น

สวัสดีครับ บทนี้อันที่จริงหัวข้อที่ตั้งไว้ในตอนแรกคือ "Hello GWT " , "Hello world in GWT" แต่ก็ต้องล้มเลิกไป เพราะว่าเราต้องมาเข้าใจอะไรต่ออะไรซักหน่อยในโปรเจกของเรา เพื่อโพสถัดไป เราจะมาเริ่มเขียนโปรเจกแบบไม่ต้องพึงปลั๊กอินให้เขียนโค๊ดเริ่มต้นมาให้เรา เพราะถ้าไม่เข้าใจเรื่องพื้นฐานซะแล้ว ก็จะแก้ไขปัญหาที่กำลังจะเกิดขึ้นไม่ได้ และก็ไม่รู้ว่าปัญหาเกิดจากอะไร ว่าแล้วก็มาเริ่มเข้าใจไปทีละอย่างกันเลยครับ

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

ว่าแล้วก็ไม่รอช้า สร้างโปรเจกใหม่ให้โปรเจกชื่อว่า StickNote  แพกเกจเนมเป็น com.javachef.sticknote เอา User Google App Engine ออก กด Finish.

com.javachef.sticknote นี่เป็นการตั้งชื่อแพกเกจ อย่างที่เรารู้แล้วว่าการเขียนจาวาเราต้องเก็บคลาสต่างๆไว้เป็นระบบแบบชั้นๆ (hierarchy) ในที่นี้เราได้ตั้งชื่่อตามหลักที่นิยมโดยทั่วไปคือการตั้งชื่อย้อนกับชื่อเว็บไซต์เช่น javachef.com ก็ทำการกลับมันซะ ส่วน sticknote ก็อาจจะเป็นชื่อโปรเจก หรือโมดูล แผนกงาน อะไรพวกนี้ ท่านสามารถเข้าไปศึกษารายละเอียดเพิ่มเติ่มสำหรับการตั้งชื่อได้ที่นี่




จากรูปข้างบน src คือโฟอเดอร์ที่เราจะทำการเขียนโค๊ดทั้งหมดใส่เข้าไป test คือ โฟเดอร์ที่เราสามารถเขียน Junit เข้าไปในส่วนนี้ GWT SDK [GWT -2.6.0] คือ Library ของ GWT เอง ซึ่งจะมีหลายๆอย่างให้เราใช้เช่น ปุ่ม เลเบล เรดิโอ รวมไปถึงการรับส่ง request ฯลฯ JRE ก็คือ Library ของจาวาเอง ส่วน war โฟเดอร์คุณก็น่าจะทราบแล้ว่าคืออะไร หากได้ลองทำตามในเรื่องการติดตั้ง Tomcat และ deploy ลง Tomcat ในที่นี่สั้นๆอีกทีก็คือ เป็นโฟเดอร์ที่เราจะเอาไปขึ้นเซิฟเวอร์ครับ

ให้คุณเปิดเข้าไปใน โฟเดอร์ src ก็จะเห็นมี 4 แพกเกจด้วยกัน(ถ้านับแพกเกจลูกแยกกัน)




ถ้าคุณเห็นแบบนี้ แสดงว่า Eclipse ของคุณเปิดการแสดงแพกเกจแบบ Flat คุณสามารถ คุณสามารถเปิดแบบ Hierarchical ได้โดยคลิกสามเหลี่ยมคว่ำเล็กในระดับเดียวกับปุ่มลบที่คุณเห็นในภาพข้างบน เลือก Package presentation > Hierarchical ดังภาพ





พอเซ็ตเป็นแบบ Hierarchical แล้วก็ทำให้ดูง่ายขึ้นใช่ไหมครับ เป็นชั้น เป็นสัดเป็นส่วน หรือถ้าคุณชอบแบบแรกก็ใช้แบบแรกได้ไม่ว่ากัน

Module

ก่อนอื่นเลยไปดูที่ไฟล์ชื่อ HelloWorld.gwt.xml ตัวนี้เรียกว่า โมดูล. แต่ละ GWT โปรเจกจำเป็นที่จะต้องมี โมดูลอยู่ 1 โมดูล ตัวนี้จะเป็นตัวบอกให้ GWT คอมไพเลอร์รู้ว่าต้องทำอะไรบ้าง อย่างแรกเลยคือ

  <inherits name='com.google.gwt.user.User'/>
 โปรเจกทุกตัวของ GWT จะต้อง inherit ตัว User นี้เข้ามา เพราะเป็นตัวที่บอกกฏพื้นฐานสำหรับ GWT คอมไพเลอร์เอง. อย่างที่สอง คือ
<inherits name='com.google.gwt.user.theme.clean.Clean'/>
ตัวนี้ก็จะบอกคอมไพเลอร์ให้ใช้ธีมของ Clean คุณสามารถลองดูธีมอื่นๆได้ โดยทำการคอมเมนต์ตัวนี้แล้วไปลองใช้ตัวถัดไป

ส่วนตัวนี้ครับ
<entry-point class='com.javachef.sticknote.client.StickNote'/>
จะเป็นตัวบอกว่าคลาสไหนจะเป็นคลาสเริ่มต้น ในที่นี่ก็คือ คลาส StickNote ในแพกเกจ  client หากคุณเข้าไปดูก็จะเป็นโค๊ดได้ทำการ implements EntryPoint เอาไว้ครับ .
อีกอย่างหนึ่งคือ
<source path='client'/>
<source path='shared'/>
จะเป็นตัวบอกให้ว่า path ไหนบ้างที่จะทำการคอมไพล์เป็นจาวาสคริป  ในที่นี่ client กับ shared จะถูกคอมไพล์ไปเป็นจาวาสคริปเท่านั้น ส่วน server ก็จะไม่ถูกแตะต้องจาก GWT Compiler เอง. ลองคิดดูนะครับ เช่น โค๊ดสำหรับการเข้าถึงดาต้าเบสจากทางฝั่ง server. แต่หากเราบอกให้คอมไพล์ไปเป็น Javascript แล้วจะต้องเป็น Javascript แบบไหน ? ใช่ไหม? มันไม่ได้ . อีกตัวอย่างหนึ่งเช่น การเรียกไฟล์ เขียนไฟล์ เซฟไฟล์ เรารู้ว่า JS ไม่สามารถเข้าถึงไฟล์ของ client ได้ก็เพราะความปลอดภัย ถึงเราจะสามารถเขียนจาวาให้ไปหาไฟล์ในเครื่องได้ แต่ระหว่างการคอมไฟล์เป็น JS , JS ก็ไม่ยอมอยู่ดี

ประมาณนี้นะครับ ท่านก็ได้เห็นภาพคร่าวๆแล้วว่า Module คืออะไร ทำงานอย่างไร ถ้าไม่ค่อยแน่ใจว่ามันคืออะไร ทำงานอย่างไร แต่พอรู้ว่า "มันทำอะไร" เราก็รู้ละว่า "มันทำอะไร" โว๊ะ เมาอักษร !!

Entry Point 

ดังที่ข้าพเจ้าได้เรียนท่านๆได้ทราบไปแล้วว่า Entry Point ( StickNote.java ) จะคล้ายๆ main คลาสของ Java ทั่วไป แต่พิเศษตรงที่ Entry Point จะต้องมีฟังก์ชั่น
public void onModuleLoad()
ซึ่งจะขาดมิได้เลย  และการสร้างเพียงแค่ Entry Point  ไม่เพียงพอ คุณต้องบอกใน Module ด้วยว่าจะให้เอ็นทรีไหนเป็นตัวเริ่มต้น หากไม่ได้บอกไว้ เว็บก็รันนะ แต่จะไม่มีอะไรเกิดขึ้นนอกจาก landing page เปล่าๆ

สำหรับ GreetingService , GreetingServiceAsync เพกเกจ server และ shared เราจะค่อยๆไปว่ารายละเอียดกันทีหลัง แต่ในที่นี้ขอกล่าวคร่าวๆคือ GreetingService กับ GreetingServiceAsync เป็นการเรียกเซิร์ฟเวอร์จากบราวเซอร์ในโหมด asynchronous  หมายความว่าเรียกไปแล้วไม่หยุดรอผลลัพท์ แต่จะทำงานในบรรทัดถัดไปเลยทันที ไว้ผลลัพธ์มาถึงเมื่อไหร่ค่อยกลับไปจัดการกับมัน . ส่วน server ก็เป็นแพกเกจที่เราไม่ได้ระบุไว้ใน Module ว่าให้คอมไพล์ไปเป็น JS ดังนั้น โค๊ดต่างๆในส่วนของ Server ก็จะถูกเก็บไว้ที่ตรงนี้ ส่วน shared นี่คือคอมไพล์ไปเป็น Javascript เหมือนกัน แต่โค๊ดในส่วนของ server ก็สามารถเรียกใช้ได้ด้วย

war โฟเดอร์





นี่คือ Web Archive คือทุกสิ่งอย่างที่เราจะทำการส่งขึ้นไปบนเซิฟเวอร์ บางทีก็เยอะเกินไปนะ ท่านคิดว่าเราควรมาเริ่มจากอันไหนดี ??? ๑_๑
เริ่มจาก StickNote.html ก็แล้วกัน ตัวนี้มันจะเป็น html ธรรมดาเฉยๆ ( อย่าถามนะ html พิเศษเป็นแบบไหน ที่นี่ไม่มีเนื้อสดลูกชิ้น ) หากคุณเปิดเข้าไปดู ก็จะเห็นบรรทัดนี้
<script type="text/javascript" language="javascript" src="sticknote/sticknote.nocache.js"></script>
ตัวสคริปนี้แหละครับที่อยู่ใน war > stcknote.nocache.js หากคุณลองเปิดเข้าไปดูในไฟล์ JS นี้ก็อาจต้องร้อง โอ้วซาร่า นี่มันจาวาสคริปหรือภาษายึกยือยึกยือ  ไอ้นี่แหละครับที่ GWT Compiler ทำการคอมไพล์มาหให้เรา แล้วเราก็เอาตัวนี้แหละไปใช้ใน html.

กลับมาต่อกันที่ html อีกที ตรงนี้นะครับ
<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
เป็นเทคนิคหนึ่งที่ GWT จะทำการสร้างระบบ History. หากคุณเป็นแฟน Ajax ก็อาจเข้าใจได้ว่าแต่ละ state นั้นบางทีมันก็น่าปวดหัวเหมือนกันเวลาผู้ใช้งานกดปุ่ม Back / forward ในบราวเซอร์ แล้วไม่เกิดอะไรขึ้น GWT ทำการแก้ไขปัญหานี้เรียบร้อยแล้วครับ แต่เราต้องสร้าง History token ด้วยตัวเราเองนะ จำทำได้ยังไง ก็คิดตามโพสที่เกี่ยวกับ History นะครับ

แค่นี่แหละครับ นอกนั้นจาก <h1> ....... เรื่องไปจนถึง </table> ก็แค่ html ธรมมดา
ส่วน StickNote.css ก็คือ css ครับ. จบนะ อย่าไปยาว

คราวนี้ web.xml ที่อยุ่ในโฟเดอร์ WEB-INF นี่น่าสนใจ เปิดเข้าไปโลด

  <!-- Default page to serve -->
  <welcome-file-list>
    <welcome-file>StickNote.html</welcome-file>
  </welcome-file-list>
 web.xml นี่จะเป็นตัวตั้งค่าในเว็บแอปเรา เพื่อให้เซิฟเวอร์รู้อีกทีหนึ่งว่าอะไรเป็นอะไร อย่างในโค๊ดข้างบนก็จะเป็นการบอกว่า ไฟล์เริ่มต้นก็คือ StickNote.html หากคุณเหลือบตาขึ้นไปมองข้างบนจาก Eclipse ของคุณ ก็จะเห็น servlet  , servlet-mapping พวกนี้จะเป็นตัวบอกว่า URL นี่จะไปคลาสไหน ซึ่งนอกจากจะใช้กับ request แบบทั่วไปแล้ว ยังใช้ได้กับ Remote Procedure Call  (RPC) อีกด้วย . ยังไม่ต้องอะเลิทตอนนี้ครับ ใจเย็นๆเราจะไปว่ากันทีหลังแน่นอน ทั้งเรื่อง mapping ทั้ง RPC และเราได้เตรียมตัวอย่างเกี่ยวกับการอับโหลดไฟล์ ดาวโหลดไฟล์ไว้ด้วย ทีหลัง ใจร่มๆนะครับตอนนี้

ทดสอบความกล้าหาญ
เราจะมาลองเขียนชื่อเราใน GWT ให้รับในเว็บแทน ง่ายๆครับ

  1. คลิก GreetingService.java กด Del
    สิ่งที่เกิดขึ้นอัตโนมัต GreetingServiceAsync.java ถูกลบไปโดยอัตโนมัติ
    แพกเกจ server ว่างเปล่าไปโดยอัตโนมัติ
    web.xml ในส่วนของ Servlet ก็ถูกลบไปโดยอัตโนมัต
    StickNote.java ในแพกเกจ client ผิดตรึม

  2. แก้ StickNote.java ให้เป็น


  3. ในส่วนของ StickNote.html ใน war . ลบ <h1> กับ <table> ออกไปทั้งหมด ( ประมาณบรรทัดที่ 47 - 60 )

  4. เซฟทุกอย่างให้เรียบร้อยแล้วรันดูผลลัพท์ผ่านทางบราวเซอร์ครับ 


สรุป 

ทั้งหมดทั้งมวลที่เว้ามาหลายๆก็ประมาณนี้แหละครับ ไม่เข้าใจตอนนี้ก็ยังไม่เป็นไร แค่ให้รู้ว่าอะไรทำงานอะไรก็พอ จำไม่ได้ค่อยมาเปิดดูบ่อยๆ ที่สำคัญกว่านี้คือการฝึกเขียนโค๊ดไปด้วยกันทีละนิดทีละน้อยครับ ไม่นานก็ได้แน่นอน ( มันสรุปตรงไหนว่ะ 555)