Total Pageviews

2017/04/30

2017/04 Travel

台北燈會
DSC01401

DSC01409

DSC01405

DSC01460

DSC01445

中山堂光雕秀
DSC01420

DSC01423

DSC01424

2017/04/10

[webMethods] 如何在 Java Service 中,將資料寫入 Integration Server 中的 Cache

Problem
假設我們已經在 Integration Server 中,在 Public Cache Managers 中建立一個名為 Test 的 Cache Manager,並於 Test 中建立一個名為 hello 的 cache



若我們希望在 Java Service 中,用 webMethods 提供的套件來:
1. 新增資料到 cache
2. 從 cache 中取出資料
3. 移除 cache 中的資料  


該如何做?



How-to

以下是 sample code:
// --- <<IS-BEGIN-SHARED-SOURCE-AREA>> ---
    
    private static final String cacheManagerName = "Test";
    private static final String cacheName = "hello";
    
    public static void addValueToCacheByKey(IData pipeline, String key, Object value) throws ServiceException {
        IDataCursor cursor = pipeline.getCursor();
    
        IDataUtil.put(cursor, "cacheManagerName", cacheManagerName);
        IDataUtil.put(cursor, "cacheName", cacheName);
        IDataUtil.put(cursor, "key", key);
        IDataUtil.put(cursor, "value", value);
    
        try {
            Service.doInvoke("pub.cache", "put", pipeline);
        } catch (Exception e) {
            throw new ServiceException(e);
        }
        cursor.destroy();
    }
    
    public static Object getValueFromCacheByKey(IData pipeline, String key) throws ServiceException {
        IDataCursor cursor = pipeline.getCursor();
    
        IDataUtil.put(cursor, "cacheManagerName", cacheManagerName);
        IDataUtil.put(cursor, "cacheName", cacheName);
        IDataUtil.put(cursor, "key", key);
        
        IData data = null;
        try {
            data = Service.doInvoke("pub.cache", "get", pipeline);
        } catch (Exception e) {
            throw new ServiceException(e);
        }
        Object result = IDataUtil.get(data.getCursor(), "value");
        
        cursor.destroy();
        
        return result;
    }
    
    public static void removeCacheByKey(IData pipeline, String key) throws ServiceException {
        IDataCursor cursor = pipeline.getCursor();
        
        IDataUtil.put(cursor, "cacheManagerName", cacheManagerName);
        IDataUtil.put(cursor, "cacheName", cacheName);
        IDataUtil.put(cursor, "key", key);
        
        try {
            Service.doInvoke("pub.cache", "remove", pipeline);
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }   
    // --- <<IS-END-SHARED-SOURCE-AREA>> ---




2017/04/09

[webMethods] 如何設定在 Integration Server 啟動時,執行 Java Service

Problem
假設我們有一個 OPC Connection 的 Java Service,我們希望這個 Java Service 在啟動 integration server 時,順便啟動此 OPC_Connection Java Service,取得OPC connection,完成初始化的相關動作


How-to
步驟1. 點選要設定的 Java Service 所屬的 package,按下右鍵,並選擇Property



步驟2. 在 dialog 中,點選最後一個選項 (Startup / Shutdown Services),在 Startup Services 處,將 OPC_Connection Service 選取到 Selected services,按下 OK (若要將 flow service 設定為 startup service,其程序相同)


步驟3. 重啟 Integration Server,可以到 administration console 中看到 OPC_Connection 印出的 log



若日後有更動 folder 位置,記得要重做步驟 1 與步驟 2,Designer不會自動更新 service 的位置,會出現以下錯誤
Startup service acme.albert.adapters:OPC_Connection was not found in Acme package


2017/04/08

[webMethods] 如何在Designer 中 create 的 Java Service,使用已經寫好的外部的Java Class

步驟1. 先將所寫好的程式包成一個 jar file


步驟2. 將包好的 jar file 與其相依賴的 jar files 放到 ESB 特定package的目錄中 (即 [integration_server_dir]/packages/[your_pacakge_name]/code/jars ),並重啟 webMethods Integration Server

步驟3. 在出現編譯錯誤的程式碼,按下修正錯誤,點選 Fix project setup...



步驟4. 點選 here



步驟5. 點選 Add External Jars


步驟6. 選取所需用到的 jar files,按下開啟舊檔



步驟7. 按下 OK



步驟8. 此時即可 import 我所寫好的 Java class




若日後有更動外部的Java code,步驟如下:

步驟1. 先將所寫好的程式包成一個 jar file

步驟2. 將包好的 jar file 放到 ESB 特定 package 的目錄中,並重啟 webMethods Integration Server


步驟3. 將 jar file 更新到你的 Designer 會用到的 library directory

步驟4. 點選目前正在開發的 package,點選右鍵並按下 Reload Package,這樣 Designer 裡就可以用到最新版本的 Java code

2017/04/07

[webMethods] 如何安裝 Designer 工具

Installation Steps
1. 執行 installer,等待出現 installation window 以後,點選 Advanced Options


2. 點選 Images tab、勾選 Use installation image、選取要安裝的 image file,先點選 Validate Image 確定所選取的 image file 是否完整,確認 image file 是正確的才點選 OK



3. 選擇要安裝的 Installation directory,點選 Next



4. 選擇要安裝的 packages,點選 Next



5. 點選 checkbox,按下 Next




6. 選取 trial license file,按下 Next



7. 直接按下 Next



8. 直接按下 Next



9. 直接按下 Next



10. 此步驟需要等待數分鐘



11. 安裝完成畫面,按下 Close 即可完成安裝步驟




Designer Configuration Steps

1. 啟動 Designer 工具


2. Window => Preferences






3. 點選 Integration Servers 的選項



4. 輸入你要連線的 Integration Server 的 IP、Port、User name、Password,點選 Verify Server 可以檢查是否可以正常連上 Integration Server,按下 OK 即可完成設定


5. 完成設定後,若可以正常連上 Integration Server,Status 會顯示 Connected



Reference

[1] http://techcommunity.softwareag.com/pwiki/-/wiki/Main/Guide+to+Downloading+and+installing+the+webMethods+Free+Trial+Version

2017/04/06

[Failsafe] Retry with backoff

Problem
I would like do retry if I fail to connect to database.  
My requirement is 
  • retry 5 times at most and sleep 5 second then retry again
  • Sets the delay between retries (i.e. 5 seconds), exponentially backing off to the maxDelay (i.e. 120 seconds) and multiplying successive delays by the delayFactor (i.e. 2).

How-to
Here has the sample 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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package albert.practice.retry;

import java.sql.Connection;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;

import lombok.extern.slf4j.Slf4j;
import net.jodah.failsafe.Failsafe;
import net.jodah.failsafe.RetryPolicy;

@Slf4j
public class RetryTest {

    private int count = 0;

    public static void main(String[] args) throws ConnectionException {
        new RetryTest().connectWithRetry();
    }

    public Connection connectWithRetry() {
        // create a retry policy with 5 max retries and have 2 seconds delay among retries
        RetryPolicy retryPolicy = new RetryPolicy();

        // create a retry policy and sets the delay 5 seconds between retries, exponentially backing off to the maxDelay 120
        // seconds and multiplying successive delays by the delayFactor 2.
        retryPolicy.retryOn(ConnectionException.class).withMaxRetries(5).withBackoff(5, 120,
                TimeUnit.SECONDS, 2);

        // Using Fallbacks allow you to provide an alternative result for a failed execution.
        // In this example, it will retry again after 5 seconds.
        Connection conn = Failsafe.with(retryPolicy).withFallback(() -> retryIfFail())
                .get(() -> connect());

        return conn;
    }

    public void retryIfFail() throws InterruptedException {
        log.debug("GG at " + getCurrentTime());
        Thread.sleep(5000);

        log.debug("retry....." + getCurrentTime());
        connectWithRetry();
    }

    public Connection connect() throws ConnectionException {
        log.debug(" time = " + getCurrentTime());
        Connection conn = null;
        if (count < 9) {
            count++;
            throw new ConnectionException("connection fail!");
        } else {
            log.debug("get connection successfuly...");
        }
        return conn;
    }

    private String getCurrentTime() {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");
        return dateFormat.format(new Date());
    }
}

Execution log:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
[main] DEBUG albert.practice.retry.RetryTest -  time = 2016/11/23 17:31:51.495
[main] DEBUG albert.practice.retry.RetryTest -  time = 2016/11/23 17:32:01.509
[main] DEBUG albert.practice.retry.RetryTest -  time = 2016/11/23 17:32:21.515
[main] DEBUG albert.practice.retry.RetryTest -  time = 2016/11/23 17:33:01.498
[main] DEBUG albert.practice.retry.RetryTest -  time = 2016/11/23 17:34:21.499
[main] DEBUG albert.practice.retry.RetryTest -  time = 2016/11/23 17:36:21.539
[main] DEBUG albert.practice.retry.RetryTest - GG at 2016/11/23 17:36:21.539
[main] DEBUG albert.practice.retry.RetryTest - retry.....2016/11/23 17:36:26.545
[main] DEBUG albert.practice.retry.RetryTest -  time = 2016/11/23 17:36:26.545
[main] DEBUG albert.practice.retry.RetryTest -  time = 2016/11/23 17:36:36.554
[main] DEBUG albert.practice.retry.RetryTest -  time = 2016/11/23 17:36:56.564
[main] DEBUG albert.practice.retry.RetryTest -  time = 2016/11/23 17:37:36.571
[main] DEBUG albert.practice.retry.RetryTest - get connection successfuly...

2017/04/05

[Failsafe] Retry with Fallback

Scenario
If we cannot get connection, then we will retry 5 times with 2 seconds delay.
If we fail to retry with 5 times, then we will pause X minutes then retry again.
How to implement it?


How-to
You can make good use of failsafe to fulfill this implement.
In this exampe, it will demonstrate:
1. create a retry policy with 5 max retries and have 2 seconds delay among retries
2. If you got failed execution, it will retry again after 5 seconds.
 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.retry;

import java.sql.Connection;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;

import lombok.extern.slf4j.Slf4j;
import net.jodah.failsafe.Failsafe;
import net.jodah.failsafe.RetryPolicy;

@Slf4j
public class RetryTest {

    private int count = 0;

    public static void main(String[] args) throws ConnectionException {
        new RetryTest().connectWithRetry();
    }

    public Connection connectWithRetry() {
        // create a retry policy with 5 max retries and have 2 seconds delay among retries 
        RetryPolicy retryPolicy = new RetryPolicy();
        retryPolicy.retryOn(ConnectionException.class).withDelay(2, TimeUnit.SECONDS)
                .withMaxRetries(5);

        // Using Fallbacks allow you to provide an alternative result for a failed execution. 
        // In this example, it will retry again after 5 seconds.
        Connection conn = Failsafe.with(retryPolicy).withFallback(() -> retryIfFail())
                .get(() -> connect());

        return conn;
    }

    public void retryIfFail() throws InterruptedException {
        log.debug("GG at " + getCurrentTime());
        Thread.sleep(5000);

        log.debug("retry....." + getCurrentTime());
        connectWithRetry();
    }

    public Connection connect() throws ConnectionException {
        log.debug(" time = " + getCurrentTime());
        Connection conn = null;
        if (count < 9) {
            count++;
            throw new ConnectionException("connection fail!");
        } else {
            log.debug("get connection successfuly...");
        }
        return conn;
    }

    private String getCurrentTime() {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");
        return dateFormat.format(new Date());
    }
}


Console log:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
DEBUG albert.practice.retry.RetryTest -  time = 2016/11/05 11:42:13.832
DEBUG albert.practice.retry.RetryTest -  time = 2016/11/05 11:42:15.837
DEBUG albert.practice.retry.RetryTest -  time = 2016/11/05 11:42:17.837
DEBUG albert.practice.retry.RetryTest -  time = 2016/11/05 11:42:19.837
DEBUG albert.practice.retry.RetryTest -  time = 2016/11/05 11:42:21.838
DEBUG albert.practice.retry.RetryTest -  time = 2016/11/05 11:42:23.839
DEBUG albert.practice.retry.RetryTest - GG at 2016/11/05 11:42:23.839
DEBUG albert.practice.retry.RetryTest - retry.....2016/11/05 11:42:28.839
DEBUG albert.practice.retry.RetryTest -  time = 2016/11/05 11:42:28.839
DEBUG albert.practice.retry.RetryTest -  time = 2016/11/05 11:42:30.839
DEBUG albert.practice.retry.RetryTest -  time = 2016/11/05 11:42:32.839
DEBUG albert.practice.retry.RetryTest -  time = 2016/11/05 11:42:34.840
DEBUG albert.practice.retry.RetryTest - get connection successfuly...

Reference
[1] https://github.com/jhalterman/failsafe#fallbacks

2017/04/04

[Angular2] fail to load data items in ng2-select component

Problem
I am using ng2-select to implement a dropdown list function.
But my dropdown list cannot be showed just like the example:


Here is my code snippet:
   <div class="row">
    <div class="col-sm-12">
        <div class="form-group">
           <label> 負責人員 </label>
           <div style="width: 300px; margin-bottom: 20px;">
              <ng-select [allowClear]="true" 
                         [items]="items" 
                         [data]="selectedItem"
                         (data)="refreshValue($event)" 
                         (selected)="selected($event)"
                         (removed)="removed($event)" 
                         placeholder="請選擇負責人員">
              </ng-select>
           </div>
        </div>
    </div>
   </div>


How-to
Owning to the data items in ng2-select example is static:

The data items in my function which will retrieve them from 
database, so we need to wait until data items had been finished then create the DOM element.

Owing to I do not know how long I need to wait, so I add *ngIf in the first div tag.
   <div class="row" *ngIf="items && items.length > 0">
    <div class="col-sm-12">
        <div class="form-group">
           <label> 負責人員 </label>
           <div style="width: 300px; margin-bottom: 20px;">
              <ng-select [allowClear]="true" 
                         [items]="items" 
                         [data]="selectedItem"
                         (data)="refreshValue($event)" 
                         (selected)="selected($event)"
                         (removed)="removed($event)" 
                         placeholder="請選擇負責人員">
              </ng-select>
           </div>
        </div>
    </div>
   </div>


Reference
[1] https://valor-software.com/ng2-select/


2017/04/03

[UML] How to Draw a Scheduler Service in Sequence Diagram

Problem
Assume I have a HeartBeatService and HeartbeatProducerService.
HeartBeatService will call HeartbeatProducerService every 5 seconds to check system is alive or not. 

How to show this kind of scheduler job in sequence diagram.


How-to
You can add a loop combined fragment in sequence diagram, it looks like:



2017/04/02

[Failsafe] Simple, sophisticated failure handling

Scenario
We have a Java application to connect to OPC server, if it fail to connect to OPC server it will retry 5 times.


How-to
You can make good use of Failsafe to fulfill this requirement. 
Failsafe is a lightweight, zero-dependency library for handling failures. It was designed to be as easy to use as possible, with a concise API for handling everyday use cases and the flexibility to handle everything else.

Maven dependency:
1
2
3
4
5
6
7
<dependencies>
   <dependency>
      <groupId>net.jodah</groupId>
      <artifactId>failsafe</artifactId>
      <version>0.9.5</version>
   </dependency>
</dependencies>


If I catch ConnectionException, it will do retry, the retry policy is as bellows:

  • it will delay 2 seconds between retries
  • it will retry 5 times at most


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

import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.TimeUnit;

import lombok.extern.slf4j.Slf4j;
import net.jodah.failsafe.Failsafe;
import net.jodah.failsafe.RetryPolicy;

@Slf4j
public class RetryTest {

    public static void main(String[] args) throws ConnectionException {
        @SuppressWarnings("unchecked")
        RetryPolicy retryPolicy = new RetryPolicy().retryOn(ConnectionException.class)
                .withDelay(2, TimeUnit.SECONDS).withMaxRetries(5);
        Failsafe.with(retryPolicy).run(() -> new RetryTest().connect());
    }

    public void connect() throws ConnectionException {
        log.debug("time=" + new Date(Calendar.getInstance().getTimeInMillis()));
        if (true) {
             throw new ConnectionException("connection fail!");
        }
    }
}



Reference
[1] https://github.com/jhalterman/failsafe

2017/04/01

[閱讀筆記] Waltzing with Bears (1/2)


  1. 經營管理是企業體的成長與永續之道,投資理財是個人的安身之道,而經濟趨勢則是會影響這兩者的變數
  2. 風險管理的事務,著重於成因風險(cause risk)的管理,亦即你能管理的部分
  3. 風險就是還沒發生的問題,問題是已經發生的風險
  4. 風險管理是在問題發生之前,預先思考應變措施的過程;危機管理則是在問題發生之後,嘗試處理善後
  5. 軟體工程規範原地踏步了許多年,他始終缺乏跟上資訊時代並滿足資訊社會所需要的成熟工程規範
  6. 很多軟體專案會失敗,並非風險管理方法不好,而是他根本就沒花任何功夫在風險管理上,反而在祈禱風險不會發生
  7. 風險管理就是把不確定性侷限在一個範圍內,或許你害怕僅憑少量資訊就要把問題解決掉。但是,若連這點資訊都沒有,情況會更糟糕。無窮無盡的不確定性,結果不是讓人過分保守,就是讓人變得莽撞,兩者都不是好事
  8. 進行風險管理不會使問題消失,只能保證不會讓你遭受突如其來的衝擊,殺的你措手不及
  9. 當你在祈禱所有的好運都降臨在你身上,當運氣其成為你整體策略的一部分時,小心,你的麻煩要來了
  10. 風險管理往往能提供你想要的更多事實真相
  11. 有些組織一廂情願的相信可以控制一切,即使心知肚明這並非事實,還是慣用控制的假象來蒙蔽現實。最常見的特徵,就是一開始弄出一個精確到令人可笑的預估結果,事後卻證明他跟事實差了十萬八千里
  12. 你可以管理風險,但不可能使風險消失
  13. 在最糟糕的組織中,報壞消息的人會被懲罰,但壞結果卻不會被檢討。當你提出風險時,就會有另外一位同儕會搶著說包在他身上,他一定可以如期完成。在這種文化中,大家都會先把牛吹大,因為這遠比按時交貨來得重要。如果再這種公司上班,把風險評估收起來,自己私底下用就好
  14. 組織不允許不確定性存在,風險管理就不用做了。這樣的組織,成員不可以對「一切如期完成」表現出一丁點的疑慮。事情做錯沒關係,就是不可以不確定
  15. 組織常常缺少能發出「災難」訊號的自主神經系統,常常自以為掌握了所有風險(潛在問題),其實只掌握了一部份而已(已有解決方案的潛在問題)
  16. 當你決定忽略某個風險時,就等於要賭運氣,賭這個風險不會發生
  17. 當專案包裝成一項挑戰時,就相當於強迫你去賭運氣。例如,你是全公司最後的希望,希望你能在這個月底完成這個專案
  18. 專案一開始就以個人挑戰的形式出發,便很難有明智的風險管理,這種專案就是在賭運氣
  19. 做軟體專案,你一定要把失敗的可能性限制在一定範圍內
  20. 我們在做預估的時候,記得把預估背後依賴的假設統統列舉出來
  21. 專案偏離時程,陷入泥沼,很少是因為工作比預期的更花時間,多半是為了處理原本沒有規劃到的事情
  22. 越棘手的風險,高層主管想弄走他的壓力就越大。根據經驗,高層主管若抓狂到某種地步,就比較不會想去了解為什麼風險會消失,反正只要它不見了就好
  23. 在軟體專案中,你不知道的問題,那通常就是風險所在。無論是什麼事情不知道,只要會造成不利的負面影響,就是風險。蒐集各種「我不知道」的問題,把不知道的根本原因找出來,你就可以得到一份完整的風險列表