Posts Tagged ‘Integration’

Starbucks ไม่ใช้ 2-phase-commit

August 25th, 2010

แปลมาจาก Starbucks Doesn’t use two phase commit
Hotto Cocoa o Kudasai
ผมเพิ่งกลับมาจากทริปญี่ปุ่นได้สองสัปดาห์ ระหว่างการเดินทางที่ญี่ปุ่นครั้งนี้มีสิ่งหนึ่งที่ผมคุ้นตามากมันคือสัญลักษณ์รูป ทรงกลมเขียวอันเป็นเอกลักษณ์ของ Starbucks นั่นเองโดยเฉพาะแถวๆเขต Shinjuku และ Roppongi และระหว่างที่ผม รอรับเครื่องดื่ม “Hotto Cocoa” ของผมผมก็สังเกตเห็นอะไรบางอย่างในกระบวนการจัดการ Order ของ Starbucks แนวคิดหลักของ Starbucks และธุรกิจอื่นๆคือการรับ Order ให้ได้มากที่สุดเท่าที่จะมากได้เพราะยิ่งรับ Order มากเท่าไหร่มันหมายถึงรายได้ที่เพิ่มขึ้นมาตามจำนวน นั่นเป็นสาเหตุให้ Starbucks เลือกใช้กระบวนการจัดการ Order แบบ Asynchornous ถ้าเราลองนึกภาพตามการสั่งกาแฟที่ Starbucks จะเริ่มจากเราสั่งกาแฟที่ cashier จากนั้น cashier จะจดรายการนั้นลงไปที่แก้วแล้ววางไว้ที่ Queue ระหว่างเครื่องชงซึ่ง Queue นี้เป็นปัจจัยหลักที่ทำให้ Cashier สามารถทำงานเป็นอิสระ (Decouple) จาก Barista ซึ่งจะทำให้ Cashier สามารถรับ Order ต่อไปได้เรื่อยๆโดยไม่ต้องสน ใจว่า Barista จะยุ่งขนาดไหนหรือเราสามารถมีจำนวน Barista ที่เพิ่มขึ้นได้ในกรณีที่ร้านยุ่งมากๆ
Correlation
อย่างไรก็ตามในเมื่อ Starbucks สามารถใช้ประโยชน์ของการจัดการ Order แบบ Asynchronus แล้ว Starbucks เองก็ยังต้องแก้ปัญหาที่มีมากับการทำงานแบบ Async เช่นเรื่องของ Correlation เนื่องจากกาแฟที่เราสั่งไปไม่สามารถทำ ให้เสร็จได้ที่ cashier เลยนั่นหมายความว่ามันต้องถูกส่งต่อไปให้ Barista เป็นคนทำ และในกรณีที่เรามี Barista หลายๆคนแต่ละคนก็อาจจะต้องทำงานกับเครื่องชงกาแฟหลายๆแบบผมที่ตามมาคือระยะเวลาในการทำจะไม่ท่ากันเช่นกาแฟที่ต้อง Blend ต้องใช้เวลานากว่ากาแฟสำเร็จ หรือ Barista อาจจะทำการรวบ Order หลายๆอันมาทำในครั้งเดียว กันเพื่อเพิ่มความเร็วในการทำงาน ผลคือปัญหาเรื่อง Correlation จะเกิดขึ้นเพราะการส่งกาแฟออกมาจะไม่ตรงตาม ลำดับของการสั่ง ซึ่ง Starbucks แก้ปัญหานี้ด้วยการใช้ pattern ที่อยู่ในกลุ่มของ messaging architecture นั่นคือ Correlation Identifier เราจะเห็นได้จากจังหวะการสั่งพนักงานที่ cashier จะจดชื่อของเราลงไปบนแก้วและจะเรียกชื่อเจ้า ของเมื่อ order เสร็จแต่ในบางประเทศอาจใช้ชื่อเครื่องดื่มแทน แต่ยังยังไม่พอยังมีอย่างอื่นอีกนั่นคือ Exception Handling
Exception Handling
การทำ Exception Handling ในมุมของ Async เป็นเรื่องยากระดับคลาสสิค ดังนั้นเพื่อให้เคสนี้ต่อเนื่องกันเราจะมาดูวิธี การจัดการกับ Exception ของ Starbucks กัน เร่ิมจากการยกตัวอย่าง พนักงานจะทำอย่างไรถ้าเราไม่สามารถจ่ายเงินได้ ? การแก้ปัญหาคือเททิ้งถ้ากาแฟแก้วนั้นทำเสร็จแล้ว หรือถ้ายังก็ทำแค่เพียงดึงแก้วออกจาก Queue แต่ถ้ากาแฟถูก ทำผิดไม่ตรงตามคำสั่งพนักงานก็ทำใหม่ แต่ถ้าเครื่องทำกาแฟพังก็ไม่ยาก “คืนเงิน” นี่เป็น Scenario มาตรฐานที่เกิดเสมอในร้านกาแฟแต่ถ้าเราจัดกลุ่มการทำงานเราจะพบว่าเราสามารถจำแนกได้ตามนี้
1.Write-off – นี่เป็นการจัดการกับปัญหาที่ตรงไปตรงมาและง่ายที่สุดคือ “ปล่อยมันไป” แนวทางนี้นิยมมากกับปัญหาที่ไม่ส่งผลกระทบกับรายได้มากนักและไม่คุ้มที่จะสร้างระบบที่ใช้จัดการ Exception ยกตัวอย่างเช่น ISP บางเจ้าจะไม่สนใจ Error ที่เกิดขึ้นในขั้นตอนของการทำ Billing/Provisioning ดังนั้นจึงมีความเป็นไปได้ที่ลูกค้าจะได้ใช้บริการโดยไม่ถูกเรียกเก็บเงิน เนื่องจากรายได้ที่เสียไปไม่กระทบกับภาพ รวมของระบบทั้งหมด อย่างไรก็ตามสุดท้ายจะมีการสร้าง report สำหรับการทำ reconciliation ตามเวลาที่กำหนดเพื่อปิดบริการฟรีเหล่านั้น
2.Retry – order ใหญ่เกิดขึ้นจากการประกอบของ order ย่อยๆ เรามีทางเลือกสองทางคือหนึ่งยกเลิกอันที่ทำไปแล้ว หรือพยายามทำอันที่ล้มเหลวจนสำเร็จ ทางแรกเป็นทางเลือกที่ดีในกรณีที่ความเป็นไปได้ในการทำใหม่ให้สำเร็จ สูงมาก ซึ่งเราสามารถนำเอาแนวคิดเรื่อง Idempotent Receiver เข้ามาใช้ได้คือไม่ว่าเราจะพยายามทำ order เก่าซ้ำกันกี่ครั้งก็ตาม เราจะไม่เจอปัญหาเรื่อง duplicate message เลย
3.Compensating Action – ทางเลือกสุดทายคือ undo งานที่ทำเสร็จแล้วเพื่อทำให้ ระบบย้อนกลับไปสู่สถานะเดิม ทางเลือกนี้เหมาะสมกับระบบที่รองรับการทำานในเรื่องของการทำ re-credit ได้

เราจะเห็นว่าการรับมือกับ Exception แบบนี้ต่างกับ two-phase commit เนื่องจาก asynchronous จะทำการแยก prepare และ excecute ออกจากกันถ้าดังนั้นถ้าเรามองกลับไปที่ Starbucks เราจะพบว่าเราจต้องรอที่ cashier พร้อมกับ reciept และเงินจนกว่ากาแฟจะชงเสร็จ ซึ่งจะเห็นได้ว่าในกรณีนี้ทั้ง cashier และลูกค้าจะไม่มีใครสามารถละจากตำแหน่ง ของตัวเองได้เลยจนกว่า Transaction นั้นจะสำเร็จ ซึ่งถ้า Starbucks เลือกใช้เทคนิคแบบ Two-Phase-Commit กับธุรกิจ ตัวเองมันอาจจะส่งผลให้เกิดการขาดทุนหรือล้มเหลวได้สูงมากเนื่องจากระบบจะไม่สามารถรองรับจำนวนลูกค้าได้เป็นปริมาณมากๆ นี่จึงเป็นอีกหนึ่งตัวอย่างที่เราจะเห็นได้ว่า Two-Phase-Commit ทำใหชีวิตเราง่ายขึ้นแต่มันก็ทำให้เราไม่ สามารถเป็นอิสระจากกระบวนการส่ง message ได้เนื่องจากเราต้องจัดการ state ของระบบไปตลอดเวลา
Conversations
ตัวอย่างของการมีปฎิสัมพันธ์กันในร้านกาแฟเป็นตัวอย่างที่เหมาะกับ Conversation Pattern มากๆซึ่งเราจะเห็นได้ว่าจริงๆแล้วการสื่อสารระหว่างคนสองกลุ่มนี้ประกอบไปด้วย Short Synchronous เช่นการทำ order และการจ่ายเงินและอีกส่วนคือ Long Asynchronous เช่น การทำกาแฟและการรับกาแฟ ซึ่งเราสามารถนำกระบวนการที่เกิดขึ้นนี้ไปประยุกติ์ใช้กับการทำธุรกรรมแบบอื่นๆอีกก็ได้เช่นกันเช่น การสร้าง order ใน amazon เราจะเห็น short synchronous เช่นการกำหนด Order Number ส่วนกระบวนการที่เหลือจะกลายเป็น Asynchronous ทั้งหมดไม่ว่าจะเป็น charging, packaging และ shipping หลังจากนั้นเราจะได้รับอีเมล์ยืนยันจาก amazon ทันทีเมื่อการทำ Transaction สำเร็จลง และในกรณีที่เกิดปัญหานั้น Amazon จะแจ้งเตือนเราผ่าน email (Async) หรือแม้กระทั่งกระบวนการ Refund ก็ทำในลักษณะเดียวกันไม่ว่าจะเป็นการจ่ายเงินคืนหรือการพยายามส่งสินค้าชิ้นใหม่แทนชิ้นเก่าที่ส่งไม่สำเร็จ
สรุปว่าในโลกแห่งความเป็นจริงเราจะเห็น Scenario ต่างๆที่เป็น Asynchronous มีมากมาย ในกระบวนทำงานต่างๆของเราไม่ว่าจะเป็นการอ่าน การตอบ email การซื้อกาแฟ ดังนั้น asynchronous messaging architecture จึงเป็นรูปแบบที่สามารถนำไปใช้งานได้อย่างเป็นธรรมชาติมากกว่า เราสามารถนำเอากระบวนการในชีวิตประจำวันของเรามาช่วยเพื่อให้เกิดความสำเร็จในการออกแบบเรื่องของ messaging ได้เป็นอย่างดี “Domo arigato gozaimasu! ”

JavaRebel + Spring in Eclipse WTP plug-in

May 12th, 2009

จากที่พี่ @roofimon พูดถึงเรื่อง JavaRebel มันก็ช่างโดนใจน้อยๆของผมเหลือเกิน เพราะไอ้เรื่องนี้ก็ทิ่มแทงใจผมมาตั้งแต่วันแรกที่ทำเลยลองทำตาม blog ดูก็โอ้ว happy แต่ด้วยความที่ผมใช้ cmd maven แล้วมันไม่ถนัดมือไปหน่อยเลยว่ากันด้วยเรื่อง ide ก็เลยมานั่งนึกดู ถ้ายังนึกถึงรักเก่าที่ยังคบหาอยู่ก็ Netbeans พอมานั่งคุยกับรักปัจจุบันก็ eclipse ก็เลยมานั่งเทียบสิ่งนึงที่ javarebel ทำคือเมื่อมีการเปลี่ยนแปลง class มันจะทำการ reload ให้เรางั้นก็มานั่งลองดูเริ่มกันที่ Netbean ผมใช้ 6.5 นั่นคือผมว่ามันน่ารักสู้ eclipse ไม่ได้ในงานนี้ตรงที่มันไม่มี compile on save แต่เห็นว่า 6.7 มีนะครับแต่ก็ไม่รู้จะหล่อแค่ไหนเลยคิดว่าเรื่องที่เป็นจุดน่าจะเลือกก็คือ compile on save เลยมามองว่า eclipse ทำได้ดีกว่าเลย เอาวะ eclipse ก็ eclipse ก็มานั่งดู web ของ javarebelที่ http://www.zeroturnaround.com/javarebel/ อ้ะๆ เกิดสวรรค์น้อยๆที่เค้ามีการ ทำ eclipse plug-in ออกมาให้ด้วยแถมยังคงต่อกับ wtp plug-in ที่ eclipse เค้าคุยนักคุยหนาว่านี่หล่ะเจ๋งพอๆกะ netbeans ก็เลยเอาหล่ะเอามาลงกันก่อนเลย
ผมใช้ eclipse 3.4 codename***** และ wtp plug-in ซึ่งมันติดมาอยู่แล้วถ้าใครโหลดตัวที่เป็น web dev มาโดยการ ติดตั้ง plug-in ก็ตามฟอร์มครับ update site โลดโดย update site อยู่ที่ http://www.zeroturnaround.com/update-site/
แล้วก็ติดตั้งกันไป

หลังจากเราติดตั้งเรียบร้อยก็ว่ากันต่อที่การใช้งานหล่ะต๊กตาในการใช้งานของผมคือ Appfuse คงไม่ต้องร่ายยาวว่ามันคืออะไรนะครับ อันนี้คาดว่าน่าจะเคยลองเล่นกันแล้วแต่ถ้ายังขอให้บอกวันหลังจะเอามาเขียนเป็นอีกหนึ่ง entry ครับโดยผมก็เอา appfuse-springmvc มา adapt นิดหน่อยโดยไม่ใช้ maven ครับ ด้วยเหตุผลของเด็กน้อยโปรแกรมเมอร์จนๆ อย่างผมไม่มีเน็ตแรงๆ 5mb ไว้ใช้งานที่บ้านเลยต้อง offline กันไป

แต่ผมก็จะทำตามขั้นตอนของ คุณ @roofimon นะครับโดยขั้นตอนพี่เค้าเขียนไว้อย่างเมพแล้วเลยขอทำตามขั้นตอนหน่อยแต่เปลี่ยนวิธีก็เลยเอาของพี่มา adapt apply หน่อยๆ อิอิ

ไป download ไลบรารี่มาก่อนที่ http://www.zeroturnaround.com/javarebel/
จากนั้นเราก็ต้องบอกให้ Servlet Container ที่เราใช้ว่าเราช่วยโหลดได้นี่เข้าไปหน่อยนะจังหวะที่มัน Start-up ซึ่งในที่นี้ผมประมาณว่าทุกคนใช้ Tomcat นะครับดังนั้นสิ่งที่เราต้องทำคือไปที่ catalina.bat แล้วเพิ่มคำสั่งนี้เข้าไป(เอาไว้ประมาณ บรรทัดที่ 231)

 set JAVA_OPTS=-noverify -javaagent:{PATH_TO_JAVAREBEL}javarebel.jar %JAVA_OPTS% 

เมื่อเราใช้ ide + plug-in เราก็ใช้วิธีการ

ไปที่ Window » Preferences » JavaRebel แล้วก็จะเจอความงามซ่นอยู่ครับโดยเราก็เลือก JavaRebel jar location ครับเพื่อให้ ตัว wtp ของเรารู้จัก JavaRebel แล้วก็ไป

run >> run config… ก็จะเจอหน้าตาสวยงามดังนี้ครับ

ตามที่วงเลยครับเท่านี้ก็ลองมา test start server กันดูก็จะเห็นแบบนี้ใน console

ถ้าที่ comsole มีข้อความนี้แสดงขึ้นมาแสดงว่าเรามาถูกทาง

#############################################################

ZeroTurnaround JavaRebel 2.0 (200903241906)

(c) Copyright Webmedia, Ltd, 2007-2009. All rights reserved.

เปิดการใช้งานให้กับตัว servlet container ของเราผมใช้ tomcat 6 นะครับโดยไปเปิด server editor ขึ้นมาแล้วเตะสองทีเร็วๆจากนั้นจะพบกับหน้าจอ tomcat config แบบนี้ครับ

พอดีไปโขมยเค้ามาเด่วผมมาแก้รูปให้นะครับพอดีมัน upload ขึ้น server ไม่ได้

น่านยังมีกันเราลืมโดยบอกว่าให้เช็คให้ดีนะให้เราไปปิด auto publish ซะตอนแรกผมก็ไปปิดครับเชื่อคนง่ายพอมาเขียนโอ้ว happy อย่างยิ่งแต่เราลืมมองไปว่าแก้ class มันไม่มีปัญหาครับแต่ถ้าเราแก้ jsp มันไม่ publis ไปให้เราอ่ะงงเลยเลยทำตามนี้ไปก่อนแล้วกันครับเด่วจะ เล่าให้ฟังหลังๆ

mvn archetype:create -DgroupId=com.mycompany.app -DartifactId=my-webapp -DarchetypeArtifactId=maven-archetype-webapp

เราก็จะได้เวบโปรเจคโง่ๆมาหนึ่งอันหนึ่งชื่อ my-webapp จากนั้นเราต้องเพิ่มความสามารถของ JavaRebel เข้าไปให้ maven ด้วยโดยให้เราเปิด pom.xml ขึ้นมาแล้วเพิ่ม plugin เข้าไปดังนี้

ที่บรรทัดประมาณที่ 11

<pluginRepositories>
<pluginRepository>
<id>zt-repo</id>
<name>Zero turnaround repo</name>
<url>http://repos.zeroturnaround.com/maven2</url>
</pluginRepository>
</pluginRepositories>

อีกส่วนที่ประมาณบรรทัดที่ 139 ในส่วนของ plugins

<plugin>
<groupId>org.zeroturnaround</groupId>
<artifactId>javarebel-maven-plugin</artifactId>
<executions>
<execution>
<id>generate-rebel-xml</id>
<phase>process-resources</phase>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>

เมื่อเรียบร้อยแล้วให้สั่ง mvn javarebel:generate คำสั่งนี้จะไปสร้างไฟล์ชื่อ rebel.xml ที่ WEB-INF/classes ครับโดยไฟล์นี้จะทำหน้าที่กำหนด target ที่เก็บ class ไฟล์และ resources ต่างที่เราต้องการให้ทำ auto-reload เมื่อเกิดการเปลี่ยนแปลง

ขั้นตอนนี้ผมข้ามเรียบครับเพราะผมสร้างproject มาเอง dynamic web project manage มือใช้ ant ครับส่วน maven ที่อาไว้ gen file rebel.xml ก็ไม่ต้องครับเด่วเราใช้เวทมนต์ตามประสา วิสาดดดด

โดยไปคลิกขวาที่โปรเจ็คแล้วจะเห็นเมนูให้เรา generate rebe.xml ครับ แล้วให้ไปเลือกที่ที่เราไว้นั่นคือ output folder นั่นเอง
เท่ากับว่าตอนนี้เราก็มาถึง

<?xml version="1.0" encoding="UTF-8"?>
<application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.zeroturnaround.com" xsi:schemaLocation="http://www.zeroturnaround.com/alderaan/rebel-2_0.xsd">
<classpath>
<dir name="D:/workspace-seanet/TMS/build/classes">
</dir>
</classpath>
</application>

ละ พอ เหนื่อยครับทดลอง run โลดครับเมื่อรันจะเห็นว่าจะมี log ท่อนนึงบอกเราว่า

=============================== [JavaRebel Spring Framework Plugin DISABLED] ===============================
Plugins are contributed by third party and can cause compatibility problems.
If you have any troubles set -Drebel.spring_plugin=false to disable it.
------------------------------------------------------------------------------------------
Description: Supports adding new beans and adding new bean dependencies using
annotations or XML. Singletons will be reconfigured after the change. It also
supports adding or changing Spring MVC controllers or handlers.
=============================== [/JavaRebel Spring Framework Plugin DISABLED] ] ==============================

โห งอแง เลยครับไม่ตรงตัณหาของผมอย่างยิ่งเพราะผมจะเอามาใช้กับ spring แล้วขึ้นมายังงี้มันยอมไมได้เลยอ่าน log เล่นๆ เอ้อเค้าก็บอกวิธีมานี่หว่า If you have any troubles set -Drebel.spring_plugin=false to disable it.
เอาเลยผมไปจัดการไปที่ run>>condig… แล้วก็ไปเพิ่มที่นี่เลยครับ

เท่านี้หล่ะแล้วลองใหม่ก็จะเห็ฯlogหน้าตาพอจะสวยงามประมาณนี้

=============================== [JavaRebel Spring Framework Plugin ===============================
Plugins are contributed by third party and can cause compatibility problems.
If you have any troubles set -Drebel.spring_plugin=false to disable it.
------------------------------------------------------------------------------------------
Description: Supports adding new beans and adding new bean dependencies using
annotations or XML. Singletons will be reconfigured after the change. It also
supports adding or changing Spring MVC controllers or handlers.
=============================== [/JavaRebel Spring Framework Plugin ] ==============================

เท่านี้ก็หรูแล้ว

ทีนี้ลองแก้ file .java ดูแล้วไป refresh ดูครับไม่ต้องไปคลิก run ใหม่นะครับไม่ตรงจุดประสงค์อย่างยิ่งเพราะอย่างที่รู้มันก็จะไป restart server หรือไม่ก็ deploy ทับซึ่งมันไม่เหมาะกับเครื่องโปรแกรมเมอร์จนๆแรมน้อยๆอย่างผมครับแต่ก็นะพอไปดู log เฮ้ยมัน publih ไปให้เรา

ก็นั่นหล่ะครับเพราะว่าเรายังไมได้ตั้งให้มัน ปิดการ auto publish แต่ปัญหาอยู่ตรงนี้ครับพอเราไปตั้งให้มัน never auto publish มันก็จะไม่ยอม publish jsp ให้เราแต่ ตัว class แน่นอนอยู๋แล้วว่า javarebel agent รับผิดชอบเราก็เลยต้องโกง wtp กันหน่อยโดยยังตั้ง auto publish
อยู่แล้วไปเลือกเป็น module ให้มันปิดการ publish ซะเท่านี้เลย

พิมซะเมื่อยครับลองรันแล้วเทสกันดูหลาย case นะครับโดยรวมมันรวดเร็วอำนวยความสะดวกให้เราชาว spring66 มากมายผมซื้อแน่ๆ เขียนไปเขียนมาอ่านไปอ่านมายังงงอยู่ครับเอาเป็นว่าใครลองแล้วติด comment ถามกันมาแล้วกันครับ

ปล. ขอโทษด้วยครับ คุณ @roofimon นัดไว้ว่าจะขึ้นเที่ยงคืนแต่มาเอาเที่ยงวันครับ

Introducing Spring Batch แบบ ผิวๆ บางๆ (ภาคต่อ)

February 4th, 2009

ความเดิมตอนที่แล้ว :
กล่าวถึงการ cofig เบื้องต้นของ spring-batch แล้วก็ xml ตัวพ่ออย่าง pom มาตอนนี้ ไม่พูดพร่ำทพเพลงครับ เด่วลืม เขียนต่อกันไปเลยดีกว่า

เราก็มาดูกันต่อเลย ก็คือ config ตัวพระเอกของเราคือตัว job กันหล่ะครับ โดยเราก็ ไป regis bean

<bean id="tm" class="org.springframework.batch.support.transaction.ResourcelessTransactionManager"/>

<bean id="jobRepository" class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean">
        <property name="transactionManager" ref="tm"/>
</bean>

<bean id="usersLoadStep" class="org.springframework.batch.core.step.item.SimpleStepFactoryBean">
        <property name="transactionManager" ref="tm"/>
        <property name="jobRepository"      ref="jobRepository"/>
        <property name="itemReader"         ref="reader"/>
        <property name="itemWriter"         ref="writer"/>
</bean>

<bean id="usersLoadJob" class="org.springframework.batch.core.job.SimpleJob">
        <property name="jobRepository" ref="jobRepository"/>
        <property name="steps">
            <list>
                <ref bean="usersLoadStep"/>
            </list>
        </property>
</bean>

<bean id="writer" class="com.spring66.tutorial.batch.DatabaseWriter"/>

ว่ากันที่ตัวแรก tm ว้าววว ไม่น่าแปลกใจ เพราะ job ก็คือ งานงานนึงที่สำคัญ จึงมี TransactionManager มาครอบไม่น่าสงสัย
ตัวที่สอง ก็ jobRepository ตัวนี้เล่าแล้วยาวมาก ขอให้ตามไปอ่านเอานะครับ จริงๆ แล้วก็ ผมเองก็ไม่ได้เข้าใจแบบสามารถอธิบายได้ดีนัก
เหมือน design pattern ที่นิยมชมชอบ FactoryBean หรือ step ที่เราพูดถึงตอนแรก usersLoadJob นี่หล่ะพระเอกของเรา
โดยจุดที่น่าสนใจคือ list parameter

 <property name="steps">
            <list>
                <ref bean="usersLoadStep"/>
            </list>
 </property>

นั่นเอง นั่นคือจุดที่บอกว่าหนึ่งงานอาจจะมีหลาย step ก็ได้ นั่นเอง ตรงนี้หล่ะจร้า
ส่วนตัวสุดท้าย

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

package com.spring66.tutorial.batch;

import org.springframework.batch.item.ClearFailedException;
import org.springframework.batch.item.FlushFailedException;
import org.springframework.batch.item.ItemWriter;

/**
 *
 * @author Phongsak
 */
public class DatabaseWriter implements ItemWriter {

    public void write(Object item) throws Exception {
        System.out.println(" "+ item.getClass().toString());
        System.out.println("insert to database...");
    }

    public void flush() throws FlushFailedException {
    }

    public void clear() throws ClearFailedException {
    }

}

อ่ะ ใช้ sout debug แบบเมพๆ เนี่ยหล่ะครับ ดูแล้วก็ น่าสนใจถ้า เราทำการ อะแด๊พ แอ๊พพาย หน่อยก็เอาไปต่อกับ dao ของคุณ roofimon ได้เลย โอ้วช่างสมใจ
อ่ะเท่านี้หล่ะทีนี้ก็หาทางทำให้มันทำงานกันดีกว่า คำเท่ๆ พูดให้ชินทำให้ เคยมือ ก็คือ เขียน test ครับ

package com.spring66.tutorial;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.job.SimpleJob;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.test.AbstractDependencyInjectionSpringContextTests;

public class BaseSpringTestCase extends AbstractDependencyInjectionSpringContextTests {

    protected final Log log = LogFactory.getLog(getClass());

    @Override
    protected String[] getConfigLocations() {
        setAutowireMode(AUTOWIRE_BY_NAME);
        return new String[]{
                    //"classpath:/applicationContext.xml",
                    "classpath*:/applicationContext.xml" // for modular projects
                //"classpath:**/applicationContext*.xml" // for web projects
                };
    }

    public void testLoadUsers() {

        Job job = (SimpleJob) super.applicationContext.getBean("usersLoadJob");
        JobParameters jobParameters = new JobParameters();
        JobRepository jobRepository = (JobRepository) super.applicationContext.getBean("jobRepository");

        try {
            JobExecution je = jobRepository.createJobExecution(job, jobParameters);
            job.execute(je);
        } catch (Exception ex) {
            ex.printStackTrace();
        }

    }
}

ถึงตรงนี้ผมคงไม่ขอขยายความนะครับ ลองแก้ ลองเขียนกันไปเลยดีกว่า แล้วแบ่งปันประสบการกันบ้างนะครับ มันยังมีอีกหลายวิธีวันหลัง จะมาต่อนะครับ
เพราะอีกเดี๋ยวผมคงต้องเอาไป implements ในงานเหมือนกัน ตอนนี้แค่เอามาอ่านเฉยๆ เลยออกมาไม่ค่อย เคลียเท่าไหร่

Solving Integration Problems using Patterns ภาค 1

January 12th, 2009

อยากเขียนเกี่ยวกับ Spring Integration แต่เค้าแนะนำให้ไปอ่าน Enterprise Integration Pattern ก่อนอ่านไปอ่านมาแปลเลยดีกว่าเอาไปภาคแรก

Solving Integration Problems using Patterns

บทนี้เราจะมาว่ากันถึงเรื่องการใช้ Integration Pattern เข้ามาช่วยแก้ปัญหาเรื่องการ Integration โดยวิธีการที่เราจะนำเสนอนั้นจะออกมาในรูปของการสร้างสถานการ์ณจำลองขึ้นมาก่อนและทำการออกแบบแนวทางการแก้ปัญหาที่เหมาะสมกับโจทย์ที่เราตั้งขึ้นมา โดยการใช้ pattern ต่างๆเข้ามาช่วยเหลือ โดยที่หลังจากจบบทนี้เราจะได้รู้จัก pattern ต่างๆมากพอสมควร
The Need for Integration
ก่อนอื่นมารู้จักคำว่า Enterprise กันก่อนโดยที่คำว่า Enterprise มักจะอ้างอิงถึงบริษัทที่มีระบบหรือแอพพลิเคชั่นหลักร้อยขึ้นไปโดยที่ระบบเหล่านั้นเป็นแบบร้อยพ่อพันแม่คือ สร้างเอง จ้างคนมาทำ แพคเกจ และอื่นๆอีกมากมาย นอกจากนี้ระบบปฏิบัติการก็มีทุกระบบในโลก ==”

Integration Challenges

ดังนั้นเราก็ทำใจไว้ได้เลยว่า Enterprise Integration เป็นเรื่องยากมากๆ เนื่องจากการทำ Enterprise Integration นั้นอย่างที่เรารู้ๆกันว่าเราต้องไปยุ่งวุ่นวายการแอพพลิเคชั่นที่ทำงานอยู่บนหลายแพลทฟอร์ม จะเห็นได้ว่าความท้าทายของการทำ integration นั้นคือมันจะครอบคลุมไปทั้งแง่ของธุรกิจและเทคโนโลยี เนื่องจาการทำ Enterprise Integration นั้นจะไม่ใช่เพียงการเชื่อมต่อระหว่างระบบหรือแอพพลิเคชั่นต่างๆเข้าด้วยกันแต่ยังต้องทำให้หน่วยธุรกิจและหน่วยงาน IT สามารถสื่อสารกันได้อย่างประสิทธิภาพมากอีกด้วย
ดังนั้นจากความกว้างและหลากหลายในการทำ integration นั้นทำให้หลายๆครั้งที่การทำ integration มีส่วนเข้าไปเกี่ยวข้องกับ application ที่มีความสำคัญมากๆเช่น Billing, CRM นั่นหมายความว่าการ integrate ที่ผิดพลาดอาจส่งผลกระทบมหาศาลต่อการทำธุรกรรมที่สำคัญเหล่านั้น อีกปัจจัยที่ยากมากสำหรับการทำ integration คือความสามารถในการเข้าถึง application ที่เราต้องไป integrate ด้วยเนื่องจากระบบบางอย่างเป็นระบบที่เก่ามากหรือเป็นระบบที่ซื้อแพกเกจมาใช้งานทำให้ไม่สามารถเข้าไปแตะต้องได้มากนัก ซึ่งเมื่อนักพัฒนาด้าน untegration ไม่สามารถเข้าไปปรับปรุง service อะไรบางอย่างของ แอพพลิเคชั่นเดิมๆได้ทำให้การทำ integration เป็นเรื่องยากมากเพราะเราไม่สามารถกำหนด service contact point ได้ง่ายๆ
เรื่องต่อไปที่ต้องทำความสนใจคือเรื่องของเทคโนโลยีที่ถูกใช้ในการทำ integration เพราะถึงแม้ว่าการทำ integration นั้นจะต้องเข้าไปเกี่ยวข้องกับระบบจำนวนมหาศาลแต่เทคโนโลยีที่ถูกใช้นั้นมีน้อยจนน่าตกใจซึ่งทั้งหมดก็อยู่ในตระกูล XML, XSL และ Web Services แต่อย่างไรก็ตามเนื่องจากปัจจัยเรื่องของการตลาดทำให้มีการแต่งเสริมเติมแต่งความสามารถพิศดารต่างๆเข้าไปให้ Web Services อีกจึงทำให้พักหลังๆเราจะเห็นว่าจะมีการใส่พวก extension และ interpretations ใหม่ๆเข้าไปอีก การกระทำแบบนี้ทำให้เรามองย้อนกลับไปยังปัญหาเรื่องของระดับของการทำ interoperability ที่ต่ำของ “standards-pompliant” ระหว่างผลิตภัณท์ที่มาจากบริษัทที่ต่างกันของสถาปัตยกรรม CORBA ที่ถูกใช้งานมาอย่างยาวนานในเรื่องของการทำ EAI
อย่างไรก็ตามการทำ integration ด้วย Web Services นั้นก็ยังมีหลสยจุดที่ยังเป็นที่สงสัยยกตัวอย่างเช่น หลายครั้งที่เราให้คำนิยาม XML ว่าเป็น “Lingua franca” เนื่องจากการบังคับให้การแลกเหลี่ยนข้อมูลต้องทำด้วย XML นั้นไม่ต่างไปจากการเขียนเอกสารทั่วๆไป เนื่องจาก XML ต้องมี TAG ในการอธิบายความหมายของข้อมูลในโหนดต่างๆซึ่งบางครั้งก็ทำให้เสียเวลามากๆ ถึงแม้ว่าการใช้สตริงเป็นตัวแทนของข้อมูลแต่ก็ยังมีปัญหาเนื่องจากภาษาที่ใช้นั้นหลากหลายภาษามากทำให้ยังไงก็อ่านไม่เข้าใจอยู่ดี และปัญหาคาใจหลักๆอีกข้อคือการใช้ TAG เพื่ออธิบาย Data นั้นบางครั้งก็ไม่สามารถสื่อถึงข้อมูลจริงๆที่ใช้อยู่ได้เช่นคำว่า account นั้นจริงๆแล้วมีได้หลายความหมายมาก
และถ้าเราคิดว่าการพัฒนา EAI Solution เป็นเรื่องที่ซับซ้อนมากแล้ว สิ่งที่ทำยากกว่าการพัฒนาคือเรื่องของการดูแลรักษา เนื่องจากมันเป็นเรื่องของความหลากหลาย ทำให้การ deployment monitoring และ triuble-shoot เป็นเรื่องที่สุดยอดน่ากลัวมาก และการจัดการบริหารงานในลักษณะนี้จำเป็นต้องใช้ skill set ที่หลากหลายมากและบ่อยครั้งที่ skill set ที่ใช้ในการบริหารทั้งหมดไม่สามารถหาได้จากคนๆเดียวได้แต่จะต้องใช้คนเยอะมากในการทำงาน และสำหรับคนที่เคยผ่านงานด้าน EAI มาแล้วจะพบว่ามันเป็นส่วนที่สำคัญมากๆในการทำธุรกิจปัจจุบันแต่อย่างไรก็ตามการทำ EAI นั้นไม่ใชเรื่องง่ายที่จะทำให้สำเร็จเต็มรูปแบบเนื่องจากกระบวนการทำให้เกิดได้จริงกับแผนและนโยบายนั้นเป็นเรื่องที่ยากและซับซ้อนมากๆ

How Integration Patterns Can Help

การทำ Enterprise Integration ไม่ใช่เรื่องง่าย ในมุมมองของผู้เขียนใครก็ตามที่กล้าเอ่ยปากออกมาว่า integration นั้นง่ายคนๆนั้นสามารถเป็นได้สองแบบคือ ฉลาดโคตร กับ มีเหตุผลซ่อนเร้นเรื่องเงินๆทองๆที่ต้องตะล่อมเราให้เข้าใจว่ามันง่าย
ดังนั้นการทำ Integration เป็นเรื่องที่กว้างและยากมากและในโลกของการทำ integration จะไม่มีตำราในแนว “Tech Yourself Integration in 21 days” โดยคนที่มีประสบการ์ณเรื่องของการทำมากกว่าย่อมได้เปรียบเนื่องจากเขาเหล่านั้นสามารถดึงเอาวิธีแก้ปัญหาที่เคยทำมาแล้ว มาใช้กับการแก้ปัญหาในปัจจุบันได้ หรือเราอาจเรียกได้ว่าคนเหล่านั้นมี “PATTERN” ในการแก้ปัญหา
โดยที่คำว่า “PATTERN” ไม่ใช่ copy-paste นะครับแต่มันเป็นเรื่องของ “แนวทาง” ที่ควรทำตามในการแก้ปัญหาที่เกิดขึ้นบ่อยๆ ซึ่งการใช้ “PATTERN” จะช่วยให้ช่องว่างระหว่างมุมมองของผู้บริการกับการลงมือทำจริงให้แคบลงมาได้

The Wide World of Integration

ที่ผ่านมาเราได้รับรู้ถึงข้อมูลที่สำคัญเบื้องต้นเกี่ยวกับ integration แล้วว่ามันคือการเชื่อมต่อทุกสิ่งทุกอย่างเข้าาด้วยกันไม่ว่าจะเป็น Services, คน แม้กระทั่งบริษัทเข้าด้วยกันเพื่อให้เกิดกระบวนการทางธุรกิจบางอย่างตามที่เราต้องการ ต่อไปเราจะมาดูถึงวิธีการในการทำ integration ในแบบต่างๆที่ได้รับการยอมรับว่าดี โดยที่เราสามารถแบ่งได้เป็น 6 วิธีใหญ่ๆด้วยกันดังนี้

  1. Information Portals
  2. Data Replication
  3. Shared Business Functions
  4. Service-Oriented Architectures
  5. Distributed Business Processes
  6. Business-to-Business Integration

วิธีการทั้งหกแบบนี้เป็นวิธีการหลักๆที่ช่วยให้เราสามารถเห็นภาพของการทำ integration กันได้ง่ายขึ้นในเชิงของ Architect ซึ่งเราสามารถจับเอาวิธีการเหล่านี้มาผสมรวมกันเพื่อแก้ปัญหาได้