2014年12月16日 星期二

java.lang.NoSuchMethodError: org.apache.hadoop.conf.Configuration.addDeprecations

這個錯誤訊息是因為不同的 Hadoop 版本所造成的

主要是因為 org.apache.hadoop.conf.Configuration 這個類別在 Hadoop 2.3 之後

新增了一個方法(method) addDeprecations

出現這個問題就有可能代表你的環境內有 Hadoop 2.3 的 jar 以及比 2.3 還早的 jar 


我會遇到這個問題是因為

我的專案本身透過 Maven 引入 Hadoop 2.3 的 package

另外也相依了 solr-core 4.1.0 這個 package

剛好 solr-core 4.1.0 它有相依 Hadoop 某些 jar,但卻是 Hadoop 2.2 的

可以在 Solr-core 4.1.0 maven repository 內看到,如下圖









所以導致這樣的問題

解法部外乎就是把你專案本身的 Hadoop 2.3 降到 2.2

或是在 Maven 中用 exclusion 標籤排除掉以上那 4 個 jar  

2014年11月1日 星期六

AngularJS 教學 - Mocking a service

在前一篇  AngularJS 教學 - Service 測試 有簡單介紹到如何對 Service 進行測試

另外因為 Controller 常常需要依賴一些 Service Object 來做一些邏輯處理或後端的溝通

因此也說明了運用了 $injector 來將 Service Object 注入到 Controller,以利 Controller 的測試


不過有時候在開發的過程中,常常會遇到我們所開發的元件中所相依的元件還沒開發完成或是是別人的工作

例如我在開發某個 Controller 元件的時候,可能需要依賴很多的 Service

但這些 Service 可能尚未完成等等之類的因素,但為了確保我的 Controller 能夠如期完成並政常運作

先用模擬的方式來模擬這些 Service ,讓我的開發與測試能夠順利完成

而這些被模擬的東西我們可以稱為 mock object 或是 fake object

所以本篇會說明如何利用 $provide 來建立一個 mock 的 Service object

假設在 SampleCtrl 中我們需要依賴一個 TodoService

angular.module('sampleApp', [])
     .controller("SampleCtrl", function($scope, TodoService){
     $scope.todos = TodoService.getTodos();
 });

2014年10月30日 星期四

AngularJS 教學 - Service 測試

本偏簡單介紹該如何測試 Service,並說明該如何在測試中解決依賴注入的問題(Dependency Injection)

如果不太清楚 AngularJS 的測試,可以看 http://programer-learn.blogspot.com/2014/10/angularjs-unit-testing.html

以下是本次範例的頁面,在 Text Box 輸入名子,按下 Button 後,Text Box 的值就會改變












接下來看一下原始碼 (index.html)

<html xmlns="http://www.w3.org/1999/xhtml" ng-app="sampleApp">
     <head>
         <title>Demo</title>
         <script type="text/javascript" src="lib/angular.min.js"></script>
         <script type="text/javascript" src="js/app.js"></script>
     </head>
     <body>
         <div ng-controller="SampleCtrl">
              Name:<input type="text" ng-model="name"/>
              <br/><button ng-click="echo()">Echo</button>
         </div>
     </body>

</html>

2014年10月27日 星期一

AngularJS 教學 - Controller 測試

這篇要簡單介紹一下 AngularJS Controller 的測試該如何實現

以下還是用 Karma + Jasmine 來進行測試,如果不熟悉這些可以先看之前寫的文章 AngularJS 教學 - 單元測試(Unit Testing)

首先先列出我們要測試的範例程式,範例很簡單

頁面上有兩個 Button 負責針對 counter 的值進行遞增或遞減

以下是 index.html 的範例程式

<html xmlns="http://www.w3.org/1999/xhtml" ng-app="sampleApp">
     <head>
         <title>Demo</title>
         <script type="text/javascript" src="lib/angular.min.js"></script>
         <script type="text/javascript" src="js/app.js"></script>
     </head>
     <body>
         <div ng-controller="SampleCtrl">
              Counter : {{counter}}<br/>
              <button ng-click="add()">Increase</button><br/>
              <button ng-click="minus()">Decrease</button>
         </div>
     </body>

</html>


再來是 SampleCtrl 的程式(js/app.js)

2014年10月25日 星期六

AngularJS 教學 - 單元測試(Unit Testing)

本篇先小篇幅介紹如何建構一個 AngularJS 的單元測試

內容很簡單,之後再放上進一步的介紹,包括 Controller、Service、Ajax 等等

單元測試顧名思義就是要能夠確保程式的某個 function 或是部分的程式邏輯是正確的

至於單元測試所帶來的好處就不花時間描述了

不過單元測試除了驗證正確性外其實也是描述了系統的 Spec (Specification)

也就是單元測試中的每一個測試函式就表明了一件 Spec

回歸到 AngularJS 上,目前 JavaScript 領域中有很多單元測試的框架(Testing Framework)

包括 QUnit、Mocha、Jasmine 等等

除了測試框架之外還有所謂的 Testing Runner

例如我們接下來要介紹的 Karma,它不同於 Testing Framework

2014年10月23日 星期四

Grunt 教學 - 檔案管理(1)

本篇會介紹部分 Grunt 如何操作檔案,如果對 Grunt 不熟的可以先看 Grunt 教學 - Getting Started

在使用 Grunt 建構 JavaScript 專案時一定會常常接觸到檔案或是資料夾的整理

或是你想寫一些相關的 Grunt plug-in 時,也會遇到相同的情形

因為篇幅的關係,所已先簡單介紹一下如何建立與刪除資料夾

之後有空再補充其他關於檔案管理的技巧

以下是建立資料夾的 Grunt 程式

module.exports = function(grunt){
     grunt.initConfig({
         file: {
              params: {
                  sampleFolder: "sample"
              }
         }
     });
    grunt.registerTask("createFolder", function(){
         // grunt.config.requires() 會確保 config 有被設定
         // 如下就會確保 file.params.sampleFolder 是有先被設定過的
         // 假如沒有設定會拋出以下訊息
         //   Verifying property file.params.sampleFolder exists in config...ERROR
         //   >> Unable to process task.
         //   Warning: Required config property "file.params.sampleFolder" missing. Use --force to continue.
         grunt.config.requires("file.params.sampleFolder");

         // 利用 grunt.config.get() 來取得 config 的值
         grunt.file.mkdir(grunt.config.get("file.params.sampleFolder"));
    });

}

完成之後在你專案的 root 目錄下執行 Grunt 的指令 $grunt createFolder

結束之後,會在你的專案目錄下看到一個 sample 的資料夾

如果是刪除資料夾的話,就用 grunt.file.delete(),如下所示

grunt.registerTask("deleteFolder", function(){
         grunt.config.requires("file.params.sampleFolder");
         grunt.file.delete(grunt.config.get("file.params.sampleFolder"));

});

所以同樣在你專案的 root 目錄下執行 Grunt 的指令 $grunt deleteFolder

就會發現剛剛建立的 sample 資料夾被移除了

2014年10月6日 星期一

Grunt 教學 - Getting Started

Grunt 是一個 JavaScript Task Runner,這是 Grunt 的官方網站 GRUNT : The JavaScript Task Runner

它真正的目的是讓開發者可以更容易的建構(Build)他們的 JavaScript 專案

在一般的建構過程中,不外乎包含自動化測試、JS 與 CSS 的壓縮或合併、檔案操作等等

而且目前 JavaScript 專案或多或少都會包含很多第三方套件,會讓你的建構過程相當複雜

所以現在 Grunt 也有很多 Contributors 貢獻了很多的 Grunt plug-ins 來改善建構的過程

因此有了 Grunt 與這些 plug-ins 工具之後,勢必能夠改善你的工作效率

接下來就初步介紹一下 Grunt 的安裝與使用

2014年9月23日 星期二

AngularJS 教學 - Java RESTful 範例

AngularJS 教學 - $resource service 詳細介紹到如何使用 ngResource 的 $resource service 進行後端的 RESTful 溝通

所以我花點時間打算寫一些 AngularJS RESTful 一個完整的前後端範例

可能想到要用 Java 和 Node.js 作為範例後端吧,所以本篇先提供以 Java 為後端的範例程式吧


以下我用 Todo 作為範例,整個程式我並不會介紹太多,基本的可以先看 AngularJS 教學 - $resource service

先列出專案目錄結構





























2014年9月17日 星期三

AngularJS 教學 - $resource service

這篇要來介紹一下 AngularJS 提供的一個 Service,就是 $resource

$resource 讓你能夠容易地和後端的 RESTful Service 做溝通,以便建構出一個 CRUD 的應用

$resource 也是建構在 $http 之上,其中 $http 提供了 AngularJS 一個執行 Ajax 的方式

如果對 $http 不熟的可以看 AngularJS 教學 - AjaxAngularJS 教學 - Ajax(1)

接下來就開始介紹   如何利用 $resource 來與 RESTful Service 溝通


1.準備 angular-resource.js
首先要使用 $resource,需要先額外引入 angular-resource.js 到你的 HTML 內

因為 $resource 並不在原本 AngularJS 核心的 JS 檔案內,所以才需要額外引入 JS 檔



2.一個 Todo REST 範例
URL
Method
Body
Result
/todos
GET
Nothing
Get all Todos
/todos
POST
Todo JSON String
Add a Todo
/todos/:id
GET
Nothing
Get a Todo by id
/todos/:id
PUT
Todo JSON String
Update a Todo
/todos/:id
DELETE
Nothing
Delete a Todo


2014年9月16日 星期二

Passive View vs Supervising Controller

MVP (Model View Presenter) 設計模式 中有詳細介紹了什麼是 MVP 設計模式

這篇簡單介紹一下 MVP 中可以運用的兩種變型,分別是 Passive View 與 Supervising Controller

如果想要對這兩種設計模式想更進一步了解可以看看 Martin Fowler大師的介紹


Passive View(PV) 從字面上來看就是"被動的視圖",簡單說就是 View 只負責顯示,

並由 Controller 或是 Presenter 負責處理使用者的動作 (action),也就是 View 都是被動的

只能透過 Controller 或是 Presenter 給的命令 (command) 來做事情

採用 PV 的好處是可以讓你容易獨立的測試 Controller 或是 Presenter,而且不需依賴任何 UI 測試框架

但我認為這前提是你的 View 與 Presenter 或是 Controller 的關係要盡量是鬆散耦合的

也就是說當有任何的使用者互動,View 都是發出事件(Event)給 Controller 或是 Presenter

來處理,且送出去的資料盡量都不要跟 View 有任何一點關係

2014年9月11日 星期四

MVP (Model View Presenter) 設計模式

在 GUI 的架構開發中,最顯為人知就是 MVC (Model View Controller) 了

而 MVP (Model View Presenter) 模式也類似於 MVC,從下圖我們可以看到 MVP 與 MVC 的區別



上圖參考於 http://joel.inpointform.net/software-development/mvvm-vs-mvp-vs-mvc-the-differences-explained/

2014年9月10日 星期三

AngularJS 教學 - Ajax(1)

上一篇 簡單介紹了 AngularJS 使用 Ajax 的方式 接下來繼續介紹一些 AngularJS 常用的 Ajax 設定

AngularJS 利用 $http 這個 Service 物件做為 Ajax 的一個管道

但是在多數複雜的應用中,我們的 Ajax 請求或回傳可能稍微複雜需要設定一些額外的參數

譬如說 HTTP 的請求表頭、HTTP 的 method(POST、PUT、DELET)之類的

所以以下列出幾個比較常用到的參數設定

首先在上一篇看過一個簡單的 Ajax 方式,如下:

$http.get("todos.json").success(function (data) {
    return data;
});

如果要加上額外的設定,可以類似這樣:

var config = {
    //你的設定參數在這
};
$http.post("/todos", config).success(function (data) {
    return data;
});

2014年8月16日 星期六

AngularJS 教學 - 模組化及開發模式

AngularJS 提供了一個 Javascript 的 MVC 框架讓開發者能夠輕易的在前端開發中實現 MVC 架構

但我認為 AngularJS 帶給前端開發者最重要的思維還是模組化以及開發模式

先從模組化談起

模組化(Modularity)已經是前端開發中一個很重要的準則了,就像大部分書籍說的

模組化能夠讓我們更能夠輕易重用(reuse)各個模組,另外能夠讓你容易地進行測試

也能夠幫助開發者快速並明確地釐清一個大型的前端應用的架構

但要組織一個大量模組間相互依賴的關係其實是一個蠻重要的課題

如果處理不當容易造成模組間的緊密耦合關係,並且降低重用性以及難於測試

要如何解耦?你可以透過 Mediator Pattern 或是 Observer Pattern 這類型的設計模式

這其實就有點像是 Event Driven Development

2014年8月3日 星期日

AngularJS 教學 - Ajax

AngularJS 教學 - MVC 介紹 中有特別提到 Model(模型) 的職責

其中一項就是用來跟後端作資料的操作 (CRUD)

而 AngularJS 提供了 REST 以及 Ajax 這兩種方式讓你能夠跟後端的應用程式作溝通

以下就介紹 AngularJS 的 Ajax 方法吧

首先 AngularJS 提供了 一個 Service 讓開發者能夠運用 Ajax,那個 Service 就叫做 $http

當你的模組需要用到 Ajax 的時候,可以將 $http 直接注入到你的模組中,就像 Controller 的 $scope 一樣

接著就看一下一個簡單的範例吧

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" ng-app="demoApp">
     <head>
         <title>Examples</title>
         <script type="text/javascript" src="js/angular.min.js"></script>
         <script>
              var demoApp = angular.module("demoApp", []);
              demoApp.factory("Todo", function($http){
                  return {
                       list: function(){
                            $http.get("todos.json").success(function (data) {
                                return data;
                            });
                       }
                  };
              });
              demoApp.controller("demoCtrl", function($scope, Todo){
                  $scope.loadData = function(){
                       $scope.todos = Todo.list();
                  }
             });
         </script>
     </head> 
     <body>
         <div ng-controller="demoCtrl">
              <button ng-click="loadData()">Load Todos</button></br>
              <table>
                  <tr>
                       <td>NO.</td><td>Name</td><td>Priority</td>
                  </tr>
                  <tr ng-repeat="todo in todos">
                       <td>{{todo.id}}</td>
                       <td>{{todo.name}}</td>
                       <td>{{todo.priority}}</td>
                  </tr>
              </table>
         </div>
     </body>

</html>