星期一, 11月 20, 2017

Odd-e Certified ScrumMaster 心得分享 3 - 快速交付,小步快跑

快速交付,小步快跑


雖然,認識 Agile 或是 Scrum 已經有一段時間,自認對於快速交付及小步快跑也有一定程度的理解。但是,卻沒有像這次在課堂上感受這麼深刻。

在課堂上,我們進行了一個 workshop,規範了一個明確的產出物作為目標,然後我們有 30 分鐘作為一個 Sprint 來完成一個可交付的產出。時間相當的緊湊,事後想想,如果採用 Scrum 的模型來執行,我們應該每 3 分鐘或 6 分鐘應該進行一次進度的同步工作。然後,在每 3 分鐘到 6 分鐘的時間,為最後的產出做努力。

但是,相場實際的狀況卻是,大家開始討論起該怎麼完成這個產品。整個過程中,我們大約有一半的時間在討論與規劃,就是還沒針對最終產出物捲起袖子開幹。等到,大家討論出一個方針後,我們開始進行製作產品的相關工作。這個 workshop 最有趣的地方,就在於他還必須完成一個 Deployed 的動作。

我們必須讓產品上線,這個 Sprint 才能夠算成功。在製作產品完成後,我們還有五分鐘左右。於是,我們嘗試進行部署。卻發現部署的時間比我們想像的還要久很多。最終,這個 Sprint 我們宣告失敗。

這裡面,其實有很多隱含許多的觀念,底下是自己回顧的心得:

1. 以終為始:我們應該快速地,發布一版到正式環境,以確認團隊了解整個發布程序,並且排除發佈時的風險。對應到實際的案例上,軟體工程師應該都很常遇到,這東西在我們本地端執行都沒問題,但是一移轉到正式環境問題就一大堆。透過這樣的思維邏輯,我們可以更早地面對正式環境的狀況,不會在做了很久之後,才發現有東西需要調整。

2. 用最短的時間產出 End to End 的價值,頻繁地發佈。快速地取得回饋,要比周詳的計畫,但是做了很久專案延宕,無法上線取得價值來說,更有意義。

3. 在之前協同合作時有提到,以拔河為例。當只有一個人的時候,你肯定會用上 100% 的力量。但是,當人一多的時候,大家可能就有所保留。在整個 workshop 中,我們應該沒有發揮整體團隊 100% 的戰力。

4. 快速交付,小步快跑的開發習慣是必須要一段時間練習,讓自己逐漸熟悉這種模式的思維,以任務下來時大家的反應來看。我們都需要一些時間來精熟這樣的模式。

星期五, 11月 17, 2017

Odd-e Certified ScrumMaster 心得分享 2 - 順暢的溝通




順暢的溝通

在二戰之前,法國的陸軍部隊擁有實力堅強的裝甲車設備。但是,在二戰的時候,卻被德國的陸軍打敗。據說,這中間的關鍵就是「溝通」。當時,法國的裝甲車部隊使用旗語在不同的坦克車之間進行溝通,而德國的部隊則是使用「無線電」進行溝通的工作。

在旗語跟無線電之間,我們可以清楚的知道這兩個工具產生的溝通效率不同。使用旗語時,溝通的效果有限,除了距離的限制之外。在作戰期間,坦克車的操作人員也很難時時刻刻探出頭來檢視其他坦克之間的狀況。這使得法國的坦克車部隊,像是一盤散沙,雖然裝備強大但是沒有辦法集中戰力,發揮團隊的力量。

反觀,德國的部隊,因為可以很快的進行有效的溝通工作。當其中一部坦克,打通了某個關卡之後,可以快速地通知其他的夥伴集結,快速地針對現況做出應對與改變,近一步達到戰略上的效果,而獲得最後的勝利。

對比軟體的工作模式,我們可以看到一個團隊雖然共同在打造一個產品,或是執行一個專案。團隊成員之間也有透過會議來進行資訊的同步。但,感覺很多時候,成員跟成員之間還是彼此不知道對方在做什麼,進行怎樣的工作,如何進行。

這使得專案團隊之間,對於產生的問題,或是良好的工法無法有效地快速傳播。所以,我們現在是用「旗語」還是「無線電」?

星期一, 11月 13, 2017

Odd-e Certified ScrumMaster 心得分享 1 - 協同合作



大約在兩年前吧,有一次到趨勢科技參加一個 Scrum 的分享會議,那時候第一次遇到 Daniel 老師。那次會議中分享了如何組成一個 Scrum 團隊,說明了 Cross Function Team 如何組建。

之後,也經常在社群裡,聽聞許多人對於 Daniel 老師的課程讚譽有加,所以當社群內出現了報名資訊後,我就立馬用手機完成了報名程序。接著,過著一段非常忙碌的專案執行生活。一直到上課前一天,都還有著許多工作上煩人的事。

但是,既然都已經報名了這個課程,就必須讓自己放空好好的沈浸在課程之中,以發揮學習最大的效益。

在課程中,我記下了大量的資訊,每一個 Key Word 都有一些啟發,基於養成習慣持續性的交付這項學習心得來看,只好把心得的部分切成許多小的 story 來 release 了!

協同合作

   Scrum 本來就是延伸自橄欖球運動中的爭球,所以一直以來我認為一個良好的 Scrum Team 就是要像一個合作無間的球隊,成員間彼此有默契,能夠互相合作。但是,一個團隊的協同合作就像拔河一樣,當只有一個人的時候,你可能會發揮 100% 的力量。如果,現在我們有一個團隊一起進行,每個人的力量貢獻度就不一定是 100%。

   「協同合作」是我在第一天筆記時,寫下的第一個關鍵字。在第三天,我們在討論什麼是一個好的 Product Backlog 時,卻突然有了體會。在哪份 Product Backlog Item 上,已分配好的工作都有指定一個負責人。

   假設,今天我們在談的是協同合作。一個 Product Backlog Item 為何是指定給特定人士來完成? Product Backlog Item 是一個 User Story,是一個對於客戶來說有價值的 End to End 功能特性的交付。這其中涵蓋許多的細節,包含分析、設計、開發、測試等一切我們必須進行的工作,也是一個交付的目標。

  既然,這是一個目標性的交付,應該是由團隊一起協同合作,完成一個 Product Backlog Item 的交付,否則團隊會在什麼時間點進行合作?

  大家只是各自處理各自的任務,是一個不協同合作的偽團隊罷了!仔細想想,這也是最常看到的分工模式。雖然,大家一起在為一個產品或專案努力,但是彼此之間卻互不相干,不互相幫助。

  一個良好的團隊,應該是共同為一個目標努力。中間有什麼問題需要協助,需要補位,喊一聲就會有人接替。我想,在這樣一個團隊下工作,應該是相當愉快的一件事。所以,也要好好跟團隊同仁分享一下這樣的概念,促進團隊在協同合作上的成長。



星期四, 6月 22, 2017

IBM MobileFirst 7.1 拒絕存取


延續之前 MobileFirst 7.1 的 Server Farm 機制無法正常啟用,經過好一陣子與 IBM Lab 之間的往返,還是沒有一個好的解決方案。


所以,只好考慮直接裝一套新的 Server,並且把專案移轉到新的伺服器上來。
但是,在移轉之後卻出現如上圖所示的錯誤。

因為,通常我們會在 App 啟動時,使用 WL.Client.connect 與 MobileFirst 伺服器連線,以確認 Client 與 Server 之間的版本,並檢查管理者有沒有設定任何通知訊息。

但是,在移轉後,App 端會出現「Access Denied」的錯誤,無法正常啟動 App。

伺服器端,也可以觀察到下列的錯誤訊息:
FWLSE0335E: Authorization failed: 
ClientId f5ac9a8cda443cfca33d1e7f926a71f90f8c67a1 was not found 
on the server.
這個情況,可以透過移除該 App 並且重新安裝,來解除此問題。

所以,我們大概可以推測,MobileFirst 的 Client 端在跟 Server 連結之後,會在手機端留下一些資訊。這些資訊,應該是 MobileFirst 用來確保安全的機制。

1. 可以避免,我們連接到的 Server 與之前的不同
2. 從伺服器端的角度來看,如果先前該手機已經跟伺服器註冊過。但是,現在我們卻無法在伺服器上找到該 ClientId 的話。這個裝置是不是該被視為有問題的裝置。

當然,這種安全機制,有時候還是會造成我們的困擾。

所以,為了避免要求大量使用者重新安裝 App,我們可以採取下列兩種方案,來解決此問題。

1. 在 MobileFirst 7.1 之後,與先前開始有所不同,採用 Session Independent 作為伺服器運作的預設機制。當採用 Session Independent 時,MobileFirst 的相關資訊就會被存於資料庫中。所以,必須調整 MobileFirst 處理 Session 的機制,讓資訊是存於記憶體之中。這樣,就可以解決上述遇到的問題。但是,當採用這樣的機制,勢必會影響到後續 Server 做平行的擴充。所以,除非是以單一機器提供服務,不然不建議採用這個解決方案。

2. 既然,App 移除重裝之後就可以解決此問題。那麼,就是需要在程式中加上一段清除手機上暫存的這些資訊,如此就可以使 App 恢復正常運作。經測試,先前假設沒錯,就是有一段資料被存在手機上。移除之後,就可以正常與伺服器連線。

「參考資料」
1. MobileFirst 7.1 Server Access Denied when using WL.Client.connect API

星期一, 3月 27, 2017

IBM MobileFirst 7.1 WebSphere Liberty Server Farm Unresponsive

前一陣子有客戶反應,他們公司的 MobileFirst Server 無法正常啟動。

於是,開始這段伺服器搶救的過程。

1. 因為 console.log 及 message.log 中都沒有紀錄錯誤訊息,所以為了看更多的資訊,必須打開 trace.log

需要再 server.xml 中加上下列資訊,就可以產生 trace.log 了!
<logging maxfiles="10" maxfilesize="20" 
         tracefilename="trace.log" 
         traceformat="BASIC" 
  tracespecification="com.worklight.*=all:com.worklight.*=all:*=info">
</logging>
中間經歷了很多次重開的過程,Server 就是無法順利啟動。

在沒辦法之下,我只好使用 MobileFirst 的 Configuration-Tool 試著用 update 的方式,中置一下 worklight admin 服務及 runtime environment 的三個 war 檔案。

突然,其中一部 Server 正常啟動了。

心想,應該修好了!

結果在啟動另一個 Server 時,卻卡住了!

這時候剛剛啟動的 Server 也無法正常運作。

觀察一下 tracelog,後來我發現每 30 秒會出現一次下列紀錄

com.worklight.core.clustering.ClusterSynchronizationTask
解到這邊,我一直觀察資料庫內的資料跟伺服器運作的模式。
感覺,就是同步作業失敗,然後一直重做。

上網找了一下資料,看起來跟這個問題比較像的是:
IBM MobileFirst 7.1.0 Liberty Server Farm Unresponsive

但是,內文也是說重建 Server Instance 跟重新設定 Server Farm 就好了!

目前,重建後只能讓單一伺服器恢復運作。
只要想同時啟動 Server Farm 中的兩個伺服器,就會陷入同步失敗的問題。

現在還在等 IBM 原廠回覆此問題的正確解法。

星期二, 8月 09, 2016

Kendo Grid 教學 4 - 解決 REST Service 回應 HTTP 403

在先前「RestTemplate 無法呼叫 Rest Service」的文章中有提到,有些後台被 Spring Security 保護著,並啟用 Cross-site request forgery (CSRF) 的保護機制,並免他人因為知道服務的端點,就可以直接呼叫相關的服務。

Kendo UI 可以透過 Datasource 中 transport 的屬性設定,可以完成資料的讀取及寫入工作。針對新增、修改、刪除及查詢的部分,分別提供 create、update、destory 及 read 的 function 來進行相關作業的處理。
    transport:{
        create:{...},
        update:{...},
        destroy{...},
        read{...}
    }
開發人員可透過上述設定,完成 kendo grid 上 CRUD 的相關動作。

但是,當我們碰上後端具有 CSRF 保護的服務時,可能會出現 「HTTP 403 : Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'」的錯誤訊息。

這代表,我們正常地呼叫後端的服務。以整合 Spring Security 來說,當我們完成登入後,可以從 Request Header 中觀察到,HTTP Request 都會帶著兩個 Cookies 的資訊,分別是 JSESSIONID 及 XSRF-TOKEN 資訊。

然後,我們再看一下錯誤的訊息「HTTP 403 : Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'」。看起來,後端要的服務需要我們的 Header 送一個 X-CSRF-TOKEN 的資訊過去。上網找一下參考資料「Invalid CSRF Token 'null' 解決方案」看起來也是這樣說明沒錯。而且,X-CSRF-TOKEN 的內容跟 XSRF-TOKEN 一樣 (一樣的東西,底層竟然沒有自己處理掉 .... 看來還要找時間看看到底為什麼有這樣的限制)。 

所以,接著要思考的是如何在 Kendo Grid 呼叫後端服務時,將  X-CSRF-TOKEN 動態的塞入。後來,我在 「Transport and basic authentication」找到了解答。我們可以在 create、update、destroy 跟 read 等方法上加上 「beforeSend」的方法來加入 X-CSRF-TOKEN。

beforeSend: function(req){
    req.setRequestHeader('X-XSRF-TOKEN', $cookies.get('XSRF-TOKEN'));
}
如此一來,就可以正常使用後端服務了!

[參考資料]
1. 跨網站請求偽造
2. Invalid CSRF Token 'null' 解決方案
3. Transport and basic authentication

星期一, 8月 08, 2016

RestTemplate 無法呼叫 Rest Service

最近有人問我一個問題,現象是他的應用程式呼叫被 Spring Security 保護的服務時,如果未將 csrf disable,系統就無法正常運作。

Spring Security 啟用 CSRF 後可保護 Server Side 的 Resource,避免跨網域攻擊 (從別的機器發出 Request 以取得後端的資訊)。所以,當 Spring Security 啟用 CSRF 後,我們會在前端的頁面加上

   <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>

以便,證明我們是從同一個網域發送的請求。

然而,這個問題卻不是上述原因造成!第一時間的猜想錯誤,所以我就開始檢視程式碼內容,來看看到底那邊出了問題。

後來,發現在後端的程式中有一段使用 RestTemplate 去呼叫 REST 服務。基本上,如果在內部應該可以直接呼叫相關的物件,而不需要透過 RestTemplate 來進行呼叫 (多繞了一圈)。不過,依照範例來看是個教學程式,所以就先不討論合理性的問題。

RestTemplate 其實是一個增強化的 HTTP Client ,所以在使用 RestTemplate 時我們可以想像自己開了一個新的瀏覽器,然後存取該服務。此時,RestTemplate 中根本就沒有儲存相關的 Session。因為他的 Request 中沒有帶任何經過驗證的資訊。所以,會被 Spring Security 視為不合法的存取。

我們必須在 RestTemplate 中加入一些資訊,才可讓這個呼叫合法。相關資訊,可參考下列參考資訊的網址。

HttpHeaders headers = new HttpHeaders();
headers.add("cookie", req.getHeader("cookie"));
HttpEntity requestEntity = new HttpEntity(null, headers);
ResponseEntity rssResponse =
restTemplate.exchange( your_service_url,
HttpMethod.GET,
requestEntity, List.class);
1. 建立 HttpHeader 物件,並將 request header 中的 cookie 值取出,設定到自己建立的 HttpHeader 中。(因為 Session 就存在這裡)

2. 建立 HttpEntity 物件,並利用先前建立的 HttpHeader 進行初始化。

3. 使用 restTemplate 呼叫後端服務,取得 ResponseEntity 以進行後續邏輯運算


[參考資料]

星期三, 8月 03, 2016

Kendo Grid 教學 3 - 建立新增功能

在 「Kendo Grid 教學 2 - Inline Edit」的文章中提到怎麼樣進行 inline edit 的工作。但是,以先前提供的範例來看,並未交代如何進行新增的作業。

但是,如果有依據參考資料進入 「Kendo Grid Grid Inline Edit Demo」檢視範官方的範例程式的話,應該已經發現如何把「Add New Record」的按鈕加上去。

$scope.mainGridOptions = {
    dataSource: $scope.datasource,
    pageable: true,
         height: 300,
toolbar: ["create"],
    columns: [
     { field: "id",  title: "商品編號", width: "120px"},
     { field: "name", title: "商品名稱", width: "120px" },
      { field: "price", title: "商品價格", width: "120px"},
{ command: ["edit", "destroy"], title: "&nbsp;", width: "250px" }
          ],
editable: 'inline'
};
};
在原本 mainGridOptions 中,加入 toolbar 的元素,並指定要使用 create 功能,就可以像官方的範例,有一個 「Add New Record」的按鈕。

當這個按鈕按下去之後,以 inline 編輯模式來看,Kendo Grid 的第一行會進入編輯模式,讓我們輸入資料後進行新增作業。

[參考資料]
1. Kendo Grid Grid Inline Edit Demo

星期三, 7月 27, 2016

Kendo Grid 教學 2 - Inline Edit

在 「Kendo Grid 教學 1 - 建立列表」的文章中,有兩個主要的變數要設定,以便讓 Kendo Grid 可以運作起來,並透過 Rest Service 拿到列表資訊。分別是 datasource 與 mainGridOptions。

Datasource

其中,datasource 可以看作是 kendo grid 的資料來源。在先前的文章中,設定了 transport 與 schema  兩個主要屬性。

transport


透過 transport 的屬性設定,可以完成資料的讀取及寫入工作。針對新增、修改、刪除及查詢的部分,分別提供 create、update、destory 及 read 的 function 來進行相關作業的處理。
    transport:{
        create:{...},
        update:{...},
        destroy{...},
        read{...}
    }
開發人員可透過上述設定,完成 kendo grid 上 CRUD 的相關動作。

schema

Schema 在 Datasource 中扮演兩個重要的角色:

  1. 透過 schema.model.fields 定義 kendo grid 的資料模型,設定排序 (sorting)、篩選 (filtering),並確保使用對應的編輯元件,例如: 數字輸入框對應到數字型別的資料。
  2. 透過 schema.model.id 定義 kendo grid 中的 id 欄位,以確保新增、修改、刪除等工作可以正確執行。

schema: {
      model: {
           id: "id", 
           fields: {
                 id: { editable: false, nullable: true, defaultValue: null},
                 name: {validation: { required: true }},
                 price: { type: 'number', defaultValue: 0, validation: { required: true, min: 0}}
           }
       }
}



parameterMap

在 Kendo Grid 與後端服務整合的部分,透過設定可以採用 json, jsonp, odata 等不同資料模式。所以,在請求資料 (request) 真的往後送之前,我們需要透過 parameterMap function 幫我們處理資料的轉置問題。

下列為,parameterMap 中的範例程式。因為 read 方法不需要傳參數即可拿到資料,所以在範例程式中,我們把 read 方法過濾掉。然而,在 create, update 及 destory 的部分,我們將前端 Form 內的第一個元素取出 (因為 options.models 預設是 array),並將其當作參數往後面的服務拋送。

parameterMap: function(options, operation) {
if (operation !== "read" && options.models) {
        return JSON.stringify(options.models[0]);
     }
 }


mainGridOptions


在前一篇文章中,我們有看到下列 mainGridOptions 之設定。設定的內容可以進一步分成幾個區塊。


  1. 設定 datasource,作為 kendo grid 的資料來源
  2. 利用 pageable 設定是否分頁
  3. 透過 height 設定 kendo grid 的高度
  4. 透過 columns 設定 kendo grid 的表頭應該呈現什麼
    4.1. filed 的設定會與 datasource 底下 schema 內的 fields 做呼應,相同名稱的會對在一起,是一種透過設定抓相對應資料的概念。
  5. columns 中還有一個設定為 command,在每一列上會顯示編輯 (edit) 與刪除 (destory) 的按鈕
  6. editable 設定為 inline 代表該 grid 會使用 inline 的方式進行編輯作業
      其中,標紅色字樣的部分是本次要做 inline edit 新加的部分


$scope.mainGridOptions = {
    dataSource: $scope.datasource,
    pageable: true,
         height: 300,
    columns: [
     { field: "id",  title: "商品編號", width: "120px"},
     { field: "name", title: "商品名稱", width: "120px" },
      { field: "price", title: "商品價格", width: "120px"},
{ command: ["edit", "destroy"], title: "&nbsp;", width: "250px" }
          ],
editable: 'inline'
};
};

建立對應新增、修改、刪除、查詢的方法

在本文前面有提到 datasource 中的 transport 就是讓我們進行 create、update、destory 及 read 的 function 撰寫。

在本文中,以 update 為例:

1. url : 記錄遠端服務的端點
2. type:  使用 HTTP  通訊協定的方法 (例如:GET, PUT, POST, DELETE 等)
3. contentType 傳輸內容的類型
4. complete function: 服務呼叫成功後,要做的相關動作可以寫在此處
5. error function: 服務呼叫失敗後,要做的相關動作可以寫在此處

update: {
     url: "your service endpoint",
     type: "PUT",
     dataType: "json",
     contentType: 'application/json',
     complete: function (data) {
// 呼叫服務成功後,要做什麼事
     },
     error: function (xhr, error) {
         // 呼叫服務失敗後,要做什麼事
     }
}

其他,關於 destory 及 create 也是採用相同的方式進行撰寫。雖然,在這裡並沒有說明如何建立一筆新的資料。但,後面還會有其他文章提到。

備註:
我們做 Rest Service 的時候,可能經常將 create、update 及 delete 的 method 預設為不回傳值。以 Java 來說,就是宣告回傳的是 void。

但是,這樣可能會導致 kendo grid 不 work。所以,我們必須回傳一個 JSON 字串回來。針對,create 及 update 的方法,需要回傳新增或是更新的那個物件回來。避免 kendo grid 呈現一個空白列在那邊。

有關 inline edit 的實際 demo,可以進一步參考官網上 Inline Edit 的範例。

「參考資料」
1. Kendo Grid CRUD Data Operation
2. Kendo Grid Grid Inline Edit Demo

Kendo Grid 教學 1 - 建立列表

近年來,前端 javascript 的技術突飛猛進,有許多的 framework 出現,學都學不完。而在,公司的專案需求上,我們需要開始研究 Kendo UI 這套框架。

Grid View 是我們建置 Web 應用程式中相當常用的 UI 元件。記得十多年前,同時接觸 .NET 與 Java 時,總覺得為什麼 .NET 上做一個 Grid View 相當容易,而在 Java 上卻需要自己寫那麼多程式。一個 Page 一個 Page  一直寫著重覆類似的程式碼。

雖然知道,這裡應該要被元件化,但始終沒有下手去做這類整理的事。那時候,還是以 Server Page 為主的時代。AJAX 的興起是在那之後兩三年的事情。

而到了現在,檯面上已經有非常多這種前端的元件,而且透過 javascript 技術的發展。現在,前端的頁面已經鮮少使用 Server Page 相關的 Tag 。而改由 HTML5 + javascript + css 來進行所有的事情。至於後端採用什麼語言 (C#, Java or PHP) 似乎已經沒那麼重要,也徹底實現 Web 端的 MVC 概念。

底下,我們就建立一系列的文章,來探討使用 Kendo UI 的心路歷程:

1. 下載 kendo ui 的相關套件 Kendo UI Download Free Trial
 
解壓縮後,將套件內的 js 與  styles 資料夾放到專案目錄中。以我自己的範例來看,這兩個資料夾放在 [your project]/webapp/resources/lib/ui/ 底下。

2. 下載 kendo.all.min.js

我是認為 kendo.all.min.js 應該涵蓋在第一步驟中所下載的內容裡。但是,不知道為什麼沒有。可能這樣可以收一點顧問費,畢竟它是需要付費的!所以,只好從官網的範例偷偷把 js 檔載回來。一樣放在 [your project]/webapp/resources/lib/ui/ 底下。

此使,該目錄下有 js 及 styles 兩個資料夾再加上 kendo.all.min.js 這個檔案。

3. 建立後端 RESTFUL Services,讓 Service 回傳下列這串 JSON 訊息回來

[
  {"id":4,"name":"Starbucks","price":300},
  {"id":5,"name":"BrownCafe","price":200},
  {"id":6,"name":"CityCafe","price":100}
]
4. 撰寫前端頁面

4.1. CSS 與 JS 引用之宣告

<link rel="stylesheet" href="./resources/scripts/lib/ui/styles/kendo.common.min.css" />
<link rel="stylesheet" href="./resources/scripts/lib/ui/styles/kendo.default.min.css" />
<link rel="stylesheet" href="./resources/scripts/lib/ui/styles/kendo.default.mobile.min.css" />
<script src="./resources/scripts/lib/ui/js/jquery.min.js"></script>
<script src="./resources/scripts/lib/ui/js/angular.min.js"></script>
<script src="./resources/scripts/lib/ui/kendo.all.min.js"></script>
4.2. 在 HTML 頁面上,宣告要使用 Kendo Grid (以 AngularJS 為範例,官網上還有許多 JQuery 的範例)

<div id="example" >
    <div ng-controller="MyCtrl">
        <kendo-grid options="mainGridOptions">
        </kendo-grid>
    </div>
</div>
4.3. AngularJS

4.3.1. kendo UI 元件在 AngularJS 中被實作成 directives 所以當我們要使用 kendo ui 時需要注入 kendo.directives
var app = angular.module('myApp', ['kendo.directives']);
4.3.2. Controller

app.controller('MyCtrl', function($scope){
$scope.datasource = {
transport: {
read: {
url: [your service address]
dataType: "json"
}
},
schema: {  
model: {
                 fields: {
                    id: { editable: false},
                    name: {validation: { required: true }},
                        price: { type: 'number', defaultValue: 0, validation: { required: true, min: 0}}
                    }
                }
            }
};
$scope.mainGridOptions = {
    dataSource: $scope.datasource,
    pageable: true,
         height: 300,
    columns: [
     { field: "id",  title: "商品編號", width: "120px"},
     { field: "name", title: "商品名稱", width: "120px" },
      { field: "price", title: "商品價格", width: "120px"},
          ]
};
};
依據此方式,即可完成下列表格之設計。雖然,做了很多事才弄出這張表。但是,使用這個元件可以讓後續新增、修改跟刪除的 UI 操作快很多,只需要再加上一些設定。




[參考資料]
1. Kendo UI - Grid Example

星期一, 7月 25, 2016

IBM MobileFirst 7.1 DirectUpdate 失效


最近,有客戶反應他們的 MobileFirst Server 升級到 7.1 後,Direct Update 僅能更新一次,之後就無法再進行更新。

因為客戶說,他們當天要準備上線作業,這個功能必須能正常運作。所以,我跟同事就開始研究問題可能發生的原因。

根據客戶描述,一開始的時候是部署 wlapp 到 MobileFirst Console 時會出現警告訊息如下:


FWLSE3210W: Environment: android of application [YOUR Application] 
version 1.1 has been deployed with a different version of the native 
MobileFirst SDK. 

Direct updates will no longer be available for existing clients with 
other versions of the MobileFirst SDK. 

To Continue to use direct updates, increment the app version, publish it 
to the public app store, deploy to the server, and (optionally) block/notify 
older versions of the app to enforce customers to upgrade to the new version 
from the app store.

針對上述部分,需要修改 wlapp 的版本。因為 version 1.1 的時候是使用 MobileFirst 先前的版本進行打包。依據 IBM 對於 Direct Update 的定義來看,如果有 Native SDK 更新的話,是必須整個 App 重新下載安裝,而非僅更新 Web Content 就可以。

而升級的時候,IBM MobileFirst 底層的 SDK 有可能被更換掉,所以會出現上述訊息。故,我們將 version 1.1 換成 1.2。如此,在部署 wlapp 時,就不會有 FWLSE3210W 的警告訊息。

但是,上述問題解決後。客戶驗證 Direct Update 的系統發現還是只能更新一次。所以,問題實際上還沒有被解決。

後來,我們又發現 worklight.properties 檔案中,有一個參數是 wl.realm.expiration.directUpdate 的值預設為 3600 (一小時內,Direct Update 不會再生效)。在舊版的值似乎是 -1。但是,目前設定 -1  MobileFirst Server 又無法正常啟動。所以,只好設定個 60 秒 (反正改程式應該都會超過一分鐘吧!)。

修改後,重新更新 MobileFirst Server 的 Runtime WAR 檔之後,Direct Update 的更新頻率就換成1分鐘後可重覆更新的模式。

[參考資料]
1. The direct update doesn't work in MobileFirst Studio v7.1


星期四, 8月 13, 2015

Certificate Scrum Developer 認證課程心得




最近剛上完 Certificate Scrum Developer 課程,授課老師是 Jacky Shen。在這門課程當中討論「持續整合」,「TDD」,「重構」,「Simple Design」,「Git version control」,「Pair Programming」等相關議題。

在最近一年的時間裡,我陸續取得 PMI-ACP,CSPO 及CSM等證照。有了這些知識,卻感覺還少那麼一點東西。Scrum 團隊有 Product Owner,Scrum  Master 及 Development Team 這三個角色。其中,Team 的人數最多,卻很少有人坐下來好好地把什麼是一個好的 Development Team,以及我們該如何成為這樣的團隊。

所以,有 Product Owner 的認證,有 Scrum Master 的認證,當然我們也需要知道如何培養自己或是團隊成為一個敏捷開發團隊成員之一。所以,基於一個這樣的念頭,讓我在颱風隔天連續上了兩天 12 小時的馬拉松課程。


從整個課程的內容來看,初步可以將課程內容分成兩個主要觀念。

          (1) 專注品質

1.1. 在課程中有提到許多好的程式概念,例如:程式碼要讓其他人一目了然,快速地了解。程式碼要可被信賴。程式碼必須是可維護的。

1.2. Test Driven Development: 確保每一段程式碼都有其對應可執行的測試案例。

1.3. 頻繁且持續地測試,保持程式碼永遠是可動的,並且合於需求。

1.4. 透過重構,不斷地改善程式碼的品質,降低程式的壞味道。

          (2) 減少浪費

2.1. 不做過度的設計,減少浪費。

2.2. 花時間進行重構,可以降低日後一次性大規模的調整。(這讓我想起「不要惹公司的程式設計師啊」。)

2.3. 建立自動化的測試案例,可以降低人為測試不斷重工的浪費。


但是,我認為上述的內容還不是最重要的。在 Scrum Alliance 的網站上,說明怎樣是一個成功的 CSD?

A successful Scrum Developer is committed to continuous improvement.

課程最重要的內容是

讀書、練習、分享

努力不懈地提升自己,透過練習不斷地提升自己實務的能力,並且將這些知識分享出去,發揮影響力,讓團隊可以更精進。

最後,感謝長宏的團隊促成以及一起上完這兩天馬拉松式課程的同學們,讓這次Certificate Scrum Developer 課程能在百般的艱難下開課成功。感謝 Jacky  老師充實的課程使大家獲益良多。

星期日, 5月 03, 2015

Deploy IBM Worklight Server to WebSphere Liberty Profile Manually


最近,有一個客戶要將 IBM Mobile First 7 安裝在 AIX 6.1 上。但是,在裝好後,我卻發現 MobileFirst Platform 的目錄中沒有 Worklight Configuration Tool。

心裡面的OS是,這不是IBM的產品嗎?為什麼沒有自家 OS 的工具。

所以,只好開始研究看看,怎麼手動將 Worklight Server 手動佈到伺服器上。

首先,第一步就是檢視 MobileFirst 的安裝目錄,看看裡面有什麼設定檔,反正根據過去經驗應該可以找到一些東西。

終於,在 WorklightServer 的資料夾底下,找到 configuration-samples 的資料夾。在這裡面發現了許多的 xml 檔案 (例如:configure-liberty-db2.xml)。從這些檔案的命名規則,大概可以推敲出可能的解決方案。

於是,我將該檔案打開來進行編輯。依據 xml 檔案內容的提示,置換相關的資料進去。

隨後,執行下列幾個指令:

ant -f configure-liberty-db2.xml admdatabases
ant -f configure-liberty-db2.xml databases

ant -f configure-liberty-db2.xml adminstall

ant -f configure-liberty-db2.xml install

記得每個指令執行後都必須要看到 BUILD SUCCESSFUL 關鍵字,才可以執行下一個指令。


[參考資料]
1. IBM Mobile First 7 Knowledge Center

星期一, 3月 30, 2015

Windows 磁碟壓縮後 Microsoft SQL Server 無法正常使用

使用 Apple Mac Book Pro 最大的問題應該就是硬碟空間太小。

前幾天,我電腦中 windows 的 VM 空間滿了。讓我無法執行寫程式與測試的工作 (因為只要想寫檔案,系統就會出現,磁碟空間不足的錯誤訊息)。

所以,在這種清況下,為了清出空間來使用,只好使用 Windows 的磁碟壓縮功能。

服用後,多出了 20%左右的空間,使得手邊的工作得以繼續。

就在這兩天,我準備打開 Microsoft SQL Server 進行一些相關技術驗證時,就出現資料庫檔案是壓縮檔,無法正常使用的錯誤。

於是,我開始在網路上找尋 solution,花了十幾分鐘,也沒看到一個好的建議方案。


只好自己想辦法處理。如果跟據先前的分析來看,我應該要設法解除磁碟壓縮的狀態。

但是,如果解決磁碟壓縮,就會面臨空間不足的另外一個問題。所以,只好探索是否能部份解除。

後來,我在相關的資料夾的進階設定選單中發現了設定選項。解除該資料夾底下的磁碟壓縮狀態。

設定方法如下:
1. 選定該資料夾,按右鍵選擇「內容」,並且點選「進階」按鈕
2. 系統跳出右邊視窗,取消勾選「壓縮內容,節省磁碟空間(C)」

弄完後,Microsoft SQL Server 就恢復正常了!

星期二, 1月 20, 2015

修改 WebSphere Application Server 上的 JESSIONID cookie name

       Java Servlet API 2.5 之前規定,session identification coolie 必須叫做 JESSIONID。但是,這個規定在 Servlet API 3.0 後已經解除,而 WebSphere Application Server 第八版之後就已經支援 Java Servlet API 3.0 的規格,所以我們可以修改 WebSphere Application Server 上的 JESSIONID cookie name。

        基於,以上的原因。最近突然有人說有改這個東西。當然,先前完全沒改過這個項目!所以,到 IBM 的 Knowledge Center 翻出了下列修改方式:


1. 開啓 WebSphere Application Server 管理主控台
2. 選擇 Servers > Application Servers > Server_Name > Web Container Settings > Session management > Enable Cookies
3. 修改 Session Cookie 的值,預設為“JSESSIONID”
4. 點選確認,然後儲存相關修改設定
5. 重新啟動 WebSphere Application Server
6. 重新啟動 plugin 檔案

待確認問題:
1. 假設在 Cluster 的環境上,我們只修改某一台 Server 的 JESSION Cookie Name 會發生什麼事?

2. 如果 WebSphere Application Server 上裝著以前的舊程式 (Java Servlet API 2.5 以前),會不會被影響?

3. 修改後的 plugin-cfg.xml 會有什麼變化?

4. 這個跟 IBM HTTP Server 以及 WebSphere Application Server Plugin 的版本有沒有關係 (例如:IBM HTTP Server v7.0 是否支援)?


未完,待續 .....


參考資料:
1. 修改 HTTP Cookie Name

星期四, 10月 02, 2014

IBM Installation Manager 啟動錯誤

今天到客戶端進行 IBM HTTP Server 的升級,想說這是一個秒殺的工作,含把檔案放到伺服器上的時間,應該一個上午就可以搞定!

不過,通常事情沒有這麼順。

近年來,IBM 很多軟體大概都透過 Installation Manager 來進行安裝與更新,一切圖形化操作介面,相當地方便。

所以,對於一個軟體升級的工作來說,沒其他狀況的話就是勾一勾,然後下一步,下一步就可以結束。

如果這麼簡單,客戶為什麼一花一筆錢來請我們進行維護?當然,不是要應付這種狀況!而是,我接下來要講的突發狀況。

一開始是客戶跟我反應他們進行弱點掃描時,有掃出 DoS 的弱點,要求補強。於是,我到 IBM 的修正中心看看有沒有修補程式。剛好看到最新的修補程式中,有他們提到的特性,所以我就把修補程式下載下來,並且與客戶約時間,準備進行更新作業。

當客戶幫設定好工作環境後,我打開 Installation Manager 時卻發生了一個錯誤:

Unexpected error in startup resynchronization.

java.lang.illegalStateException: No metadata found for installed package com.ibm.websphere.WCT.v85 8.5.0.20120501_1108.
這下就麻煩了,沒有 installation manager 幾乎什麼事都不能做,所以只能想辦法修復了!

從剛剛的訊息中,我整理出來的相關情報如下:
1. 目前的軟體環境是用 Flush Copy 過來的,會不會少了什麼檔案?
2. 系統呈現的錯誤訊息表示 WCT 這個元件有問題
3. IBM Installation Manager 的檔案結構可分成兩個部分,其中之一是 eclipse 相關的資料,另外一個部分是我們安裝進去的相關資料檔 (在 UNIX 的環境該資料目錄就是 /var/ibm/InstallationManager/ 中)

後來,我到 /var/ibm/InstallationManager/installRegistry/metadata/Offerings 這個目錄中,看到裡面有下列資訊:

com.ibm.websphere.WCT.v85_8.5.0.20120501_1108.jar
com.ibm.websphere.WCT.v85_8.5.0.20120501_1108.jar0
其中,com.ibm.websphere.WCT.v85_8.5.0.20120501_1108.jar 的檔案大小是 0,另外應該還少一個 com.ibm.websphere.WCT.v85_8.5.0.20120501_1108_SE.jar 的檔案。

於是,在請 User 將這兩個檔案補上後,Installation Manager 就可以正常啟動了!
然後就迅速地完成 IBM HTTP Server 的更新,完成這次的任務。

【參考文章】
1. A "No metadata found for installed package" message is seen by Installation Manager with WebSphere Enterprise Service Bus (WESB)

星期四, 9月 25, 2014

在 MAC 中開啓 Linux 裡的 X 視窗

在 Windows 中,我們可以透過 Xming 來叫起 Linux 或 Unix 上的 X 視窗。但是,最近換了 MAC Book Pro 後,突然想到那 MAC 該怎麼處理?

於是,我就上網找找看解決方案。後來找到 XQuartz 這個工具,他是蘋果電腦在 MAC OS 上對於 X Window 的實作。

當我們在 MAC OS 上安裝了 XQuartz 後,可以透過下列指令,來啟動 Linux 上的 X 視窗應用程式:

ssh -X user@servername
xeyes

執行完上面的指令,應該可以看到下列這個眼睛!這就代表設定完成了。





參考資料

1. XQuartz 維基百科, http://zh.wikipedia.org/wiki/XQuartz



JBoss 4.2.3 JSP page cache


這兩天遇到一個棘手的問題。因為,某些因素我需要去修改某個產品的登入程式,讓他支援二次驗證。理論上,我修改 JSP 的程式後,不需要重啟 Server,該 Server 可以自動生效。

不過,神奇的事情就發生在我完成整合後,要丟給客戶看時,確一直看到舊的 JSP (就算我把那個檔案刪掉了,也是一樣)。

然後,我就重開 JBoss Server,看到的還是舊的 JSP!(這真是見鬼了)

一直重開,我還是看到舊的 JSP!

後來,我才想到,JBoss 的 Redeploy 的驅動點好像是檔案的時間。

所以,我就把檔案動一下再存檔,以更新檔案的最後存取時間。

結果,這招果然奏效了。不然,在那邊換檔案換半天就是沒有效。

讓客戶在旁邊看笑話了。

星期二, 9月 23, 2014

CentOS command line install Tomcat

最近突然有一個需求,就是在 Linux 上安裝 Tomcat。但是,因為使用 VM 的關係,GUI 的操作不是很靈敏,又沒有弄 Xming,所以只好用指令來完成安裝啦!也順被把這樣的程序整理起來。


安裝 JDK 7 Update 67

wget --no-cookies --no-check-certificate --header "Cookie: gpw_e24=http%3A%2F%2Fwww.oracle.com%2F; oraclelicense=accept-securebackup-cookie" "http://download.oracle.com/otn-pub/java/jdk/7u67-b01/jdk-7u67-linux-x64.tar.gz"
下載回來後,檔名為:
「jdk-7u67-linux-x64.tar.gz?AuthParam=1411398968_5826ae3ee1898fbb3d1e25e9de936e9d」

此時,將該檔案檔名修改為「jdk-7u67-linux-x64.tar.gz」。再執行下列指令,進行解壓縮的工作。
tar xzf jdk-7u67-linux-x64.tar.gz
接著,使用 alternatives 指令進行 java 安裝,指令如下:

cd /opt/jdk1.7.0_67/
alternatives --install /usr/bin/java java /opt/jdk1.7.0_67/bin/java 2
# alternatives --config java (如果該機器中有多個 java 環境,可利用此指令進行篩選)
設定 JAVA_HOME 及 PATH 等環境變數,將 .bash_profile 設定修改如下 (紅字部分為增加之設定)

# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
        . ~/.bashrc
fi
# User specific environment and startup programs
export JAVA_HOME=/opt/jdk1.7.0_67
PATH=$PATH:$HOME/bin:/opt/jdk1.7.0_67/bin
export PATH
unset USERNAME



安裝 Apache Tomcat

執行下列指令,進行 tomcat 下載 (本範例下載到 /usr/Apache 目錄底下)
wget http://apache.stu.edu.tw/tomcat/tomcat-7/v7.0.55/bin/apache-tomcat-7.0.55.zip
執行下列指令,將下載回來的 Tomcat Server 檔案解壓縮

unzip apache-tomcat-7.0.55.zip
至 apache-tomcat-7.0.55 目錄底下的 bin,執行下列指令,啟動 Tomcat Server

./startup.sh
接著可以使用 http://serverip:8080/ 測試 Tomcat 伺服器是否正常運作。



星期五, 9月 12, 2014

Sencha Touch 入門 - 環境建置 for MAC (1)


隨著行動應用的發展,App 開發的專案越來越多。最近,IBM Worklight 的詢問度似乎有提高的趨勢。面對 Hybrid App 的開發,大家通常提出來的第一個問題就是「效能會不會很差」。為了,能夠推廣 Hybrid App 的開發,我們當然要很努力地扭轉這樣的局面。

所謂,Hybrid App 指的就是利用 HTML5 + JavaScript + CSS3 來開發行動應用 App。當然,利用這樣的技術來製作 App 效能是比寫 Objective-C 或 Java 來得差。但是,使用者真的需要那麼快的 UI 響應嗎?

開發 Hybrid App 時,處理程式邏輯最重要的部分非 JavaScript 莫屬。在現今許多Framework並起的時代,以 Sencha Touch 的平台效能響應最快。因此,我們就開始 Sencha Touch 的 Survey 了!

這篇文章,算是個起頭!先交代如何建立 Sencha Touch 的環境。後面,再寫幾篇文章來說明我們實驗的過程。

安裝 Sencha Cmd

首先,把下載回來的檔案「SenchaCmd-5.0.1.231-osx.app.zip」解壓縮。解壓縮後可以看到「SenchaCmd-5.0.1.231-osx」檔案。點選該檔案後,開始進行 Sencha Cmd 的安裝。


在上述畫面,點選「打開」後,開始進行 Sencha Cmd 的安裝工作。在下列畫面中,點選下一步,進行 Sencha Cmd 的安裝工作。


在 License Agreement 的畫面上,選擇「I accept the agreement」後,點選「Next」繼續進行安裝工作。


選擇 installation Directory (可以採用預設的建議目錄),點選「Next」


在 Ready to Install 畫面上,點選「Next」 開始進行安裝程序


等待安裝程序完成!


點選 Finish 完成安裝!


開啓「終端機」,輸入「sencha」可以看到下列畫面,代表 Sencha Cmd 已經安裝完成了!


Sencha Touch 2.4 


  1. 將下載回來的「touch-2.4.0-commercial.zip」檔案解壓縮
  2. 將終端機中的路徑,切換到「touch-2.4.0-commercial.zip」 解壓縮的位址
  3. 輸入下列畫面中的指令,來建立 Sencha Touch 專案

成功建立 Sencha Touch 專案後,可以看到上列畫面。接著,執行下列指令打開 Chrome 瀏覽器「open /Applications/Google\ Chrome.app/ --args --disable-web-security」。然後再從檔案中選到 index.html 後即可看到預設的範例程式。
到了這一步,表示基本環境已經建置完成。


參考資料:

下載 Sencha Touch : http://www.sencha.com/products/touch/
下載 Sencha Cmd: http://www.sencha.com/products/sencha-cmd/download