Total Pageviews

2018/01/08

[GitLab] How to build WAR file automatically

Problem
If I hope GitLab can build a WAR file when I commit source code, how to do it?
I am using Maven 3 and JDK 7 in eclipse, and using mvn clean package -U to build WAR file in eclipse.

How-To

Step 1. Add .gitlab-ci.yml to the root directory of my project, the content looks like: 
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
image: maven:3-jdk-7

build:
  stage: build
  script: "mvn clean package -U"
  artifacts:
    expire_in: 1 week
    when: always
    paths:
    - target/*.war

Step 2. Add, commit and Push .gitlab-ci.yml to GitLab
Step 3. Seeing the status of your pipeline and jobs 

Reference

[1] https://docs.gitlab.com/ce/ci/quick_start/README.html
[2] https://hub.docker.com/r/library/maven/tags/

2018/01/07

[Maven] Cannot find IBM-related jar files in Maven Central Repository

Problem
If I would like to use some proprietorial jar files (i.e. IBM DB2 jdbc jar file, IBM MessageQueue jar files) in my Maven project, and add them into dependency. 
How to do it?

How-To

Step 1. Download jar files, ex. DB2 jdbc jar file
Step 2. Launch command prompt, change directorty to db2 jar file and execute the following command:
mvn install:install-file -Dfile=db2jcc4-4.22.29.jar -DgroupId="com.ibm.db2.jcc" -DartifactId="db2jcc4" -Dversion="4.22.29" -Dpackaging="jar"

Step 3. Add dependency to pom.xml
    <dependency>
        <groupId>com.ibm.db2.jcc</groupId>
        <artifactId>db2jcc4</artifactId>
        <version>4.22.29</version>
    </dependency>


Step 4. Go to .m2 folder and copy com/ibm/db2/jcc/db2jcc4 to your project, for example:


Step 5. Add repository setting in your pom.xml
    <repositories>
        <repository>
            <id>my-local-repo</id>
            <!-- ${basedir} represents the directory containing pom.xml -->
            <url>file://${basedir}/local-repo</url> 
        </repository>
    </repositories>




2018/01/06

[Git] fatal:LF would be replaced by CRLF

Problem
As I try to use the git add command adds a change in the working directory to the staging area, it show the error:
fatal: LF would be replaced by CRLF


Here has a post to solve this problem: https://albert-kuo.blogspot.tw/2016/12/git-fatal-lf-would-be-replaced-by-crlf.html

But if I have hundreds of file have this problem, how to solve this problem?


Solution

Step 1. download file from http://www.bastet.com/uddu.zip

Step 2. Unzip and copy UNIX2DOS.EXE and UNIX2DOS.C to the root directory of your project.


Step 3. Assign the file extension you would like to do replacement in the command and execute this command:

for /f %f IN ( 'dir /b /s *.xml *.pom *.sha1' ) DO @unix2dos %f

Step 4. Remove  UNIX2DOS.EXE and UNIX2DOS.C from your project.

2018/01/05

[Fortify] Fix Unreleased Resource: Database

Before
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.dbutils.QueryRunner;

public class DaoBase {

    public Connection getConnection() throws SQLException {
        return MyDataSource.getInstance().getDatasource().getConnection();
    }

    public List<Map<String, Object>> find(String sql) throws SQLException {
        List<Map<String, Object>> datas = new ArrayList<Map<String, Object>>();

        Connection con = null;
        Statement stmt = null;
        ResultSet rs = null;

        try {
            con = getConnection();
            stmt = con.createStatement();
            rs = stmt.executeQuery(sql);

            // ...
        } catch (SQLException e) {
            throw e;
        } finally {
            if(rs != null) {
                rs.close();
            }
            if(stmt != null) {
                stmt.close();
            }
            if(con != null) {
                con.close();
            }
        }

        return datas;
    }
}



After
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.dbutils.QueryRunner;

public class DaoBase {

    public Connection getConnection() throws SQLException {
        return MyDataSource.getInstance().getDatasource().getConnection();
    }

    public List<Map<String, Object>> find(String sql) throws SQLException {
        List<Map<String, Object>> datas = new ArrayList<Map<String, Object>>();

        Connection con = null;
        Statement stmt = null;
        ResultSet rs = null;

        try {
            con = getConnection();
            stmt = con.createStatement();
            rs = stmt.executeQuery(sql);

            // ignore...
        } catch (SQLException e) {
            throw e;
        } finally {
            close(rs);
            close(stmt);
            close(con);
        }

        return datas;
    }

    public void close(ResultSet rs) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
            }
        }
    }

    public void close(Statement stmt) {
        if (stmt != null) {
            try {
                stmt.close();
            } catch (SQLException e) {
            }
        }
    }

    public void close(Connection con)  {
        if (con != null) {
            try {
                con.close();
            } catch (SQLException e) {
            }
        }
    }
}




2018/01/04

[Fortify] Fix SQL Injection

Before

code snippet:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
    public List<AccountDtl> getAcctDetail(List<String> acctNos) throws SQLException {

        List<AccountDtl> result = new ArrayList<AccountDtl>();

        Connection conn = null;
        PreparedStatement pst = null;
        ResultSet rs = null;

        String accounts = "";
        for (String account : acctNos) {
            accounts = accounts + "'" + account + "',";
        }
        
        String sql = "select DISTINCT ( TRIM(REC_ID))  , NO , ID from " + Table.test.getFullName()
                + " where acct_no in (" + accounts.substring(0, accounts.length() - 1) + ")";
        
        try {
            conn = getConnection();
            pst = conn.prepareStatement(sql);
            rs = pst.executeQuery();
            // ignore code snippet regarding get values 
        } catch (SQLException e) {
            throw e;
        } finally {
            close(rs);
            close(pst);
            close(conn);
        }

        return result;
    }


After


Add dependency to your pom.xml
1
2
3
4
5
    <dependency>
        <groupId>org.owasp.esapi</groupId>
        <artifactId>esapi</artifactId>
        <version>2.1.0</version>
    </dependency>



Updated code snippet (If you are not using DB2 as your database, please apply other Codec, ex. OracleCodec):
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
     import org.owasp.esapi.ESAPI;
     import org.owasp.esapi.codecs.DB2Codec;

     // ignore code snippet
     
     public List<AccountDtl> getAcctDetail(List<String> acctNos) throws SQLException {

        List<AccountDtl> result = new ArrayList<AccountDtl>();

        Connection conn = null;
        PreparedStatement pst = null;
        ResultSet rs = null;

        String accounts = "";
        for (String account : acctNos) {
            accounts = accounts + "'" + ESAPI.encoder().encodeForSQL(new DB2Codec(), account) + "',";
        }
        
        String sql = "select DISTINCT ( TRIM(REC_ID))  , NO , ID from " + Table.test.getFullName()
                + " where acct_no in (" + accounts.substring(0, accounts.length() - 1) + ")";
        
        try {
            conn = getConnection();
            pst = conn.prepareStatement(sql);
            rs = pst.executeQuery();
            // ignore code snippet regarding get values 
        } catch (SQLException e) {
            throw e;
        } finally {
            close(rs);
            close(pst);
            close(conn);
        }

        return result;
    }



2018/01/03

[閱讀筆記] Peak and Valleys (1/2)


  1. 知識不僅僅是擁有它,還要知道怎麼使用它
  2. 真正的發現之旅不在於尋找新風景,而是擁有新眼光
  3. 世界上的每個人、每個地方,在生活上、在工作中,本來就會有高峰和低谷
  4. 人們總是會希望儘速離開低谷;在高峰待久一點;在未來能夠擁有較多的高峰、較少的低谷
  5. 當你在幫助別人的同時,其實你也在幫助你自己
  6. 無論在工作或是人生,你一定會遇到無數的高峰與低谷。順境或逆境,可能持續幾分鐘、幾個月、甚至更久。
  7. 個人的高峰與低谷猶如地球表面上的高峰與低谷,貌似分散,實際上又彼此相連。你可能在工作上感覺是高峰,但生活上感受低谷,這是很自然的事,世界上的每個人都如此
  8. 高峰與低谷不僅僅是發生在你身上的順境或逆境的時刻,還包含你內心的感受以及你如何對外部事件的反應
  9. 你內心深處如何感受,端視於你如何看待你目前的處境。即便是壞事降臨在你身上,你內心還是能保持良好狀態
  10. 高峰與低谷彼此是相連的。你在高峰時期犯的錯誤,會造成明日的低谷。你在低谷時期做的明智的事情,會造就明日的高峰
  11. 太多人無法有效管理他們的高峰時期,沒有注意到他們正在造成未來的低谷。他們浪費太多資源,遠離初衷,忽略什麼是最重要的事
  12. 我們會感到快樂與痛苦,待在低谷(valleys)的時間可能比我們想像得還要長,但這些都免不了,人生就是如此。高峰(peaks)和低谷(valleys)不僅僅代表快樂與痛苦,同時也是自我心境的反應,換句話說,只要能改變自己的心境,就能越快走出低谷。
  13. 感恩與渴求也是一種高峰與低谷的展現,當你每天感恩自己擁有的東西,你就處於高峰;當你渴求自己所缺少的東西,就處於低谷。
  14. 如果你能避免比較,你就會擁有較少的低谷;若你能享受愉快的時光,你就會感覺你在高峰
  15. 你無法控制外部事件,但你可以藉由你想的與你所做的,來控制你個人的高峰與低谷
  16. 要將低谷改變成高峰,你必須要改這兩件事情中的一件:若你可以改變現況,那是最好的狀況;如果你無法改變現況,你可以改變你的想法,選擇較好的想法通常會讓你得到較佳的結果
  17. 當你改變看待事情的角度,離開低谷的路就會出現。當兩位被前公司資遣的面試者前來面試,一位看起來被受不公平對待且不斷在抱怨前雇主如何無底對待的面試者,與另外一位即便是在低谷但仍保持正面態度、想要追求新的機會的面試者,你會選哪一位呢?
  18. 在低谷時,記得將低谷視為一個契機,發掘其中隱藏的、之前未發覺的問題,想辦法改善問題,讓事情變得更好,就會從低谷走向高峰
  19. 高峰與高峰之間所間隔的總是低谷,如何管理與改善你的低谷,決定你多快離開低谷、走向下一個高峰
  20. 如果你無法在低谷中學習到教訓,你會變得易怒、怨天尤人;若你可以從低谷中學習到可貴的事物,你會變得更好,並找到離開低谷的道路
  21. 當遇到棘手問題一直無法解決時,先抽離當下,休息一下、反思一下,經過一夜好眠或是幾天的休息之後,你獲得重新注入的能量,原本的問題就可迎刃而解
  22. 當你心存感激且明智地管理你的 good times,你就可以擁有較少的 bad times
  23. 你的自我(ego)會讓你在高峰時感到自負,在低谷時感到恐懼。這會讓你看不見真實情況,你的自我(ego)會扭曲事實。當你在高峰時,你的自我(ego)會讓你過度樂觀,當你在低谷時,你的自我(ego)會讓你過度悲觀。讓你覺得高峰會永遠持續,讓你恐懼低谷不會結束


2018/01/02

[閱讀筆記] The Four Pillars of Investing (1/12)


  1. 大部分民眾把理財一事看得太簡單,也太輕率。投資前甚少做足周密的功課,投資產生虧損時則選擇長期持有,認為不賣出就沒有虧損
  2. 投資四大關鍵
    1. 高獲利一定伴隨高風險
    2. 投資過熱後一定泡沫化,歷史總是不斷的重演
    3. 人性是理財的最大殺手,唯有反市場操作才能投資獲利
    4. 認清金融機構的遊戲規則,才不會淪為短線進出幫金融業者賺手續費
  3. 所有投資都伴隨著風險,應先認清自己的希望與需求是什麼,冀求一蹴可幾,可能跌跌撞撞還不見得到的了終點站,掌握局面循序漸進,反倒可以安穩到達目的地
  4. 在國家國事強大時買進公債的人,報酬率會遠低於國家風雨飄搖之際買進的投資人,因為情勢危急,所以債券需要用更高的預期報酬來補償、吸引投資人。又如狀況差的公司,正因風險較高,所以需要用比較高的報酬補償投資人。所以我們能掌握,報酬就是來自於承擔風險。有了這種理解,可以使投資人面對市場大跌時,具備買進的勇氣。因為他會知道,這正是金融資產預期報酬較高的時候。正確的理解,將帶來低點買進的勇氣。正確的觀念,才是獲取更高報酬的基礎
  5. 雖然說報酬來自於風險,但不是去冒風險就一定有報酬。高風險資產所成弄的是更高的「預期」報酬,注意,是「預期」,未必是「實際」。投資不是膽子大的人就會贏,投資是一個小心地在金融市場中,承擔必要風險的大腦活動
  6. 投資風險有兩個面相,一個是來自市場,另一個來自於投資人自己
  7. 在上漲時樂觀地買進,在下跌中悲觀地賣出,這種高買低賣的行為,是標準且常見的財務自殺
  8. 歷史一再重演,這些最悲觀、大家都說市場最不值得投資的時刻,往往就是預期報酬最高的時間點
  9. 投資大眾很有趣的一點就在於:大家都承認市場是不理性的,但是每一個人都覺得自己是理性的
  10. 投資不是只有下跌的風險,錯過報酬一樣是風險
  11. 很多基金業者的專長不是資產管理,是行銷,他們是行銷業者,只是剛好在賣基金
  12. 投資是一個務實的過程,能幫助自己達成人生各階段重要目標的投資計畫,就是滿分的投資
  13. 看的越多,越覺得自己所知不足
  14. 幾乎所有投資管理人的績效表現都歸功於運氣,而非技術
  15. 你最大的投資風險在於「沒有妥善地分散資產」
  16. 投資組合真正重要的關鍵在於整體投資組合的表現如何,而不在於單一資產的表現狀況
  17. 人們總是被那些成功機率極小的高報酬方案所吸引,儘管在樂透彩每投資一美元的平均報酬不過 0.5 美元。讓自己變窮的最快方法就是講自己的投資首要目標設定成找到 next google
  18. 大多數投資者常見的病態投資行為有:
    1. 傾向極端過度自信
    2. 系統性地在特定類別股票上投資過多
    3. 在高成本的情況下,過度頻繁交易
    4. 經常非理性的進出股市
  19. 經紀商不是你的朋友,基金公司的利益和你的利益是相衝突的
  20. 基金公司只為了一個目的而存在:從投資大眾的行為中收取費用和佣金


2018/01/01

[閱讀筆記] Purple Cow (1/2)


  1. 做為一頭 purple cow 的元素,就是必須 remarkable (卓越非凡)。remarkable 是指值得討論、注意的事情,獨一無二且全新有趣
  2. 保有一個老客戶所花的錢,比開發一個新客戶所花的錢便宜多了
  3. 世界已經改變,人們有太多的選擇,但時間卻越來越少,也讓人不知從何選擇起
  4. 除了利用科技和專業配合顧客的標準製造更好的商品之外,同時也邀請使用者體驗,並改變顧客的行為,你的商品效果將出奇的好
  5. 在還居於市場領先地位時,要把握該得的利潤,別再把錢花在市調研究上,把市場價格提高到合理的地位,把獲得的利潤投入吹造更有前瞻性的新產品上
  6. 不要投資在垂死的產品,要把獲得的利潤投資在建立新產品上
  7. 沒人會急著去使用你的新產品,大多消費者都是滿足現況、停滯不前的。你該把新產品賣給那些喜歡改變、喜歡嘗試新東西的消費者,他們會積極發掘你是葫蘆裡賣什麼藥的人,然後將你的創意傳播出去
  8. 你必須設計出卓越非凡的產品,吸引「早期接受者」;同時這項產品必須設計的夠彈性、夠討喜,能夠讓「早期接受者」輕易、快速地傳播出去
  9. 你該做的是,設計卓越非凡的產品,主打摩爾曲線左邊的「早期接受者」,然後讓「早期接受者」推銷出去
  10. 一個新商品,就是一個創意。能被傳播的創意,遠比不能流傳的創意容易成功,這就是所謂的「創意病毒」(ideavirus)。該如何創造出ideavirus,就是絕對不是試圖製造一個大家都可以適用的產品,為自己的產品找到一個特殊的市場,而非最大市場。
  11. 現在是一個消費者自主選擇的時代,是消費者決定要不要聽你說話,還是忽略你的存在
  12. 面對沒有人願意聽你說話的市場,最聰明的計畫就是「走為上策」
  13. 別盡想著要滿足所有人的需求,如果可以選擇,應該讓廣告(和產品)滿足你所選擇的客戶的需求,試著想想,如何開發這群人、向他們宣傳,就別在乎其他人了
  14. 如果你可以找出一個人別人無法提供服務的利基,並且提供這項服務,結果會如何?為什麼不開發一個與你自己競爭的產品,一個在市場上突出而引人注目的商品?
  15. 在商品充斥的市場中,和別人相同就是失敗;在競爭對手林立的市場中,平凡就是代表隱形
  16. 平凡無奇永遠是最危險的策略,平凡無趣永遠註定要失敗
  17. 評量的意義在於讓你知道哪裡有破洞,才知道要去修補。只要你願意做評量,就有改善的可能
  18. 在擁有一些不凡的成功事蹟之後,事業生活一帆風順通常是容易的,也以致於無法決定是否參加下一回合的戰火,而把時間和精力花在鞏固已經得到的東西,而不願意投資在未來的發展
  19. 一旦你準備創造某些真正卓越非凡的東西,你的挑戰就是同時處理這兩件事情
    1. 任何為乳牛添加養分的事情都是值得做的,要想辦法延續紫牛的生命,並且盡可能拉長從紫牛身上獲利的時間
    2. 創造一個你可以即時創造新紫牛的環境,在地一支子牛利潤竭盡時,隨時取而代之
  20. 正確的行銷是:把行銷的重點放在可以改變產品哪些設計,而不是廣告包裝上