2012年2月29日

DocPad - static web sites generator using Node.js

近來可以動態產生的「靜態網站」(static web site)逐漸被廣泛採用,主要是針對一些需求簡單的網站,讓網站設計師不必為了簡單的功能而開發維護後端程式、資料庫,因為有很多功能藉由 JavaScript 在前端就可以辦到,而且許多免費的服務可以組裝應用(例如留言回應功能用 Disqus、訪客統計功能用 Analytics)。

但是要動態產生靜態網站,還是要藉由程式的幫忙,雖然最後都一樣產生 HTML,放到 Server 之後沒什麼差別,但是產生的過程還是需要動用開發環境。因此不同程式語言的愛好者,可能會偏好使用自己熟悉的開發環境有關的工具,例如 Ruby 有很強大的 Jekyll,Python 也有很棒的 Hyde

那...新興的 Node.js 有什麼呢?

用 Google 不難發現已經有 Node 愛好者建立以下專案:

  • https://github.com/caolan/petrify
  • https://github.com/bevry/docpad
  • https://github.com/creationix/wheat


其中,我比較喜歡的是 docpad 這個專案,因為個人偏好的 Markdown、CoffeeScript、SASS/LessCSS ... 它都已經支援。

安裝:

sudo npm install -g docpad

建立專案(資料夾):

mkdir helloweb
cd helloweb

接下來的步驟有一點詭異,需要動用 sudo(第一次執行 docpad 的初始化,需要 root 權限,以加裝 plugins 及 skeletons)

sudo docpad run

跑完可能產生一些錯誤訊息,多等一下確定它真的跑完,再用 ctrl+c 終止。

因為上個步驟使用 sudo,因此產生的檔案都是 root permissions,先用 chown 切換回目前的 user。

sudo chown -R USERNAME:GROUP *

然後,就可以啟動本地測試伺服器(預設 port = 9778,唸起來很像在罵髒話)。用瀏覽器打開:

http://localhost:9778/

接下來,有興趣的朋友,請參考 DocPad 專案的 README,並協助改善這個專案。

https://github.com/bevry/docpad

目前這篇文章並不打算分享更多教學,因為很多功能一試就爆炸...,暫時先留給大家自己練功了。

雖然 DocPad 已經是 Node.js 目前相對比較完整的 static site generator,但未來還有很長遠的路要走,也因此適合想練功玩 Node.js 的朋友。如果急著要產出一個網站,還是多參考 Jekyll 吧!


便宜容易上手的迷你遙控直升機

228的四天連假訂了些小玩具,其中一個就是迷你遙控直升機。在 Y! 拍購買 $590+$60運費 入手。

一開始並沒有抱什麼期待,因為3年前也曾買過差不多價位的遙控直升機,只覺得飛得起來就算不錯了。但是開箱之後,很驚訝機身的金屬和塑膠零件質感不錯,雖然算不上完美,但也能用精美來形容,外觀有很高的C/P值。

經過數十次撞牆和墜機,主翼稍有磨損,但不影響飛行。

這是尾風葉、後馬達,包裝盒內附一組備用。

中間的馬達。機身的組裝很扎實。

前馬達。

遙控器。這是三動的入門機種,很容易上手,基本上第一次玩就可以輕易空中停懸。

內附USB充電線,可以連接電腦的USB孔。用手機的行動電源也可以充電,這是出外更棒的選擇。
雖然是便宜的遙控玩具,但網拍也買得到消耗品,如主翼、鋰電池、主軸、尾風葉...等。而且整台玩壞最多也不過幾百元花費,算是很超值的入門遙控直升機。

 

最近新聞剛好有報導用 iPad / iPhone / Android 手機操作遙控直升機,該款 App 的名稱是「i.Copter Syma」,搭配的遙控直升機為 Syma(司馬)的機型(如 S107),手機的部份必須加裝紅外線發射器(連接音源孔),發射器和直升機在網拍可以找到,而 App 則需要從 App Market(Store)搜尋下載。



2012年2月28日

Node.js on Windows 建議安裝 Cygwin 以相容 unix-like 開發環境

Node.js 早期(<=0.4.6)並沒有提供編譯過的 Windows 版本,因此許多教學都建議安裝 Cygwin,再下載或自行編譯一份。

雖然新的 Node.js 已經提供 Windows 專用版本(含安裝程式),也內建 NPM 工具。

不過,目前還是建議開發者考慮將 Cygwin 裝上。主要的考量是許多 module 在開發時,並沒有考慮到跨平台的需求,而直接在程式碼中執行 unix-like 指令或程式如 bash,這會造成有些 module 在 Windows 系統執行發生問題。

因為 node modules 通常都是 JavaScript 撰寫,在 node 下執行不會有問題。最常發生問題的階段是在使用 npm 安裝新 module 時,因為安裝的 script 不慎呼叫了 Windows 剛好沒提供的指令。(在 Linux 及 Mac OS X 環境下,這些指令通常都是系統內建,所以 module 維護者偷懶也是有道理的!)

安裝 Cygwin 可以讓 Windows 也能執行常用的 unix-like 指令,第一次安裝只需要安裝 base 預設選取的套件。

http://www.cygwin.com/

預設情況下,安裝後仍需要打開 Cygwin Shell 才能使用 unix-like 指令。

接下來,可以將 Cygwin 的 bin 資料夾加入 PATH 環境變數中,例如:

c:\cygwin\bin

如此一來,就可以在 Windows 的「命令提示字元」執行 npm 指令,並且相容 script 中使用的 unix-like 指令。

雖然很多人(包括我)都不是很喜歡用 Cygwin,畢竟,把 Windows 格式化重灌 Ubuntu 才是開發的王道;但如果遇到不得已的情況,請記得還有 Cygwin 可以幫你 hold 住。

2012年2月27日

Eclipse 3.7.2 + Android SDK 4.0.x 開發環境設定小筆記

利用 228 連假,宅在家開發 Android/Arduino 遙控車。雖然 Arduino 的部份異常順利,一個晚上就完成自走車的測試程式;但使用 Eclipse 3.7.2 + Android SDK 4.0.x 卻發現問題接二連三,因此有了這個小筆記...

----

問題:

  • Error generating final archive: Debug Certificate expired on ...


解決方法:

  • 刪除 ~/.android 資料夾


----

問題:

  • Eclipse 3.7 以上打包 .apk 檔產生錯誤:
  • trouble writing output: null
    Conversion to Dalvik format failed with error 2

解決方法:

  • 更新 proguard 4.6 以上版本(下載解壓縮覆蓋 $ADK_HOME/tools/proguard)
  • 移除 eclipse.ini 的 -XX:+AggressiveOpts 設定 



----

問題:

  • Eclipse 執行 .apk 打包、發佈及除錯,速度緩慢或沒有回應。
解決方法:
  • 修改 eclipse.ini 記憶體相關配置
    • -XX:PermSize=512m
    • -XX:MaxPermSize=512m
    • -Xms512m
    • -Xmx1024m

2012年2月21日

使用 Groovy 的 MarkupBuilder 輸出 XML/HTML/XHTML 原始碼

Groovy 可以很容易設計 Builders/DSL,在 Java 程式要輸出 XML 資料,需要用到 SAS 等複雜的函式庫,這使得許多開發人員都用偷吃步的方法,像是:

System.out.println("<root><data>something</data></root>");

但是遇到複雜的資料結構,以及需要處理 Escape Characters 時,就很容易不斷踩到地雷。

當 Java 開發者,開始改用 Groovy 讓軟體開發工作更敏捷,就不能錯過 MarkupBuilder。

Groovy 提供許多種 Builder,基本上這就是一種 DSL(Domain-Specific Languages),讓開發者可以使用更簡單易懂的程式語法,來解決特定的用途。

而 MarkupBuilder 就是產生 XML 專用的 Groovy Builder,以下有關 MarkupBuilder 的文件,可以看到 Groovy 如何輕鬆地處理 XML 產生的工作。

如果,我們要使用 MarkupBuilder 輸出 HTML/XHTML,則只需要在加上一些設定:
  • html.doubleQuotes = true
    屬性使用慣用的雙引號,例如 class="icons"。
  • html.expandEmptyElements = true
    讓標籤成對顯示。
  • html.omitEmptyAttributes = false
    不要移除沒有值的屬性。
  • html.omitNullAttributes = false
    不要移除值為 NULL 的屬性。

另外,mkp.yield 與 mkp.yieldUnescaped 是特殊的用法。當遇到某些內容需要直接輸出,而不要被包含在子標籤中,就可以利用 yield;而 yieldUnescaped 則是直接輸出未經過 escape 處理的內容。


選購嬰兒推車心得筆記 Aprica Karoon 629

上週六到嬰幼兒用品的採購聖地---新竹朝聖,雖然養小孩的日子離我還很遙遠,但朋友最近順利生得龍子,嬰兒車短暫成為我的新敗家目標,剛好利用這次選購嬰兒車的機會,多瞭解...一個全新的敗家領域。

採購行程的第一站,是網路傳說中的「藍印子」;這家生意好到很誇張的地步,附近的停車位很難找,不管內外都很像倉庫的門市,人擠得像沙丁魚,走路都要側身才行,結帳也要大排長龍。但不管再多不方便,都不會減少它「便宜、很便宜、超級便宜」帶來的致命吸引力;一定要空車來才能滿載而歸。

藍印子的嬰兒車在二樓有展示區,數量並不少,主要是「TonyBear(湯尼熊)」及「Merissa(美瑞莎)」幾個品牌。現場展示的推車,基本上都是平價的實用款,如果預算在3000-5000元,應該可以找到滿意的款式。

藍印子資訊
  • 電話:03-5311260
  • 地址:新竹市北區西大路888號
  • 營業時間:10:00~22:00
在藍印子我們對嬰兒車還沒什麼概念,只聽過「Combi(康貝)」及「Zooper」等品牌,藍印子的服務人員說他們沒有賣,但一樓的客訂區有「Aprica」的型錄可以選購。

我們購買嬰兒車的預算約1萬元左右,想要買到現貨、同時也不想只看看型錄就下訂單,所以繼續前往另一家傳說中的熱門店---POMPOM(澎彭)。

POMPOM 的店面比較小,但對面是博愛國小,路旁停車較方便。有些藍印子缺貨的商品,到 POMPOM 可能有機會找到。例如,網友推薦第一名的「泰爾茂迷你耳溫槍」(MamiBuy 網站唯一推薦的耳溫槍),在藍印子一支都不剩,但我們到 POMPOM 還有看到兩支現貨。

以價格來說,藍印子可能便宜一些;但遠道而來的朋友,還是可以順便到 POMPOM 逛逛,兩家店距離大概不到 20 分鐘車程。

POMPOM資訊
  • 電話:03-5537699,傳真03-5559975
  • 地址:新竹縣竹北市博愛街123號
POMPOM 的手推車主要是「Merissa」及「Chicco」等品牌,現場展示的款式很少。

準備要離開的時候,我打開 iPad 把新竹有賣嬰兒車的 Y! 拍賣搜尋一遍,同時也從論壇尋找較多人推薦的品牌和型號,這時發現「Maclaren(瑪格羅蘭)」的評價似乎不錯,它的 Techino XT 這款型號,有不少網友推薦,拿來和 Combi 等品牌比較,也略有勝出的好評。

為了找到 Techino XT,再用 Google 爬文一次,結果發現「俏媽咪」這家店,和 POMPOM 同樣位於竹北,大約也是20分鐘以內的車程可以到達。

俏媽咪資訊
  • 總店:新竹市北大路285-1號 
  • 電話:(03)5212990 
  • 傳真:(03)5260581 
  • 營業時間:10:00~22:00 < 全年無休 > 
  • 竹北店(非國卡特店)
  • 店址:新竹縣竹北市莊敬南路100號
  • 電話:(03)5505158
  • 營業時間:10:00~22:00 < 全年無休 >
相較之下,俏媽咪算是最好逛的一家店,商品的陳列整齊、款式也較齊全。

以嬰兒推車來說,在俏媽咪選購輕鬆得多,因為現場展示的品牌包括「Combi」、「Aprica」、「Merissa」、「Graco」、「Chicco」、「Porsche」、「Maclaren」...等,而且款式陳列也很多。

在現場比較、試用之後,Techino XT 的操控感不錯、組裝也牢靠,可是比較起來,Combi 和 Aprica 的款式比較多可以挑,其中某幾款的設計比較吸引我的目光。

其中有一款 Aprica Karoon Plus 只有 4.6 公斤的重量,有著蠻亮眼的設計,不知道是因為目光停留在這台太久,還是徘徊在前面太多次,向店員詢問時,她也是推薦這一台;雖然重量很輕,但是整體很兼顧不會搖晃,而一旁的 Combi 同樣是雙向設計,但搖晃的問題就略顯嚴重。

除了重量輕之外,Karoon 的3D吸震系統,看起來也是相當不錯的設計,車輪本身可以靠左右傾斜來減少路面顛簸的衝擊,可能幫助減少熟睡的寶寶從睡夢中醒來。

Karoon 是 2012 年新上市的系列,俏媽咪店員說這款在預購時就已經有很多人下訂;目前在 Aprica 雲端購物中心,Karoon 確實還是在預購階段。

當我們正考慮這款推車時,店員拿出一本型錄,推薦另一款重量更輕(3.6公斤)、價格更令人心動的 Aprica Karoon 629,它的輪子比 Karoon Plus 小一號,配備也比較精簡;但足足少了1公斤重量,只要一根手指頭就能輕易抬起,是壓死駱駝的最後一根稻草。

Karoon 629 在現場沒有展示,但是竹北店有現貨,所以可以請店員拆箱。實際試用後,感覺 Karoon 629 不只輕巧、好推,秒收的設計也相當順手,且收合後還可以直立、拖行,座椅、布料、管材的質感,也符合這價位應有的水準。

因為俏媽咪給的折扣已經相當優惠,價格也透明化,所以沒有再做更多比較就決定帶走一台。我想,這應該算是一次蠻愉快的購物經驗。

這段影片是 Aprica 公司提供的一段 Karoon 629 系列介紹:


結論是,買手推車相當需要現場實際試用、比較,網路的資訊只能幫助你知道有哪些品牌、主觀的優缺點認知,以及可以到哪買、多少價格才算合理。但個人認為搜尋、爬文、找拍賣網站,或是參考論壇及網站的推薦,只能算是做足功課,最重要的還是要有耐心地到賣場實際試推比較,視覺和手感自然會決定出什麼商品才真正合你意,而且...網路並不一定比賣場便宜,以嬰幼兒用品這種單靠口耳相傳就有做不完生意的市場來說,網路目前似乎還不是廠商爭奪的行銷管道。

2012年2月20日

直達 Java 虛擬機器之 Eclipse 調校優化篇

在書店的角落發現一本剛出版(2012/1月)的「直達Java虚擬機器-JVM進階與應用」,難得有進階的 Java 中文書,作者還是華人(很可惜不是台灣人),手癢就帶了一本回家。

這本書是譯自簡體版「深入理解Java虚拟机:JVM高级特性与最佳实践」,對於需要調校 Java EE 系統效能的開發者,算是一本實用的參考書。有些內容像是自己編譯 Open JDK 也許用不上,但是在更深入認識 JVM 與透過工具監視、調校 Java 程式的部份,應該可以幫助讀者節省不少研究的時間。

讀到第五章「調校優化案例分析與實戰」,作者蠻有趣地用了 Eclipse 的啟動時間最佳化當範例,剛好我最近手邊的專案開始用 Gradle + Eclipse 開發,又開始面臨肥大 Eclipse 效能不彰問題;記得每一次筆電砸重金升級記憶體,都是為了讓 Eclipse 跑快點。

書中作者詳細說明從一開始啟動 Eclipse 需要15秒,接著一步步分析、調整設定,改善到只需要7秒的時間。而其中最關鍵的就是記憶體與垃圾回收(GC,Garbage Collection)配置;GC 相當耗時,但是在記憶體充足的情況下, 根本用不到那麼多次 GC 動作。如何分析哪些動作消耗多少時間,是這一章主要在講的內容。

這本書的範例程式及設定無法從網路取得,要自己打字挺麻煩,因此我將參考書本最終範例修改的 eclipse.ini 提供給大家參考。

https://gist.github.com/1868507
(和書本範例有些差異,可自行依照不同電腦給予最佳化配置)

2012年2月17日

淺談私有 CDN(內容傳遞網路)佈署



當 Web Application(以下簡稱 WebApp)大量取代傳統桌面應用程式,資訊服務類型的軟體公司,需要解決的「重複與浪費」問題,就不只有軟體架構本身;相信大家都清楚軟體架構本身,需要模組化、元件化,讓寫好的功能(程式碼)可以盡可能再利用,最好有很多 Plugins 或 Modules,當有需要的時候就可以拿來使用或擴充。

資訊服務公司通常不會只有一或少數幾項軟體專案,而是會建立非常多系統。因此,重複造成的浪費問題就更加嚴重。

一般來說,經過編譯的程式或者原始碼本身,都不太會有體積的問題。例如封裝成 .dll 或 .jar 之後,就可以再不同專案中引用。搭配好的自動化建置機制,通常我們不需要將外部共用的模組(或元件),放到專案的版本控制系統,只有進行測試或最後發佈時,才需要把這些檔案暫時加進來。

但是 WebApp 包含的內容並不只有程式,還有許多比較像是「資源」的東西。例如:

  • jQuery core + jQuery UI + .... 一大票 jQuery Plugins
  • Ext JS + 一大票 Widgets ...
  • ICON library + ... 一大票圖庫
  • 自行開發維護的 JavaScript、CSS、ICON 共用 libraries 等
如果沒有好的解決辦法,這些資源除了被重複發佈到很多網站伺服器,造成儲存空間及頻寬的浪費,甚至也會被加到專案版本控制系統的 repository。

舉例來說,Ext JS 4 的原始碼 ext-4.0.7-gpl 解壓縮後體積高達 166MB,為了某些情況除錯方便,我們可能不會只保留必要及壓縮最佳化的檔案,而是需要完整的檔案。除非使用的 Framework 有良好的 Plugins 機制,可以引用 Ext JS 但不會實際被加到專案資料夾(只有在建置 test 或 production 階段才會加入暫存的區域);否則,一般來說都是直接在 WebApp 的資料夾中,也保存一份完整的副本。

相信有很大一部份比例的專案,都是直接就把這些資源加到專案的 repository,一起發佈到版本控制系統;這是最簡便的方式,可是也是最浪費資源。這麼做會帶來一些問題:
  1. 不屬於專案的東西,卻要納入專案的版本控管。佔空間(雖然現在硬碟很便宜,這問題顯得不大)、維護麻煩。
  2. 專案的 repository 變得十分肥大,真正屬於專案的部份也許不到 30MB,但整體卻超過 100MB。對於版本較舊的 SVN 來說,執行速度可能隨檔案愈多愈複雜而變得愈慢。
  3. 不管是新加入的成員,或經歷一次災難後需要重新取出(checkout)完整的檔案,浪費伺服器資源及網路頻寬,最重要的寶貴時間也會因此白白浪費。
  4. 假設一家資訊服務公司有 20 個系統,就造成資源 20 倍浪費。
  5. 對於導入持續整合機制的專案來說,又造成更多的浪費。
  6. 像是 GitHub 等專案托管服務,有檔案容量的限制,佔空間就是個需要考慮的問題。
即使在開發階段,解決資源重複造成的浪費問題,例如可以不必將外部資源納入版本控管;但是最終打包發佈時,放到正式的伺服器運作,還是需要加入這些檔案(可以透過最佳化讓檔案少一些、體積小一些),最終,浪費的問題還是存在。

對於資訊服務公司來說,建置私有 CDN 不僅可以得到很多好處,而且在雲端服務價格低廉的時代,更是很難找到理由不這麼做。

CDN(內容傳遞網路,content delivery network)的概念,是指一種透過網際網路互相連接的電腦網路系統,提供高效能、可擴展性、及低成本的網路將內容傳遞給使用者。

簡單地說,我們可以建置遠端的檔案服務伺服器,將 WebApp 專案常需要用到的靜態資源,都放到這些伺服器,讓這些伺服器維持高可用性、擴展性,提供足夠的負載量;如此一來,所有的專案共用的 WebApp 資源,就可以佈署到這些伺服器。

建立 CDN 的優點很多,包括開發人員可以快速利用(不必每次都要重新下載、建立 library),減少遠端佈署需要的時間,讓不同專案之間可以共用資源,降低正式伺服器的存取及頻寬消耗,幫助需要高負載的 WebApp 減輕負擔,...

事實上,Google 就建立了自己的 CDN,提供包含 jQuery、jQuery UI、Prototype 等網站常用到的資源,並且也把這個 CDN 免費開放給所有開發者使用。

不過,免費的 CDN 通常不會剛好有你需要的所有東西;以 Ext JS 來說,Google 僅提供核心部份 Ext Core,而 Sencha 雖然也有為 Ext JS GPL 架設 CDN,但實測後發現經常有找不到檔案的情況。

對資訊服務公司來說,用其他人提供的 CDN 並不是個好辦法,因為哪天該 CDN 結束運作,或者已經不提供某個版本的資源,就會造成一些系統因此受連累而掛點。所以,建置私有 CDN 是比較好的方案。

一般來說,自己租用專線架設伺服器來做 CDN 並不划算,光是要達到資料及網路的備援,以及高可用性(要預防斷電斷網路天災人禍等問題),要付出的成本實在太高。

使用虛擬主機(Virtual Host 或 VPN)是個相對便宜的方法,但是一般的虛擬主機都有容量、頻寬流量限制,以及不管有沒有用到它,都需要付基本的月租費。

所以,本文介紹的方案,是採用 Amazon S3(Simple Storage Service)及 CloudFront。

Amazon S3 的主要優點,包括它是採「使用量付費」,計費內容包括儲存空間、存取次數、傳輸量三項。因此若剛開始只需要放 500MB 的檔案,就只需要為這有用到的儲存空間及傳輸量付費,註冊 S3 服務並不需要設定容量,即使未來可能成長到幾 TB 的容量,也不需要一開始就租賃旗艦級的方案,同時也不會有每月傳輸量限制的問題。

使用 S3 建立 CDN 的步驟很簡單:
  1. 建立 S3 Bucket(儲存空間),並將名稱設為 CDN 網址(如:cdn.yourname.com)
  2. 修改 DNS 設定,將網址透過 CNAME 指向 Bucket 的 End Point 網址
  3. 設定 Bucket 的 Web Site 為 Enabled
  4. 將要放到 CDN 的檔案如 Ext JS 等,上傳至 Bucket,並設為 Public
對於 Mac 及 Linux 的使用者來說,可以用 s3cmd 工具來管理檔案,這個軟體可以在 command line 下輕鬆將本地檔案,上傳或同步到指定的 S3 位址。

除了在建立 CDN 時可以用 s3cmd,如果遇到客戶因預算或速度考量,需要把專案整個搬遷到企業內部網路可以直接存取的伺服器,也可以利用 s3cmd 做一份 mirror,維持專案使用到的資源有一致的存取配置。

如果開發的 WebApp 是需要提供給大眾使用,甚至有來自世界各地的使用者,使用 S3 可以方便地搭配 CloudFront 建置全球化的 CDN。

CloudFront 不能儲存檔案,它是用來「傳遞」S3 或其他來源的檔案,透過分散在世界各地的資料中心(S3 的 Bucket),減少網路傳遞路徑的延遲。簡單地說,CloudFront 可以讓 S3 的檔案下載速度更快,而且傳輸費用也比 S3 便宜(包括傳輸費用+存取次數)。

因此,S3+CloudFront 用於架設私有 CDN 是相對划算的方案,只要依照實際使用量付費,若未來需求不斷提高,也不會有需要升級頻寬和儲存空間的問題。

2012年2月15日

解決 Gradle Fat Jar 簽章(jarsigner)的問題


Gradle 的 Cookbook 有提供一個 Fat Jar 範例,也就是除了將專案本身的 class 打包成 jar 檔外,也一併將其他相依的 jar 套件一起打包。

Create a fat jar in Gradle http://docs.codehaus.org/display/GRADLE/Cookbook#Cookbook-Includeallruntimedependencies

使用 ant.signjar 即可在 build.gradle 順便把 jarsigner 完成。

ant.signjar(alias: 'alias', keystore: 'keyfile', keypass: 'keypass', storepass: 'storepass', preservelastmodified: 'true', jar: "project-1.0.jar", destDir: 'signedDir')

但如果相依套件多起來,執行 jarsigner 可能會遇到這個錯誤:

jarsigner: unable to sign jar: java.util.zip.ZipException: duplicate entry: META-INF/LICENSE.txt

這是因為 jar 在打包時,並不會檢查檔案是否重複,但是 jarsigner 遇到重複的檔案就會出錯。

在 jar 的設定中加入一行 exclude 即可避免。

jar {
    //...
    exclude('META-INF/*.txt')
}

使用 Gradle 開啟 Jetty 的 AJP 協定 (Ajp13SocketConnector)

使用 Gradle + Jetty Plugin 可以快速建立 Java Web App 的開發與測試環境。

但是 jettyRun 或 jettyRunWar task 預設只會啟動 8080 的 Http Server,在某情況下,我們可能需要搭配 Apache 或 Nginx,不管是為了做 load balance 或是讓 local vm 可以對外提供服務,都會用到 AJP。

Jetty 或 Tomcat 等廣泛被使用的 JavaEE Container 都支援 AJP(Apache JServ Protocol) socket connector,它可以讓 Apache(或 Nginx)與 Jetty(或 Tomcat)之間的串接效果更好,包括更好的效能及 SSL 支援等。

關於 Tomcat 及 Nginx 的設定可以參考:

介紹 Jetty + AJP 的文章不少,例如 Eclipse Wiki 提供這篇(Jetty 新版本已由 Eclipse 托管):

不難發現 Jetty 要開啟 AJP 只是在設定中增加一個 Ajp13SocketConnector,但如果要用 Gradle 內建的 Jetty Plugin 完成這件事,用「gradle Ajp13SocketConnector」卻找不到什麼參考資料。

經過一番試驗,發現這個修改可以作用:
  1. 增加一個自訂的 src/main/resources/jetty.xml,對 Jetty Server 執行 addConnector 呼叫。
  2. 在 build.gradle 增加 jetty-ajp dependencies 及 jettyConfig、additionalRuntimeJars 設定。

如此一來,使用 Gradle 建置的 Java Web App,不僅可以輕鬆將 Jetty 用於測試階段,也可以實際透過 AJP 搭配 Apache/Nginx 提供服務。(正式產品還是建議先用 Gradle 打包成 .war 檔再 deploy 到 production server。)

https://gist.github.com/1832631

2012年2月14日

使用 CharacterEncodingFilter 解決 Java Web 的編碼問題

中文編碼在 Java Web 開發經常會碰到問題,所以這些設定很常見:

JSP:
contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"

Tomcat:
URIEncoding="UTF-8"

JAVA_OPT:
-Djavax.servlet.request.encoding=UTF-8 -Dfile.encoding=UTF-8

但即使有以上的設定,在 request.getParameter 取表單資料仍可能發生亂碼情況;網路上可以找到使用 getBytes 進行轉碼的寫法,但是在每次取值時才處理轉碼,會讓程式碼很不容易維護,例如將 Tomcat 改成 Jetty 時,可能就有不同處理方式(Jetty 預設為 UTF-8,通常不需要轉碼);

所以,最好的方法就是利用 Filter 進行統一的轉碼處理。

針對這個問題,我們建議使用 Spring Framework 的 CharacterEncodingFilter 解決問題。

這個 Filter 由 spring-web.jar 提供,若採用 Gradle 建置專案,只需要加入一行 dependencies 設定:

runtime 'org.springframework:spring-web:2.5.6'

若採用 Grails 開發 Java Web,則不必略過此問題,因為 Grails 內建的設定就已採用 CharacterEncodingFilter 處理編碼。

開啟這個 Filter,需要在 web.xml 加入:

mongoskin - a better MongoDB driver for Node.js

MongoDB 是新興的 NOSQL solution;Node.js 是新興的 Web Framework。

要把它們湊成一對,首先要解決的問題就是用什麼 driver(亦稱 library 或 module)。

在 MongoDB 的網站,有一份清楚的列表:

http://www.mongodb.org/display/DOCS/node.JS

我第一次在 demo 專案中使用的 driver 是 mongoose,它確實能 work,也是不錯的 ORM/ODM 解決方案。

Mongoose http://mongoosejs.com/

不過,當我更深入瞭解 MongoDB 之後,我發現 mongoose 的設計不太對勁,主要的問題是它對 Schema/Model 的依賴。對於 MVC 的架構來說,定義 Model 是天經地義的事;但有時候我們可能想善用 MongoDB 的 schema-free 特性來設計更具彈性的系統架構,這時候以 schema 為基礎的設計就不太合適。

於是我將 mongoose 拆除,使用更低階的 native driver,這也是 mongoose 所採用的底層,它的 npm 名稱就叫「mongodb」。

Mongo DB Native NodeJS Driver https://github.com/christkv/node-mongodb-native

但實際使用 native driver 不久後就感到厭煩,也體悟到為何大多文章推 mongoose 或其他 wrapper 的原因;光是一個最簡單的 find 查詢,native driver 就需要撰寫許多層的 callback function,才能完成,而它的 async 特性也讓處理查詢結果的 code,必須塞在多層 callback 的最內層,程式的可維護性降低不少。

我試著撰寫一些 function 讓簡易查詢可以用一層完成,但總覺得這件事情不應該自己做,於是我想再嘗試尋找更好的方案。

當我試著在 Cloud9 建立 Node.js 的測試專案,並且使用 MongoHQ 的資料儲存服務時,發現 mongoskin 也許正是我想要的。(Cloud9 是線上的專案開發工具,MongoHQ 是雲端的資料庫儲存服務,搭配起來就可以只用瀏覽器開發 Web App。)

Mongoskin https://github.com/guileen/node-mongoskin

我想 mongoskin 應該會是個不錯的選擇,就像它自己宣稱的「The future layer for node-mongodb-native.」。使用 mongoskin 存取資料,使用方法比較接近 mongo shell,有一點 DSL 的味道,少了一層又一層無止盡的 callback。mongoskin 透過 Helper 的方式滿足簡易的 Model 需求,例如幫 posts 這個 collection 封裝,加入 findTo10 函式。

以下的 sample code 可以整理這三種 module 的示範:

使用 Jekyll 與 GitHub Pages 架站

使用 Jekyll 建置的 Node.js Taiwan Book Store

Jekyll 是使用 Ruby 開發的「靜態網站產生器」(static site generator),它可以當做內容管理系統(CMS)使用。

* [Jekyll](http://jekyllrb.com/)

和一般直接以 HTML 編寫靜態網站不同的地方是,Jekyll 產生的網站可以有佈景、模組等動態的好處,當你需要修改網站整體的佈局(layout),只需要設計、切換為新的佈景,重新產生的網站就會套用新的外觀。或是在日後加上留言回應、瀏覽統計的模組,就可以輕鬆擴充網站整體的功能。

靜態網站很適合用於內容被大量存取的網站類型,只要搭配高效能的伺服器軟體(如 Nginx),就可以有非常好的負載。並且可以採用價格相對便宜很多的服務來發佈網站,例如  S3 + CloudFront。

* [Amazon Simple Storage Service (S3)](http://aws.amazon.com/s3/)
* [Amazon Cloud Front](http://aws.amazon.com/cloudfront/)

這篇文章寫給 Jekyll 的入門者參考,並使用免費的 GitHub Pages 服務發佈網站。

首先,系統必須先裝有 Ruby。

* [Ruby](http://www.ruby-lang.org/zh_TW/downloads/)

以及 RubyGems。

* [RubyGems](http://rubygems.org/pages/download)

如此就能使用 gem 指令快速安裝 Jekyll。

sudo gem install jekyll

* [Install Jekyll](https://github.com/mojombo/jekyll/wiki/install)

這個網站列出不少使用 Jekyll 架設的網站,並且也提供原始碼連結,是很好的參考範本。

* [Jekyll Sites](https://github.com/mojombo/jekyll/wiki/Sites)

Jekyll 並沒有內建範本(template),對入門者來說,從頭到尾自己建立一個新的 site 並不容易,因此建議可以從 jekyll-bootstrap 開始。

* [Jekyll Bootstrap](http://jekyllbootstrap.com/)

這個範本可以讓你有個基本的網站雛形,並且可以快速發佈到 GitHub Pages。

Pages 是 GitHub 提供的專案網站托管服務,一般來說是開放源碼專案開發者,用來建立專案首頁的服務,但它的速度不錯、使用方便,因此用來當個人部落格或筆記網站,也是相當合適的選擇。

* [GitHub Pages](http://pages.github.com/)

在繼續下個步驟前,需要先註冊、登入個人的 GitHub 帳號(架設帳號為 USERNAME)。

在 Jekyll Bootstrap 的 GitHub 專案頁面,使用 Fork 按鈕,複製一份專案到自己的空間(Fork to USERNAME)。


* [Jekyll Bootstrap at GitHub](https://github.com/plusjade/jekyll-bootstrap)


使用 Admin 按鈕,將專案名稱(repository name)改名為「USERNAME.github.com」,這是 GitHub Pages 的設定方式,如此一來你就能用「http://USERNAME.github.com/」存取已發佈的網站。

接下來需要用到 Git 版本控制指令。

* [Install Git](http://git-scm.com/download)

取得專案:

git clone git@github.com:USERNAME/USERNAME.github.com.git

這會建立一個 USERNAME.github.com 資料夾,切換到該路徑下。

cd USERNAME.github.com

目錄下的檔案,就是 Jekyll Bootstrap 的檔案結構。

第一個需要修改的設定檔是「_config.yml」,包括 title 及 author 等網站基本資料。

使用「rake -T」可以查詢有哪些指令可用,剛開始會用到的指令有:


rake page           # Create a new page.
rake post           # Begin a new post in ./_posts
rake preview        # Launch preview environment


輸入「rake preview」即可建立預覽專用的伺服器,預設的 Port 號碼為 4000,所以用瀏覽器打開「http://localhost:4000/」即可預覽。之後新增、修改網頁內容,都可以重新整理瀏覽器網頁,查看更新的結果(需要等待 Jekyll 在背景產生好靜態網站)。

資料夾下的 index.md、tags.html、archive.html、categories.html、pages.html 是一些預設的基本頁面,可以直接修改內容,這些檔案的內容採用 Markdown 格式編寫。檔首的 --- 區塊有 title 等設定,是 Jekyll 網頁的特殊設定方式。

* [Markdown](http://markdown.tw/)

再來就是建立新網頁:

rake page title="about me"



rake post title="hello world"

使用 page 或 post,必須看新增的網頁內容是屬於頁面(page)或文章(post)類型,舉例來說,「關於本站」、「作者介紹」這種不會經常發佈、固定式的資料,就是用 page,而「新聞」、「活動」等日後會常發佈新內容的類型,就是 post。

建立或修改網頁內容後,使用 git 將目前的版本提交。

git add .
git commit . -m 'just another commit'
git push origin master

之後專案就會更新,使用「http://github.com/USERNAME/USERNAME.github.com」可以看一下專案更新結果。通常只需要等待片刻時間(第一次發佈會比較久),就可以從「http://USERNAME.github.com」瀏覽已發佈的網站。

如果你擁有自己的網域名稱,可以在 DNS 設定增加一筆 CNAME,例如 jekyll.YOURDOMAIN.com 這個 hostname 透過 CNAME 指向「USERNAME.github.com」。

接著在 Jekyll 專案的根目錄下,增加一個命名為 CNAME 的檔案,內容就是自訂的 hostname,如 jekyll.YOURDOMAIN.com。並且重新 git add、commit、push 一次。

這樣就可以讓 GitHub Pages 架設的網站擁有自訂網域名稱。

Node.js Taiwan Book Store 目前就是使用 Jekyll + GitHub Pages 架設,參考: http://book.nodejs.tw/

使用 GitHub Pages 入門 Jekyll 可以有個輕鬆愉快的開始,但如果是商業用途的網站,則可以搭配前面提到的 Amazon S3 + CloudFront 服務(這兩個服務皆可自訂網域名稱),就可以用相對一般虛擬主機便宜非常多的價格架站。

2012年2月13日

PragPub 適合軟體開發者的免費電子雜誌


http://pragprog.com/magazines


Pragmatic 是一家專業軟體開發書籍的出版公司,他們從 2009 年 7 月開始每月發行電子雜誌「PragPub」,為開發者提供技術發展趨勢的導讀。

http://pragprog.com/magazines

PragPub 提供的格式包括 HTML、PDF、EPUB、MOBI 等,可以支援絕大多數的閱讀裝置。

這本雜誌很適合軟體開發者閱讀,有了專欄作者的導讀,讀者可以快速瞭解新趨勢,窺探新技術的面貌,再決定要不要買一本書回家深入學習。

2012年2月1日

DIY 茂谷柑果汁模型


我們家田裡長了不少茂谷柑,可是其貌不揚,因為沒打算賣錢,所以就少了神奇藥水的加持。

天然 + 有機 + 無毒 = 肥料 :-)
這些柑仔,除了掉到地上當肥料、偶爾採一些送人,帶回家的就是打成果汁加快消耗的速度。

但是連續一個月把茂谷柑果汁當水喝,讓我開始想拿柑仔來做些什麼。所以我決定自己動手將茂谷柑做成果汁模型,讓它除了當水喝還有其它功用。

在經過改良之後,終於調配出適當的比例,以下是模型製作教學。

加入約 500cc 冷(或溫)開水

倒入洋菜粉(一包約12元),攪拌溶解並將水煮沸使粉末完全溶解,並加入適量蜂蜜及冰糖攪拌溶解

關閉爐火,待溫度由熱變溫,加入 1000cc 茂谷柑果汁(對半切,用一般榨汁機打成果汁)

等冷卻一些變成微溫後,倒入容器中

完全冷卻後就會變成果汁模型,再也不用擔心果汁灑出來弄壞心愛的 Mac
碼農在種菜(非死不可)和養驢的時候,就靠這杯茂谷果汁模型解渴(免得要不斷跑廁所時被偷菜)
茂谷果汁模型配方:

  1. 洋菜粉一包(俗稱菜燕)
  2. 水 500cc
  3. 純茂谷柑果汁 1000cc
  4. 蜂蜜及冰糖(依照個人甜度偏好適量添加)
放在冰箱即可保存多日。

補充說明:為了有更好的視覺效果,將茂谷柑果汁,加入剝皮去籽的椪柑果肉,放進果汁機攪碎約 5~10 秒,可以製造出果肉、泡沫的效果。

茂谷果汁模型,不僅有望柑止渴的視覺效果,且不會因不小心潑灑而弄壞心愛的 Mac(筆電),對於想要減重的愛美人士,更是低熱量的充飢食物,富含維生素、礦物質、纖維質等多種營養。


今年的柑仔大多數都掉到地上變有機肥料,所以明年的茂谷柑一定會更大顆更甜。

天然有機的茂谷最適合榨汁,歡迎有興趣的雲嘉南果汁店家批發訂購。

lyhcode by lyhcode
歡迎轉載,請務必註明出處!