星期二, 7月 17, 2007

struts 2: field validation and type conversion

一般web 應用中,很基本的一個功能是參數的驗證(validation),而在struts 2中,這個功能是透過validation來達成的。但是,在驗證之前,struts 2會先做type conversion 的動作,以確定輸入的參數能夠滿足action 中各個properties的需求。所以,interceptor的執行順序是
  1. 型別轉換 (type conversion)
  2. 參數驗證 (validation)
如果在型別轉換時就發生錯誤的話,相同的欄位就不會進行參數驗證。我就是忽略了這個順序,才搞了二天。

舉例來說,如果有個property 是 setDate(Date theDate),在zh_TW的locale中,預設的日期格式是mm/dd/yyyy,我想在為這個欄位加上validation, 於是,在我的Action-validation.xml中有下列的一段程式碼:


<field name="date">
<field-validator type="regex">
<param name="expression"> ...</param>
<message>wrong format for field date</message>
</field-validator>
</field>


但是,當格式錯誤時,regex卻不會抓到錯誤,問題就是出在type conversion 的interceptor 先運作了,所以總是會出現type conversion 的錯誤訊息 : "Invalid field value for field "date"",所以,對於非String 型態的property,比較有意義的validator只剩下required、date、int這幾個有意義,其他的意義都不大。

那接下來的問題就在於,怎麼把"Invalid field value for vield ..." 這段訊息換成我們想顯示的訊息。這必需透過struts 2的I18N機制來達成,根據AnnotationXWorkConverter文件中提到的,可以在ClassName.properties中設定 invalid.fieldvalue.欄位名稱,來設定特定欄位的conversion error錯誤訊息,如果要改變預設的訊息的話,則可以透過設定global的I18N屬性xwork.default.invalid.fieldvalue 來達成效果。

星期一, 7月 16, 2007

sturts 2 validation and action property

今天又犯了個豬頭錯誤,我有兩個Struts Action,程式碼類似這樣:
public class ParentAction {
protected long property;
...
public long getProperty(){
return property;
}
}

public class ChildAction extends ParentAction{
public void setProperty(int property ){
this.property = property;
}
}

當我對ChildAction 加上required validation時,問題就來了,不論我輸入的是什麼值,validation interceptor總是告訴會回報property is null,找了半天,一路trace到Ognl層,才發現問題出在,透過reflection API取得property 的method descriptor時,因為setProperty的參數型態和getProperty的參數型態不符,而getProperty又在parent,所以會只認getProperty,而把setProperty(int) 當作是一個overloading method,以致於無法設值進去,只要把setProperty 由setProperty(int)改成setProperty(long),就又能夠正常運作了。

這樣的錯誤,只能說是自己不小心造成的,但是,這種錯,應該會常常發生吧,下次,得把這類的檢查也加到test case中。

WebLogic workshop 10.1 release

這幾天的事吧,剛開始用,有幾點還不錯的改善。

  1. server console 總算可以不用另外開個console window,而能夠直接顯示在eclipse的console view了。
  2. deployee時如果發現context已經有application,會自動問你要不要把原來的application delte,換成目前的proect。
  3. compile/build/deployee的速度變快了,看起來AppXRay總算有點正面效益了。
  4. 新的 jsp editor還不錯,一個畫面切上下兩部份,下半source,上半部是jsp輸出的結果,對我這種喜歡直接寫code的人還蠻方便的。

不過,有優點當然也會有缺點囉:
  1. 還不支援portal development,幾個portal facet 會丟warning
  2. 還不支援struts 2 ....
一些有加強,但對我而言可有可無的功能,但是這些功能可能對其他人蠻有幫助的吧:
  1. spring ide support,不過,只支援到spring 2.0
  2. hibernate/bea kudo support,不過,我習慣手動寫mapping,或是利用annotation,所以對我而言效益也不大

其他一些pageflow(beehive)之類的相關功能,因為沒在用,就沒特別去試了。

星期五, 6月 01, 2007

在Struts2 中取得JAAS相關資訊

在WebWork/Struts 2的應用框架中,可以讓系統開發者在寫程式時,專注在應用系統的邏輯,透過IoC的注入(injection)方式,程式碼中可以完全看不到與JavaEE相關的程式碼。但是這種美好的世界,在遇到一些需要根據使用者傳回不同的結果的action時,就不是那麼美好,除非你所開發的應用系統自行處理使用者權限與授權相關的功能。如果是使用JAAS,那程式中不免會需要透過HttpRequest來取得remoteUser等資訊。在Struts2/WebWork中,提供了兩個介面可以做到這樣的功能 HttpRequestAwarePrincipalAware。


HttpRequestAware 是第一個會想到的介面,既然remoteUser的資料是從request來的,那就叫struts幫我們注入個request object不就成了?但是一但在action中引入HttpRequest,使用Struts2/Webwork的最大好處,與平台低相依性,易測試的優點就當場被破壞了。當引入HttpRequest之後,為了測試action,必需透過如spring-mock等等的JavaEE mock 套件,無法簡單的透過如jmock, 或是自行打造stub的方式來進行測試,而且,只是需要getRemoteUser, isUserInRole等function,卻把整個HttpRequest 都暴露在action中,怎麼看味道也不對。


PrincipalAware 就是為了解決上述的問題產生的,如果你只是很單存的需要getRemoteUser, isSecured, getPrincipal, isUserInRole等功能,那action只需要實作PrincipalAware,Struts2/WebWork會為action注入一個PrincipalProxy,提供getRemoteUser等需要的方法,又不需要將整個HttpRequest都暴露在action中,造成與平台過度的相依。更好的是,PrincipalProxy是一個interface,可以利用jmock, dynaMock等mock framework簡單的產生測試時需要的替代品,對自動測試可是一大利多。


使用WebWork到現在,也好幾年了,居然到現在才發現有這個interface,該說是後知後覺,還是太不認真了,不過,這個介面可是解決了以往為了測試這些需要principal 的action,而搞了幾乎整套的JavaEE stack的問題,又能夠滿足整個應用系統的味道能夠一致,真該認真點的。

星期五, 5月 25, 2007

下車再上車?


以前的同事pj曾經說過一個笑話,一群人開車到郊外踏青,在差不多算是荒郊野外的地方車子故障了,一群人急得想各種辦法要把車子修好,但是都徒勞無功,最後,一位在微軟工作的軟體工程師說話了:「我們把車子熄火,全部的人下車,再上車試看看,可能就沒問題了。」凡是用過電腦的人,多多少少會遇到類似下車再上車的狀況,對像可能是特定的應用程式,也可能是整個作業系統,怎麼找就是找不出問題,但是,把程式重開或是重開機之後,問題就不見了。而開發人員遇到這種狀況的機會又比一般的使用者來得高。



這種狀況,常常是因為系統在開發過程中沒有考慮到一些特定的狀況所造成的。但是隨著作業系統愈來愈複雜,今天,除了特殊的應用之外,單工的作業環境已經愈來愈少見了,導致要在開發階段就考慮到所有的狀況已經是愈來愈不可能了。為了因應這種狀況,近代的程式語言大都包含了例外處理的機制,這個機制最主要的目的就是讓程式在遇到開發時期未考慮到的狀況時,能夠死得漂亮一點,死得優雅一點,最低限度,要讓使用者知道,程式已經死了,而不是讓使用者去和一個不穩定狀態的系統打交道。



例外處理,是程式設計的一個很重要的課題,雖然有些人認為例外處理讓部份程式流程更不容易被追蹤(trace),但是不可否認的,在支援例外處理的程式中,程式碼可以以更容易被人類讀懂的方式來表示,而不是一長串的if/else if /else。畢竟,程式碼除了建立系統之外,也是程式設計師之間最主要的溝通工具。如果說,少男漫畫中的主角是用拳頭交心,那程式設計師就是用程式碼交心了。

需要wiki嗎? 自己挑一個吧!!

這幾年,wiki (維基)愈來愈紅,不管是公司、社群,甚至個人常常都會有個wiki。但是愈來愈紅代表的也就是選擇可能會愈來愈多,在wiki的領域,可選擇的軟體也愈來愈多,甚至也可以偷懶直接使用別人的wiki 主機服務。這麼多的wiki怎麼選呢? 當然,就是要靠比較多,這次介紹的網站,就是可以幫你比較常見的wiki間的差異、支援等等,讓你更方便的選擇一個自己的wiki。


這個網站收錄了87個Wiki軟體及服務(主機服務),可以讓你對各個wiki之間的功能作詳細的比較,更提供了一個Wiki Choice Wizard,透過幾個問題,先幫你作篩選,讓你不用在87個軟體間漫無目的的尋找,需要wiki嗎? 挑個自己合用的吧!!


WikiMatrix - Compare them all

星期三, 4月 04, 2007

WebLogic 10 正式發佈

中心的server才剛啟動由WebLogic 8到WebLogic 9的轉移程序,10居然就發表了,雖然以中心的理境而言,用這麼大的AppServer或是Portal Server真的是很明顯的殺雞用牛刀的狀況,但是,買都買了,預算也編了,暫時也只能維持在目前的平台,再儘可能的以符合標準的方式來作系統開發,減少日後萬一需要轉移時需要的工夫吧。



不過,這次的Workshop 10總算能以個別plugin的方式安裝在原有的Eclipse環境下,這點對我可是有很大的吸引力呢,至少不用在去處理ClearCase plugin 與 Workshop 9之間偶爾會發生的怪異狀況,再加上很多Eclipse的plugin 也都轉移到3.2的版本了,看來,可以認真考慮是不是要跳過9, 一次攻頂上到10版了。



星期一, 3月 12, 2007

Install ClearCase 7.0.0.1 fixpack

因為ClearCase 7.0.0.0 沒辦法跟ClearQuest 7.0.0.1 作協同運作,再加上Eclipse clearcase adapter 又要求安裝到7.0.0.1,於是,早上打算把fixpack裝起來,再開始下個版本的開發作業,沒想到,這次的fixpack安裝,怎麼裝怎麼不順,就是裝不起來,而不裝,後續又做不下去。

這一搞又是搞了一整天才找到問題,以往安裝fixpack都還蠻簡單的,確認完系統符合安裝的規範之後,就可以一路下一步安裝到底了,沒想到,今天在安裝的時候,就是有問題,找了半天,也找不出來,log也蠻正常的,到了下班前,才看到一篇說明,原來是需要DCOM service, 而我機器上的DCOM service不知道什麼時候被我給停下來了,把service啟動,就可以正常的安裝fixpack了,真是想不到的錯。

星期五, 3月 02, 2007

Cheet Sheet 大全

黑米看到的, Cheet Sheet 大全網頁, 幾乎可以說,只要是有在用電腦的使用者,難免就會需要,一堆用得到,用不到,想得到的全都有,真的蠻方便的。

Cheet Sheet, 簡單的說,就是小抄啦。

Cheet Sheet 大全

星期一, 2月 26, 2007

struts test with remote user

最近遇到一個閃不掉的struts系統開發,慘的是,只能用struts 1.x這個我一直很努力避免使用的framework。不過,既然遇到了,還是得用,利用StrutsTestCase來作單元測試(unit test),一開始倒也還相安無事,一直到遇到一些需要用到HttpRequest.getRemoteUser的action,一時之間,還真不知道該從何著手,只有個概念該從mock object的方向做。
不過,幸運的讓我找到一篇Testing Struts的文章,其中提到了利用MockStrutsTestCase來作security的unit test,再追了一下StrutsTestCase的原始碼,果然,在MockStrutsTestCased中使用的HttpServletRequestSimulator 這個mock object可以由程式碼給定RemoteUser等request的相關資料,總算解決了我的問題。
Struts 1.x算是個很成熟的framework,相關的討論,隨便找找也都是2004年,甚至更早的文件,很多文件,還真的跟不太上目前的狀況,還好這篇的東西還可以用,不然,就真的很麻煩了。

星期一, 2月 05, 2007

weblogic + sitemesh + spring 中文亂碼解法

看到了篇可能是解決weblogic + sitemesh + spring下中文發生問題的解法,不過,我還沒機會測試就是了。

http://www.blogjava.net/rocky/archive/2005/12/18/24467.html

星期二, 1月 16, 2007

Patch ActiveRecord-JDBC

花了一個早上的時間在找ActiveRecord-JDBC連結Oracle 9的問題,利用jruby使用ActiveRecord-JDBC來連結Oracle會出現java.sql.SQLException 數值溢位的例外,一路追下去,發現是ActiveRecord在讀取database metadata時,發生overflow的問題。

把jdbc_adapter.rb 的 convert_jdbc_type_to_reply中的 resultset.getInt改成 resultset.getLong就行了,不過,這是蠻暴力的改法就是了 。

星期三, 1月 10, 2007

Code coverage with emma

打從第一次看到有Open source 的專案使用clover來作測試覆蓋率(Test coverage)的工具, 就一直想找一個類似的工具來用,但是Clover是要錢的,如果只是寫寫自己好玩的程式,也要用這種花錢的工具,那這個興趣的成本還真是太高了,也就沒很認真看待這件事,久了,也就忘了。

前陣子,閒閒在Eclipse的網站上晃的時候,碰巧被我看到了這個plugin -- EclEmma,一個把emma整合進eclipse 環境中的plugin,裝起來試了一下,蠻有趣的,就持續用下去了,下一步,就是把emma導入作為部門中的正規流程了。

emma是一個找覆蓋率的工具,透過emma來執行Java程式,可以在程式結束的時候,顯示出執行期間所有執行到的程式碼,跟執行的狀況 -- 完全執行,未執行,部份執行(條件判斷式)。如果用來執行junit 的測試,就能夠看出執行這些測試程式的時候,執行過那些正式的程式碼。雖然說這類的資訊,只是參考用,但是對於剛開始寫測試程式,或是維護舊有的未測試程式時,也是蠻好用的工具。

Emma 官方站


EclEmma 官方站

星期六, 1月 06, 2007

OpenLogic partner

昨天突然收到OpenLogic的Partner邀請,作為他們subclipse計畫的後端支援人員,原來是他們從subclipse的comitter列表中找到我的名字,才發出邀請函。想想自己目前的工作,還算有空檔能幫幫Open source社群的一些忙,也就答應了,不過,他們有提供能協力伙伴一些金錢上的支援,會根據解決的問題,得到若干的報酬就是了。

星期三, 12月 27, 2006

CQ Web login url

搞了半天,原來不是ClearQuest web 沒裝好,而是url弄錯了,不是http://host/cqweb,要用http://host/cqweb/login才行,真是白忙一場。

星期二, 12月 26, 2006

Upgrade from WebLogic 9.1 to 9.2 on AIX

上線兩個星期,這個小小的不成材的系統,一直有一些莫明其妙的問題,今天,忍不住把整個WebLogic 從9.1 昇級到9.2,反正死馬當活馬醫,總不能過著每天被全院追殺的日子。9.2跟9.1變化不大,不過,為防萬一,還是重新建立一個新的domain,然後,啟動WebLogic Server準備開始設定LDAP跟DataSource,沒想到,最不該出事的地方,總是會出事 --
Parsing Failure in config.xml: javax.xml.namespace.QName; local class incompatible: stream classdesc serialVersionUID = 441862298102654515, local class serialVersionUID = -9120448754896609940

這這這,這叫我如何是好,google了一下,原來是JavaEE在不同版本間,變更了QName的serialVersionUID, 依照網站上的建議,加上了 -Dcom.sun.xml.namespace.QName.useCompatibleSerialVersionUID=1.0, 果然就能夠順利的啟動9.2的domain。

設了LDAP, DataSource, 再把這個不成材的應用系統放上去,果然,日子好過多了,不再出現那個奇怪的XAER_PROTO的問題了。

星期二, 12月 19, 2006

總算有空了

最近,真的是忙到翻掉,大約在一個月前,一個同事離職,而他身上的一個預定要在12/7上線的系統,就順理成章的落到了我的身上,於是,一個agile到不能agile的專案,就這麼開始了,距離上線時間不到三週,所有功能都不確定,整個上線的環境是 WebLogic + Oracle 9i on AIX,其中,我只對AIX有一點點的認識。
這算是我第一次以這種型式做專案吧,之前待的環境,總是有還算正規的開發流程,再怎麼樣也不會是功能需求可以任意修改的狀態,這次,完全不一樣,每天都有新功能,每天都有需求變更,甚至在系統已經上線一週的現在,還持續有功能變更以及新功能的要求。這當然不算太離譜的狀態,真正離譜的是,這個系統的壽命,最多最多只到明年的一月中,也就是剩大約一個月的時間,而且,使用者會隨著壽命的結束,而慢慢的變少,直到壽命終止。
打從系統開始上線到今天,系統總算處於比較穩定的狀態,原因是因為AIX+WebLogic的組合的系統調效,連續一個星期的File Open too many..直到昨天,才利用修改WebLogic 啟動script的方式,將file descriptor limit開到2000,才撐得住,原因是因為在WebLogic 9的startup script (setCommEnv.sh)中,有個resetFd的函數,會在系統啟動前,執行ulimit -n 1024的動作,導致系統執行過程中,發生File Open too many的問題。非正規解法則是,將ulimit -n 的值,調到至少與AIX的系統預設值相同(2000),就可以在一定程度避免File Open Too many 的問題,至於會不會引發其他的問題,目前,還看不出來,看起來是還好就是了。

星期五, 11月 10, 2006

WebWork if tag 與 action property


WebWork if tag 中的 test 條件,要使用action的property來作為判斷條件時,必需先透過set 將action屬性設為一個單獨的變數,才能做測試。



<ww:set name="local" value="property">

<ww:if test="#local == %{abc}">
</ww:if>


昨天為了這個問題,搞了快一個下午,還好最後有找到解法,不然,還不知道要花多少時間咧

星期四, 11月 02, 2006

method/function spec -- 如何寫好 JavaDoc

寫Java寫了那麼久,一直不知道怎麼寫JavaDoc會比較好,最近剛好在看MIT的線上課程,其中有關於function/method規格的部份,發現如果依據這種方式來寫的話,既可以清楚的表達function/method的行為,又不會把太多的實作細節寫出來,是一個很好的寫JavaDoc的格式。

規格定義

規格同時定義了使用者以及實作者雙方的責任 -- 在使用者滿足規格中所定義的條件下,實作者保證能達到規格中要求的結果。

一個function/method的規格,包含了三個部份

  • precondition -- 一般用關鍵字 requires來表示
  • postcondition -- 一般用關鍵字 effects來表示
  • frame condition -- 一般用關鍵字 modifies來表示

precondition 規範了使用者的責任,如果precondition中的條件沒有滿足的話,實作者可以用任意的方式來完成實作 (包含終止整個程序)。

postcondition 則是規範了實作者的責任,在precondition滿足的條件下,實作必需要滿足postcondition中所規範的條件。

frame condition 和 postcondition有關,讓寫規格的人能夠比較簡單、清楚的表達其他的 postcondition。在frame condition中必需明確指出其他會受要變動的物件,所有沒有列在frame condition中的物件,預設狀態都是靜態的,也就是在function/method執行期間,不會受到任何改變。

不同的軟體規格寫法

規格的寫法可分為兩大類: operational specification 跟 declarative specification,虛擬碼就是 operational specification最常見到的做法。declarative specification 並不明確定義實際達行的步驟,而是把執行前後的狀況明確的定訂下來。

在大部份的狀況下,declarative specification是比較好的寫法,因為他比較短,比較容易了解,更重要的是,declarative specification 不會提到實作的細節,讓實作的人有更大的空間,也避免使用者過度依賴特定方式的實作。

規格的強度

A specification A is at least as strong as specification B if

  • A's precondition is no stronger than B's
  • A's postcondition is no weaker than B's, for the stats that satisfy B's precondition

規格的強度,在考慮繼承的時候,更能顯示出他的重要性。

星期三, 11月 01, 2006

開張大吉

開張大吉決定把跟軟體開發的文章獨立出來,不然,死人窩那邊真的是有點亂。