Total Pageviews

2017/08/11

[DB2] Use getNextException() to retrieve the exceptions for specific batched elements. ERRORCODE=-4229, SQLSTATE=null

Problem

When I using Apache Commons DBUtils to do batch insert data into IBM DB2, I get this SQLException:
1
2
3
SQL Message: [jcc][t4][102][10040][4.14.88] Batch failure.  
The batch was submitted, but at least one exception occurred on an individual member of the batch.
Use getNextException() to retrieve the exceptions for specific batched elements. ERRORCODE=-4229, SQLSTATE=null


Code Snippet:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
    /**
     * 批次處理.
     * 
     * @param sql
     *            insert/update/delete sql statemet
     * @param params
     *            parameters
     * @throws SQLException
     *             in case of fail to do insert/update/delete
     */
    public void batchUpdate(String sql, Object[][] params) throws SQLException {
        QueryRunner run = new QueryRunner();
        run.batch(this.getConnection(), sql, params);
    }



How-To
According to the troubleshooting information from IBM Support, it said:
The error is caused by the DB2 Transaction log for the Data Warehouse becoming full and not able to process the full batch operation.


But the root case is "value too large" in insert SQL statement, having nothing to do with DB2 Transaction log.   

2017/08/10

How to Improve Code Coverage After Using Apache Lombok?

Problem
After using Project Lombok, we can find out it help use reduce our boilerplate code. 

 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
package albert.practice.lambda;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import com.google.common.base.Strings;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

public class LambdaTest {

    public List<Person> filterData() {
        List<Person> people = createData();
        return people.stream().filter(p -> p.age >= 35).filter(p -> !Strings.isNullOrEmpty(p.email))
                .collect(Collectors.toList());
    }

    public List<Person> filterDataWithSort() {
        List<Person> people = createData();
        return people.stream().filter(p -> p.age >= 35).sorted((p1, p2) -> (p1.age - p2.age))
                .sorted((p1, p2) -> p2.name.compareTo(p1.name)).collect(Collectors.toList());
    }

    public List<Person> createData() {
        Person ben = new Person("Ben Whittaker", 70, "ben@gmail.com");
        Person jules = new Person("Jules Ostin", 30, "jules@gmail.com");
        Person fiona = new Person("Fiona Farwell", 68, null);
        Person matt = new Person("Matt", 35, "matt@gmail.com");
        
        return Arrays.asList(ben, jules, fiona, matt);
    }

    @Data
    @ToString
    @AllArgsConstructor
    @NoArgsConstructor
    public static class Person {
        private String name;
        private int age;
        private String email;
    }

}

But you will also notice your code coverage rate is down dramatically.


How to improve the code coverage rate?


How-To
Add two dependencies to your pom.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<dependencies>
    <dependency>
        <groupId>org.meanbean</groupId>
        <artifactId>meanbean</artifactId>
        <version>2.0.2</version>
    </dependency>

    <dependency>
        <groupId>nl.jqno.equalsverifier</groupId>
        <artifactId>equalsverifier</artifactId>
        <version>2.2.1</version>
        <scope>test</scope>
    </dependency>
</dependencies>

Check the testPersonBean() and testEqualsAndHashCode() in this test case:
 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
package albert.practice.lambda;

import static org.junit.Assert.assertEquals;

import java.util.List;

import org.junit.Before;
import org.junit.Test;
import org.meanbean.test.BeanTester;

import albert.practice.lambda.LambdaTest.Person;
import lombok.extern.slf4j.Slf4j;
import nl.jqno.equalsverifier.EqualsVerifier;
import nl.jqno.equalsverifier.Warning;

@Slf4j
public class LambdaUnitTest {

    private LambdaTest lambdaTest = null;

    @Before
    public void setup() {
        lambdaTest = new LambdaTest();
    }

    @Test
    public void testCreateData() {
        List<Person> people = lambdaTest.createData();
        assertEquals(people.size(), 4);
    }

    @Test
    public void testFilterData() {
        List<Person> people = lambdaTest.filterData();
        log.debug("testFilterData = " + people.toString());
        assertEquals(people.size(), 2);
    }

    @Test
    public void testFilterDataWithSort() {
        List<Person> people = lambdaTest.filterDataWithSort();
        log.debug("testFilterDataWithSort = " + people.toString());
        assertEquals(people.size(), 3);
    }

    // Testing getter and setters methods
    @Test
    public void testPersonBean() {
        new BeanTester().testBean(LambdaTest.Person.class);
    }

    // Testing equals() and hashCode()
    @Test
    public void testEqualsAndHashcode() {
        EqualsVerifier.forClass(LambdaTest.Person.class)
                .suppress(Warning.STRICT_INHERITANCE, Warning.NONFINAL_FIELDS).verify();
    }

}

After running code coverage analysis, you can find out this problem had been solved:




Reference
[1] http://www.jdev.it/tips-unit-testing-javabeans/

2017/08/09

[Squirrel SQL Client] Is it possible to have Squirrel SQL auto-resize the column width of the result set?

Problem
Is it possible to have Squirrel SQL auto-resize the column width of the result set? 


How-To
Steps:
(1) move your mouse to query result grid
(2) right click on query result grid
(3) check "Always adjust all column widths"



2017/08/08

[Tools] [Text Compare] How to Compare Two Lengthy JSON String

Problem
I have two lengthy JSON String, if I would like to compare the difference between the two JSON string, how to do it?

How-To
Here are the steps to fulfill this requirement:
(1) connect to https://text-compare.com/
(2) copy first JSON string to left hand side
(3) copy second JSON string to right hand side
(4) click Compare button

(5) check the difference

2017/08/07

[SQL Server] How to find similar table / column name by SQL

I am using Microsoft SQL Server...

If I would like to get a list of table name which table name has %arap%, you can use this SQL statement to do query:
SELECT NAME 
FROM   sys.tables 
WHERE  NAME LIKE '%arap%' 



If I would like to get a list of table which has column name %apply%, you can use this SQL statement to do query:
SELECT t.NAME AS 'TableName', 
       c.NAME AS 'ColumnName' 
FROM   sys.columns c 
       JOIN sys.tables t 
         ON c.object_id = t.object_id 
WHERE  c.NAME LIKE '%apply%' 
ORDER  BY t.NAME, 
          c.NAME; 








2017/08/06

[webMethods] How to Restart / Shutdown / Startup Integration Server

Problem
若我要重新啟動 integration server 的話,該去哪裡執行重啟

How-To
有兩個方式:
(1) 到遠端到安裝 integration server 的機器,到 SoftwareAG 的安裝目錄下,如 [SoftwareAG_HOME]\profiles\IS_default\bin\

執行 restart.bat 表示 restart integration server
執行 shutdown.bat 表示 shutdown integration server
執行 startup.bat 表示 startup integration server

(2) login 到 integration server administration console
點選畫面右上角的 ShutDown and Restart



若要 shutdown integration server,click Shut Down button
若要 restart integration server,click Restart button
若要強制馬上關閉,不管 session 的工作結束與否,點選上方的 immediately radio button



2017/08/05

[webMethods] 如何更新 integration server 的 trial license

Problem
今天當我 log in 到 webMethods integration server 的 administration console 時,出現 trial license 即將 expire 的 warning message


How-To
處理步驟如下:
(1) 到 Software AG [1] download trial license
(2) 將 trial license copy 到安裝 integration server 的特定目錄下
(3) 點選 Edit Licensing Details


(4) 修改 License File 的位置與檔名


(5) restart integration server
(6) login administration console,此時可以發現 warning message 已經消失,expire date 延長到 July 31




Reference
[1] http://www.softwareag.com/Corporate/res/download/default.asp

2017/08/04

[webMethods] Software AG Designer 無法編輯 Document Type, Flow Service

Problem
當我要編輯先前已經開發好的 document type, flow service 時,發現無法進行編輯,相關可編輯的選項都被 disabled



How-To
在欲編輯的 document type 或 flow service 中,按下右鍵,選擇 Lock for Edit



此時你會發現,該 document type 的 icon 出現打勾的符號,編輯的選項也都 enabled 了






2017/08/03

[Lombok] Utilize @Builder annotation to produce complex builder APIs for your classes

Problem
If you would like to apply builder pattern in your Java class, the class will looks like:
package albert.practice.designPattern.builder;

public class User {

    private String firstName;
    private String lastName;
    private String email;

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public String getEmail() {
        return email;
    }

    private User(UserBuilder builder) {
        this.firstName = builder.firstName;
        this.lastName = builder.lastName;
        this.email = builder.email;
    }

    @Override
    public String toString() {
        return "User [firstName=" + firstName + ", lastName=" + lastName + ", email=" + email + "]";
    }

    public static class UserBuilder {
        private String firstName;
        private String lastName;
        private String email;

        public UserBuilder firstName(String firstName) {
            this.firstName = firstName;
            return this;
        }

        public UserBuilder lastName(String lastName) {
            this.lastName = lastName;
            return this;
        }

        public UserBuilder email(String email) {
            this.email = email;
            return this;
        }

        public User build() {
            User user = new User(this);
            return user;
        }
    }
}


Compared with POJO class, you may notice the number of lines of code increase at least to double in builder pattern. Does it has any convenient approach to implement and yield the same benefit which builder pattern bring for us?

How-To
You can make good use of @Builder annotation which provide by Project Lombok. The updated code look like:
package albert.practice.designPattern.builder;

import lombok.Builder;
import lombok.Getter;
import lombok.ToString;

/*
 * The @Builder annotation produces complex builder APIs for your classes.
 * @Builder lets you automatically produce the code required to have your class be instantiable with code such as:
 * Person.builder().name("Adam Savage").city("San Francisco").job("Mythbusters").job("Unchained Reaction").build();
 */
@Builder
@Getter
@ToString
public class User2 {
    
    private String firstName;
    private String lastName;
    private String email;

}


Here is the test code:
package albert.practice.designPattern.builder;

import static org.junit.Assert.assertNotNull;

import org.junit.Test;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class UserTest {

    @Test
    public void testUser() {
        User user = new User.UserBuilder().firstName("Albert").lastName("Kuo")
                .email("test@gmail.com").build();
        log.debug("user = " + user.toString());
        assertNotNull(user);
    }

    @Test
    public void testUser2() {
        User2 user2 = new User2.User2Builder().firstName("Albert").lastName("Kuo")
                .email("test@gmail.com").build();
        log.debug("user2 = " + user2.toString());
        assertNotNull(user2);
    }

}



Maven dependencies are as bellows:
  <dependencies>
        <!-- lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.8</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.21</version>
        </dependency>

        <!-- logback -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>1.1.7</version>
        </dependency>

        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.1.7</version>
        </dependency>
    </dependencies>

Reference
[1] https://projectlombok.org/features/Builder.html



2017/08/02

[閱讀筆記] 惡魔財經辭典 (The Devil’s Financial Dictionary) [4/6]


  1. 投資人的一種習性是,對真正便宜的東西視而不見,就像羊群一樣成群移動,而不是自己獨立思考。人多會追求安全感,所以投資人買進某一項資產並不是因為該資產的價值被低估,而是因為「其他人」都在買;賣出資產也不是因為某種基本面的原因,而是因為「其他人」都在賣
  2. Heuristics (捷思),譬如定錨心理(anchoring)、可得性(availability)、代表性(representativeness),用直覺取代或然率分析和統計分析。短期來看,根據 heuristics 來進行投資的人可以得到很多樂趣;長期來看,根據統計來進行投資的人可以累積很多財富
  3. Income statement(收益表)是一家公司財務報表的一部分,但可能會誇大收益、少列支出
  4. 由於 index fund (指數型基金)收費非常低廉,交易佣金也微不足道,所以華爾街常用『為什麼要甘於平庸(average)?』來奚落 index fund。不過,這個問題的答案是,從年復一年的成果來看,index fund 的績效都超越絕大多數的主動型基金,而且成本少很多
  5. Inflation(通貨膨脹)是今天喪失購買力的過程,錢隨著時間變得越來越不值錢。一般來說,inflation 的原因是,政府用印鈔票來淹沒經濟問題,以此做為解決經濟問題的方法,因此讓百姓的日常生活難以為繼(特別是窮人),使得問題更加惡化
  6. IPO (Initial Public Offerings) 是股票首次公開上市,更精確的來說, IPO 這個縮寫的意思應該是 Insiders’ Private Oportunity(內部人士私人的機會)、 Imaginary Profits Only (獲利只是想像)、It’s Probably Overprices(價格可能太高)
  7. 華爾街的 is ,其實都是現在完成進行式的 has been。當分析師說我知道這隻股票會漲(is going up),他的意思是這隻股票 has been going up
  8. Junk bonds(垃圾債券)是指投資平等不合格的債券,現在已經改名成 high-yield bond(高收益債券),比較好聽但比較不坦率(candid)
  9. Kitchen-sink(運用洗碗槽策略,巨額沖銷),用來比喻公司把所有壞消息都都近盈餘季報,好讓未來的數字相較之下比較好看。2008到2009年發生金融危機時,很多公司提前燈載將淘汰的業務和員工支出、延後認列收入、提早認列虧損。趁著整體經濟大環境壞消息不斷,順勢將自家壞消息盡數公布。如此一來,投資人不僅沒責怪他們無能、犯錯連連,反而激賞他們誠實。此外,把話消息都丟給2009年,2010年的盈餘相較之下就亮麗多了,因為獲利通常是與前一年的同一季度比較
  10. 資產流動性(liquidity)停止時,就會發生清盤(liquidation)。因此,投資人必須隨時保持警覺。盡量追求資產流動性的極大化,同時盡量減少資產清盤的必要性
  11. 華爾街一句最有智慧的俗諺:「liquidity(資產流動性、變現性)只有在你不需要的時候才會出現。」在你一心想持有某個證券時,他當時很好賣;但是當你想賣時,卻賣不掉。小型市場、新興市場的證券尤其如此。
  12. 心理學家的實驗顯示,人是厭惡損失的(lose-averse),虧損 1 元的痛苦比賺 1 元的喜悅還要強烈兩倍以上
  13. 一位善於經營管理出了名的人,去處理一家眾所皆知財務狀況不佳的公司,能保持名聲無損的,是那家公司
  14. 如果一家公司的股價(price)下跌,而公司的價值(value)維持穩定,那麼投資人的安全邊際(margin of safety)就會變大。企業的價值(value)變化緩慢,價格(price)卻會出現爆炸性的變動。因此,股市動盪不穩時,通常安全邊際(margin of safety)會拉大;也就是說,風險最大的時候,正式投資最安全的時刻。懂得善用此一弔詭現象的人,才能充分發揮投資人的潛力。
  15. 雖然你努力不要在熊市賠錢,最常見的結果反而是在牛市賺不了錢
  16. 影響你對金錢的態度的因素,往往是錢怎麼來的、你打算怎麼花,而不是你有多少錢。如年終獎金得到的錢,你會買實用的東西;樂透得到的錢,你會拿去揮霍享受
  17. 動能股(momentum stock)會隨著上漲而日益加速狂飆,無視摩擦力、金融地心引力、牛頓第一運動定律、邏輯和理性。沒有任何理論或經驗可解釋動能的元成因、為何會持續、為何最終會衰退。一旦動能(momentum)停止,動能股也不會減緩,而會以高速去撞牆,把剛好持有的投資人撞得粉身碎骨。
  18. 共同基金(mutual fund)是一點也不互相(mutual)的基金。他的投資人的確很公平地共同分擔所有風險,不過他的經理人則獨享了所有手續費
  19. 在投資裡,短視(myopia)這個缺陷是很正常的,幾乎是全面性的普遍現象,唯一的療法只能靠紀律、耐心、自制力,因此絕大多數投資人都深受其苦
  20. 每當有人試圖以「新經濟」(new economy)說服你冒更大投資風險,請記得一句話:「『新』其實非常舊,甚至可以說是最舊的東西。」
  21. 英文裡代價最高的四個字是:this time, it’s different
  22. News 是噪音,也是混亂的聲音,也是投標的價格上下波動的原因,是交易人的命脈,通常也是投資人的禍根
  23. 經常更新自己投資標的最新消息的投資人,交易頻率會增加兩成,但是平均來說,獲利卻不到不追蹤消息的投資人的一半
  24. 隨時得知金融市場的最新消息,不等於知道未來即將發生什麼
  25. 若是消息不靈通、對這個世界缺乏好奇心,不可能成為成功的投資人;不過,聰明的投資人不會日日夜夜、無時無刻在追蹤消息。財經消息就像陽光,適度吸收是必要的,但是過度曝曬很危險,甚至可能致命
  26. 由於回歸平均值(regression to the mean)的關係,股票和投資經理人在被打入冷宮之前,一定會有一段看似火紅的時期。被預言是 the next Warren Buffet 且長期下來稱得上有 Buffet 影子的人,比例也才不過 0.01%
  27. 每當看到或聽到某支股票、每個投資經理人或某個金融資產號稱是下一個 Apple、下一個 Warren Buffet,下一個你該做的動作就是把它拋到腦後
  28. 如果一開始買進價格就過高,未來業績在怎麼亮麗都於事無補
  29. Overconfidence(過度自信)就不知道自己無知,在金融市場中,絕對有必要加以克服,但要繳非常多學費
  30. 某支證券的持有部位高於平均,那就是 overweight (過重)。例如,若 Apple 公司佔 S&P 500 總市值的 3.8%,而有一支基金持有 Apple 3.9%資產,那就是 overweight了

2017/08/01

[閱讀筆記] The Black Swan: The Impact of the Highly Improbable (3/3)


  1. Gaussian(高斯)提出的常態分配 (bell curve) 在現實的世界不太管用,因為若遇到罕見的事件,用常態分配預估的錯誤機率就會越高。罕見事件總是慢慢累積、形成,然後在某個時間點給你一記重擊
  2. 統計學中使用的平均數、標準差等等,僅適用於certainty world,但是,我們身處uncertainty world
  3. 小心你所看到的統計數字,它可不科學,其實是詐騙
  4. 標準差這個數字本身沒有意義,你必須知道數字背後的意義。就像溫度計所顯示的溫度是沒有意義的,你必須要知道溫度與舒適度本身的關聯,如攝氏23~25度是個舒適的天氣,攝氏十度以下就是個令人不舒服的寒冷天氣
  5. 在真實世界哩,過去的成功,不代表會增加未來成功的機率。如同coin-flip game,每一次丟錢幣的過程都是獨立的,上一次得到正面或反面,跟這次會得到的結果無關
  6. 當你接觸到財務模型或理論時,你應該關心他的假設前提是什麼,而不是其理論。當他的假設是有問題的,與真實世界背離,這個理論與模型就是無用的了
  7. 不要誤會你可以衡量未來事件發生的機率
  8. 錯過一班火車時,只有你曾努力追趕卻沒趕上時,你才會感到痛苦
  9. 大部分的研究模型,都是根據過去有規律的事件,在預測其未來發生的可能性。但是罕見事件是非規律的,你根本無從預測,例如第一次世界大戰的爆發,你無前例可循;1987年的美股,一天崩跌23%,你也無前例可循
  10. 我們身處於非線性的世界 (線性的世界只存在你的教室裡、課本中),例如天氣預測模型深受非線性因素的影響,即便你有一個正確的模型 (實際上你一定沒有),只要一個輸入參數有變化,你可能得到完全不同的結論
  11. 面對黑天鵝,你要保護自己避免受到壞的黑天鵝的攻擊 (多掌握機會去擁抱好的黑天鵝),即便你沒有證據去證明這隻壞的黑天鵝會發生,這就像機場的安全檢查,我們無法確認那些人是恐怖份子,所以就會針對每個人及其行李做金屬探測與X光檢查。
  12. 當一個事件越罕見,我們就越沒有過去的歷史資料可以參考 (即假設未來的事情會與過去的事件一樣),我們就會越仰賴理論來推敲、預測此罕見事件發生的可能性
  13. 投資成功之道在於如何避免損失,而非如何獲取利潤
  14. 書店上充斥的某某某成功致富的書籍,卻看不到『我從破產中學到的教訓』、『人生中應該避免犯的十個錯誤』等之類書名的書籍
  15. Scenario analysis 與 stress testing 都是根據過去的資料來做預測,其預測結果不具備任何意義
  16. 記住一點,儘管你的長期收益是賠錢的,你的理專一樣一直在賺錢
  17. 一些從統計書籍出現的字眼,如linear agression、sharpe ratio、standard deviation等等,你可以直接忽略,這些東西對於罕見事件,毫無助益
  18. 華爾街的理財顧問們,永遠只有獎勵,無論他的成績如何。正常的資本主義應該是獎勵與懲罰並存,而非只有獎勵
  19. 因為全球化的關係,國與國之間的經濟網絡更加密切與複雜,這時,你投資的金融商品就應該要選擇簡單與單純的商品,避開複雜的金融商品
  20. 政府應該禁止銀行販售複雜的金融商品,因為根本沒有人了解其內容,真正能保持理性了解其內容的人更是少之又少
  21. 龐氏騙局(英語:Ponzi scheme,在華人社會又稱為「非法集資」、「非法吸金」或「種金」、老鼠會)是層壓式推銷方式的一種,參與者要先付一筆錢作為入會代價,而所賺的錢是來自其他新加入的參加者,而非公司本身透過業務所賺的錢。投資者通過不斷吸引新的投資者加入付錢,以支付上線投資者,通常在短時間內獲得回報。但隨著更多人加入,資金流入不足,騙局泡沫爆破時,最下線的投資者便會蒙受金錢損失。
  22. 前景理論 (Prospect Theory) 有兩大定律:
    1. 人們在面臨獲得時,往往小心翼翼,不願冒風險;而在面對損失時,人人都變成了冒險家
    2. 人們對損失和獲得的敏感程度是不同的,損失的痛苦要遠遠大於獲得的快樂


2017/07/11

Utilize AgeFileFilter to filter either newer files or files equal to or older

Scenario
I have an requirement to read a specific directory (including subdirectories) to find five days before log files and delete them.
How to do it?

How-To
Add commons-io to your maven dependency:
1
2
3
4
5
    <dependency>
     <groupId>commons-io</groupId>
     <artifactId>commons-io</artifactId>
     <version>2.5</version>
    </dependency>


Here has 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
32
    /**
     * 找出某個日期以前的檔案.
     * 
     * @param directory 找出某個目錄下的檔案
     * @param days 找出數天前 (如 -20)
     * @param includeSubdir 是否包含子目錄 (true / false)
     * @return List of File
     */
    public static List<File> getFilesBeforeXDays(File directory, int days, Boolean includeSubdir) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(new Date());
        cal.add(Calendar.DATE, days);
        cal.set(Calendar.HOUR, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        Date date = cal.getTime();

        IOFileFilter ageFileFilter = FileFilterUtils.ageFileFilter(date);
        IOFileFilter subDirFilter = includeSubdir ? FileFilterUtils.trueFileFilter()
                : FileFilterUtils.falseFileFilter();

        Collection<File> fileCollection = org.apache.commons.io.FileUtils.listFiles(directory, ageFileFilter, subDirFilter);
        if(CollectionUtils.isEmpty(fileCollection)){
            log.info("Cannot find any log files before " + new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS").format(date));
        } else{
            log.info("Find " + fileCollection.size() + " log file(s).");
        }
        
        return new ArrayList<File>(fileCollection);
    }




Reference
[1] https://commons.apache.org/proper/commons-io/javadocs/api-2.4/org/apache/commons/io/filefilter/AgeFileFilter.html