2007年6月8日 星期五

JBoss中Web應用程式利用Spring設定自行定義的Log4j

將在tomcat 上測好的程式包成war檔後deployjboss 後發現jboss 讀到log4j時會出現以下訊息

ERROR: invalid console appender config detected, console stream is looping.

或不出現錯誤訊息。而無法使用war檔中的log4j.properties




是的,jboss本身在[JBOSS_HOME]serverdefaultconflog4j.xml 就有這個設定檔作loger形式的初始化,如果再讓自己的webapp 有一個servlet去讀自己設定的lo4joutput type,無論是log4j.properties or log4j.xml都會造成 ----->ERROR: invalid console appender config detected, console stream is looping.

所以如果你要deploy自己的webappjboss上時 ,一般而言只要去以上的路徑的log4j.xml去修改你想要的輸出型式就ok了。

[JBOSS_HOME]serverdefaultconflog4j.xml 改或加自己的設定這不太make sense,最好還是要針對個別application有自己的log4j設定檔比較合理。因此,我們可以透過SpringLog4j的補強,得到較彈性的設定,並且額外的解決log4j設定無法在JBoss使用的問題。

Spring最擅長的,就是在別家的蛋糕上再加些cream,讓你J2EE without Spring的時候心癢癢。

log4j,可以有如下的cream

1. 動態的改變記錄級別和策略,不需要重啓Web應用,如《Effective Enterprise Java》所說。

2. log文件定在 /WEB-INF/logs/ 而不需要寫絕對路徑。

3. 可以把log4j.properties和其他properties一起放在/WEB-INF/ ,而不是Class-Path

web.xml 添加

<context-param>

<param-name>log4jConfigLocation</param-name>

<param-value>WEB-INF/log4j.properties</param-value>

</context-param>

<context-param>

<param-name>log4jRefreshInterval</param-name>

<param-value>60000</param-value>

</context-param>

<listener>

<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>

</listener>

在上文的配置裏,

Log4jConfigListener會去WEB-INF/log4j.propeties 讀取配置文件;開一條watchdog線程每60秒掃描一下配置文件的變化;並把web目錄的路徑壓入一個叫webapp.root的系統變數。

然後,在log4j.properties 裏就可以這樣定義logfile位置

log4j.appender.logfile.File=${webapp.root}/WEB-INF/logs/myfuse.log

如果有多個web應用,怕webapp.root變數重復,可以在context-param裏定義webAppRootKey

但透過Spring的設定會導致JBoss出現如下另外的錯誤訊息:

15:03:32,531 INFO [STDOUT] log4j:ERROR A "org.jboss.logging.util.OnlyOnceErrorHandler" object is no

15:03:32,546 INFO [STDOUT] log4j:ERROR The class "org.apache.log4j.spi.ErrorHandler" was loaded by

15:03:32,546 INFO [STDOUT] log4j:ERROR [WebappClassLoader

delegate: false

repositories:

/WEB-INF/classes/

----------> Parent Classloader:

java.net.FactoryURLClassLoader@1f808e6

] whereas object of type

關於這個問題只需進行以下修正即可。

1.開啟JBoss相關設定檔%jboss_home%/server/default/deploy/jbossweb-tomcat55.sar/META-INF/jboss-service.xml

2.修改指定屬性即可

<attribute name="Java2ClassLoadingCompliance">true</attribute>

<attribute name="UseJBossWebLoader">true</attribute>


Read More......

2007年6月7日 星期四

求婚大作戰(第八集)

這樣,會變成理所當然嗎?
有誰不在這裡都會變成理所當然了嗎?

比如成為社會人,結婚了,可能會沒辦法。
結束,真的挺簡單的…結束,真的很簡單。
年齡大了,自然就會消失的東西有很多。
有很多不用太過勉強的事情呀、沒有必要做的事情…會有很多。
沒意義啊、麻煩啊,一句話就打發了的事情…今後會出現很多。

但是,記憶啊、回憶啊!就是如此產生出來的東西。
真的很可惜!

真的很討厭呀!就這樣漸漸有了距離的話。



這是本集中我滿喜歡的一段話。
無論是不是戀愛,你有沒有曾經想忘了某個人。
刻意跟某個人保持距離。
也許是鬧翻的戀人、也許是大吵一架後的好友、
也許是一廂情願,卻看著別人牽著她的手的失戀宅男、也許…

那…你會怎麼做?
突然間消失在對方的生活中?
從無話不談變成唯唯諾諾?
原先幼稚的打鬧轉為客氣的寒喧?
又或者…

但…無論怎樣…總是不自然吧!
就如同上面所說,好的、壞的,都是回憶呀!
在生活中…保持最自然的你吧!

我很喜歡這一集的結果。
一般來說,當我們發脾氣、鬧彆扭時,其實是想受到別人的重視。
但通常事與願違,朋友們見到你心情不佳,狀況低落,大多逃的遠遠的。

可是你發現,若是你總是開開心心的,朋友們都會靠近你,感染你的喜稅。
當然不是說從此以後不能生氣啦!我所要表達的是,當你生氣時。你已經成功的吸引了朋友的目光。
但趕快調適好心情,再跟朋友們打成一片吧!

我很羡慕劇中的結果,縱然一開始鬧得不愉快。
但最後他們還是出現在健三的面前,表達出他們的關心!




Read More......

(2007.5月號-160期)_持續性整合開發導論(上)

在開始進入正題之前,請讀者回想一下公司目前專案開發方式,首先得有個IDE介面的開發工具(不論是商用的JBuilderWSADIDEA或著是免費的EclipseNetBeans),再者公司內多人進行協同開發,所以必須有版本控制系統(也許用古老的CVS,或目前較常用的SubVersion還是要錢的StarTeamClearCase),接者呢,討論一下工作分配後就各自開始工作了,頂多遇到問題了求教資深員工、隔幾天口頭或文件報告一下工作進度、手動輸入資料進行測試、用眼睛看看程式運作順不順暢、專案初期大家嘻皮笑臉準時下班、專案後期各個繃緊神經認命加班。最後的結論是八成以上的ProjectDelay,無法順利On Schedule,二成則靠業務或老闆的關係結案,請客戶勉強撐著用。




很熟悉嗎?在台灣如此的場景依然在無數的IT業界的各個角落上演。到底出了什麼事,未來的專案與軟體開發還是如此的循環嗎?為了追朔原因我們來簡單回顧一下軟體開發的歷史。


在過去十幾年,IT產業剛萌芽階段,對軟體開發的理解很單純就是寫程式,當時是結構化開發與設計,相對的軟體規模較小並且在崇尚個人開發技巧的狀態中完成程式的撰寫,能夠成為開發人員的都是非常令人稱羡的。由於重視個人技能且一個專案皆為一人開發,再者那時也沒有所謂的程式撰寫規範與標準,缺少有效的開發方法與軟體開發工具的支援,開發文件使用最多亦只是簡單的控制流程圖,不重視軟體開發的管理,更沒有所謂的軟體工程,因此決定軟體品質的唯一因素就是該程式開發人員的素質


時至今日,現代軟體專案不再是單打獨鬥,而是講求團隊合作,隨著資訊發達與企業成長,小型專案開發的機會少了,取而代之的是開始了為數眾多的企業級軟體專案開發,依據需要延伸出了多樣的企業級架構與觀念,包括了ERPEAIESBSCMPLMBPMSOA…等。經過幾十年經驗的累積也發展出了RUPAgileUMLDesign Patterns…等製程觀念與軟體工程理論。


但當世界都持續進步的同時,實務的軟體開發卻一直裹足不前,其原因在於開發人員多數還留有舊時代的觀念,保有一定程度的英雄主義,不擅於協同開發的方式,而大部分公司也不重視軟體工程永遠以舊思維在開發新專案與新產品,因而導致大部分的專案品質低落。


即然如此,是否能採取什麼行動來修正開發方式,妥善的管理專案的進展與狀態,追蹤程式碼的品質與提升開發人員的素質呢?為此筆者將在本期對敏捷開發中的持續性整合開發進行全面性介紹。

什麽是持續性整合

持續性整合(Continuous Integration)是一種實踐,可以讓團隊在開發過程中持續收到回饋並且進行程式的修正與流程的改進。簡而言之就是在專案的建置過程中,會自動化的反覆不斷進行編譯,依測試的分類運行單元測試、元件功能測試、系統整合測試,產生相關專案資訊、測試結果、程式可靠度報表供分析的開發方式。從測試結果與相關報表的資訊中可以快速的找到錯誤與不妥之處,不必等到開發階段後期才發現系統缺陷。


而因應多人協同開發來說持續性整合必須配合版本控制系統,促使開發團隊中的開發人員頻繁地把他們所新增與修改的程式碼提交至版本控制系統的Repository中,但在提交程式碼之前必須確認加入的程式不會破壞原始碼的編譯與建置。


為了達到快速回饋的目的,持續性整合鼓勵高頻率的Commit(提交程式碼至版本控制庫中)。 持續性整合提供了敏捷開發一個堅實的技術基礎。如果沒有一個完善的持續性整合開發環境,要想高效地進行團隊軟體開發幾乎是不可能的。


接著我們從幾個方面來看持續性整合開發必須要有什麼樣的環境、必須架構那些工具以及必須遵守怎樣的原則。


持續性整合的初始:專案的管理與建置

在以往小型或獨立專案的開發中,專案的建置其實很簡單,開啟一個常用的IDE,執行下拉式選單的[File][New Project…],即可輕鬆的產生針對IDE開發平台的專案設定,而且編譯、封裝與佈署也是直接在IDE開發環境中直接運行。


但對於大型或與多個廠商協同合作所開發的專案就無法這麼做,其原因為Java IDE開發環境為數眾多,除非強制開發人員只能使用特定的開發平台,否則每個開發人員喜好使用的工具都不一定相同。企業級的大型專案也是相同的道理,專案可能同時發包給多個廠商,廠商有錢的用JBuilder開發,經濟拮據的用EclipseNetBeans,如此一來整合就是個難題。


因為如此,在Java持續性整合的開發中有了幾個有名的跨IDE開發平台的專案管理與建置工具。

  • Ant:為Another Neat Tool的縮寫,為Java基礎的建置工具,可用於小型的個人專案,亦可用於大型、多人協同開發的軟體專案。

  • Maven1Apache的專案管理、構建、部署工具,Maven的基本概念就是專案物件模型 (Project Object ModelPOM) 描述專案的各個方面。

  • Maven2Maven的第二代,針對了AntMaven1的不足處進行了全面性的改進,增進建置速度,更少、更簡易的設定檔。


在建置工具的比較中Ant無疑是最靈活也是支援最多的工具,在開放原始碼的社群中還有為數不少的專案是建置在Ant的基礎上,包括知名的Spring FrameworkHibernateAppFuse…等。但也就是因為太過於靈活了,導致同一個功能10個人寫會有10個不同的腳本與設定,小型專案上使用非常方便,但應用在大型或者多專案的建置上經驗的不足將導致災難,將會陷入茫茫的建置與設定檔的大海之中。


Maven1的起源最初是由於進行Jakarta Turbine專案,原先專案中每一個check inCVS的不同的JAR檔都擁有他們自己的build files,在進行維護上相當的困難,因此能夠進行很簡單的建置,並且定義出一個建置多個project的標準、一個對project構成清晰的描述、一個簡單的方式發佈project的資訊與一個能夠通過幾個不同的project去分享不同的JAR檔的方式就成為Maven這個專案的目標。


很幸運的由於Maven1抽象了POM的概念,大部分的專案建置腳本被寫入了Maven1的核心架構Plugin中,如此專案建置過程被Maven1統一了,雖說如此,Maven1還是保留了自行客製化的建置腳本方式,支援Ant並且可依不同的IDE開發環境需求,產生相關的開發平台設定檔。TurbineJakarta CommonsJetspeed2…等都是使用Maven1建置的。


Maven2Maven系列的第二代,但除了POM的設定相似外,核心架構與Plugin的使用卻是大大的不相同,當然也完全不相容,為了因應需求多變的挑戰,它完完全全進行了重寫。Maven2從開放原始碼社群中頡取了十多年專案管理建置的經驗。以更高階的觀點進行抽象,拋棄Maven1的包袱,進行重新設計,當然成果不凡,從Maven1移植到Maven2上後會發現所需撰寫的建置腳本的機會愈來愈少了取而代之的是需要了解相關Plugin的使用,並進行設定,目前有為數不少的社群為Maven2 Plugin的開發無償的奉獻心力。


參考圖 1所示在Maven2中使用mvn archetype:create指定專案範本建立新專案,並可分別執行mvn eclipse:eclipsemvn idea:idea,產生符合EclipseIntelliJ IDEA開發環境的設定。而現在多數的IDE都可以透過更新Plugin的方式提供對Maven2的支援。


1 Maven2IDE平台設定


持續性整合的依據:最重要的事,測試優先

測試驅動開發(Test-Driven DevelopmentTDD)是極端軟體製程的重點特色,也推動了程式碼進行持續性整合。測試驅動開發所強調的就是測試優先,在開發功能程式之前,先撰寫測試程式碼。意謂著開發前必須先思考如何針對這個功能進行測試,並且撰寫完整的測試案例,當開發出來的程式完全滿足測試案例後,再反覆進行這一系列的步驟,直到全部功能的開發完成。


在此簡單的列出Java持續性整合開發中比較常用的測試框架:

  • JUnitJUnit是最知名的單元測試框架,幾乎所有Java測試框架的開發都是繼承於它。

  • JunitPerf:針對了JUnit進行的一個裝飾,用於進行一定時間內的效能與一定壓力下的負載測試。

  • DbUnit:是爲資料庫測試的專案提供的一個對JUnit的支援,用來維護測試前後資料的一致性。

  • HttpUnit:對網路Http協定進行自動完善測試的JUnit擴充框架,一般用於功能與整合測試。

  • Cactus:擴展了 JUnit,進行In-Container(容器內)測試,也就是說必須要啟動Web Server

  • jMock EasyMock:測試用模擬物件框架,某些測試若必須與其他物件相依時,可用MockObject

  • WebTest:進行Web功能性測試的框架,擴展自HttpUnit,用腳本測試,無需寫程式。

  • Selenium:近來滿熱門的Web整合、驗收測試工具,分為Test Runner測試模式(Scenarios進行HTML測試腳本撰寫並測試)以及Driven測試模式(以類似JUnit寫程式碼方式進行功能測試)。前者簡單並且可交由非開發人員進行腳本撰寫但測試流程較無彈性,後者測試靈活彈性高,但需寫如同JUnit一樣的程式碼,須交由開發人員處理。


參考圖 2得知透過JUnit產生報表,可保證在開發的過程中運行測試驅動最重要的功能,也就是增進程式碼的正確與穩定性,能夠在第一時間內發現程式錯誤與效能不佳之處,進行迅速的修正或進行重構,但若想有效的進行測試驅動開發,則必須遵從幾個原則。


首先嚴守測試優先,撰寫某個功能前,先以如何使用作考量,撰寫測試程式碼,再進行功能程式的撰寫,不論反覆多少次的新增功能、修改與重構,都要保持可測試性。筆者發現在以往協同開發的廠商或開發人員都以時程過趕而忽略了撰寫測試程式碼的重要性,等到發現系統過於複雜、藕合過深之後,想進行重構卻也已經來不及。測試優先不單指JUnit單元測試與元件測試,佈署到Web Container後的功能測試也必須嚴守測試優先,以往SeleniumWebTest這類使用腳本進行功能測試的工具還未出現之前,功能測試是非常麻煩的,因此開發人員寧可只單獨進行手工測試,而如今Selenium可以協助我們快速進行測試腳本的建立,但並不代表開發人員可以忽略測試優先的原則,等到系統快開發完成才一口氣寫完所有測試腳本,若是如此將會自掘墳墓,因為就算Selenium工具強大,但少數還是隱函著一些瀏覽器平台相容性的問題。測試優先不是沒有道理的,初期的測試也許會遇到一些小狀況,通常都能順利解決,隨時保持程式的可測試性,臭蟲就不會在開發結案前跳出來咬你一口。


其二必須隔離測試類別,測試分類有單元、功能、整合測試,雖然都可以使用JUnit進行,但本質上卻有不同,參考圖 3可知,每一個不同的測試對應了開發初期不同階段的需求。

  • 單元測試:為對最底層某些類別、方法所撰寫的測試單元,一般而言為測試的最小單位,多數為開發人員為測試最基本的功能是否完備而撰寫的測試邏輯,此處測試只牽涉到基礎單元程式,必須與其他不相關程式模組進行隔離。

  • 功能測試:將基礎建設中的單元進行初次整合所達到的特定功能測試,例如將多個Dao物件整合為ManagerFaçade類別,針對其功能類別進行測試。在功能測試來說可能為必須啟動Web伺服器的容器內測試或無需啟動伺服器的獨立測試,若為獨立測試則必須隔離與Web相關的類別,若不可避免必須相依其他物件的話,可使用MockObject技術配合進行測試。

  • 整合測試:因應系統設計文件所需功能所進行的測試,實作方式較多面,有用JUnit撰寫測試碼方式進行、有用WebTestSelenium撰寫程式或測試腳本方式進行,基本上已進行一定程度的實機測試,測試碼由開發人員撰寫。

  • 驗收測試:因應需求所做的測試,該測試為使用單位進行,因此多為使用者接受度測試,若希望能進行自動化測試的話,可使用Selenium進行腳本側錄,經過簡單的修改就能進行測試,參考圖 4

當考量了必須進行隔離測試的同時,開發人員會很自然的在設計上進行物件的解藕,而達到鬆散藕合的目的,撰寫不同類型測試的同時將專注在同一組功能設計上的考量,自然而然撰寫出來的程式碼將擁有高度的內聚力。


其三撰寫高可讀性的測試程式碼,因為測試碼實質上就是元件使用方式的集合,一般在開發過程中很少有時間針對原始碼撰寫使用手冊或其相關的說明文件,有了可讀性高的測試碼後就像擁有了一份完整的使用手冊,而日後相關文件的撰寫也可直接取用參考。


其四不要用IDE進行偵錯,並養成寫Log的好習慣。不可否認的IDE平台的開發環境,是非常好的開發工具,多數的開發人員也習慣於在IDE中下中斷點進行偵錯,而排斥撰寫單元測試程式碼,認為是多此一舉。但事實上在使用偵錯工具時開發人員不會記得上次的錯誤是什麼,中斷點下在那,並且因為偵錯太過於方便了,多數的開發人員就不會寫Log,就算寫也寫出無效或非關鍵點的Log訊息。若是如此當程式碼已佈署到了Server上,已經是上線的系統時,則根本無從在上線的系統中進行偵錯。


最後撰寫測試碼要小步前進。畢竟軟體開發是個非常複雜的工作,開發過程中必需經過多方面的考量,包括程式的正確性、可擴展性、效能…等,很多衍生的問題也都是程式複雜度太高所引起的。因此建議把大規模,複雜性高的功能,分解成多個小功能來完成,經過一步一步的建置,通過一步一步的測試,就能降低整個系統的複雜性。而低複雜性的程式碼,在日後也將有維護方便,易於重構的優點。


2 JUnit Report


3 測試V型圖


4 Selenium進行網頁功能測試


作者介紹

盧建州 <jazz.lu0827@gmail.com>

有多年軟體開發經驗,注重軟體工程並善用Design Patterns。專研於JavaOpen Source解決方案、跨平台技術與其異質資訊系統整合。目前為自由工作者。



Read More......

2007年6月6日 星期三

CruiseControl持續整合Maven2專案

這二天理了一下頭緒,將之前的經驗作了整理。
寫了一篇「CruiseControl持續整合Maven2專案」的心得筆記!

雖然某些部分是剪剪貼貼,不過大概也整理了12頁左右的資料,供我日後參考。
在我的王道中。Maven2將不可或缺,而CI伺服器上CruiseControl還是暫時優勝。

因牽涉到之後這篇心得會是我之後發表文章的基礎。
所以先說聲抱歉了!這篇文章暫不公開。

日後發表了我會再貼上。再次說聲!Sorry哦!

Read More......

2007年6月4日 星期一

下雨天,趕稿天!!

原本預計一天要趕完給RunPC的發表文章,結果還是多拖了一天。
看來還是太高估了自己了!是吧!

因為連續二天的忙碌,都忘了必須為接下來的工作進行安排。
看來明天得認真的接洽相關事宜。否則下一次的進帳可不知道是什麼時候了呢!

之前跟雜誌社的編輯問過,之前刊登的文章,只要發行過後一個月。
即可允許作者刊在Blog上,我想也該整理一下之前發表過的文章,一一Post上來好了!

今年該好好的經營跟推銷一下自己了!

在下雨天連趕二天的稿…老實說接下來的這幾天…我真不想再打字了…>_<|||

Read More......