<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;Dk4DR3w-fSp7ImA9WhRVFko.&quot;"><id>tag:blogger.com,1999:blog-1638080862489455885</id><updated>2012-01-16T07:49:36.255+07:00</updated><category term="JPA" /><category term="Struts" /><category term="SQL" /><category term="XP" /><category term="Seam" /><category term="Software Development" /><category term="Richface" /><category term="Oracle" /><category term="Java" /><category term="Apple" /><category term="WebSphere" /><category term="Arts" /><category term="Testing" /><category term="EJB" /><category term="NOSQL" /><category term="BlazeDS" /><category term="DB2" /><category term="Eclipse" /><category term="Tivoli Directory" /><category term="Flex" /><category term="JSF" /><category term="Data Warehouse" /><category term="Spring" /><category term="Facelets" /><category term="Servlet" /><category term="dot Net" /><category term="Cassandra" /><title>Phamonyut</title><subtitle type="html">/** &lt;br&gt;
* Blog &lt;br&gt;
* @return Solution. &lt;br&gt;
*/</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://phamonyut.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://phamonyut.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Phamon P</name><uri>https://profiles.google.com/105136402217293967127</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh3.googleusercontent.com/-2AzJSisfnE0/AAAAAAAAAAI/AAAAAAAAAtA/koK-fzCuwVc/s512-c/photo.jpg" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>39</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/Phamonyut" /><feedburner:info uri="phamonyut" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;D0MCRXc4cCp7ImA9WhdXE04.&quot;"><id>tag:blogger.com,1999:blog-1638080862489455885.post-5236948849316140310</id><published>2011-08-26T12:06:00.002+07:00</published><updated>2011-08-26T12:11:04.938+07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-26T12:11:04.938+07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><category scheme="http://www.blogger.com/atom/ns#" term="Richface" /><category scheme="http://www.blogger.com/atom/ns#" term="JSF" /><title>Bootstrap twitter integrate with Richface4</title><content type="html">หลังจากใช้ Richface มานานรู้สึกเบื่อกับ theme มานานละ และไปเจอกับ &lt;a href="http://twitter.github.com/bootstrap/"&gt;bootstrap twitter&lt;/a&gt; ทำให้นักพัฒนาหยิบไปใช้ เข้าท่าทีเดียวเลยหยิบมารวมกับ Richface 4 ปรับแต่งนิดหน่อยก็ได้อย่างที่เห็น เอิ่มมันก็ไม่ได้ยากนะ&amp;nbsp;แต่เป็นงานที่ต้องใช้ความอดทน แต่คงได้ปรับแก้อีกเยอะกว่าจะสมบูรณ์&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-BgrgYbSq1Io/TlcoNQpgFNI/AAAAAAAAAvM/nJXHxbBTgdg/s1600/Bootstrap+%252820110826%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://2.bp.blogspot.com/-BgrgYbSq1Io/TlcoNQpgFNI/AAAAAAAAAvM/nJXHxbBTgdg/s400/Bootstrap+%252820110826%2529.png" width="179" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1638080862489455885-5236948849316140310?l=phamonyut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Phamonyut/~4/Bnv17QvWEko" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://phamonyut.blogspot.com/feeds/5236948849316140310/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://phamonyut.blogspot.com/2011/08/bootstrap-twitter-integrate-with.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/5236948849316140310?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/5236948849316140310?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Phamonyut/~3/Bnv17QvWEko/bootstrap-twitter-integrate-with.html" title="Bootstrap twitter integrate with Richface4" /><author><name>Phamon P</name><uri>https://profiles.google.com/105136402217293967127</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh3.googleusercontent.com/-2AzJSisfnE0/AAAAAAAAAAI/AAAAAAAAAtA/koK-fzCuwVc/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-BgrgYbSq1Io/TlcoNQpgFNI/AAAAAAAAAvM/nJXHxbBTgdg/s72-c/Bootstrap+%252820110826%2529.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://phamonyut.blogspot.com/2011/08/bootstrap-twitter-integrate-with.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUIHRHs_fyp7ImA9Wx5UF08.&quot;"><id>tag:blogger.com,1999:blog-1638080862489455885.post-8609721314971724611</id><published>2010-10-22T11:58:00.000+07:00</published><updated>2010-10-22T11:58:55.547+07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-10-22T11:58:55.547+07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><category scheme="http://www.blogger.com/atom/ns#" term="Apple" /><title>[News] Apple update Java Deprecation</title><content type="html">Apple ประกาศเกี่ยวกับ Java Deprecation เห็นมีการปรับเนื้อหาเล็กน้อย&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_al1ANReYFEE/TMEZeSQjrOI/AAAAAAAAAnc/Sh_DMHOcYMM/s1600/Apple+Java+Deprecation++before.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="210" src="http://3.bp.blogspot.com/_al1ANReYFEE/TMEZeSQjrOI/AAAAAAAAAnc/Sh_DMHOcYMM/s400/Apple+Java+Deprecation++before.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;ไปเป็น&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_al1ANReYFEE/TMEZtHxIdeI/AAAAAAAAAng/hXAkC9pwKUg/s1600/Apple+Java+Deprecation++after.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="207" src="http://4.bp.blogspot.com/_al1ANReYFEE/TMEZtHxIdeI/AAAAAAAAAng/hXAkC9pwKUg/s400/Apple+Java+Deprecation++after.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;
&lt;/div&gt;แต่ความหมายยังคงเดิม&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1638080862489455885-8609721314971724611?l=phamonyut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Phamonyut/~4/Vs4IYl72iOo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://phamonyut.blogspot.com/feeds/8609721314971724611/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://phamonyut.blogspot.com/2010/10/news-apple-update-java-deprecation.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/8609721314971724611?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/8609721314971724611?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Phamonyut/~3/Vs4IYl72iOo/news-apple-update-java-deprecation.html" title="[News] Apple update Java Deprecation" /><author><name>Phamon P</name><uri>https://profiles.google.com/105136402217293967127</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh3.googleusercontent.com/-2AzJSisfnE0/AAAAAAAAAAI/AAAAAAAAAtA/koK-fzCuwVc/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_al1ANReYFEE/TMEZeSQjrOI/AAAAAAAAAnc/Sh_DMHOcYMM/s72-c/Apple+Java+Deprecation++before.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://phamonyut.blogspot.com/2010/10/news-apple-update-java-deprecation.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkIAQXY_fSp7ImA9Wx5VFko.&quot;"><id>tag:blogger.com,1999:blog-1638080862489455885.post-5996002000352774464</id><published>2010-10-10T08:35:00.000+07:00</published><updated>2010-10-10T08:35:40.845+07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-10-10T08:35:40.845+07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Oracle" /><title>oracle of Oracle</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_al1ANReYFEE/TLEYHqaMTsI/AAAAAAAAAmY/zd7GPrVdF1Q/s1600/Picture+1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="152" src="http://3.bp.blogspot.com/_al1ANReYFEE/TLEYHqaMTsI/AAAAAAAAAmY/zd7GPrVdF1Q/s320/Picture+1.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
รูปจาก Iron man2&lt;br /&gt;
...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1638080862489455885-5996002000352774464?l=phamonyut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Phamonyut/~4/7TMCj7rkUNo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://phamonyut.blogspot.com/feeds/5996002000352774464/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://phamonyut.blogspot.com/2010/10/oracle-of-oracle.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/5996002000352774464?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/5996002000352774464?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Phamonyut/~3/7TMCj7rkUNo/oracle-of-oracle.html" title="oracle of Oracle" /><author><name>Phamon P</name><uri>https://profiles.google.com/105136402217293967127</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh3.googleusercontent.com/-2AzJSisfnE0/AAAAAAAAAAI/AAAAAAAAAtA/koK-fzCuwVc/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_al1ANReYFEE/TLEYHqaMTsI/AAAAAAAAAmY/zd7GPrVdF1Q/s72-c/Picture+1.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://phamonyut.blogspot.com/2010/10/oracle-of-oracle.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0EHRnYzfip7ImA9Wx5WFUw.&quot;"><id>tag:blogger.com,1999:blog-1638080862489455885.post-6182224364696389939</id><published>2010-09-26T21:33:00.000+07:00</published><updated>2010-09-26T21:33:57.886+07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-09-26T21:33:57.886+07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Cassandra" /><category scheme="http://www.blogger.com/atom/ns#" term="NOSQL" /><title>Setup Cassandra cluster in 10 minute</title><content type="html">จำลองทำ Cassandra cluster โน็ตไว้กันลืมด้วย&lt;br /&gt;
&lt;br /&gt;
my env:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;โหนดแรกเป็นเครื่องหลักผมเองใช้ Mac OSX (Leopard) ติดตั้ง Cassandra .65&lt;/li&gt;
&lt;li&gt;โหนดที่สองจำลองขึ้นมาบน VMWare เป็น Windows XP ติดตั้ง Cassandra .65&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
กำหนด hostname ให้เรียบร้อยทั้งสองโหนด&lt;br /&gt;
โหนดแรกชื่อเครื่อง tofu และ cassvm เป็นของโหนดที่สอง&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_al1ANReYFEE/TJ9SDOY57NI/AAAAAAAAAlk/4wZwNOMMs8I/s1600/hosts.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="168" src="http://1.bp.blogspot.com/_al1ANReYFEE/TJ9SDOY57NI/AAAAAAAAAlk/4wZwNOMMs8I/s320/hosts.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
กำหนด Seed เพื่อให้ Cassandra รู้ว่ามีสมาชิกอยู่ที่ใดกันบ้างและกำหนด ThriftAddress, ListenAddress ทั้งสองโหนด&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_al1ANReYFEE/TJ9Sh9WBqYI/AAAAAAAAAlo/OAbs_90nBkk/s1600/seeds.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="130" src="http://3.bp.blogspot.com/_al1ANReYFEE/TJ9Sh9WBqYI/AAAAAAAAAlo/OAbs_90nBkk/s320/seeds.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
ถัดมาลองสั่งรันที่โหนดแรกดู (อย่าลืมกำหนด Commitlog และ log4j ก่อนให้เรียบร้อย)&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_al1ANReYFEE/TJ9S5XAootI/AAAAAAAAAls/gcoQSsEWjuk/s1600/commitlog.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="40" src="http://4.bp.blogspot.com/_al1ANReYFEE/TJ9S5XAootI/AAAAAAAAAls/gcoQSsEWjuk/s320/commitlog.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_al1ANReYFEE/TJ9S6drz1yI/AAAAAAAAAlw/Yv8zmkqVh88/s1600/log4j.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="16" src="http://4.bp.blogspot.com/_al1ANReYFEE/TJ9S6drz1yI/AAAAAAAAAlw/Yv8zmkqVh88/s320/log4j.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_al1ANReYFEE/TJ9UEdRNNbI/AAAAAAAAAl0/j0N-P8fAapA/s1600/Picture+1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="22" src="http://2.bp.blogspot.com/_al1ANReYFEE/TJ9UEdRNNbI/AAAAAAAAAl0/j0N-P8fAapA/s320/Picture+1.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
หลังจากนั้นลองรันที่อีกโหนดดูที่เป็น VMWare&lt;br /&gt;
จะขึ้นหน้าจอประมาณนี้ และ process hinted handoff ก็เริ่มทำงานไปพร้อมๆ กัน&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_al1ANReYFEE/TJ9Y-ZXPuHI/AAAAAAAAAl4/HiHN-H6Xkcs/s1600/Picture+2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="35" src="http://1.bp.blogspot.com/_al1ANReYFEE/TJ9Y-ZXPuHI/AAAAAAAAAl4/HiHN-H6Xkcs/s320/Picture+2.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
ok เสร็จเรียบร้อยแล้วครับ ถ้าเข้าใจแนวคิด และทุกอย่างไม่พลาด ไม่น่าเกิน 10 นาทีก็ทดลองอย่างอื่นต่อได้แล้วครับ&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1638080862489455885-6182224364696389939?l=phamonyut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Phamonyut/~4/GvLGmv0BuQc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://phamonyut.blogspot.com/feeds/6182224364696389939/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://phamonyut.blogspot.com/2010/09/setup-cassandra-cluster-in-10-minute.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/6182224364696389939?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/6182224364696389939?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Phamonyut/~3/GvLGmv0BuQc/setup-cassandra-cluster-in-10-minute.html" title="Setup Cassandra cluster in 10 minute" /><author><name>Phamon P</name><uri>https://profiles.google.com/105136402217293967127</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh3.googleusercontent.com/-2AzJSisfnE0/AAAAAAAAAAI/AAAAAAAAAtA/koK-fzCuwVc/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_al1ANReYFEE/TJ9SDOY57NI/AAAAAAAAAlk/4wZwNOMMs8I/s72-c/hosts.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://phamonyut.blogspot.com/2010/09/setup-cassandra-cluster-in-10-minute.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEUEQHg5fyp7ImA9Wx5WEEk.&quot;"><id>tag:blogger.com,1999:blog-1638080862489455885.post-8559815758094286792</id><published>2010-09-21T11:10:00.000+07:00</published><updated>2010-09-21T11:10:01.627+07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-09-21T11:10:01.627+07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Cassandra" /><category scheme="http://www.blogger.com/atom/ns#" term="NOSQL" /><title>CAP theorem</title><content type="html">&lt;b&gt;ความสามารถในการขยายตัวของระบบ (Scalable) กับ Service&lt;/b&gt;&lt;br /&gt;
รูปข้างล่างเป็นจำนวนผู้ใช้บน Facebook&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_al1ANReYFEE/TJguomGV8lI/AAAAAAAAAlg/wD4EMNrLx9U/s1600/Facebook-Chart-Number-of-Users-December-2004-to-July-21-2010.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="211" src="http://3.bp.blogspot.com/_al1ANReYFEE/TJguomGV8lI/AAAAAAAAAlg/wD4EMNrLx9U/s400/Facebook-Chart-Number-of-Users-December-2004-to-July-21-2010.gif" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;lu&gt;&lt;li&gt;ใน Facebook ตอนนี้มีผู้ใช้กว่า 500 ล้านคน&lt;/li&gt;&lt;li&gt;ประมาณ 50% ของผู้ใช้ทั้งหมดเข้าใช้งานทุกวัน&lt;/li&gt;&lt;li&gt;แต่ละคนใช้งานระบบเฉลี่ยอยู่ที่ 20 นาทีต่อคน&lt;/li&gt;&lt;li&gt;ในแต่ละเดือนมี 30 ล้าน content เช่น status update, comments, likes, photo uploads, video uploads, chat messages, inbox messages, group events, fan pages, friend connects, ... ถูกแชร์บน facebook&lt;/li&gt;&lt;li&gt;ในแต่ละเดือน application ถูกใช้มากกว่าล้านคน&lt;/li&gt;&lt;/lu&gt;&lt;br /&gt;
ลองคิดเล่นๆ ว่าเค้าต้องออกแบบระบบยังไงให้ยืดหยุ่นรองรับการขยายตัว เพื่อให้รองรับปริมาณการใช้บริการต่างๆ จะเห็นว่าความสามารถในการขยายตัว จะสัมพันธ์กับสัดส่วนของบริการ และ product ใหม่ๆ ที่จะตามออกมา เหมือนอย่างที่ Google หลังจากค้นคว้าวิจัยเทคโนโลยี GFS, MapReduce, BigTable และถูกนำไปใช้ไม่นานหลังจากนั้นก็มีบริการและ product ใหม่ๆ ออกมา ในสัดส่วนที่เร็วกว่าแต่ก่อนมาก จะเห็นว่าภาพจะเป็นไปในแนวทางนี้ Infrastructure (scalable) -&gt; Services-&gt; Customer need&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Distributed system กับ ทฤษฏี CAP&lt;/b&gt;&lt;br /&gt;
ระบบที่มีความสามารถในการขยายตัวส่วนใหญ่จะเป็นอยู่ใน model ของ distributed system เมื่อเราพูดถึง distributed เราจะต้องเจอกับทฤษฏี CAP ซึ่งมันเป็นแนวคิดที่เรียบง่ายแต่ไว้ใช้อธิบายเรื่องที่ซับซ้้อน ตัวทฤษฏี CAP มีต้นกำเนิดมาจาก Dr. Eric Brewer ในปี 2000 และกลายมาเป็นทฤษฏีที่มีผลกระทบต่อ โลก internet ในเวลาต่อมา&lt;br /&gt;
&lt;br /&gt;
CAP มาจากคำว่า Consistency, Availability, Partition Tolerance ซึ่งมันบอกว่าระบบที่เป็น distributed storage จะสามารถรองรับคุณสมบัติแค่สองคุณสมบัติเท่านั้น นั่นคือเราไม่สามารถเลือกทั้งหมดได้พร้อมๆ กัน ณ เวลาใดเวลาหนึ่ง ซึ่งแต่ละคุณสมบัติมีรายละเอียดดังนี้&lt;lu&gt;&lt;li&gt;&lt;b&gt;Consistency&lt;/b&gt; ทุก node จะเห็นข้อมูลกันเดียวกันในเวลาเดียวกันไม่ว่าจะเข้าถึงข้อมูลที่ node ใดใน cluster ก็ตาม ดังนั้นข้อมูลจึงมีแค่สองสถานะคือถูก กับไม่ถูก โดย consistency มีสองประเภทคือ strongly consistent และ weak consistency&lt;lu&gt;&lt;li&gt;ตัวอย่างของ strongly consistent จะเทียบได้กับ database ที่มีคุณสมบัติ ACID (Atomicity, Consistency, Isolation, Durability)&lt;/li&gt;&lt;li&gt;ส่วน weak consistency จะเจอเมื่อเนื้อข้อมูลของเรามีการ replicate กันโดยแต่ละ node ใน cluster ก็จะมีข้อมูลเดียวกันอยู่ แต่อาจไม่ใช่ version ล่าสุด ข้อมูล version ล่าสุดจะถูกเก็บอยู่ใน node ใด node หนึ่งในวง cluster แล้วจะ replicate ข้อมูลล่าสุดออกไป ดังนั้นในตอนสุดท้ายข้อมูลในทุก node ก็จะเป็นข้อมูลชุดเดียวกัน&lt;/li&gt;&lt;/lu&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Availability&lt;/b&gt; ถึงแม้ node ใด node หนึ่ง fail แต่ก็จะไม่ขัดขวางการทำงานของระบบ ตัวระบบยังคงสามารถให้บริการต่อได้ เท่ากับว่าระบบจะต้องถูกออกแบบให้มี High-Availability เพื่อให้บริการได้ตลอดเวลาไม่ว่าจะเกิดเหตุการณ์ใดๆ ขึ้น เช่นเมื่อมีบาง node failures ขณะที่ software หรือ hardware กำลัง upgrade แต่ระบบโดยรวมยังคงให้บริการได้ต่อไป&lt;/li&gt;&lt;li&gt;&lt;b&gt;Partition Tolerance&lt;/b&gt; ระบบยังคงต้องทำงานต่อไปถึงแม้ว่าเส้นทางการเชื่อมต่อระหว่าง node จะเสียหาย แต่ client ยังเข้าถึงได้อยู่&lt;lu&gt;&lt;li&gt;ถ้าระบบสามารถทนต่อสภาพเช่นนี้ได้ ตัว database ก็จะสามารถทำงานได้ตาม อ่าน, เขียนได้ตามปกติขณะที่ database 2 rack แยกออกจากกัน&lt;/li&gt;&lt;li&gt;ถ้าไม่รองรับคุณสมบัตินี้แล้วเราอาจทำการอ่านข้อมูลได้เพียงอย่างเดียว แต่ไม่สามารถที่จะเขียนข้อมูลลงใน database ได้&lt;/li&gt;&lt;/lu&gt;&lt;/li&gt;&lt;/lu&gt;&lt;br /&gt;
สำหรับ RDBMS ได้คุณสมบัติ CA นั่นคือ Consistency และ Availability แต่ no Partition tolerance นั่นคือเมื่อ host หนึ่ง fail ไป RDBMS ก็จะหยุดการทำงานไปด้วย ดังนั้น RDBMS จึงต้องพยายามการันตีว่าจะต้องให้บริการได้ตลอด (High-Availability) เพราะฉะนั้นจึงไม่เกิดกรณี Partition Tolerance แน่ๆ&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1638080862489455885-8559815758094286792?l=phamonyut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Phamonyut/~4/8p4NXUnjk2M" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://phamonyut.blogspot.com/feeds/8559815758094286792/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://phamonyut.blogspot.com/2010/09/cap-theorem.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/8559815758094286792?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/8559815758094286792?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Phamonyut/~3/8p4NXUnjk2M/cap-theorem.html" title="CAP theorem" /><author><name>Phamon P</name><uri>https://profiles.google.com/105136402217293967127</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh3.googleusercontent.com/-2AzJSisfnE0/AAAAAAAAAAI/AAAAAAAAAtA/koK-fzCuwVc/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_al1ANReYFEE/TJguomGV8lI/AAAAAAAAAlg/wD4EMNrLx9U/s72-c/Facebook-Chart-Number-of-Users-December-2004-to-July-21-2010.gif" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://phamonyut.blogspot.com/2010/09/cap-theorem.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkcEQXk-fSp7ImA9Wx5XGUk.&quot;"><id>tag:blogger.com,1999:blog-1638080862489455885.post-6946409808467126601</id><published>2010-09-20T09:00:00.000+07:00</published><updated>2010-09-20T09:00:00.755+07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-09-20T09:00:00.755+07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Cassandra" /><category scheme="http://www.blogger.com/atom/ns#" term="NOSQL" /><title>Cassandra Sorting</title><content type="html">Cassandra ไม่มีความสามารถในการ query เหมือน RDBMS ทั่วไป ดังนั้นเราจึงไม่สามารถกำหนดรูปแบบการเรียงลำดับ ขณะที่ดึงข้อมูลออกมา&lt;br /&gt;
เมื่อเราต้องการดึงข้อมูลแล้วให้มันเรียงลำดับ สิ่งเหล่านั้นเราต้องกำหนดลงใน ColumnFamily แต่ความจริง Cassandra จะเรียงลำดับข้อมูลตั้งแต่ตอนที่ใส่ข้อมูลลงใน cluster และคงที่ลำดับตัวข้อมูลเหล่านั้นไว้ดังนั้นเมื่อเราดึงข้อมูล ตัวข้อมูลเหล่านั้นจะถูกเรียงลำดับโดยอัตโนมัติ&lt;br /&gt;
การเรียงลำดับสามารถกำหนดใน ColumnFamily ด้วย attribute ที่ชื่อ CompareWith ด้วยชนิดข้อมูลดังนี้&lt;br /&gt;
ByteType, UTF8Type, LexicalUUIDType, TimeUUIDType, AsciiType, LongType การเรียงลำดับจะเรียงตาม Column.name และขึ้นอยู่กับชนิดข้อข้อมูลที่เรากำหนด&lt;br /&gt;
ตัวอย่างการ Config เช่น&lt;br /&gt;
&lt;pre class="xml" name="code"&gt;&lt;columnfamily comparewith="UTF8Type" name="Authors"&gt;&lt;/columnfamily&gt;
&lt;/pre&gt;ในกรณีของ SuperColumns เราสามารถใช้ attribute ที่ชื่อ CompareSubcolumnsWith เพื่อกำหนดชนิดข้อมูลเพื่อเรียงลำดับใน Column ที่อยู่ใน SuperColumn ได้&lt;br /&gt;
ตัวอย่างการ Config เช่น &lt;br /&gt;
&lt;pre class="xml" name="code"&gt;&lt;columnfamily columntype="Super" comparesubcolumnswith="UTF8Type" comparewith="UTF8Type" name="Posts"&gt;
&lt;/columnfamily&gt;
&lt;/pre&gt;ตัวอย่าง Column ถ้าเรามีข้อมูลตามนี้&lt;br /&gt;
&lt;pre class="java" name="code"&gt;{name: 123, value: "hello there"},
{name: 832416, value: "kjjkbcjkcbbd"},
{name: 3, value: "101010101010"},
{name: 976, value: "kjjkbcjkcbbd"}
&lt;/pre&gt;แล้วกำหนด CompareWith เป็นชนิดข้อมูล LongType ข้อมูลใน ColumnFamily จะถูกเรียงดังนี้&lt;br /&gt;
&lt;pre class="java" name="code"&gt;{name: 3, value: "101010101010"},
{name: 123, value: "hello there"},
{name: 976, value: "kjjkbcjkcbbd"},
{name: 832416, value: "kjjkbcjkcbbd"}
&lt;/pre&gt;แต่ถ้ากำหนด CompareWith เป็นชนิดข้อมูล UTF8Type ข้อมูลใน ColumnFamily จะถูกเรียงดังนี้&lt;br /&gt;
&lt;pre class="java" name="code"&gt;{name: 123, value: "hello there"},
{name: 3, value: "101010101010"},
{name: 832416, value: "kjjkbcjkcbbd"},
{name: 976, value: "kjjkbcjkcbbd"}
&lt;/pre&gt;ตัวอย่าง SuperColumn ถ้าเรามีข้อมูลดังนี้&lt;br /&gt;
&lt;pre class="java" name="code"&gt;{
 name: "workAddress",  value: {   street: {name: "street", value: "1234 x street"},   city: {name: "city", value: "san francisco"},   zip: {name: "zip", value: "94107"}         } ,  {
name: "homeAddress",
 value: {   street: {name: "street", value: "1234 x street"},   city: {name: "city", value: "san francisco"},   zip: {name: "zip", value: "94107"}  } }
&lt;/pre&gt;แล้วกำหนด CompareSubcolumnsWith &amp;amp; CompareWith เป็น UTF8Type จะได้ผลลัพธ์ดังนี้&lt;br /&gt;
&lt;pre class="java" name="code"&gt;{
 name: "homeAddress",  value: {   city: {name: "city", value: "san francisco"},  
street: {name: "street", value: "1234 x street"},
 zip: {name: "zip", value: "94107"}
}
,  {
name: "workAddress",
 value: {   city: {name: "city", value: "san francisco"},  
street: {name: "street", value: "1234 x street"},
 zip: {name: "zip", value: "94107"} }
}
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1638080862489455885-6946409808467126601?l=phamonyut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Phamonyut/~4/yJCo-YPPv8c" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://phamonyut.blogspot.com/feeds/6946409808467126601/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://phamonyut.blogspot.com/2010/09/cassandra-sorting.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/6946409808467126601?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/6946409808467126601?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Phamonyut/~3/yJCo-YPPv8c/cassandra-sorting.html" title="Cassandra Sorting" /><author><name>Phamon P</name><uri>https://profiles.google.com/105136402217293967127</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh3.googleusercontent.com/-2AzJSisfnE0/AAAAAAAAAAI/AAAAAAAAAtA/koK-fzCuwVc/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://phamonyut.blogspot.com/2010/09/cassandra-sorting.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkcESHg4eCp7ImA9Wx5XF0k.&quot;"><id>tag:blogger.com,1999:blog-1638080862489455885.post-1317754352515808085</id><published>2010-09-17T09:47:00.009+07:00</published><updated>2010-09-18T00:20:09.630+07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-09-18T00:20:09.630+07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Cassandra" /><category scheme="http://www.blogger.com/atom/ns#" term="NOSQL" /><title>Cassandra Data Model #2</title><content type="html">ถัดจากตอนแรก &lt;a href="http://phamonyut.blogspot.com/2010/09/cassandra-data-model-1.html"&gt;Cassandra Data Model #1&lt;/a&gt; มาว่ากันต่อเรื่อง Data model&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;ColumnFamilies&lt;/b&gt;&lt;br /&gt;
เราสามารถจัดกลุ่มของ Column ได้ผ่าน ColumnFamily เพื่อให้มองภาพง่ายขึ้นตัวโดยโครงสร้างข้อมูลของ ColumnFamily จะเหมือนกับ table (ใช่แล้วผมหมายถึง table ใน RDBMS หนะแหละครับ) ซึ่งแต่ละ table ก็จะประกอบด้วยกี่ Row ก็ได้ และแต่ละ Row ก็จะเก็บ Column เท่าไหร่ก็ได้ &lt;br /&gt;
ความยืดหยุ่นในโครงสร้างมันอยู่ตรงนี้ ให้สังเกตุว่าแต่ละ Row เราจะเก็บกี่ Column ก็ได้เท่ากับว่าเราไม่ต้องมีการกำหนดตายตัวว่าแต่ละ Row จะมีได้แค่เท่านั้นเท่านี้ Column จุดนี้เองจึงทำให้ Cassandra ได้คุณสมบัติ Schemaless&lt;br /&gt;
การเก็บข้อมูลของ Cassandra ตอนเก็บจะมีการเรียงลำดับข้อมูลทุกครั้งก่อนเก็บ ซึ่งการเรียงลำดับจะเรียงตาม key ของแต่ละ row&lt;br /&gt;
การสร้าง ColumnFamily เรากำหนดได้ในไฟล์ storage-conf.xml แต่ในกรณีที่เราต้องการเปลี่ยนแปลง (เพิ่ม, แก้ไข, ลบ) ColumnFamily จำเป็นที่จะต้อง Restart Cassandra process ก่อนนะครับ ถึงจะเห็นผล&lt;br /&gt;
ตัวอย่างการสร้าง ColumnFamily&lt;br /&gt;
&lt;pre class="xml" name="code"&gt;&amp;lt;keyspaces&amp;gt;
&amp;lt;keyspace Name="Posts"&amp;gt;  
&amp;lt;columnfamily CompareWith="UTF8Type" Name="Tags"&amp;gt;&amp;lt;/ColumnFamily&amp;gt;  
&amp;lt;columnfamily CompareWith="BytesType" Name="Authors"&amp;gt;&amp;lt;/ColumnFamily&amp;gt; 
&amp;lt;/Keyspace&amp;gt;
&amp;lt;/Keyspaces&amp;gt;
&lt;/pre&gt;เราสร้าง ColumnFamily ชื่อ Tags, Authors และกำหนดชนิดข้อมูลที่ใช้เป็น UTF8Type, ByteType ตามลำดับ&lt;br /&gt;
&lt;br /&gt;
ตัวอย่างโครงสร้างข้อมูลถ้ามองภาพในโลก Java&lt;br /&gt;
&lt;pre class="java" name="code"&gt;public class ColumnFamily{
 Byte[] name;
 Map&lt;Byte[], Column&gt; value;
}
ColumnFamily cf = new ColumnFamily();
cf.name = "AddressBook";
Map&lt;Byte[], Column&gt; row = new HashMap&lt;Byte[], Column&gt;();
row.put("firstname", new Column("firstname", "Maomao"));
row.put("familyname", new Column("familyname", "Mathies"));
row.put("city", new Column("city", "Leiden"));
cf.put("person1", row);

Map&lt;Byte[], Column&gt; row = new HashMap&lt;Byte[], Column&gt;();
row.put("firstname", new Column("firstname", "Maomao"));
row.put("familyname", new Column("familyname", "Chen"));
row.put("city", new Column("city", "Leiden"));
cf.put("person2", row);
&lt;/pre&gt;ตัวอย่างถ้ามองภาพในโลก JSON&lt;br /&gt;
&lt;pre class="java" name="code"&gt;UserProfile = {
 name: “phamonyut”, 
 value: {
  username: {name: “username”, value: “tofu”, timestamp: 123456789},
  blog: {name: “blog”, value: “http://phamonyut.blogspot.com”, timestamp: 123456789},
  gender: {name: “gender ”, value: “male”, timestamp: 123456789}
 },
 name: “plaumkamon”,
 value: {
  username: {name: “username”, value: “plaumkamon”, timestamp: 123456789},
  blog: {name: “blog”, value: “http://plaumkamon.blogspot.com”, timestamp: 123456789},
  gender: {name: “gender ”, value: “undecided”, timestamp: 123456789},
  age: {name: “age”, value: “25”, timestamp: 123456789},
  email: {name: “email”, value: “plaumkamon@example.com”, timestamp: 123456789}
 }
}
&lt;/pre&gt;ด้วยความที่มัน Schemaless ค่าที่เก็บในแต่ละ row จึงแตกต่างกันได้ สังเกตุว่า row ที่สองจะมีเพิ่ม Column age และ name&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Keyspace&lt;/b&gt;&lt;br /&gt;
ข้ามมาพูดถึง Keyspace ก่อนเข้าไปที่ SuperColumnFamily ตัว Keyspace เพื่อให้มองภาพง่ายขึ้นเปรียบได้กับ Database ใน RDBMS ซึ่งเป็น “มิติ” แรกของ Cassandra hash ที่เราใช้เวลาดึงข้อมูล (คำว่ามิติแรก ก็จะเทียบได้กับ syntax get[keyspace][columnFamily][...]) โดยภายในจะประกอบด้วย ColumnFamily (ซึ่งเปรียบได้กับ Table ใน RDBMS) ก็เท่ากับเรามีทั้ง Database และ table ที่ใช้เก็บข้อมูลแล้ว ซึ่งแต่ละ application ก็จะมีแค่หนึ่ง keyspace &lt;br /&gt;
แต่อย่างลืมว่า ColumnFamily ไม่ใช่ table จริงๆ และมันไม่มี Join จึงอย่าคาดหวังว่า key ของ row นึงจะต้องมีอยู่ในอีก ColumnFamily นึงด้วย&lt;br /&gt;
เราจะ config Keyspace ในไฟล์ storage-conf.xml &lt;br /&gt;
&lt;pre class="xml" name="code"&gt;&amp;lt;keyspaces&amp;gt;
&amp;lt;keyspace name="Blogs"&amp;gt; 
... 
&amp;lt;/Keyspace&amp;gt;
&amp;lt;/Keyspaces&amp;gt;
&lt;/pre&gt;&lt;b&gt;SuperColumnFamily&lt;/b&gt;&lt;br /&gt;
โครงสร้างจะเหมือนกับ ColumnFamily แตกต่างตรงที่ ในแต่ละ row จะเก็บ SuperColumn ตัว map คือ key ที่เป็น  name ของแต่ละ SuperColumn และ value คือตัว SuperColumn มัีนเอง&lt;br /&gt;
ตัวอย่างในมุมมองของ JSON&lt;br /&gt;
&lt;pre class="java" name="code"&gt;Posts= {
 name: "Cassandra-data-model", 
 value: {
 name: "Post"
 value: {
  "title": {name: "title", value: "Cassandra data model", timestamp: 123456789},
  "body": {name: "body", value: "Blah Blah ...", timestamp: 123456789},
  "author": {name: "author", value: "Phamonyut", timestamp: 123456789},
 }, 
 name: "Tag"
 value {
  "0": {name: "0", value: "cassandra", timestamp: 123456789},
  "1": {name: "1", value: "nosql", timestamp: 123456789},
 }
 }, 
 name: "Android-programming",
 value: {
 name: "Post"
 value: {
  "title": {name: "title", value: "Android Programming", timestamp: 123456789},
  "body": {name: "body", value: "Blah Blah ...", timestamp: 123456789},
  "author": {name: "author", value: "Plaumkamon", timestamp: 123456789},
  "createdate": {name: "createdate", value: "07/07/2007", timestamp: 123456789}
 }, 
 name: "Tag"
 value {
  "0": {name: "0", value: "Android", timestamp: 123456789},
  "1": {name: "1", value: "Tutorial", timestamp: 123456789},
 }
 }
}
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1638080862489455885-1317754352515808085?l=phamonyut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Phamonyut/~4/c6KVvdLCNjI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://phamonyut.blogspot.com/feeds/1317754352515808085/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://phamonyut.blogspot.com/2010/09/cassandra-data-model-2.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/1317754352515808085?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/1317754352515808085?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Phamonyut/~3/c6KVvdLCNjI/cassandra-data-model-2.html" title="Cassandra Data Model #2" /><author><name>Phamon P</name><uri>https://profiles.google.com/105136402217293967127</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh3.googleusercontent.com/-2AzJSisfnE0/AAAAAAAAAAI/AAAAAAAAAtA/koK-fzCuwVc/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://phamonyut.blogspot.com/2010/09/cassandra-data-model-2.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEMNQ3w_fCp7ImA9Wx5XFkg.&quot;"><id>tag:blogger.com,1999:blog-1638080862489455885.post-5406612467253166003</id><published>2010-09-17T00:01:00.000+07:00</published><updated>2010-09-17T00:01:32.244+07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-09-17T00:01:32.244+07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Cassandra" /><category scheme="http://www.blogger.com/atom/ns#" term="NOSQL" /><title>Cassandra Data Model #1</title><content type="html">[Column | SuperColumn] &gt;- [ColumnFamily | SuperColumnFamily]  &gt;- Keyspace/Application &gt;- Cluster &lt;br /&gt;
&lt;br /&gt;
โครงสร้างข้อมูลของ Cassandra แบ่งออกเป็นสองประเภทหลักๆ ได้แก่ Column และ SuperColumn ซึ่งสองชนิดนี้สามารถจัดกลุ่มรวมกันได้โดยใช้อีกสองประเภทคือ ColumnFamily และ SuperColumnFamily&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Schema&lt;/b&gt;&lt;br /&gt;
Cassandra จะเป็นลักษณะของไม่มี schema (schema-less) จะเห็นภาพชัดขึ้นเมื่อพูดถึง Column Family&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Cluster&lt;/b&gt;&lt;br /&gt;
หนึ่ง Clusters สามารถเก็บได้หลาย keyspace &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Columns&lt;/b&gt;&lt;br /&gt;
โครงสร้างข้อมูลจะประกอบด้วยสามส่วนได้แก่ name, value และ timestamp &lt;br /&gt;
&lt;pre class="java" name="code"&gt;public class Column {
 Byte[] name;
 Byte[] value;
 Long timestamp;
}
&lt;/pre&gt;ถ้ามองเป็นโครงสร้างแบบ JSON จะได้รูปแบบดังนี้&lt;br /&gt;
&lt;pre class="java" name="code"&gt;{
 "name": "emailAddress"
 "value": "foo@bar.com"
 "timestamp": 123456789
}
&lt;/pre&gt;ค่า name และ value จะเก็บเป็น binary ถึงแม้ว่า application จะใ้ช้ UTF8 ก็ตาม และสังเกตุว่ามีการเก็บค่า timestamp ด้วย ซึ่งมันถูกใช้เพื่อแก้ปัญหาความขัดแย้งกันของข้อมูล โดยจะเกิดเมื่อเรามีข้อมูลเดียวกันสองชุด ค่านี้จะบอกเราว่าข้อมูลชุดใดเป็นเวอร์ชั่นใหม่สุด และข้อมูลเก่าจะถูกแทนที่ด้วยข้อมูลที่ใหม่กว่า&lt;br /&gt;
บางครั้งเวลาเราพูดถึง column มักจะตัด timestamp และมองภาพแค่การจับคู่กันของ name กับ value&lt;br /&gt;
ดังนั้นในเอกสารนี้ส่วนของ timestamp จะถูกตัดออกเพื่อให้อ่านง่ายขึ้น&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;SuperColumns&lt;/b&gt;&lt;br /&gt;
โครงสร้างข้อมูลของ SuperColumn จะเก็บ name และ value โดย value จะเก็บ map ของ key/Column โดย key จะมีค่าเหมือนกับชื่อของ column ที่มันเก็บอยู่ (มองง่ายๆ SuperColumn จะเก็บ Column อีกที ซึ่งมีมากกว่าหนึ่งก็ได้)&lt;br /&gt;
สิ่งที่แตกต่างระหว่าง Column และ SuperColumn คือ Column.value เก็บชนิดข้อมูลเป็น String แต่ SuperColumn.value เก็บชนิดข้อมูลเป็น map ของ column และ SuperColumn ไม่เก็บ timestamp ซึ่งค่านี้จะเก็บอยู่ใน Column เท่านั้น&lt;br /&gt;
ถ้ามองในมุม Java เราจะเขียนโครงสร้างได้หน้าตาดังนี้ ซึ่งดูแล้วง่ายกว่ามองจากรูปมาก&lt;br /&gt;
&lt;pre class="java" name="code"&gt;public class SuperColumn {
 Byte[] name;
 Map&lt;Byte[] /*key*/, Column&gt; value;
}
SuperColumn sc = new SuperColumn();
sc.name = “person1”;
sc.value.put(“firstname”, new Column(“firstname”, “Ronald”));
sc.value.put(“lastname”, new Column(“familyname”, “Mathies”));
&lt;/pre&gt;ถ้ามองเป็นโครงสร้าง JSON จะได้ดังรูปนี้&lt;br /&gt;
&lt;pre class="java" name="code"&gt;{
 name: “Post”
 value: {
  “title”: {name: “title”, value: “Cassandra data model”, timestamp: 123456789},
  “body”: {name: “body”, value: “Blah Blah ...”, timestamp: 123456789},
  “author”: {name: “author”, value: “Phamonyut”, timestamp: 123456789},
 }, 
 name: “Tag”
 value {
  “0”: {name: “0”, value: “cassandra”, timestamp: 123456789},
  “1”: {name: “1”, value: “nosql”, timestamp: 123456789},
 }
}
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1638080862489455885-5406612467253166003?l=phamonyut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Phamonyut/~4/F5YDye7hREs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://phamonyut.blogspot.com/feeds/5406612467253166003/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://phamonyut.blogspot.com/2010/09/cassandra-data-model-1.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/5406612467253166003?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/5406612467253166003?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Phamonyut/~3/F5YDye7hREs/cassandra-data-model-1.html" title="Cassandra Data Model #1" /><author><name>Phamon P</name><uri>https://profiles.google.com/105136402217293967127</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh3.googleusercontent.com/-2AzJSisfnE0/AAAAAAAAAAI/AAAAAAAAAtA/koK-fzCuwVc/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://phamonyut.blogspot.com/2010/09/cassandra-data-model-1.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUcBRng6fyp7ImA9Wx5WGEg.&quot;"><id>tag:blogger.com,1999:blog-1638080862489455885.post-3491037393222987553</id><published>2010-07-18T14:18:00.001+07:00</published><updated>2010-09-30T21:30:57.617+07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-09-30T21:30:57.617+07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Testing" /><title>10 rules when you need to testing software</title><content type="html">ช่วงนี้ต้องทดสอบอย่างหนัก เพื่อให้มั่นใจว่าเราจะทดสอบอย่างถูกต้อง จึงต้องยึดมั่นกับแนวคิดการทดสอบสิบข้อนี้&lt;ol&gt;&lt;li&gt;การออกแบบตัว test case เราต้องรู้ว่าจะใส่ input อะไร และผลลัพธ์ที่ออกมาควรจะเป็นอย่าไร&lt;/li&gt;
&lt;li&gt;นักพัฒนาโปรแกรมไม่ควรจะทำการทดสอบโค้ดที่ตัวเองเป็นคนเขียน (การทดสอบโปรแกรมนี้ ไม่ใช่การ debug ซึ่งถ้าเป็นการ debug นักพัฒนาโปรแกรมจะต้องเป็นคนทำเอง) เพื่อหลีกเลี่ยงเข้าข้างโค้ดตัวเอง&lt;/li&gt;
&lt;li&gt;อย่าให้บริษัทที่พัฒนาโปรแกรมมาทดสอบโปรแกรมเอง&lt;/li&gt;
&lt;li&gt;ทุกครั้งที่ทำการทดสอบ ผลลัพธ์ที่ออกมาจะต้องตรวจสอบอย่างละเอียดรอบคอบ&lt;/li&gt;
&lt;li&gt;Test case ต้องเขียนให้ครอบคลุมทั้งกรณีที่ถูกต้อง และกรณีที่ผิด โดยจำลองได้จากการนำข้อมูลที่ผิดใส่ลงไปใน Test case แล้วดูผลลัพธ์ว่ามันผิดอย่างที่เราตั้งไว้หรือไม่&lt;/li&gt;
&lt;li&gt;พยายามนึกความหมายของ bugs ในทุกครั้งที่ทำการทดสอบ&lt;/li&gt;
&lt;li&gt;พยายามเขียน Test case เผื่อให้อนาคตสามารถนำกลับมาใช้ใหม่ได้&lt;/li&gt;
&lt;li&gt;ต้องวางแผนทดสอบภายใต้การหาข้อผิดพลาด โดยคิดที่อยากจะหาข้อผิดพลาดอยู่เสมอ เพราะเราไม่ได้ทดสอบโปรแกรมที่ทำงานถูกต้อง&lt;/li&gt;
&lt;li&gt;การทดสอบเป็นงานที่ต้องอาศัยความคิดสร้างสรรค์ และใช้ความคิดอย่ามาก&lt;/li&gt;
&lt;li&gt;ความน่าจะเป็นของการเกิดข้อผิดพลาด มักจะแปลผันตรงกับจำนวนข้อผิดพลาดที่พบก่อนหน้านั้นแล้ว คือเมื่อมีการเจอข้อผิดพลาด ณ จุดใดมักจะเพิ่มขึ้นมาเรื่อยๆ ณ จุดนั้น&lt;/li&gt;
&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1638080862489455885-3491037393222987553?l=phamonyut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Phamonyut/~4/XH_oLOUTQrw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://phamonyut.blogspot.com/feeds/3491037393222987553/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://phamonyut.blogspot.com/2010/07/10-rules-when-you-need-to-testing.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/3491037393222987553?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/3491037393222987553?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Phamonyut/~3/XH_oLOUTQrw/10-rules-when-you-need-to-testing.html" title="10 rules when you need to testing software" /><author><name>Phamon P</name><uri>https://profiles.google.com/105136402217293967127</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh3.googleusercontent.com/-2AzJSisfnE0/AAAAAAAAAAI/AAAAAAAAAtA/koK-fzCuwVc/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://phamonyut.blogspot.com/2010/07/10-rules-when-you-need-to-testing.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUUAR3c7fCp7ImA9WxFQGEg.&quot;"><id>tag:blogger.com,1999:blog-1638080862489455885.post-3413841214355062508</id><published>2010-05-14T23:56:00.003+07:00</published><updated>2010-05-15T00:14:06.904+07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-05-15T00:14:06.904+07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><category scheme="http://www.blogger.com/atom/ns#" term="Oracle" /><title>Security-driven design #2 - SQL Injection</title><content type="html">ผมเขียนตอนแรก &lt;a href="http://blog.oracle.in.th/2010/05/security-driven-design-1-xss.html"&gt;ไว้ที่&lt;/a&gt; เป็นเรื่องเกี่ยวกับการโจมตีจุดอ่อน XSS&lt;br /&gt;
บทความในตอนนี้เป็นตอนต่อเนื่องที่พูดเกี่ยวกับจุดอ่อนที่เรามักพบกันได้บ่อย นั่นคือ SQL Injection โดยเป็นการโจมตีโดยการฉีค SQL query ผ่านช่องทางต่างๆ ที่ให้เราส่ง input จาก client ไปหาตัวระบบได้ เมื่อทำสำเร็จแล้วผู้โจมตีจะสามารถเข้าถึงข้อมูลเพื่อทำ CRUD ที่อยู่ในฐานข้อมูลได้ โดยไม่ต้องผ่านการตรวจสอบสิทธิของ application นั้นๆ&lt;br /&gt;
ผลกระทบของ SQL Injection ขึ้นอยู่กับปัจจัยเหล่านี้&lt;ul&gt;&lt;li&gt;จุดที่ฉีคเข้ามา query&lt;/li&gt;
&lt;li&gt;สิทธิของ user ที่ execute query นั้น&lt;/li&gt;
&lt;li&gt;database platform และ version&lt;/li&gt;
&lt;li&gt;database configuration&lt;/li&gt;
&lt;/ul&gt;ยกตัวอย่าง SQL Injection ที่เกิดขึ้นเมื่อนักพัฒนาสร้าง dynamic query โดยนำมารวมกับ input ที่ผู้ใข้ส่งเข้ามาโดยไม่ผ่านวิธีการที่เหมาะสม&lt;br /&gt;
&lt;pre class="java" name="code"&gt;String query = “Select * from Users Where username = ‘“ + request.getParameter(”username”) + “‘ and password = ‘“ + request.getParameter(”password”) + “‘“;
  try {
    Statement statement = connection.createStatement( … );
    ResultSet results = statement.executeQuery( query );
  }
&lt;/pre&gt;แล้วถ้าใช้ url ลักษณะนี้&lt;br /&gt;
http://www.yoursite.com/login?username=tofu’%20or%20‘1’%20=%20’1&amp;password=1’%20or%20’1’%20=%20’1&lt;br /&gt;
เท่ากับเราจะได้ query ที่ค่าจะออกมาเป็น true และ query ผลลัพธ์ออกมาได้&lt;br /&gt;
&lt;pre class="java" name="code"&gt;Select * from Users Where username = ‘tofu’ or ‘1’=’1’ and password=’1’ or ‘1’=’1’ 
&lt;/pre&gt;นอกจากนี้ยังมี query อีกสารพัดแบบที่ถูกฉีคเข้ามาทดสอบความอ่อนแอของ application เราหาได้ใน google&lt;br /&gt;
&lt;br /&gt;
แนวทางป้องกันหลัก&lt;ul&gt;&lt;li&gt;Parameterized query&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;ใช้ Prepared Statement / HQL / ...&lt;/li&gt;
&lt;li&gt;ใช้ Stored Procedures&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Character escaping&lt;/li&gt;
&lt;li&gt;User-input Handling ได้กล่าวไปในบท &lt;a href="http://blog.oracle.in.th/2010/05/security-driven-design-1-xss.html"&gt;ก่อนหน้านี้&lt;/a&gt; และดูเพิ่มเติมได้จาก &lt;a href="http://www.owasp.org/index.php/OWASP_Validation_Regex_Repository"&gt;นี้&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;ซ่อน error message ที่มาจาก database server เนื่องจากการทำ SQL injection จะเกิด error message ที่ return ออกมาจาก &lt;/li&gt;
&lt;li&gt;database server ได้ซึ่ง message ดังกล่าวมันช่วยให้ผู้ไม่ประสงค์ดีนำไปวิเคราะห์ และนำกลับมาโจมตีเราใหม่&lt;/li&gt;
&lt;li&gt;ใช้ user ที่มีสิทธิ์เท่าที่จำเป็นต่อการ execute query นั้นเท่านั้น ไม่ควรใช้ sa, dba หรือ admin&lt;/li&gt;
&lt;/ul&gt;ตัวอย่างการใช้ Prepared Statement เพื่อส่งผ่าน parameter &lt;pre class="java" name="code"&gt;String query = “Select * from Users Where username = ? and password = ?”;
  try {
    PrepareStatement pstmt = conn.prepareStatement(query);
    pstmt.setString(1, username);
    pstmt.setString(2, password);
    ResultSet results = pstmt.executeQuery(query);
  }
&lt;/pre&gt;ใน query language ของ framework ต่างๆ ก็มี parameter statment ให้ใช้ เช่น Hibernate Query Language (HQL) &lt;pre class="java" name="code"&gt;Query query = session.createQuery(”from Users where username =:username and password =:password”;
  query.setParameter(”username”, username);
  query.setParameter(”password”, password);
&lt;/pre&gt;ตัวอย่างการใช้ Stored Procedure เพื่อส่งผ่าน parameterized query  &lt;pre class="java" name="code"&gt;String username = request.getParameter(”username”);
  String password = request.getParameter(”password”);
  try {
   CallableStatement cs = conn.prepareCall(”{call getUsers(?, ?)}”);
   cs.setString(1, username);
   cs.setString(2, password);
   ResultSet results = cs.executeQuery();
  } 
&lt;/pre&gt;เทคนิค Escape  อีกทางเลือกหนึ่งกรณีที่เราไม่ใช้ Parameterized query และส่งผลต่อ &lt;a href="http://phamonyut.blogspot.com/2010/05/improve-performance-in-jdbc.html"&gt;ประสิทธิภาพ&lt;/a&gt; ถ้าใช้งานอย่างไม่เหมาะสม เพื่อสร้าง dynamic query ลองเลือกเทคนิค Escape (เช่นเดียวกับ Java ที่มี character escaping) แต่อย่างไรก็ตามเทคนิคนี้ค่อนข้างเปราะบางกว่าเมื่อเทียบกับ parameterized query อ่านรายละเอียด character escaping ของ DBMS แต่ละเจ้าได้ดังนี้&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.orafaq.com/wiki/SQL_FAQ#How_does_one_escape_special_characters_when_writing_SQL_queries.3F"&gt;Oracle&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://mirror.yandex.ru/mirrors/ftp.mysql.com/doc/refman/5.0/en/string-syntax.html"&gt;MySql&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blogs.msdn.com/raulga/archive/2007/01/04/dynamic-sql-sql-injection.aspx"&gt;SQL Server&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;ศึกษาตัวอย่าง escape ได้จากโค้ด &lt;a href="http://code.google.com/p/owasp-esapi-java/source/browse/trunk/src/main/java/org/owasp/esapi/codecs/OracleCodec.java"&gt;OracleCodec&lt;/a&gt; class ของ &lt;a href="http://code.google.com/p/owasp-esapi-java/"&gt;owasp-esapi&lt;/a&gt; &lt;pre class="java" name="code"&gt;//encode ' to '' 
  public String encodeCharacter( char[] immune, Character c ) { 
    if ( c.charValue() == '\'' ) 
      return "\'\'";
    return ""+c; 
  } 
&lt;/pre&gt;Note: การเลือกใช้ &lt;a href="http://phamonyut.blogspot.com/2010/05/improve-performance-in-jdbc.html"&gt;PreparedStatement หรือ Statement และการเพิ่มประสิทธิภาพการทำงาน&lt;/a&gt;  

เพิ่มเติม: 
&lt;a href="http://www.owasp.org/index.php/Reviewing_Code_for_SQL_Injection"&gt;Review Code for SQL Injection&lt;/a&gt; 
&lt;a href="http://www.owasp.org/index.php/Testing_for_SQL_Injection_(OWASP-DV-005)"&gt;Test for SQL Injection&lt;/a&gt; 

Reference: &lt;a href="http://www.owasp.org/index.php/SQL_injection"&gt;SQL injection&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1638080862489455885-3413841214355062508?l=phamonyut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Phamonyut/~4/yE9ymgIIjr0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://phamonyut.blogspot.com/feeds/3413841214355062508/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://phamonyut.blogspot.com/2010/05/security-driven-design-2-sql-injection.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/3413841214355062508?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/3413841214355062508?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Phamonyut/~3/yE9ymgIIjr0/security-driven-design-2-sql-injection.html" title="Security-driven design #2 - SQL Injection" /><author><name>Phamon P</name><uri>https://profiles.google.com/105136402217293967127</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh3.googleusercontent.com/-2AzJSisfnE0/AAAAAAAAAAI/AAAAAAAAAtA/koK-fzCuwVc/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://phamonyut.blogspot.com/2010/05/security-driven-design-2-sql-injection.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkMCRHY_eip7ImA9WxFQFUw.&quot;"><id>tag:blogger.com,1999:blog-1638080862489455885.post-4761214537556128565</id><published>2010-05-10T23:39:00.004+07:00</published><updated>2010-05-10T23:54:25.842+07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-05-10T23:54:25.842+07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><category scheme="http://www.blogger.com/atom/ns#" term="Oracle" /><title>Improve performance in JDBC</title><content type="html">&lt;div style="background-color: transparent; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span id="internal-source-marker_0.44326200778596103" style="background-color: transparent; color: black; font-family: Arial; font-size: 10pt; font-style: normal; font-weight: bold; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;เลือก Driver ให้เหมาะกับงานที่กำลังทำอยู่&lt;/span&gt;&lt;br /&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 10pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;JDBC สร้าง driver ออกมาสี่ประเภทขึ้นอยู่กับความต้องการที่เราจะต้องเลือกไปใช้&lt;/span&gt;&lt;ul&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 10pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 10pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;JDBC-ODBC ใช้เมื่อไม่มี driver ที่สร้างสำหรับภาษา Java แต่มีรองรับ ODBC แต่การเชื่อมต่อด้วยแบบนี้จะช้ากว่าประเภทอื่นๆ เพราะต้องเรียกผ่าน ODBC อีกทีหนึ่ง&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 10pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 10pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Native API ใช้เมื่อมี driver ที่สร้างสำหรับ Java เพื่อไม่ต้องผ่าน ODBC เหมือนกับแบบ JDBC-ODBC ดังนั้นประสิทธิภาพจึงดีกว่าประเภทที่ 1 แต่ประสิทธิภาพจะปานกลาง เมื่อเทียบกับแบบที่ JDBC-Net&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 10pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 10pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;JDBC - Net ใช้เมื่อติดต่อผ่าน proxy server เช่นพวก application server ทั้งหลาย (websphere, weblogic, ...) ประเภทนี้ง่ายต่อการ optimization เช่น connection pooling, caching, loga balancing และอื่นๆ&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div style="background-color: transparent; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;br /&gt;&lt;span id="internal-source-marker_0.44326200778596103" style="background-color: transparent; color: black; font-family: Arial; font-size: 10pt; font-style: normal; font-weight: bold; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;เลือกที่จะควบคุม transaction เอง&lt;/span&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 10pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 10pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;java.sql.Connection interface เตรียม method เพื่อจัดการกับ transaction ดังนี้&lt;/span&gt;&lt;ul&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 10pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 10pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;boolean getAutoCommit();&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 10pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 10pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;void setAutoCommit(boolean autocommit);&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 10pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 10pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;void commit();&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 10pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 10pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;void rollback();&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 10pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;ด้วย default JDBC transaction จะ commit ให้เองเมื่อแต่ละ statement ถูก execute นั่นคือ AutoCommit mode เป็น true โดยเราไม่จำเป็นต้องเรียก commit() method เอง มันง่ายต่อนักพัฒนา ถ้าเราต้องการ execute แค่หนึ่ง statement แต่จะให้ประสิทธิภาพที่ไม่ค่อยดีเมื่อมีหลาย statement ที่ต้อง execute เพราะว่ามันจะ commit หลังจากที่ statement แรกทำงานจบโดย default จึงควรตั้ง AutoCommit mode เป็น false และเรียก commit() method หลังจากเรียกกลุ่มของ statement execute เอง และใช้ rollback() method ใน catch block เมื่อไหร่ก็ตามที่เกิด exception ขึ้นในโปรแกรม&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial; font-size: 13px; white-space: pre-wrap;"&gt;ตัวอย่าง&lt;/span&gt;&amp;nbsp;&lt;/div&gt;&lt;pre class="java" name="code"&gt;try{&lt;br /&gt;    connection.setAutoCommit(false);&lt;br /&gt;    PreparedStatement ps = connection.preareStatement( "UPDATE employee SET Address=? WHERE name=?");&lt;br /&gt;    ps.setString(1,"Austin");&lt;br /&gt;    ps.setString(2,"RR");&lt;br /&gt;    ps.executeUpdate();&lt;br /&gt;    PreparedStatement ps1 = connection.prepareStatement( "UPDATE account SET salary=? WHERE name=?");&lt;br /&gt;    ps1.setDouble(1, 5000.00);&lt;br /&gt;    ps1.setString(2,"RR");&lt;br /&gt;    ps1.executeUpdate();&lt;br /&gt;    connection.commit();&lt;br /&gt;    connection.setAutoCommit(true);&lt;br /&gt;    }catch(SQLException e){ connection.rollback();}&lt;br /&gt;    finally{&lt;br /&gt;             if(ps != null){ ps.close();}&lt;br /&gt;             if(ps1 != null){ps1.close();}&lt;br /&gt;   if(connection != null){connection.close();}&lt;br /&gt;}&lt;/pre&gt;&lt;div style="background-color: transparent; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;pre style="white-space: pre-wrap; word-wrap: break-word;"&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="background-color: transparent; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-color: transparent; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;div style="background-color: transparent; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span id="internal-source-marker_0.44326200778596103" style="background-color: transparent; color: black; font-family: Arial; font-size: 10pt; font-style: normal; font-weight: bold; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Statement vs PreparedStatement&lt;/span&gt;&lt;br /&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 10pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;เรามักเข้าใจผิดว่า PreparedStatement จะให้ประสิทธิภาพที่ดีกว่าเมื่อหยิบมาใช้งาน ความจริงแล้วใช่ว่าจะเป็นเช่นนั้น เมื่อเราใช้ PreparedStatement object เพื่อ execute SQL Statement มันจะถูก compile และเก็บไว้ใน cache และเมื่อเราเรียกใช้อีกมันจะไม่ถูก compile เป็นครั้งที่สอง เพราะมันจะถูกพบใน cache และนำกลับมาใช้ใหม่ ซึ่งเป็นการเพิ่มประสิทธิภาพการทำงานเพราะลดเวลา compile&lt;/span&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 10pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;แต่เมื่อเราใช้ Statement ทุกครั้งที่เราจะ execute SQL Statement มันจะถูก compile ใหม่ทุกครั้ง&lt;/span&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 10pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;ถ้าดูตามเหตุผลด้านบนนี้ PreparedStatement เหมาะสมกับการถูกนำมาใช้อย่างยิ่ง แต่ &lt;/span&gt;&lt;a href="http://oreilly.com/catalog/jorajdbc/chapter/ch19.html"&gt;&lt;span style="background-color: transparent; color: #000099; font-family: Arial; font-size: 10pt; font-style: normal; font-weight: normal; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;"&gt;ความจริง&lt;/span&gt;&lt;/a&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 10pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt; ไม่ได้เป็นอย่างนั้น &lt;/span&gt;&lt;br /&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 10pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;เมื่อเราเห็นผลการทดสอบดังกล่าว จะสรุปได้ว่าสำหรับ enterprise application ที่มีผู้ใช้จำนวนมากที่จะ execute SQL statement เดียวกันบ่อยๆ การลดเวลา compile ได้สามารถช่วยเพิ่ม performance ให้กับ database ได้ แต่สำหรับ client-side การใช้ PreparedStatement ใช้เวลานานกว่า Statement &lt;/span&gt;&lt;br /&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 10pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;แต่ถึงอย่างไรถ้าเรากังวลกับเรื่องของ SQL injection PreparedStatement ก็จะเป็นตัวเลือกที่สมควรหยิบไปใช้&lt;/span&gt;&lt;br /&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 10pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 10pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;นอกจากนี้ยังมีอีกหลายประเด็นทีน่าสนใจเช่นเรื่องของ batch, pre-fetch value ที่ผมยังไม่มีเวลาสรุป ลองศึกษาเพิ่มเติมได้ครับ &lt;/span&gt;&lt;br /&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 10pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 10pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Referenece: &lt;/span&gt;&lt;br /&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 10pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;a href="http://oreilly.com/catalog/jorajdbc/chapter/ch19.html"&gt;&lt;span style="background-color: transparent; color: #000099; font-family: Arial; font-size: 10pt; font-style: normal; font-weight: normal; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;"&gt;http://oreilly.com/catalog/jorajdbc/chapter/ch19.html&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1638080862489455885-4761214537556128565?l=phamonyut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Phamonyut/~4/0sreRaOMnqY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://phamonyut.blogspot.com/feeds/4761214537556128565/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://phamonyut.blogspot.com/2010/05/improve-performance-in-jdbc.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/4761214537556128565?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/4761214537556128565?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Phamonyut/~3/0sreRaOMnqY/improve-performance-in-jdbc.html" title="Improve performance in JDBC" /><author><name>Phamon P</name><uri>https://profiles.google.com/105136402217293967127</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh3.googleusercontent.com/-2AzJSisfnE0/AAAAAAAAAAI/AAAAAAAAAtA/koK-fzCuwVc/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://phamonyut.blogspot.com/2010/05/improve-performance-in-jdbc.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CU4HQX07cCp7ImA9WxFQEEk.&quot;"><id>tag:blogger.com,1999:blog-1638080862489455885.post-733423069424719301</id><published>2010-05-05T12:33:00.001+07:00</published><updated>2010-05-05T14:18:50.308+07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-05-05T14:18:50.308+07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Servlet" /><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><title>HTTPOnly cookie flag</title><content type="html">HTTPOnly เป็นวิธีหนึ่งที่ใช้ป้องกัน client side script เข้าถึง cookie โดยที่เราไม่อนุญาตเพื่อป้องกันจุดอ่อนของ web application ที่ลดความเสี่ยงเรื่องของ XSS&lt;br /&gt;&lt;br /&gt;เริ่มต้นจาก blog ของนาย Jordan Wiens, "No cookie for you!" (ตอนนี้ไปเป็น CTO ของ white hat security) แล้วถูกนำไป implement ครั้งแรกในปี 2002 ใน browser ของ microsoft internet explorer&lt;br /&gt;ถ้าพูดตามหลักแล้ว HttpOnly เป็นเพียงการเพิ่ม flag ลงใน Set-Cookie HTTP response header แต่ browser จะต้องรองรับ flag นี้ด้วยถึงจะเข้าใจความหมาย&lt;br /&gt;&lt;br /&gt;ถ้า HttpOnly flag เพิ่มลงใน Http response header, cookie จะไม่สามารถเข้าถึงได้ผ่าน client side script ผลก็คือถ้าเกิด cross-site scripting (XSS) คือผู้ใช้เผลอกด link ที่ไปเข้าหน้าที่เกิด XSS ตัว browser จะกัน client side script ไม่ให้เข้าถึง cookie ได้ แล้วจะ return เป็น empty string กลับคืนมาให้&lt;br /&gt;ถ้า browser ไม่รองรับ HttpOnly และ website ได้มีการกำหนดค่า HttpOnly ตัว client side script ก็จะสามารถเข้าถึง cookie ได้&lt;br /&gt;&lt;br /&gt;ตอนนี้มี browser ที่รองรับได้แก่&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Internet Explorer 6 sp1+ http://www.petefreitag.com/item/644.cfm&lt;/li&gt;&lt;li&gt;Firefox 2.0.0.5+ http://www.petefreitag.com/item/644.cfm&lt;/li&gt;&lt;li&gt;Opera since 9.5+ (Prevents Read) http://manicode.blogspot.com/2008/06/opera-95-httponly-read-prevention.html&lt;/li&gt;&lt;li&gt;Netscape 9.0b3+&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;ตัวอย่างการใช้งาน&lt;br /&gt;&lt;pre class="java" name="code"&gt;String sessionId= request.getSession().getId();response.setHeader("SET-COOKIE", "JSESSIONID=" + sessionId + "; HttpOnly");&lt;/pre&gt;ใน tomcat 6  เราสามารถกำหนด useHttpOnly=true ใน context.xml ได้&lt;br /&gt;&lt;br /&gt;สำหรับ servlet 3.0 รองรับ HTTPOnly เช่นกันผ่าน method&lt;br /&gt;&lt;pre class="java" name="code"&gt;void setHttpOnly(boolean isHttpOnly)boolean isHttpOnly()&lt;/pre&gt;&lt;br /&gt;Reference: &lt;br /&gt;http://msdn.microsoft.com/en-us/library/ms533046.aspx&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1638080862489455885-733423069424719301?l=phamonyut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Phamonyut/~4/j78FNL7rYmo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://phamonyut.blogspot.com/feeds/733423069424719301/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://phamonyut.blogspot.com/2010/05/cookie-httponly-flag.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/733423069424719301?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/733423069424719301?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Phamonyut/~3/j78FNL7rYmo/cookie-httponly-flag.html" title="HTTPOnly cookie flag" /><author><name>Phamon P</name><uri>https://profiles.google.com/105136402217293967127</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh3.googleusercontent.com/-2AzJSisfnE0/AAAAAAAAAAI/AAAAAAAAAtA/koK-fzCuwVc/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://phamonyut.blogspot.com/2010/05/cookie-httponly-flag.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CU4HQ30-eCp7ImA9WxBRE0g.&quot;"><id>tag:blogger.com,1999:blog-1638080862489455885.post-3955411983947680459</id><published>2009-12-26T09:26:00.021+07:00</published><updated>2010-01-01T20:52:12.350+07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-01T20:52:12.350+07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Servlet" /><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><title>Servlet 3.0: Introduction</title><content type="html">วันนี้อยู่ว่างๆ อยากลองความสามารถใหม่ของ servlet v.3 แต่ตอนนี้พบว่ายังไม่มี application server ตัวไหนรองรับ นอกจาก GlassFish v.3 เข้าใจว่าตอนนี้ application server ค่ายต่างๆ คงกำลังเร่งพัฒนาความสามารถของตัวเองอย่างเต็มที่เพื่อแย่งชิงส่วนแบ่งการใช้งานตรงจุดนี้&lt;br /&gt;ไม่รอช้าครับ ผมโหลดมาติดตั้งเรียบร้อย &lt;br /&gt;&lt;br /&gt;เปิด IDE คู่ใจขึ้นมาลองเลยครับ ถ้าใช้ Eclipse Galileo แล้วเกิดปัญหาไม่สามารถเพิ่ม application server adapter ใหม่ที่เป็น GlassFish v.3 เข้าไปได้ ให้ &lt;a href="http://blog.arungupta.me/2009/08/totd-97-glassfish-plugin-with-eclipse-3-5/"&gt;แก้ตามนี้&lt;/a&gt; ส่วน Netbean ไม่ต้องลีลาเยอะสามารถใช้งานได้เลย&lt;br /&gt;&lt;br /&gt;ในเวอร์ชั่นนี้ค่อนข้างให้ความสำคัญกับเรื่องของ annotation ที่จะนำมาเป็นทางเลือกหนึ่งในการ configuration web application ได้ค่อนข้างลงตัวทีเดียว ซึ่งในบทความนี้ผมจะละ deployment description (web.xml) ออกไปแล้วหันมาใช้ annotation แทน &lt;br /&gt;&lt;br /&gt;เริ่มกันที่ตัวแรก &lt;span style="font-weight:bold;"&gt;@WebServlet&lt;/span&gt; ใช้เพื่อลงทะเบียน Servlet เพื่อบอกกับ servlet container ว่า class นี้เป็น Servlet class เพื่อให้ servlet container จัดการกับ class ตาม servlet lifecycle ข้างในมี attribute ดังนี้&lt;ul&gt;&lt;li&gt;name&lt;/li&gt;&lt;li&gt;description&lt;/li&gt;&lt;li&gt;value&lt;/li&gt;&lt;li&gt;urlPatterns&lt;/li&gt;&lt;li&gt;initParams&lt;/li&gt;&lt;li&gt;loadOnStartup&lt;/li&gt;&lt;li&gt;asyncSupported&lt;/li&gt;&lt;li&gt;smalIcon&lt;/li&gt;&lt;li&gt;largeIcon&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;ซึ่งความหมายทุกตัวค่อนข้างชัดเจนอยู่แล้ว ถ้าใครเคยเขียน Servlet v.2 มาก่อนมั่นใจว่าเข้าใจได้โดยไม่ต้องอธิบาย ยกเว้นจะมีแต่ asyncSupported ที่เพิ่งเพิ่มเข้ามาใน Servlet v.3 ในตัวอย่างใช้ urlPatterns เพื่อ mapping กับ url โดยมันเก็บค่าที่เป็น array จึงสามารถ mapping url ได้มากกว่า 1 &lt;pre name="code" class="java"&gt;&lt;br /&gt;@WebServlet(urlPatterns="/hello")&lt;br /&gt;public class HelloServlet extends HttpServlet { &lt;br /&gt; public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {&lt;br /&gt;  res.setContentType("text/html");&lt;br /&gt;  res.getOutputStream().print("&lt;h1&gt;context path: " + req.getContextPath() + "&lt;/h1&gt;");&lt;br /&gt;  res.getOutputStream().print("&lt;h2&gt;hello world!&lt;/h2&gt;");&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;ถ้าต้องการส่ง init parameter ให้กับ servlet หรือ filter ใช้  &lt;span style="font-weight:bold;"&gt;@WebInitParam&lt;/span&gt; ซึ่งมี attribute &lt;ul&gt;&lt;li&gt;name&lt;/li&gt;&lt;li&gt;value&lt;/li&gt;&lt;li&gt;description&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;ตัวอย่างการใช้งาน&lt;pre name="code" class="java"&gt;&lt;br /&gt;@WebServlet (name="SimpleServlet", &lt;br /&gt;  urlPatterns={"/simple"},&lt;br /&gt;  initParams={&lt;br /&gt;   @WebInitParam(name="name", value="Phamonyut"),&lt;br /&gt;   @WebInitParam(name="penname", value="tofu")})&lt;br /&gt;public class SimpleServlet extends HttpServlet {&lt;br /&gt; public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {&lt;br /&gt;  PrintWriter out = res.getWriter();&lt;br /&gt;  out.println("name parameter: " + getInitParameter("name"));&lt;br /&gt;  out.println("penname parameter: " + getInitParameter("penname"));&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight:bold;"&gt;@WebListener&lt;/span&gt; ใช้เพื่อลงทะเบียน listener ตามประเภทของ listener ดังนี้&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Context Listener (javax.servlet.ServletContextListener)&lt;/li&gt;&lt;li&gt;Context Attribute Listener (javax.servlet.ServletContextAttributeListener)&lt;/li&gt;&lt;li&gt;Servlet Request Listener (javax.servlet.ServletRequestListener)&lt;/li&gt;&lt;li&gt;Servlet Request Attribute Listener (javax.servlet.ServletRequestAttributeListener)&lt;/li&gt;&lt;li&gt;Http Session Listener (javax.servlet.http.HttpSessionListener)&lt;/li&gt;&lt;li&gt;Http Session Attribute Listener (javax.servlet.http.HttpSessionAttributeListener)&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;ใน @WebListener มี attribute ดังนี้&lt;ul&gt;&lt;li&gt;filterName&lt;/li&gt;&lt;li&gt;description&lt;/li&gt;&lt;li&gt;displayName&lt;/li&gt;&lt;li&gt;initParams&lt;/li&gt;&lt;li&gt;servletNames&lt;/li&gt;&lt;li&gt;value&lt;/li&gt;&lt;li&gt;urlPatterns&lt;/li&gt;&lt;li&gt;dispatcherTypes&lt;/li&gt;&lt;li&gt;asyncSupported&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;การใช้งาน WebListener (ถ้าไม่ implement listener interface มาจะเกิดข้อผิดพลาดได้)&lt;pre name="code" class="java"&gt;&lt;br /&gt;@WebListener&lt;br /&gt;public class FooApplication implements ServletContextListener {&lt;br /&gt; public void contextInitialized(ServletContextEvent event) {&lt;br /&gt;  System.out.println("inti context");&lt;br /&gt; }&lt;br /&gt; public void contextDestroyed(ServletContextEvent event) {&lt;br /&gt;  System.out.println("destory context");&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight:bold;"&gt;@WebFilter&lt;/span&gt; ไว้ลงทะเบียน filter ซึ่งมี attribute ดังนี้&lt;br /&gt;&lt;ul&gt;&lt;li&gt;filterName&lt;/li&gt;&lt;li&gt;description&lt;/li&gt;&lt;li&gt;displayName&lt;/li&gt;&lt;li&gt;initParams&lt;/li&gt;&lt;li&gt;servletNames&lt;/li&gt;&lt;li&gt;value&lt;/li&gt;&lt;li&gt;urlPatterns&lt;/li&gt;&lt;li&gt;dispatcherTypes&lt;/li&gt;&lt;li&gt;asyncSupported&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;@WebFilter(value="/hello",&lt;br /&gt;  initParams={&lt;br /&gt;   @WebInitParam(name="message", value="Servlet says:")&lt;br /&gt;  })&lt;br /&gt;public class TestFilter implements Filter {&lt;br /&gt; private FilterConfig filterConfig;&lt;br /&gt; public void init(FilterConfig filterConfig) throws ServletException {&lt;br /&gt;  this.filterConfig = filterConfig;&lt;br /&gt; }&lt;br /&gt; public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException {&lt;br /&gt;  PrintWriter out = res.getWriter();&lt;br /&gt;  out.print(filterConfig.getInitParameter("message"));&lt;br /&gt;  System.out.println("call request -&gt; filter");&lt;br /&gt;  chain.doFilter(req, res);&lt;br /&gt;  System.out.println("call filter &lt;- response");&lt;br /&gt; }&lt;br /&gt; public void destroy() {}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;@WebServlet(value="/hello")&lt;br /&gt;public class HelloServlet extends HttpServlet {&lt;br /&gt; public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {&lt;br /&gt;  System.out.println("call hello servlet");&lt;br /&gt;  PrintWriter out = res.getWriter();&lt;br /&gt;  out.println("Hello world!");  &lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1638080862489455885-3955411983947680459?l=phamonyut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Phamonyut/~4/IOL9kK8dnLI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://phamonyut.blogspot.com/feeds/3955411983947680459/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://phamonyut.blogspot.com/2009/12/servlet3-introduction.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/3955411983947680459?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/3955411983947680459?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Phamonyut/~3/IOL9kK8dnLI/servlet3-introduction.html" title="Servlet 3.0: Introduction" /><author><name>Phamon P</name><uri>https://profiles.google.com/105136402217293967127</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh3.googleusercontent.com/-2AzJSisfnE0/AAAAAAAAAAI/AAAAAAAAAtA/koK-fzCuwVc/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://phamonyut.blogspot.com/2009/12/servlet3-introduction.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0EFRnwzcCp7ImA9WxBSGUw.&quot;"><id>tag:blogger.com,1999:blog-1638080862489455885.post-2509607501611910985</id><published>2009-12-21T20:23:00.008+07:00</published><updated>2009-12-27T19:06:57.288+07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-12-27T19:06:57.288+07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Servlet" /><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><title>Java Captcha</title><content type="html">เพื่อนติดปัญหาช่วยแก้เกี่ยวกับ captcha ลองหาดูพบว่า jcaptcha ใช้งานได้ค่อนข้างดี และ implement ไม่ยากนำไปผูกกับ framework ได้อย่างลงตัว&lt;br /&gt;&lt;br /&gt;เริ่มแรกไปโหลด library jCaptcha และ library ที่เกี่ยวข้องมาให้เรียบร้อย&lt;ul&gt;&lt;li&gt;commons-collections-3.2&lt;/li&gt;&lt;li&gt;commons-logging-1.0.4&lt;/li&gt;&lt;li&gt;filters-2.0.235&lt;/li&gt;&lt;li&gt;jcaptcha-2.0-alpha-1-SNAPSHOT&lt;/li&gt;&lt;li&gt;jcaptcha-api-1.0&lt;/li&gt;&lt;li&gt;jcaptcha-integration-simple-servlet-2.0-alpha-1-SNAPSHOT&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;web.xml ระบุว่า jcaptcha ที่จะทำหน้าที่เป็นตัวสร้างภาพ captcha ตัว class ใด และจะเรียกใช้ผ่าน url อย่างไร&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&lt;servlet&gt;&lt;br /&gt;        &lt;servlet-name&gt;jcaptcha&lt;/servlet-name&gt;&lt;br /&gt;        &lt;servlet-class&gt;com.octo.captcha.servlet.image.SimpleImageCaptchaServlet&lt;/servlet-class&gt;&lt;br /&gt;&lt;/servlet&gt;&lt;br /&gt;&lt;servlet-mapping&gt;&lt;br /&gt;        &lt;servlet-name&gt;jcaptcha&lt;/servlet-name&gt;&lt;br /&gt;        &lt;url-pattern&gt;/jcaptcha.jpg&lt;/url-pattern&gt;&lt;br /&gt;&lt;/servlet-mapping&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;ตัวอย่างการเรียกใช้งาน&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;&lt;form action="submit.action"&gt;&lt;br /&gt;    &lt;img src="jcaptcha.jpg" /&gt; &lt;br /&gt;    &lt;input type="text" name="jcaptcha" value="" /&gt;&lt;br /&gt;&lt;/form&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;ฝั่ง server รับไปประมวลผล&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;PrintWriter pw = response.getWriter();&lt;br /&gt;String userCaptchaResponse = request.getParameter("jcaptcha");&lt;br /&gt;boolean captchaPassed = SimpleImageCaptchaServlet.validateResponse(request, userCaptchaResponse);&lt;br /&gt;if(captchaPassed){&lt;br /&gt;    pw.println("good job");&lt;br /&gt;}else{&lt;br /&gt;    pw.println("fail");&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;เสร็จเรียบร้อย run ได้เลย&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1638080862489455885-2509607501611910985?l=phamonyut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Phamonyut/~4/QnsJb1oHtDg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://phamonyut.blogspot.com/feeds/2509607501611910985/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://phamonyut.blogspot.com/2009/12/java-captcha.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/2509607501611910985?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/2509607501611910985?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Phamonyut/~3/QnsJb1oHtDg/java-captcha.html" title="Java Captcha" /><author><name>Phamon P</name><uri>https://profiles.google.com/105136402217293967127</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh3.googleusercontent.com/-2AzJSisfnE0/AAAAAAAAAAI/AAAAAAAAAtA/koK-fzCuwVc/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://phamonyut.blogspot.com/2009/12/java-captcha.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Dk8MQXw9fSp7ImA9WxNaEE8.&quot;"><id>tag:blogger.com,1999:blog-1638080862489455885.post-1778898865042648587</id><published>2009-11-24T08:08:00.000+07:00</published><updated>2009-11-24T08:08:00.265+07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-24T08:08:00.265+07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Tivoli Directory" /><title>Manage IBM Tivoli Directory Log</title><content type="html">การจัดการ log ของ Tivoli Directory ปกติแ้ล้วสามารถจัดการได้โดยปกติผ่านเครื่องมือของ Tivoli แต่ถ้าเรานำ Tivoli ไปลงบน OS ที่ไม่รองรับมันจะไม่ทำงาน &lt;br /&gt;อย่างในกรณีของผมเองตอนนี้ใช้ Tivoli Directory v.6.2 แต่มีความจำเป็นต้องนำไปติดตั้งบน windows server 2008 แน่นอนว่ามันไม่รองรับกับ OS ดังกล่าว จึงต้องเขียนโปรแกรมขึ้นมาเพื่อจัดการเอง&lt;br /&gt;ความต้องการขั้นต่ำคือ &lt;ul&gt;&lt;li&gt;เก็บ log ทั้งหมดลงใน zip ไฟล์เพื่อลดเนื้อที่ โดยชื่อไฟล์จะมีวันที่ต่อท้ายด้วย&lt;/li&gt;&lt;li&gt;ตัวโปรแกรมต้องบอกได้ว่าทำงานสำเร็จหรือไม่สำเร็จ และเพราะคำสั่งไหน เพราะอะไร เก็บลง log file แยกตะหาก&lt;/li&gt;&lt;li&gt;จัดการ log ที่เก็บได้ว่าต้องการให้อยู่กี่วัน (ตามนโยบายคือเก็บ log ไว้ 90 วัน)&lt;/li&gt;&lt;/ul&gt;ผมเขียน batch ครับแล้วตั้งเป็น job เอาไว้ให้ทำงานทุกเสาร์ตอนตีสาม (เพราะมี job อีกหลายตัวทำงานก่อน และถ้ามีปัญหาเรายังมีเวลาเข้าไปแก้ก่อนถึงเช้าวันจันทร์) ผมไม่ได้จะมา demo ทั้งหมดให้ดูหรอกครับ แต่จะหยิบคำสั่ง ldap บางอย่างที่จำเป็นต้องใช้ เพื่อนำไปพัฒนาต่อได้มาแปะไว้ (ส่วนโปรแกรมจริงไม่ขอเอามาแสดงครับเพราะจะยาวไป)&lt;br /&gt;&lt;br /&gt;ดึงวันที่และเวลาปัจจุบันออกมา&lt;br /&gt;@echo off&lt;br /&gt;:: set datetime variable&lt;br /&gt; SETLOCAL&lt;br /&gt; For /f "tokens=1-3 delims=1234567890 " %%a in ("%time%") Do set "delims=%%a%%b%%c"&lt;br /&gt; For /f "tokens=1-4 delims=%delims%" %%G in ("%time%") Do (&lt;br /&gt; Set _hh=%%G&lt;br /&gt; Set _min=%%H&lt;br /&gt; Set _ss=%%I&lt;br /&gt; Set _ms=%%J&lt;br /&gt; )&lt;br /&gt; :: Strip any leading spaces&lt;br /&gt; Set _hh=%_hh: =%&lt;br /&gt;&lt;br /&gt; :: Ensure the hours have a leading zero&lt;br /&gt; if 1%_hh% LSS 20 Set _hh=0%_hh%&lt;br /&gt;&lt;br /&gt; ENDLOCAL&amp;Set _time=%_hh%%_min%%_ss%&lt;br /&gt;&lt;br /&gt;@echo off&amp;SETLOCAL&lt;br /&gt; :: This will return date into environment vars&lt;br /&gt; :: Works on any NT/2K/XP machine independent of regional date settings&lt;br /&gt; :: 20 March 2002&lt;br /&gt; FOR /f "tokens=1-4 delims=/-. " %%G IN ('date /t') DO (call :s_fixdate %%G %%H %%I %%J)&lt;br /&gt; goto :s_print_the_date&lt;br /&gt;&lt;br /&gt; :s_fixdate&lt;br /&gt; if "%1:~0,1%" GTR "9" shift&lt;br /&gt; FOR /f "skip=1 tokens=2-4 delims=(-)" %%G IN ('echo.^|date') DO (&lt;br /&gt;    set %%G=%1&amp;set %%H=%2&amp;set %%I=%3)&lt;br /&gt; goto :eof&lt;br /&gt;&lt;br /&gt; :s_print_the_date&lt;br /&gt; ENDLOCAL&amp;SET _date=%yy%%mm%%dd%&lt;br /&gt;&lt;br /&gt;เปลี่ยนชื่อ ldap log ผมเขียนเป็น function ไว้เพื่อเรียกง่ายๆ&lt;br /&gt;call :changefileconfigldap ibmslapd ibmslapd&lt;br /&gt;call :changefileconfigldap ibmdiradm Admin&lt;br /&gt;call :changefileconfigldap adminaudit Admin Audit&lt;br /&gt;call :changefileconfigldap audit Audit&lt;br /&gt;call :changefileconfigldap bulkload Bulkload&lt;br /&gt;call :changefileconfigldap idstools Tools&lt;br /&gt;call :changefileconfigldap db2cli db2cli&lt;br /&gt;call :changefileconfigldap lostandfound Replication&lt;br /&gt;:changefileconfigldap (&lt;br /&gt;  cd "%_path_tivoli%"&lt;br /&gt;  echo dn: cn=%2 %3,cn=Log Management,cn=Configuration &gt; %_filename_ldapConfig%&lt;br /&gt;  echo changetype: modify &gt;&gt; %_filename_ldapConfig%&lt;br /&gt;  echo replace: ibm-slapdlog &gt;&gt; %_filename_ldapConfig%&lt;br /&gt;  echo ibm-slapdlog: %_path_logldap%\%1-%_date%%_time%%_extension% &gt;&gt; %_filename_ldapConfig%&lt;br /&gt;  call idsldapmodify -D cn=root -w %_password% -k -i "%_path_tivoli%\%_filename_ldapConfig%"&lt;br /&gt;  echo change cn: %2 %3 complete &gt;&gt; "%_path_logerr%\%_filename_logerr%"&lt;br /&gt;  goto :eof&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;แต่้ถ้าเราไม่รู้ว่าตอนนี้มี log file ชื่ออะไรบ้างที่ใช้อยู่ให้ใช้ ldapsearch ตัวอย่างเช่น&lt;br /&gt;ldapsearch -D %username% -w %password% -p %port% &lt;br /&gt;-b cn=Configuration -s sub cn=ibmslapd ibm-slapdLog&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1638080862489455885-1778898865042648587?l=phamonyut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Phamonyut/~4/sMRaif9qLOI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://phamonyut.blogspot.com/feeds/1778898865042648587/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://phamonyut.blogspot.com/2009/11/manage-ibm-tivoli-directory-log.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/1778898865042648587?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/1778898865042648587?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Phamonyut/~3/sMRaif9qLOI/manage-ibm-tivoli-directory-log.html" title="Manage IBM Tivoli Directory Log" /><author><name>Phamon P</name><uri>https://profiles.google.com/105136402217293967127</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh3.googleusercontent.com/-2AzJSisfnE0/AAAAAAAAAAI/AAAAAAAAAtA/koK-fzCuwVc/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://phamonyut.blogspot.com/2009/11/manage-ibm-tivoli-directory-log.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CU4DQHwzfSp7ImA9WxNbGUs.&quot;"><id>tag:blogger.com,1999:blog-1638080862489455885.post-1758568370890601348</id><published>2009-11-23T14:53:00.005+07:00</published><updated>2009-11-23T15:12:51.285+07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-23T15:12:51.285+07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="WebSphere" /><title>Create self-signed certificate</title><content type="html">การสร้าง self-signed certificate โดยใช้เครื่องมือ iKeyman ที่ติดมาพร้อมกับ product ตระกูล IBM มีขั้นตอนดังนี้&lt;ul&gt;&lt;li&gt;รันเครื่องมือ iKeyman ในตัวอย่างผมติดตั้ง IBM WebSphere ดังนั้นจะอยู่ที่ WAS_HOME\bin&lt;/li&gt;&lt;li&gt;สร้าง key database file แล้วตั้งชื่อ และใส่ password ให้เรียบร้อย&lt;/li&gt;&lt;li&gt;สร้าง self-signed certificate แล้วใส่ข้อมูลที่จำเป็นดังนี้&lt;ul&gt;&lt;li&gt;Key Label&lt;/li&gt;&lt;li&gt;Key Size&lt;/li&gt;&lt;li&gt;Common Name&lt;/li&gt;&lt;li&gt;Organization Name&lt;/li&gt;&lt;li&gt;Organization Unit (optional)&lt;/li&gt;&lt;li&gt;Locality (optional)&lt;/li&gt;&lt;li&gt;State / Province (optional)&lt;/li&gt;&lt;li&gt;Zipcode (optional)&lt;/li&gt;&lt;li&gt;Country&lt;/li&gt;&lt;li&gt;Validity Period&lt;/li&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;จากนั้นก็ export นำออกไปใช้ ได้แ้ล้วครับ&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1638080862489455885-1758568370890601348?l=phamonyut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Phamonyut/~4/VhXzi3ygueM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://phamonyut.blogspot.com/feeds/1758568370890601348/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://phamonyut.blogspot.com/2009/11/create-self-signed-certificate.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/1758568370890601348?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/1758568370890601348?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Phamonyut/~3/VhXzi3ygueM/create-self-signed-certificate.html" title="Create self-signed certificate" /><author><name>Phamon P</name><uri>https://profiles.google.com/105136402217293967127</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh3.googleusercontent.com/-2AzJSisfnE0/AAAAAAAAAAI/AAAAAAAAAtA/koK-fzCuwVc/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://phamonyut.blogspot.com/2009/11/create-self-signed-certificate.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0ENQ3w5fSp7ImA9WxNbGUw.&quot;"><id>tag:blogger.com,1999:blog-1638080862489455885.post-6199392558121671251</id><published>2009-11-23T00:35:00.005+07:00</published><updated>2009-11-23T00:41:32.225+07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-23T00:41:32.225+07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="WebSphere" /><title>How to create new profile on WebSphere 6.x</title><content type="html">ผมสะดวกมากกว่าที่จะใช้ command line&lt;br /&gt;&lt;br /&gt;ก่อนอื่นเข้าไปที่ WebSphere home แล้วเรียกใช้เครื่องมือ wasprofile โดยตัวมันเองมี options ดังนี้&lt;br /&gt;&lt;br /&gt;wasprofile.bat -create &lt;br /&gt;              -profileName &lt;span style="font-style:italic;"&gt;profile_name&lt;/span&gt;&lt;br /&gt;              -profilePath &lt;span style="font-style:italic;"&gt;fully_qualified_profile_path &lt;/span&gt;&lt;br /&gt;              -templatePath &lt;span style="font-style:italic;"&gt;template_path&lt;/span&gt; &lt;br /&gt;              -nodeName &lt;span style="font-style:italic;"&gt;node_name&lt;/span&gt; &lt;br /&gt;             [-cellName &lt;span style="font-style:italic;"&gt;cell_name&lt;/span&gt;] &lt;br /&gt;              -hostName &lt;span style="font-style:italic;"&gt;host_name&lt;/span&gt; &lt;br /&gt;             [-isDefault]&lt;br /&gt;             [-startingPort starting_port | -portsFile file_path]&lt;br /&gt;             [-winserviceCheck true | false]&lt;br /&gt;             [-winserviceAccountType specified_user | localsystem]&lt;br /&gt;             [-winserviceUserName &lt;span style="font-style:italic;"&gt;your_user_name&lt;/span&gt;]&lt;br /&gt;             [-winservicePassword &lt;span style="font-style:italic;"&gt;your_password&lt;/span&gt;]&lt;br /&gt;             [-winserviceStartupType manual | automatic | disabled]&lt;br /&gt;             [-debug] &lt;br /&gt;&lt;br /&gt;ตัวอย่างเช่น&lt;br /&gt;C:\Program Files\IBM\WebSphere\AppServer\bin&gt;wasprofile -create -profileName AppSrv01 -profilePath "c:\Program Files\IBM\WebSphere\AppServer\profiles\AppSrv01" -templatePath "c:\Program Files\IBM\WebSphere\AppServer\profileTemplates\default" -nodeName test -cellName Node01Cell -hostName localhost&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1638080862489455885-6199392558121671251?l=phamonyut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Phamonyut/~4/nFr6M-xhODc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://phamonyut.blogspot.com/feeds/6199392558121671251/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://phamonyut.blogspot.com/2009/11/how-to-create-new-profile-on-websphere.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/6199392558121671251?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/6199392558121671251?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Phamonyut/~3/nFr6M-xhODc/how-to-create-new-profile-on-websphere.html" title="How to create new profile on WebSphere 6.x" /><author><name>Phamon P</name><uri>https://profiles.google.com/105136402217293967127</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh3.googleusercontent.com/-2AzJSisfnE0/AAAAAAAAAAI/AAAAAAAAAtA/koK-fzCuwVc/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://phamonyut.blogspot.com/2009/11/how-to-create-new-profile-on-websphere.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEUMQX8zcCp7ImA9WxNTEUg.&quot;"><id>tag:blogger.com,1999:blog-1638080862489455885.post-4799600363291964231</id><published>2009-08-13T16:38:00.001+07:00</published><updated>2009-08-13T16:38:00.188+07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-13T16:38:00.188+07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="dot Net" /><title>dotNet send and receive SMS via PC Connectivity API</title><content type="html">ค้างไว้เมื่อ&lt;a href="http://phamonyut.blogspot.com/2009/08/java-send-sms-via-at-command.html"&gt;ตอนก่อนหน้า&lt;/a&gt;นี้ ครั้งนี้จะมาเขียนรับ/ส่ง sms โดยใช้ Nokia PC Connectivity API โค้ดนี้ไม่ได้เขียนเองทั้งหมดบางส่วนหยิบมาจาก forumn ของ nokia แต่ผมนำมาเขียนส่วนของการรับ sms เพิ่มเข้าไป&lt;br /&gt;&lt;br /&gt;โค้ดบางส่วน&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;Imports System.Runtime.InteropServices&lt;br /&gt;&lt;br /&gt;Public Class SMS&lt;br /&gt;&lt;br /&gt;    Public Shared Sub ReadSMS(ByVal strSerialNumber As String)&lt;br /&gt;        Dim intSMSHandle As Integer = 0&lt;br /&gt;        Dim intOperationHandle As Integer = 0&lt;br /&gt;        Dim intStatusCode As Integer = CAAPI_Initialize(30, 0)&lt;br /&gt;&lt;br /&gt;        intSMSHandle = OpenSMSConnection(strSerialNumber)&lt;br /&gt;&lt;br /&gt;        Dim folderInfo As CA_FOLDER_INFO&lt;br /&gt;        folderInfo = New CA_FOLDER_INFO&lt;br /&gt;        folderInfo.iSize = Marshal.SizeOf(folderInfo)&lt;br /&gt;        folderInfo.iFolderId = CA_MESSAGE_FOLDER_INBOX&lt;br /&gt;        Dim bufFolderInfo As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(GetType(CA_FOLDER_INFO)))&lt;br /&gt;        Marshal.StructureToPtr(folderInfo, bufFolderInfo, True)&lt;br /&gt;        intStatusCode = CAGetFolderInfo(intSMSHandle, bufFolderInfo)&lt;br /&gt;&lt;br /&gt;        intStatusCode = CABeginOperation(intSMSHandle, 0, intOperationHandle)&lt;br /&gt;        If intStatusCode &lt;&gt; CONA_OK Then&lt;br /&gt;            Throw New Exception("Error in CABeginOperation-function: " &amp; CONAError2String(intStatusCode) &amp; " (" &amp; intStatusCode.ToString &amp; ")")&lt;br /&gt;        End If&lt;br /&gt;&lt;br /&gt;        Dim caIDList As CA_ID_LIST&lt;br /&gt;        caIDList.iSize = Marshal.SizeOf(caIDList)&lt;br /&gt;        Dim bufList As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(caIDList))&lt;br /&gt;        Marshal.StructureToPtr(caIDList, bufList, True)&lt;br /&gt;        intStatusCode = CAGetIDList(intSMSHandle, folderInfo.iFolderId, 0, bufList)&lt;br /&gt;        caIDList = Marshal.PtrToStructure(bufList, GetType(CA_ID_LIST))&lt;br /&gt;&lt;br /&gt;        Dim i As Integer = 0&lt;br /&gt;        For i = 1 To caIDList.iUIDCount&lt;br /&gt;            Dim itemId As CA_ITEM_ID&lt;br /&gt;            itemId.iSize = Marshal.SizeOf(itemId)&lt;br /&gt;            itemId.iFolderId = CA_MESSAGE_STATUS_READ&lt;br /&gt;            itemId.iStatus = 0&lt;br /&gt;            itemId.iTemporaryID = i&lt;br /&gt;            itemId.iUidLen = 0&lt;br /&gt;            itemId.pbUid = IntPtr.Zero&lt;br /&gt;            Dim bufItemId As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(GetType(CA_ITEM_ID)))&lt;br /&gt;            Marshal.StructureToPtr(itemId, bufItemId, True)&lt;br /&gt;&lt;br /&gt;            Dim dataSMS As CA_DATA_MSG&lt;br /&gt;            dataSMS.iSize = Marshal.SizeOf(dataSMS)&lt;br /&gt;            dataSMS.bAddressCount = 0&lt;br /&gt;            dataSMS.iDataLength = 0&lt;br /&gt;            dataSMS.iInfoField = 0&lt;br /&gt;            dataSMS.pAddress = IntPtr.Zero&lt;br /&gt;            dataSMS.pbData = IntPtr.Zero&lt;br /&gt;            Dim bufDataSMS As IntPtr = Marshal.AllocHGlobal(dataSMS.iSize)&lt;br /&gt;            Marshal.StructureToPtr(dataSMS, bufDataSMS, True)&lt;br /&gt;&lt;br /&gt;            intStatusCode = CAReadItem(intOperationHandle, bufItemId, CA_OPTION_USE_CACHE, CA_DATA_FORMAT_STRUCT, bufDataSMS)&lt;br /&gt;            If intStatusCode = CONA_OK Then&lt;br /&gt;                dataSMS = Marshal.PtrToStructure(bufDataSMS, GetType(CA_DATA_MSG))&lt;br /&gt;                Dim message As String = Marshal.PtrToStringUni(dataSMS.pbData, dataSMS.iDataLength / 2)&lt;br /&gt;                ' something ...&lt;br /&gt;            Else&lt;br /&gt;                Throw New Exception("Error in CAReadItem-function: " &amp; CONAError2String(intStatusCode) &amp; " (" &amp; intStatusCode.ToString &amp; ")")&lt;br /&gt;            End If&lt;br /&gt;        Next&lt;br /&gt;&lt;br /&gt;        intStatusCode = CAEndOperation(intOperationHandle)&lt;br /&gt;        If intStatusCode &lt;&gt; CONA_OK Then&lt;br /&gt;            Throw New Exception("Error in CAEndOperation-function: " &amp; CONAError2String(intStatusCode) &amp; " (" &amp; intStatusCode.ToString &amp; ")")&lt;br /&gt;        End If&lt;br /&gt;        CloseSMSConnection(intSMSHandle)&lt;br /&gt;&lt;br /&gt;    End Sub&lt;br /&gt;&lt;br /&gt;    Public Shared Sub SendSMS(ByVal strSerialNumber As String, ByVal strPhoneNo As String, _&lt;br /&gt;        ByVal strMessage As String, ByVal boolDontDelete As Boolean)&lt;br /&gt;&lt;br /&gt;        Dim intSMSHandle As Integer = 0&lt;br /&gt;&lt;br /&gt;        Dim intStatusCode As Integer = CAAPI_Initialize(30, 0)&lt;br /&gt;&lt;br /&gt;        Try&lt;br /&gt;            intSMSHandle = OpenSMSConnection(strSerialNumber)&lt;br /&gt;&lt;br /&gt;            Try&lt;br /&gt;                Dim folderInfo As CA_FOLDER_INFO&lt;br /&gt;                folderInfo = New CA_FOLDER_INFO&lt;br /&gt;                folderInfo.iSize = Marshal.SizeOf(folderInfo)&lt;br /&gt;                Dim bufItem As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(GetType(CA_FOLDER_INFO)))&lt;br /&gt;                Marshal.StructureToPtr(folderInfo, bufItem, True)&lt;br /&gt;                intStatusCode = CAGetFolderInfo(intSMSHandle, bufItem)&lt;br /&gt;&lt;br /&gt;                Dim intOperationHandle As Integer = 0&lt;br /&gt;                intStatusCode = CABeginOperation(intSMSHandle, 0, intOperationHandle)&lt;br /&gt;                If intStatusCode &lt;&gt; CONA_OK Then&lt;br /&gt;                    Throw New Exception("Error in CABeginOperation-function: " &amp; CONAError2String(intStatusCode) &amp; " (" &amp; intStatusCode.ToString &amp; ")")&lt;br /&gt;                End If&lt;br /&gt;&lt;br /&gt;                Dim itemUid As CA_ITEM_ID&lt;br /&gt;                itemUid.iSize = Marshal.SizeOf(itemUid)&lt;br /&gt;                itemUid.iFolderId = CA_MESSAGE_STATUS_SENT&lt;br /&gt;                itemUid.iStatus = 0&lt;br /&gt;                itemUid.iTemporaryID = 0&lt;br /&gt;                itemUid.iUidLen = 0&lt;br /&gt;                itemUid.pbUid = IntPtr.Zero&lt;br /&gt;                Dim buf As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(GetType(CA_ITEM_ID)))&lt;br /&gt;                Marshal.StructureToPtr(itemUid, buf, True)&lt;br /&gt;&lt;br /&gt;                Dim objSMSMessage As CA_DATA_MSG&lt;br /&gt;                objSMSMessage.iSize = Marshal.SizeOf(objSMSMessage)&lt;br /&gt;                CA_SET_DATA_FORMAT(objSMSMessage.iInfoField, CA_DATA_FORMAT_UNICODE)&lt;br /&gt;                CA_SET_DATA_CODING(objSMSMessage.iInfoField, CA_DATA_CODING_UNICODE)&lt;br /&gt;                CA_SET_MESSAGE_STATUS(objSMSMessage.iInfoField, CA_MESSAGE_STATUS_DRAFT)&lt;br /&gt;                CA_SET_MESSAGE_TYPE(objSMSMessage.iInfoField, CA_SMS_SUBMIT)&lt;br /&gt;&lt;br /&gt;                objSMSMessage.bAddressCount = 1&lt;br /&gt;                objSMSMessage.pAddress = CreateSMSPhoneNoReference(strPhoneNo)&lt;br /&gt;&lt;br /&gt;                objSMSMessage.iDataLength = strMessage.Length * 2&lt;br /&gt;                objSMSMessage.pbData = Marshal.StringToCoTaskMemUni(strMessage)&lt;br /&gt;&lt;br /&gt;                CreateTimestamp(objSMSMessage.messageDate)&lt;br /&gt;&lt;br /&gt;                Dim buf2 As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(GetType(CA_DATA_MSG)))&lt;br /&gt;                Marshal.StructureToPtr(objSMSMessage, buf2, True)&lt;br /&gt;&lt;br /&gt;                intStatusCode = CAWriteItem(intOperationHandle, buf, 0, CA_DATA_FORMAT_STRUCT, buf2)&lt;br /&gt;&lt;br /&gt;                If intStatusCode &lt;&gt; CONA_OK Then&lt;br /&gt;                    Throw New Exception("Error in CAWriteItem-function: " &amp; CONAError2String(intStatusCode) &amp; " (" &amp; intStatusCode.ToString &amp; ")")&lt;br /&gt;                End If&lt;br /&gt;&lt;br /&gt;                Marshal.FreeHGlobal(buf2)&lt;br /&gt;                Marshal.FreeHGlobal(buf)&lt;br /&gt;                Marshal.FreeCoTaskMem(objSMSMessage.pbData)&lt;br /&gt;                Marshal.FreeCoTaskMem(objSMSMessage.pAddress)&lt;br /&gt;&lt;br /&gt;  Dim lstIDs As CA_ID_LIST&lt;br /&gt;                lstIDs.iSize = Marshal.SizeOf(GetType(CA_ID_LIST))&lt;br /&gt;                Dim lstbuf As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(GetType(CA_ID_LIST)))&lt;br /&gt;                Marshal.StructureToPtr(lstIDs, lstbuf, True)&lt;br /&gt;&lt;br /&gt;                intStatusCode = CACommitOperations(intOperationHandle, lstbuf)&lt;br /&gt;&lt;br /&gt;                If intStatusCode &lt;&gt; CONA_OK Then&lt;br /&gt;                    Throw New Exception("Error in CACommitOperations-function: " &amp; CONAError2String(intStatusCode) &amp; " (" &amp; intStatusCode.ToString &amp; ")")&lt;br /&gt;                End If&lt;br /&gt;&lt;br /&gt;                If Not boolDontDelete Then&lt;br /&gt;                    ' Picking the first (and only) message from list and deleting it&lt;br /&gt;                    lstIDs = Marshal.PtrToStructure(lstbuf, GetType(CA_ID_LIST))&lt;br /&gt;                    Dim objViestiUID As CA_ITEM_ID = GetUidFromBuffer(0, lstIDs.pUIDs)&lt;br /&gt;&lt;br /&gt;                    DeleteMessage(intOperationHandle, objViestiUID)&lt;br /&gt;&lt;br /&gt;                    intStatusCode = CACommitOperations(intOperationHandle, IntPtr.Zero)&lt;br /&gt;&lt;br /&gt;                    If intStatusCode &lt;&gt; CONA_OK Then&lt;br /&gt;                        Throw New Exception("Error in CACommitOperations-function: " &amp; CONAError2String(intStatusCode) &amp; " (" &amp; intStatusCode.ToString &amp; ")")&lt;br /&gt;                    End If&lt;br /&gt;                End If&lt;br /&gt;&lt;br /&gt;                intStatusCode = CAEndOperation(intOperationHandle)&lt;br /&gt;&lt;br /&gt;                If intStatusCode &lt;&gt; CONA_OK Then&lt;br /&gt;                    Throw New Exception("Error in CAEndOperation-function: " &amp; CONAError2String(intStatusCode) &amp; " (" &amp; intStatusCode.ToString &amp; ")")&lt;br /&gt;                End If&lt;br /&gt;            Catch ex As Exception&lt;br /&gt;                Throw ex&lt;br /&gt;            Finally&lt;br /&gt;                CloseSMSConnection(intSMSHandle)&lt;br /&gt;            End Try&lt;br /&gt;        Catch ex As Exception&lt;br /&gt;            Throw ex&lt;br /&gt;        Finally&lt;br /&gt;            CAAPI_Terminate(0)&lt;br /&gt;        End Try&lt;br /&gt;    End Sub&lt;br /&gt;&lt;br /&gt;    Private Shared Sub DeleteMessage(ByVal intOperationHandle As Integer, ByVal objItem As CA_ITEM_ID)&lt;br /&gt;        Dim bufViesti As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(objItem))&lt;br /&gt;        Marshal.StructureToPtr(objItem, bufViesti, True)&lt;br /&gt;        Dim intStatusCode As Integer = CADeleteItem(intOperationHandle, bufViesti, 0)&lt;br /&gt;&lt;br /&gt;        If intStatusCode &lt;&gt; CONA_OK Then&lt;br /&gt;            Throw New Exception("Error in CADeleteItem-function: " &amp; CONAError2String(intStatusCode) &amp; " (" &amp; intStatusCode.ToString &amp; ")")&lt;br /&gt;        End If&lt;br /&gt;    End Sub&lt;br /&gt;&lt;br /&gt;    Private Shared Function GetUidFromBuffer(ByVal iIndex As Integer, ByVal pUIds As IntPtr) As CA_ITEM_ID&lt;br /&gt;        ' Calculate beginning of item 'iIndex'&lt;br /&gt;        Dim iPtr As Int64 = pUIds.ToInt64 + (iIndex * Marshal.SizeOf(GetType(CA_ITEM_ID)))&lt;br /&gt;        ' Convert integer to pointer&lt;br /&gt;        Dim ptr As IntPtr = IntPtr.op_Explicit(iPtr)&lt;br /&gt;        ' Copy data from buffer&lt;br /&gt;        GetUidFromBuffer = Marshal.PtrToStructure(ptr, GetType(CA_ITEM_ID))&lt;br /&gt;    End Function&lt;br /&gt;&lt;br /&gt;    Private Shared Function OpenSMSConnection(ByVal strSerialNumber As String) As Integer&lt;br /&gt;        Dim pstrSerialNumber As IntPtr = Marshal.StringToCoTaskMemUni(strSerialNumber)&lt;br /&gt;        Dim iMedia As Integer = API_MEDIA_ALL&lt;br /&gt;        Dim iTarget As Integer = CA_TARGET_SMS_MESSAGES&lt;br /&gt;        Dim intSMSHandle As Integer = 0&lt;br /&gt;        Dim intStatusCode As Integer = DAOpenCA(pstrSerialNumber, iMedia, iTarget, intSMSHandle)&lt;br /&gt;&lt;br /&gt;        If intStatusCode &lt;&gt; CONA_OK Then&lt;br /&gt;            Throw New Exception("Error in DAOpenCA-function: " &amp; CONAError2String(intStatusCode) &amp; " (" &amp; intStatusCode.ToString &amp; ")")&lt;br /&gt;        End If&lt;br /&gt;&lt;br /&gt;        Marshal.FreeCoTaskMem(pstrSerialNumber)&lt;br /&gt;&lt;br /&gt;        Return intSMSHandle&lt;br /&gt;    End Function&lt;br /&gt;&lt;br /&gt;    Private Shared Sub CloseSMSConnection(ByVal intSMSHandle As Integer)&lt;br /&gt;        ' Close PIM connection&lt;br /&gt;        Dim intStatusCode As Integer = DACloseCA(intSMSHandle)&lt;br /&gt;        If intStatusCode &lt;&gt; CONA_OK Then&lt;br /&gt;            Throw New Exception("Error in DACloseCA-function: " &amp; CONAError2String(intStatusCode) &amp; " (" &amp; intStatusCode.ToString &amp; ")")&lt;br /&gt;        End If&lt;br /&gt;    End Sub&lt;br /&gt;&lt;br /&gt;    Private Shared Function CreateSMSPhoneNoReference(ByVal strNumber As String) As IntPtr&lt;br /&gt;        Dim dataAddress As CA_DATA_ADDRESS&lt;br /&gt;        dataAddress = New CA_DATA_ADDRESS&lt;br /&gt;        dataAddress.iSize = Marshal.SizeOf(dataAddress)&lt;br /&gt;        dataAddress.iAddressInfo = CA_MSG_ADDRESS_TYPE_NUMBER&lt;br /&gt;        dataAddress.pstrAddress = strNumber&lt;br /&gt;        ' Allocate memory for buffer&lt;br /&gt;        Dim bufDataAddress As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(dataAddress))&lt;br /&gt;        Marshal.StructureToPtr(dataAddress, bufDataAddress, True)&lt;br /&gt;        Return bufDataAddress&lt;br /&gt;    End Function&lt;br /&gt;&lt;br /&gt;    Private Shared Sub CreateTimestamp(ByRef pimDate As CA_DATA_DATE)&lt;br /&gt;        Dim dateCurrent As Date = Date.Now&lt;br /&gt;        pimDate.iSize = Marshal.SizeOf(pimDate)&lt;br /&gt;        pimDate.wYear = System.Convert.ToUInt16(dateCurrent.Year)&lt;br /&gt;        pimDate.bMonth = dateCurrent.Month&lt;br /&gt;        pimDate.bDay = dateCurrent.Day&lt;br /&gt;        pimDate.bHour = dateCurrent.Hour&lt;br /&gt;        pimDate.bMinute = dateCurrent.Minute&lt;br /&gt;        pimDate.bSecond = dateCurrent.Second&lt;br /&gt;    End Sub&lt;br /&gt;End Class&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1638080862489455885-4799600363291964231?l=phamonyut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Phamonyut/~4/lOkAoW9u0EA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://phamonyut.blogspot.com/feeds/4799600363291964231/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://phamonyut.blogspot.com/2009/08/dotnet-send-and-receive-sms-via-pc.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/4799600363291964231?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/4799600363291964231?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Phamonyut/~3/lOkAoW9u0EA/dotnet-send-and-receive-sms-via-pc.html" title="dotNet send and receive SMS via PC Connectivity API" /><author><name>Phamon P</name><uri>https://profiles.google.com/105136402217293967127</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh3.googleusercontent.com/-2AzJSisfnE0/AAAAAAAAAAI/AAAAAAAAAtA/koK-fzCuwVc/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://phamonyut.blogspot.com/2009/08/dotnet-send-and-receive-sms-via-pc.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0YMRXY8fyp7ImA9WxJaGUo.&quot;"><id>tag:blogger.com,1999:blog-1638080862489455885.post-8708093909482869231</id><published>2009-08-11T13:20:00.009+07:00</published><updated>2009-08-11T14:19:44.877+07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-11T14:19:44.877+07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><title>Java send SMS via AT Command</title><content type="html">เราใช้ AT Command ในการคุยกับอุปกรณ์เคลื่อนที่้ ในโทรศัพท์มือถือทุกวันนี้ก็ได้ implement at command ลงไปเพียงแต่ว่า แต่ละรุ่นก็ใส่ function ลงไปไม่เหมือนกัน ดังนั้นก่อนใช้งานต้องตรวจสอบก่อนว่าโทรศัพท์มือถือที่เราจะติดต่อนั้นรองรับ function ใดบ้าง&lt;br /&gt;&lt;br /&gt;การส่ง AT Command ไปให้โทรศัพท์มือถือทำได้ไม่ยาก โดยใช้ Java I/O และจากนั้นส่งคำสั่งผ่าน stream&lt;br /&gt;&lt;br /&gt;ตัวอย่างด้านล่างผมเขียนเป็น class util ง่ายๆ ไว้ใช้งานโดยมันสามารถสั่งให้อุปกรณ์มือถือเราส่ง SMS ดังนั้นมันจะเหมือนกับการส่ง SMS ผ่านมือถือปกติแต่จะแตกต่างเพียงแค่ว่าเราสั่งจาก PC ซึ่งมันยืดหยุ่นกว่าในกรณีที่เราจะเขียนโปรแกรมต่อยอดไปอีก&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;&lt;br /&gt;import java.io.*;&lt;br /&gt;import java.util.*;&lt;br /&gt;import javax.comm.*;&lt;br /&gt;import com.sun.comm.*;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;class Mobile {&lt;br /&gt;&lt;br /&gt; //com.sun.comm.Win32SerialPort&lt;br /&gt; //timeout second / 10&lt;br /&gt; private static final int RESPONSE_TIMEOUT = 50;&lt;br /&gt; //timeout second / 1000&lt;br /&gt; private static final int DEVICE_TIMEOUT = 1000;&lt;br /&gt; private static final String NEWLINE = "\n";&lt;br /&gt; private static final String ENTER = "\r";&lt;br /&gt; private static final String CTRL_Z = "\u001A";&lt;br /&gt; private static final String CONNECTION = "connect";&lt;br /&gt;&lt;br /&gt; private InputStream in;&lt;br /&gt; private OutputStream out;&lt;br /&gt;&lt;br /&gt; private SerialPort port;&lt;br /&gt; private CommPortIdentifier portID;&lt;br /&gt;  &lt;br /&gt; public Mobile(String appName, CommPortIdentifier portID) throws IOException, PortInUseException, UnsupportedCommOperationException {&lt;br /&gt;  this.portID = portID;&lt;br /&gt;  //this.portID.addPortOwnershipListener(new MyCommPortOwnershipListener());&lt;br /&gt;  port = (SerialPort) portID.open(appName, DEVICE_TIMEOUT); &lt;br /&gt;  port.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);&lt;br /&gt;  port.setFlowControlMode(port.FLOWCONTROL_NONE);&lt;br /&gt;  in = port.getInputStream();&lt;br /&gt;  out = port.getOutputStream();&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void close() throws IOException {&lt;br /&gt;  in.close();&lt;br /&gt;  out.close();&lt;br /&gt;  port.close();&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public static Map&amp;lt;String, CommPortIdentifier&amp;gt; listPort() throws IOException {&lt;br /&gt;  Map&amp;lt;String, CommPortIdentifier&amp;gt; listPort = new Hashtable&amp;lt;String, CommPortIdentifier&amp;gt;();&lt;br /&gt;  Enumeration portList = CommPortIdentifier.getPortIdentifiers();&lt;br /&gt;  while (portList.hasMoreElements()) {&lt;br /&gt;   CommPortIdentifier portID = (CommPortIdentifier) portList.nextElement();&lt;br /&gt;   listPort.put(portID.getName(), portID);&lt;br /&gt;  }&lt;br /&gt;  return listPort;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public String sendSMS(String tel, String msg) throws IOException, InterruptedException {&lt;br /&gt;  String result = null;&lt;br /&gt;  sendCommand("AT+CMGF=1");&lt;br /&gt;  writeRequest("AT+CMGS=\"" + tel + "\"");&lt;br /&gt;  result = sendCommand(msg + CTRL_Z);&lt;br /&gt;  return result;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public String sendCommand(String cmd) throws IOException, InterruptedException {&lt;br /&gt;  writeRequest(cmd);&lt;br /&gt;  return readResponse();&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; private void writeRequest(String req) throws IOException {&lt;br /&gt;  out.write(new String(req + ENTER).getBytes());&lt;br /&gt;  out.flush();&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; private String readResponse() throws IOException, InterruptedException {&lt;br /&gt;  String strIn = "";&lt;br /&gt;  for (int i=0; i&amp;lt;RESPONSE_TIMEOUT; i++){&lt;br /&gt;   int numChars = in.available();&lt;br /&gt;   if (numChars &amp;gt; 0){&lt;br /&gt;    byte[] bb = new byte[numChars];&lt;br /&gt;    in.read(bb, 0, numChars);&lt;br /&gt;    strIn += new String(bb);&lt;br /&gt;   }&lt;br /&gt;   if (strIn.indexOf("&amp;gt;" + ENTER + NEWLINE) != -1) { &lt;br /&gt;    break; &lt;br /&gt;   }&lt;br /&gt;   if (strIn.indexOf("OK" + ENTER + NEWLINE) != -1) {&lt;br /&gt;    break;&lt;br /&gt;   }&lt;br /&gt;   if (strIn.indexOf("ERROR") != -1 &amp;&amp;&lt;br /&gt;    strIn.indexOf(ENTER + NEWLINE, strIn.indexOf("ERROR") + 1) != -1) { &lt;br /&gt;    break;&lt;br /&gt;   }&lt;br /&gt;   Thread.sleep(100);&lt;br /&gt;  }&lt;br /&gt;  return strIn;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt; ส่วนตอนเรียกใช้งานก็ง่ายๆ &lt;pre name="code" class="java"&gt;&lt;br /&gt;import java.util.*;&lt;br /&gt;import javax.comm.*;&lt;br /&gt;&lt;br /&gt;public class Client {&lt;br /&gt;&lt;br /&gt; public static void main(String[] args) throws Exception {&lt;br /&gt;  //choose port&lt;br /&gt;  Map&amp;lt;String, CommPortIdentifier&amp;gt; listPort = Mobile.listPort();&lt;br /&gt;  System.out.println(listPort);&lt;br /&gt;  Mobile mobile = new Mobile("SMS/GSM Nokia N73", listPort.get("COM12"));&lt;br /&gt;  System.out.println(mobile.sendSMS("+66123456789", "Hello World"));&lt;br /&gt;  System.out.println("---");&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;แน่นอนครับนอกจากส่ง SMS ได้แล้วยังสามารถทำอย่างอื่นได้อีกเช่น รับ SMS, สั่งโทรออก เป็นต้นแต่เราต้องแน่ใจก่อนว่าโทรศัพท์มือถือรองรับ function ดังกล่าว&lt;br /&gt;&lt;br /&gt;แล้วเราจะรู้ได้อย่างไรว่าโทรศัพท์มือถือที่เราจะสื่อสารด้วยนี้รองรับ AT Command อะไรบ้าง?&lt;br /&gt;วิธีตรวจสอบง่ายๆ คือการส่งคำสั่ง AT Command ที่เราจะใช้แล้วตามด้วย =? ถ้าตอบกลับมาเป็น ERROR นั่นหมายความว่าไม่อุปกรณ์ที่เราจะติดต่อนั้นไม่รองรับคำสั่งดังกล่าว&lt;br /&gt;&lt;br /&gt;นอกจาก AT Command ยังมีวิธีอื่นๆ อีกครับที่สามารถใช้ติดต่อกับโทรศัพท์มือถือได้แต่นั่นก็ขึ้นอยู่กับผู้ผลิตมือถือแต่ละเจ้าด้วย อย่างที่ผมทดสอบผมใช้ Nokia N73 ซึ่งมันไม่รองรับ AT Command (AT+CGMR) ที่จะให้อ่าน SMS เลยต้องไปใช้ Nokia PC Connectivity API แทนครับ&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1638080862489455885-8708093909482869231?l=phamonyut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Phamonyut/~4/ACxn8Do8jv0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://phamonyut.blogspot.com/feeds/8708093909482869231/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://phamonyut.blogspot.com/2009/08/java-send-sms-via-at-command.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/8708093909482869231?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/8708093909482869231?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Phamonyut/~3/ACxn8Do8jv0/java-send-sms-via-at-command.html" title="Java send SMS via AT Command" /><author><name>Phamon P</name><uri>https://profiles.google.com/105136402217293967127</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh3.googleusercontent.com/-2AzJSisfnE0/AAAAAAAAAAI/AAAAAAAAAtA/koK-fzCuwVc/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://phamonyut.blogspot.com/2009/08/java-send-sms-via-at-command.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEMAQno5eSp7ImA9WxJREE8.&quot;"><id>tag:blogger.com,1999:blog-1638080862489455885.post-5595987740661061969</id><published>2009-05-11T10:32:00.007+07:00</published><updated>2009-05-11T13:14:03.421+07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-11T13:14:03.421+07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="DB2" /><title>DB2 in Editplus</title><content type="html">หลังจากลองเล่น DB2 มาได้ซักระยะหนึ่ง รู้สึกขัดใจ (ช้า, หน้าตาไม่น่าใช้, เปลี่ยน font ที่ต้องการไม่ได้) เมื่อใช้ tool DB2 Control Center ที่มาพร้อมกับ DB2 &lt;br /&gt;จะใช้ Toad for DB2 ก็นะ ผมชอบพิมพ์ command มากกว่า&lt;br /&gt;เลยหันมา run SQL บน command line แทนแต่รู้สึกมันถึกไปหน่อย&lt;br /&gt;จากนั้นเลยหาวิธีให้มาทำงาน editplus &lt;br /&gt;&lt;br /&gt;Command: db2cmd.exe&lt;br /&gt;Argument: -c -w -i db2 -tvf $(FileName)&lt;br /&gt;Initial directory: $(DirWin)&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_al1ANReYFEE/SgefRa7ISDI/AAAAAAAAAWo/GIpQzQ84sfc/s1600-h/db2onedp.PNG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 342px;" src="http://3.bp.blogspot.com/_al1ANReYFEE/SgefRa7ISDI/AAAAAAAAAWo/GIpQzQ84sfc/s400/db2onedp.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5334407405277562930" /&gt;&lt;/a&gt;&lt;br /&gt;ขอให้สนุกกับการเขียน SQL&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1638080862489455885-5595987740661061969?l=phamonyut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Phamonyut/~4/WsPrmbrOVns" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://phamonyut.blogspot.com/feeds/5595987740661061969/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://phamonyut.blogspot.com/2009/05/db2-in-editplus.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/5595987740661061969?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/5595987740661061969?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Phamonyut/~3/WsPrmbrOVns/db2-in-editplus.html" title="DB2 in Editplus" /><author><name>Phamon P</name><uri>https://profiles.google.com/105136402217293967127</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh3.googleusercontent.com/-2AzJSisfnE0/AAAAAAAAAAI/AAAAAAAAAtA/koK-fzCuwVc/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_al1ANReYFEE/SgefRa7ISDI/AAAAAAAAAWo/GIpQzQ84sfc/s72-c/db2onedp.PNG" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://phamonyut.blogspot.com/2009/05/db2-in-editplus.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0cBQ349fyp7ImA9WxJREE8.&quot;"><id>tag:blogger.com,1999:blog-1638080862489455885.post-8282738329040464696</id><published>2009-05-10T09:06:00.017+07:00</published><updated>2009-05-11T13:57:32.067+07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-11T13:57:32.067+07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="DB2" /><category scheme="http://www.blogger.com/atom/ns#" term="SQL" /><title>DB2 Tip</title><content type="html">ผมเป็นคนสาย Oracle พอเปลี่ยนมาเล่น DB2 เลยต้องปรับตัวเล็กน้อย&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Dummy Table &lt;/span&gt;&lt;br /&gt;ใน Oracle มีั DUAL เป็น dummy table ใน DB2 ก็มีเช่นกันแต่อยู่ใน sysibm.sysdummy1&lt;br /&gt;&lt;pre name="code" class="sql"&gt;&lt;br /&gt;select 'dummy table' from sysibm.sysdummy1;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;List Table&lt;/span&gt;&lt;br /&gt;ใน Oracle มี select * from tab ใช้แสดง table ทั้งหมด ใน DB2 ใช้้ได้หลายรูปแบบ&lt;br /&gt;&lt;pre name="code" class="sql"&gt;&lt;br /&gt;list tables for all;&lt;br /&gt;list tables for schema sysibm;&lt;br /&gt;select tabschema, tabname from syscat.tables&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Describe Table&lt;/span&gt;&lt;br /&gt;ใน Oracle ใช้ DESC ใน DB2 ใช้ describe &lt;br /&gt;&lt;pre name="code" class="sql"&gt;&lt;br /&gt;describe select * from  employee;&lt;br /&gt;describe table employee;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Current Date&lt;/span&gt;&lt;br /&gt;ใน Oracle ใช้ SYSDATE ใน DB2 ใช้ current timestamp นอกจากนั้นยังมี current time, current date&lt;br /&gt;&lt;pre name="code" class="sql"&gt;&lt;br /&gt;select current timestamp from sysibm.sysdummy1;&lt;br /&gt;select current time from sysibm.sysdummy1;&lt;br /&gt;select current date from sysibm.sysdummy1;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Limit row&lt;/span&gt;&lt;br /&gt;ใน Oracle มี rownum ใน DB2 ใช้ fetch&lt;br /&gt;&lt;pre name="code" class="sql"&gt;&lt;br /&gt;select * from emp&lt;br /&gt;order by firstnme&lt;br /&gt;fetch first 5 rows only;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Date function&lt;/span&gt;&lt;br /&gt;ใน Oracle ใช้ &lt;a href="http://blog.middleware.co.th/2008/01/extract-function.html"&gt;EXTRACT&lt;/a&gt; ใน DB2 ใช้ DAY, MONTH, YEAR นอกจากนี้ยังมี HOUR, MINUTE, SECOND&lt;br /&gt;&lt;pre name="code" class="sql"&gt;&lt;br /&gt;select day(current timestamp) from sysibm.sysdummy1;&lt;br /&gt;select month(current timestamp) from sysibm.sysdummy1;&lt;br /&gt;select year(current timestamp) from sysibm.sysdummy1;&lt;br /&gt;select hour(current timestamp) from sysibm.sysdummy1;&lt;br /&gt;select minute(current timestamp) from sysibm.sysdummy1;&lt;br /&gt;select second(current timestamp) from sysibm.sysdummy1;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1638080862489455885-8282738329040464696?l=phamonyut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Phamonyut/~4/Mov28gQ2yYE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://phamonyut.blogspot.com/feeds/8282738329040464696/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://phamonyut.blogspot.com/2009/05/db2-tip.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/8282738329040464696?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/8282738329040464696?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Phamonyut/~3/Mov28gQ2yYE/db2-tip.html" title="DB2 Tip" /><author><name>Phamon P</name><uri>https://profiles.google.com/105136402217293967127</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh3.googleusercontent.com/-2AzJSisfnE0/AAAAAAAAAAI/AAAAAAAAAtA/koK-fzCuwVc/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://phamonyut.blogspot.com/2009/05/db2-tip.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkYDSHsycSp7ImA9WxJSFU0.&quot;"><id>tag:blogger.com,1999:blog-1638080862489455885.post-5781485512728453816</id><published>2009-05-05T12:04:00.005+07:00</published><updated>2009-05-05T12:09:39.599+07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-05T12:09:39.599+07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Data Warehouse" /><title>Data Warehouse Overview</title><content type="html">ข้อมูลหลายแหล่ง &lt;br /&gt;พูดในมุมมองที่หลากหลาย &lt;br /&gt;แต่สุดท้ายก็พูดถึงตัวเดียวกัน&lt;br /&gt;สรุปแล้วบันทึกประเด็นที่สำคัญ&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_al1ANReYFEE/Sf_JrC4XUgI/AAAAAAAAAWY/EWkdhG4VIRk/s1600-h/Data+Warehouse.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 372px; height: 400px;" src="http://1.bp.blogspot.com/_al1ANReYFEE/Sf_JrC4XUgI/AAAAAAAAAWY/EWkdhG4VIRk/s400/Data+Warehouse.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5332202225174794754" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1638080862489455885-5781485512728453816?l=phamonyut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Phamonyut/~4/RkjW9Zrck5g" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://phamonyut.blogspot.com/feeds/5781485512728453816/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://phamonyut.blogspot.com/2009/05/data-warehouse-overview.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/5781485512728453816?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/5781485512728453816?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Phamonyut/~3/RkjW9Zrck5g/data-warehouse-overview.html" title="Data Warehouse Overview" /><author><name>Phamon P</name><uri>https://profiles.google.com/105136402217293967127</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh3.googleusercontent.com/-2AzJSisfnE0/AAAAAAAAAAI/AAAAAAAAAtA/koK-fzCuwVc/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_al1ANReYFEE/Sf_JrC4XUgI/AAAAAAAAAWY/EWkdhG4VIRk/s72-c/Data+Warehouse.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://phamonyut.blogspot.com/2009/05/data-warehouse-overview.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUcGSXc4eip7ImA9WxJSEk4.&quot;"><id>tag:blogger.com,1999:blog-1638080862489455885.post-171833307471973009</id><published>2009-04-30T08:33:00.004+07:00</published><updated>2009-05-02T09:57:08.932+07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-02T09:57:08.932+07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><title>POP3 check new mail</title><content type="html">การดึงเมล์โดยใช้ protocol POP3 กับ IMAP4 มีความแตกต่างกันพอสมควรทั้งในแง่การ implement หรือคุณสมบัติต่างๆ ปัญหาอย่างนึงของ POP3 คือไม่สามารถคุยกับ mail server เพื่อดึงเฉพาะเมล์ใหม่ได้ &lt;br /&gt;เราอาจแก้ปัญหานี้ได้โดยการเข้าไปคุยกับ mail server เพื่อดึงเฉพาะ header มาตรวจสอบก่อน แต่ประเด็นของมันจึงอยู่ที่ขนาดของ header แทน ถ้าขนาดไม่กี่ kb ก็คงไม่เป็นไรแต่ถ้าขนาดใหญ่ถึง mb ดังนั้นการแก้ปัญหาด้วยการตรวจสอบจาก header จึงไม่ใช่แนวทางแก้ปัญหาที่ดี&lt;br /&gt;ทางออกของปัญหานี้จะใช้การตรวจจาก uid (unique identify) แทนเพราะมันมีขนาดเล็กไม่ต้องกังวลเรื่องขนาดของข้อมูลตอนส่ง message&lt;br /&gt;ตัวอย่าง (ตัด code มาบางส่วน)&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;Message[] message = folder.getMessages();&lt;br /&gt;POP3Folder pop3Folder = (POP3Folder)folder;&lt;br /&gt;FetchProfile fetchProfile = new FetchProfile();&lt;br /&gt;fetchProfile.add(UIDFolder.FetchProfileItem.UID);&lt;br /&gt;pop3Folder.fetch(message, fetchProfile);&lt;br /&gt;&lt;br /&gt;for (int i = 0; i&amp;lt;message.length; i++) {&lt;br /&gt; String uid = pop3Folder.getUID(message[i]);&lt;br /&gt; if (isNewMessage(uid)) {&lt;br /&gt;  // blah blah....&lt;br /&gt; } &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;ส่วนใน method isNewMessage(uid) ก็ส่งค่า uid เข้าไปตรวจจาก uid ที่เรามีอยู่แล้วโดยอาจเก็บไว้ใน database หรือ file system ก็ได้ตามสะดวก&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1638080862489455885-171833307471973009?l=phamonyut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Phamonyut/~4/fMUvYy0UAck" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://phamonyut.blogspot.com/feeds/171833307471973009/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://phamonyut.blogspot.com/2009/04/pop3-new-mail.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/171833307471973009?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/171833307471973009?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Phamonyut/~3/fMUvYy0UAck/pop3-new-mail.html" title="POP3 check new mail" /><author><name>Phamon P</name><uri>https://profiles.google.com/105136402217293967127</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh3.googleusercontent.com/-2AzJSisfnE0/AAAAAAAAAAI/AAAAAAAAAtA/koK-fzCuwVc/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://phamonyut.blogspot.com/2009/04/pop3-new-mail.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkQGSHYyfyp7ImA9WxJTGUo.&quot;"><id>tag:blogger.com,1999:blog-1638080862489455885.post-2049082734396502761</id><published>2009-04-29T08:11:00.000+07:00</published><updated>2009-04-29T08:58:49.897+07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-29T08:58:49.897+07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><title>Google Calendar API</title><content type="html">ความสามารถของ Google Calendar มีประโยชน์มากมายอย่างที่ทราบกันดี ทาง Google ก็เปิดช่องทางให้เราสามารถเข้าถึงบริการของเค้าได้ง่าย &lt;br /&gt;จึงขอลอง เพื่อเอามาประยุกต์ใช้กับโปรเจคใหม่ที่กำลังจะเกิดขึ้น&lt;br /&gt;ตัวอย่างนี้จะทำการสร้าง event และส่งเข้า Google Calendar ของเรา&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;import java.net.URL;&lt;br /&gt;import java.util.Calendar;&lt;br /&gt;import util.Constant;&lt;br /&gt;import com.google.gdata.client.calendar.CalendarService;&lt;br /&gt;import com.google.gdata.data.PlainTextConstruct;&lt;br /&gt;import com.google.gdata.data.calendar.CalendarEventEntry;&lt;br /&gt;import com.google.gdata.data.extensions.Reminder;&lt;br /&gt;import com.google.gdata.data.extensions.Reminder.Method;&lt;br /&gt;import com.google.gdata.util.AuthenticationException;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;public class GoogleCalendarUtil {&lt;br /&gt; &lt;br /&gt; public CalendarService authenticate(String username, String password) {&lt;br /&gt;  CalendarService myService = new CalendarService("exampleCo-exampleApp-1");&lt;br /&gt;  try {&lt;br /&gt;   System.out.println("authenticate: start");&lt;br /&gt;   myService.setUserCredentials(username, password);&lt;br /&gt;   System.out.println("authenticate: success");&lt;br /&gt;  } catch (AuthenticationException e) {&lt;br /&gt;   e.printStackTrace();&lt;br /&gt;  }&lt;br /&gt;  return myService;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public void createEvent(CalendarService service, String content, String username) {&lt;br /&gt;  try {&lt;br /&gt;   &lt;br /&gt;   URL postURL = new URL("http://www.google.com/calendar/feeds/" + username + "/private/full");&lt;br /&gt;   &lt;br /&gt;   Calendar calc = Calendar.getInstance();&lt;br /&gt;   calc.add(Calendar.MINUTE, 1);&lt;br /&gt;   String timeStartEvent = calc.get(Calendar.HOUR_OF_DAY) + ":" + calc.get(Calendar.MINUTE);&lt;br /&gt;//   calc.add(Calendar.MINUTE, 1);&lt;br /&gt;   String timeEndEvent = calc.get(Calendar.HOUR_OF_DAY) + ":" + calc.get(Calendar.MINUTE);&lt;br /&gt;     &lt;br /&gt;   System.out.println("addEvent: start");&lt;br /&gt;   CalendarEventEntry myEntry = new CalendarEventEntry();&lt;br /&gt;   content += " " + timeStartEvent + "-" + timeEndEvent;&lt;br /&gt;   System.out.println("content: " + content.toString());&lt;br /&gt;   myEntry.setContent(new PlainTextConstruct(content.toString()));&lt;br /&gt;   myEntry.setQuickAdd(true);&lt;br /&gt;   &lt;br /&gt;   CalendarEventEntry insertedEntry = service.insert(postURL, myEntry);&lt;br /&gt;&lt;br /&gt;   Reminder reminder = insertedEntry.getReminder().get(0);&lt;br /&gt;   reminder.setMinutes(0);&lt;br /&gt;   reminder.setMethod(Method.SMS);&lt;br /&gt;   insertedEntry.getReminder().set(0, reminder);&lt;br /&gt;   insertedEntry.update();&lt;br /&gt;   System.out.println("addEvent: complete");&lt;br /&gt;  } catch (Exception e){&lt;br /&gt;   e.printStackTrace();&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public static void main(String[] args) {&lt;br /&gt;  String username = "username";&lt;br /&gt;  String password = "password";&lt;br /&gt;  String content = "hello";&lt;br /&gt;  GoogleCalendarUtil helloGoogle = new GoogleCalendarUtil();&lt;br /&gt;  CalendarService service =  helloGoogle.authenticate(username, password);&lt;br /&gt;  helloGoogle.createEvent(service, content, username);&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;เมื่อทำงานเสร็จคุณจะได้ sms แจ้ง event ที่ใส่เข้าไป &lt;br /&gt;แน่นอนตรงจุดนี้ทำให้เราสามารถนำไปประยุกต์กับบริการต่่างๆ ได้อีกเยอะ&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1638080862489455885-2049082734396502761?l=phamonyut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Phamonyut/~4/Dhj8bJ7gxC0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://phamonyut.blogspot.com/feeds/2049082734396502761/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://phamonyut.blogspot.com/2009/04/google-calendar-api.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/2049082734396502761?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/2049082734396502761?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Phamonyut/~3/Dhj8bJ7gxC0/google-calendar-api.html" title="Google Calendar API" /><author><name>Phamon P</name><uri>https://profiles.google.com/105136402217293967127</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh3.googleusercontent.com/-2AzJSisfnE0/AAAAAAAAAAI/AAAAAAAAAtA/koK-fzCuwVc/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://phamonyut.blogspot.com/2009/04/google-calendar-api.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU8GSXg-eip7ImA9WxJTFUg.&quot;"><id>tag:blogger.com,1999:blog-1638080862489455885.post-8347186251180794961</id><published>2009-04-23T18:35:00.005+07:00</published><updated>2009-04-24T14:23:48.652+07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-24T14:23:48.652+07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><title>Receiver Mail via Gmail POP3</title><content type="html">รับ mail ของ gmail ผ่าน pop3&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;import java.util.Properties;&lt;br /&gt;import javax.mail.Folder;&lt;br /&gt;import javax.mail.Message;&lt;br /&gt;import javax.mail.MessagingException;&lt;br /&gt;import javax.mail.Session;&lt;br /&gt;import javax.mail.Store;&lt;br /&gt;import javax.mail.URLName;&lt;br /&gt;import com.sun.mail.pop3.POP3SSLStore;&lt;br /&gt;&lt;br /&gt;public class SimpleReceiver {&lt;br /&gt;&lt;br /&gt; public static void main(String[] args) {&lt;br /&gt;  try {&lt;br /&gt;   String popServer = "pop.gmail.com";&lt;br /&gt;   String user = "yourmail@gmail.com";&lt;br /&gt;   String password = "yourpassword";&lt;br /&gt;   System.out.println("receive mail");&lt;br /&gt;   receive(popServer, user, password);&lt;br /&gt;   System.out.println("--- complete ---");&lt;br /&gt;  } catch (Exception ex) {&lt;br /&gt;   ex.printStackTrace();&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public static void receive(String popServer, String user, String password) {&lt;br /&gt;  Store store = null;&lt;br /&gt;  Folder folder = null;&lt;br /&gt;  try {&lt;br /&gt;   String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";&lt;br /&gt;   Properties props = System.getProperties();&lt;br /&gt;   props.setProperty("mail.pop3.socketFactory.class", SSL_FACTORY);&lt;br /&gt;   props.setProperty("mail.pop3.socketFactory.fallback", "false");&lt;br /&gt;   props.setProperty("mail.pop3.port", "995");&lt;br /&gt;   props.setProperty("mail.pop3.socketFactory.port", "995");&lt;br /&gt;&lt;br /&gt;   URLName url = new URLName("pop3", popServer, 995, "", user, password);&lt;br /&gt;   &lt;br /&gt;   Session session = Session.getDefaultInstance(props, null);&lt;br /&gt;&lt;br /&gt;   System.out.println("connect");&lt;br /&gt;   store = new POP3SSLStore(session, url);&lt;br /&gt;   store.connect();&lt;br /&gt;&lt;br /&gt;   System.out.println("folder");&lt;br /&gt;   folder = store.getDefaultFolder();&lt;br /&gt;   folder = folder.getFolder("inbox");&lt;br /&gt;   if (folder == null) {&lt;br /&gt;    throw new Exception("No default folder");&lt;br /&gt;   }&lt;br /&gt;   &lt;br /&gt;   try {&lt;br /&gt;    folder.open(Folder.READ_WRITE);&lt;br /&gt;   } catch (MessagingException ex) {&lt;br /&gt;    folder.open(Folder.READ_ONLY);&lt;br /&gt;   }&lt;br /&gt;   &lt;br /&gt;   System.out.println("message: " + folder.getMessageCount());&lt;br /&gt;   System.out.println("new: " + folder.getNewMessageCount());&lt;br /&gt;   &lt;br /&gt;   Message[] message = folder.getMessages();&lt;br /&gt;//   FetchProfile fp = new FetchProfile();&lt;br /&gt;//   fp.add(FetchProfile.Item.ENVELOPE);&lt;br /&gt;//   folder.fetch(message, fp);&lt;br /&gt;   for (int i = 0; i&amp;lt;message.length; i++) {&lt;br /&gt;    String ct = message[i].getContentType();&lt;br /&gt;    if (message[i].isMimeType("text/plain")) {&lt;br /&gt;     System.out.println("message [" + i + "]:" + message[i].getContent());&lt;br /&gt;    } else {&lt;br /&gt;     System.out.println("message [" + i + "]:" + "not plain text.");&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;   }&lt;br /&gt;   &lt;br /&gt;  } catch (Exception ex1) {&lt;br /&gt;   ex1.printStackTrace();&lt;br /&gt;  } finally {&lt;br /&gt;   try {&lt;br /&gt;    if (folder != null) folder.close(false);&lt;br /&gt;    if (store != null) store.close();&lt;br /&gt;   } catch (Exception ex2) {&lt;br /&gt;    ex2.printStackTrace();&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1638080862489455885-8347186251180794961?l=phamonyut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Phamonyut/~4/fOVrSWg-tRU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://phamonyut.blogspot.com/feeds/8347186251180794961/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://phamonyut.blogspot.com/2009/04/receiver-mail-via-gmail-pop3.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/8347186251180794961?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1638080862489455885/posts/default/8347186251180794961?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Phamonyut/~3/fOVrSWg-tRU/receiver-mail-via-gmail-pop3.html" title="Receiver Mail via Gmail POP3" /><author><name>Phamon P</name><uri>https://profiles.google.com/105136402217293967127</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh3.googleusercontent.com/-2AzJSisfnE0/AAAAAAAAAAI/AAAAAAAAAtA/koK-fzCuwVc/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://phamonyut.blogspot.com/2009/04/receiver-mail-via-gmail-pop3.html</feedburner:origLink></entry></feed>

