Total Pageviews

2017/05/06

[webMethods] 在 Flow Service 中使用 Loop

步驟 1. 分別建立 OrderRequest 與 OrderResponse Document ,Request 與 Response 的資料結構相仿,唯一差異的地方是 Response 的 Subtotal = Request 的 Quantity * Price

步驟2. 建立 LoopFlow,並將 input 與 output 分別設定為 OrderRequest 與 OrderResponse

步驟 3. 在 LoopFlow 中,分別加入 MAP、LOOP、MAP 與 MAP,並在 LOOP Step 中設定 Input array 與 Output array


步驟 4. 在 LOOP 中進行 MAP Request 與 Response data,並加入 multiplyInts transformer 來運算 Quantity * Price = Subtotal

步驟 5. 執行 LoopFlow 並查看結果










2017/05/05

[webMethods] 在 Flow Service 中使用 Branch

步驟 1. 建立一個 Math Flow,用來展示加減乘除的數學運算


步驟 2. 建立 input / output parameters,num1 與 num2 是供輸入的兩個整數參數,operator 是輸入加減乘除用的參數,result 是運算結果


步驟 3. 在 MathFlow 中,建立一個 branch step,依照 operator 參數所輸入的值來做不同的處理


步驟 4. 依據不同的 operator 使用不同的套件,即 pub.math:addInts, pub.math:subtractInts, pub.math:multiplyInts, pub.math:divideInts,Label 的值代表是 operator 所輸入的值


步驟 5. 在 pipeline tab 拉 pub.math:addIntspub.math:subtractIntspub.math:multiplyIntspub.math:divideInts 對應的值








步驟 6. 若 operator 輸入非預期的字元,則要做額外的處理,label 設定為 $default,並設定印出 The operator is invalid 此警告訊息




步驟 7. 若 operator 沒有輸入值,,則要做額外的處理,label 設定為 $null,並設定印出 The operator is null 此警告訊息





執行結果




2017/05/04

[webMethods] 刪除 Flow Service 中不需要的參數 - Drop the Selected Variable

假設以下是一個已經完成的 Flow Service,Pipeline Out 那個 column 代表著執行此 Flow Service 會產生的三個 output parameters:



Run Flow Service 的結果如下:



若我們希望 Pipeline Output 只要有 document 物件就好,其餘兩個 parameters 不要顯示,可以在 Pipeline tab 選定 parameter(s),再點選 Drop the Selected Variable 並儲存即可



若是要還原的話,操作如下:

2017/05/03

[webMethods] 如何將 JSON String 轉換成 ESB 中的 Document 物件

我有一個 Service Class,可以透過 buildTestJson() 取得測試用的 JSON String,或者是呼叫 buildHeartbeatMsgJson() 並傳入一個 HBMessage 物件取得 JSON String
import java.io.Serializable;

import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class OpcHeartbeatService {
    
    private final static Logger logger = LoggerFactory.getLogger(OpcHeartbeatService.class);
    
    public static void main(String[] args) {
        OpcHeartbeatService test = new OpcHeartbeatService();
        logger.info("buildTestJson = " + test.buildTestJson());
    }
    
    public String buildTestJson() {
        HBMessage hb_msg = new HBMessage("test", "123445", "HBT_MSG");
        return buildHeartbeatMsgJson(hb_msg);
    }
    
    public String buildHeartbeatMsgJson(HBMessage hb_msg) {
        JSONObject dataset = new JSONObject();
        
        JSONObject hbObject = new JSONObject();
        hbObject.put("serviceId", hb_msg.getServiceId());
        hbObject.put("token", hb_msg.getToken());
        hbObject.put("type", hb_msg.getType());
        
        dataset.accumulate("heartbeatMsg", hbObject);
        
        return dataset.toString();
    }

    public static class HBMessage implements Serializable{
        private static final long serialVersionUID = 1L;
        
        private String serviceId;
        private String token;
        private String type;
        
        public HBMessage() {
            super();
        }

        public HBMessage(String serviceId, String token, String type) {
            super();
            this.serviceId = serviceId;
            this.token = token;
            this.type = type;
        }

        public String getServiceId() {
            return serviceId;
        }
        
        public void setServiceId(String serviceId) {
            this.serviceId = serviceId;
        }
        
        public String getToken() {
            return token;
        }
        
        public void setToken(String token) {
            this.token = token;
        }
        
        public String getType() {
            return type;
        }
        
        public void setType(String type) {
            this.type = type;
        }
        
        @Override
        public String toString() {
            return "HBMessage [serviceId=" + serviceId + ", token=" + token + ", type=" + type
                    + "]";
        }
    }
}



在 Design 中建立一個 Java Service,名為 OPC_Heartbeat




在 OPC_Heartbeat 中定義一個 output 參數 (i.e. heartbeatJson),用來接收 buildTestJson() 所得到的 JSON String




在 OPC_Heartbeat 中,呼叫 OpcHeartbeatService 的 buildTestJson() method,取得測試的 JSON String ,並將 JSON String 傳給 output parameter
public final class OPC_Heartbeat_SVC

{

    /** 
     * The primary method for the Java service
     *
     * @param pipeline
     *            The IData pipeline
     * @throws ServiceException
     */
    public static final void OPC_Heartbeat(IData pipeline) throws ServiceException {
        OpcHeartbeatService hbService = new OpcHeartbeatService();
        String hbJson = hbService.buildTestJson();
        
        IDataCursor pipelineCursor = pipeline.getCursor();
        IDataUtil.put(pipelineCursor, "heartbeatJson", hbJson);
        pipelineCursor.destroy();
    }
    
    // ignore......
}    



OPC_Heartbeat 執行結果




將 OPC_Heartbeat 拉近 Flow Service,並利用 pub.json:jsonStringToDocument 此現成套件協助我們將 JSON String 轉成 ESB 中的 Document 物件




2017/05/02

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


  1. 大多避險基金收取一般共同基金十倍的費用,然後交給投資人指數型基金一半的報酬。事實上,避險基金沒什麼特別厲害之處,它們大多帶來令人失望的報酬
  2. 運氣、不確定、意外,是投資的基本外力,而華爾街在在跟外界溝通時,往往否定這些外力的威力
  3. 愈是濃縮、音節愈多的行話術語,愈有可能隱藏不想讓你知道的事。抓住男人的胃或許可以抓住他的心;要撬開投資人的口袋,就得從他的耳朵下手
  4. 金融歷史事件不會完全一模一樣重現,但也相去不遠。不管別人多大聲告訴你這次不一樣,人性是不會改變的。趨勢來來去去,唯一不變的是手續費永遠要繳
  5. 上漲的,遲早會下跌(通常比大家預期的還要早);同樣的,下跌的,也一定會再度上漲(通常是在專家都說不會的時候)
  6. 華爾街賣的是股票和希望,不過真正兜售的是『希望』。投資大眾都希望有奇蹟存在,於是金融業者就不斷宣稱看得到未來、能實現奇蹟。無論如何,千萬別跟著那些人走
  7. 所謂理財成功,並不是在金融遊戲中打敗專業,而是做到自我克制。金融市場每隔幾年就來一次的狂喜或絕望之時,退一步冷靜思考
  8. AAA 等級的債券不能保證你不會賠錢,2008年前三季,有超過 11000 個 AAA 等級房貸有價證券突然遭到大幅修正,其中許多證券的價格跌了七成或更多,導致投資人損失數千億美元
  9. 銀行機構每個月或每一季寄給你的帳戶明細(account statement),會盡量隱藏、偽裝虧損與費用的部份,讓你把注意力放在收入或獲利上
  10. 股市並不是一股一致的力量,不會採取一致的行動;股市是一種機制,看相反的人在其中就彼此的差異取得價格共識
  11. Alpha 係數是指高於市場指數的投資報酬率,通常用來表示投資經理人的選股技巧與能力,但事實上 alpha 幾乎只是隨機偶發的結果
  12. Amortize 有攤提的意思,一即將開支平均分攤一段時間,直到分攤完畢為止。如一支共同基金得先付 5.75% 的手續費,看起來很多。但是如果你 amortize 到未來 25 年,每年才付 0.23% ,就可以得到我未來 25 年的顧問服務,真的很划算喔
  13. 分析師理論上會拆解、分析一家公司的組成,並估算其價值。但實際運作起來,卻變成該公司的推銷員、啦啦隊
  14. 分析師常用的定錨(achor )手法是,為一支股票設定遠高於或遠低於市場價格的目標價,然後這個數值就會深植於投資人的腦中,就像定住的錨一樣,讓他們不去思考目標價合不合理,就能逐漸把該股票的價格拉往目標價
  15. 一年一度的股東大會,公司經營高層常用來粉飾業績,假裝用心傾聽股東的願望和抱怨
  16. Anomaly (異常現象)是一種投資策略或評估技術,可以產生高於大盤的報酬率,而且沒有明顯的高風險。但是不管在哪裡找到的 anomaly,都必然帶有自我衰敗的種子,因為這只是統計上的偶然而已,當大家把資金湧入、如法炮製,潛在的報酬率也隨之降低,最後就會回歸到平均值
  17. 資產配置據說是一門科學,不過很多理財顧問並不是用數學或邏輯來推薦資產配置,而是全憑猜測,或是最近什麼商品熱門就推薦什麼
  18. 若有人向你推薦某個資產配置,務必要問問其中有哪一項曾經報酬率很低。如果都沒有,那對方根本不是在推薦什麼資產配置,而是在邀請你追逐某種熱門投資,而且極可能馬上變得不熱門了
  19. 投資的各種類別各有不同的風險和報酬率,彼此之間的關聯性不高。例如股市表現不佳時,債券往往表現很好,反之亦然;股市或債市的走勢若急轉,期貨行情有可能也會急轉
  20. 如果有某一種「新的」或「另類的」的資產類別(asset class),其持有成本高於股票和債券等傳統資產類別,那麼,其價值大概也不會維持太久
  21. 大部分的理財顧問都盡可能從越多客戶身上搜刮越多的資產,這樣就能以最少的工作量賺到最多的手續費
  22. 股市崩盤很罕見,但是造成的驚人損害會烙印到集體意識中,導致投資人錯失在非崩盤期間(上次崩盤到下次崩盤之間其實非常長)靠股票謀利的機會
  23. 絕大多數的 IPO (Initial Public Offering)都不會比大盤好賺,不過,只要有少數引人注目的 IPO 一飛沖天 (如 Google IPO),就會造成投資 IPO 可以致富的假象
  24. 對股價走勢極有影響力的紅牌分析師(axe),會一直換人,當舊的紅牌不準時,就會出現新的紅牌,這種詭異的狀況一直重複上演,而大多數的投資人卻沒發現。其實 axe 都撐不了太久,不用太認真對待
  25. 理財顧問常從Backtest (歷史回測)得出的大發現,只不過是統計上的僥倖罷了,這只會出現在樣本中,無法代表全體。
  26. 當理財顧問提出一些令人經驗的歷史數據給你,你該問幾個問題
    1. 這些數據是 backtest 嗎?
    2. 這些是多久以前的數據?
    3. 你是什麼時候開始用真正的錢實際操作這個策略?
    4. 你有更改過這項策略嗎?如果有為什麼?
    5. 決定採用這個策略前,你還試過其他多少策略?
  27. 價格走跌階段必然也意味著日後會有上漲階段。一般認為,股市平均下跌至少 20% 就算是 bear market 的開始,不過其實也沒有什麼正式的定義或門檻
  28. 一心想要 beat the market (打敗大盤)的人,通常都會被大盤所打敗
  29. Beta 係數是指某一支股票的報酬率跟大盤指數報酬的連動性。例如如果某一檔股票的 beta 係數是1.0,當大盤指數上漲 10% 時,該股票的報酬率則為 10%;若 beta 係數是 1.5 ,該檔股票在指數下跌 10% 時,會虧損 15%。依此類推, beta 係數越高,風險和報酬也越高。不過這參考看看就好,風險的部分是屢試不爽,報酬的部份則是難得一見
  30. 企業可透過操控可調節的會計項目,提前或過度認列費用和成本,以製造後來營利回彈的假象

2017/05/01

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


  1. 普遍的軟體專案的風險:
    1. 先天的時程規劃錯誤(schedule flaw)
    2. 需求膨脹(requirement inflation)
    3. 人力流失(employee turnover)
    4. 規格崩潰(specification breakdown)
    5. 低生產力(poor productivity)
  2. 常見的五個普遍的軟體專案風險,只有最後一項真正跟員工的工作表現有關,其餘四項都跟做得多辛苦、多精明幹練無關
  3. 預先為無法捉摸的事物進行合理的準備,正式風險管理的核心,預先準備並不能讓妳為失敗開脫,只能在風險造成威脅時保有緩衝的餘地
  4. 時程規劃錯誤是指時間的安排有缺陷,這是時程本身的錯誤,而非專案執行的錯誤。時程錯誤不僅是真正的風險,也是五個核心風險中對專案衝擊最大的。
  5. 七個月的專案最後卻做了十二個月,生氣的高階主管很少會怪時程規劃的人,相反的,他們會怪人員沒有盡力
  6. 從專案的角度來看,刪除某些已經做好的功能,也算是一種需求膨脹,因為這同樣增加了額外的工作負擔
  7. 在規劃時程時,常會忽略需求膨脹的議題。高階主管也不會管,類似的說詞是:客戶要X,預估十個月後交付;若你發現還要X以外的東西,那就是你的問題了
  8. 處理人員流失,你必須知道:
    1. 公司技術人員的每年平均流動率
    2. 接替人員完全進入狀況時間(ramp-up time)的預估值。想辦法做好教育訓練與技術文件,降低進入門檻
  9. 規格崩潰往往溯及專案初期談判過程的失敗,而談判正是需求界定的中心
  10. 界定需求時,為了避免與利害關係人有衝突,常會將一些關鍵的、有爭議的的問題模糊化。被掩飾的問題暫時不見,不代表永遠不見。界定需求也許可以搞得模糊,但是開發階段可模糊不得。最糟糕的是,這些問題都是專案後期才會發生,這個節骨眼幾乎是將預算與時間耗盡的階段,常給專案致命一擊
  11. 閉口不談風險,並不會讓風險消失
  12. 在工作上,我們都被要求保有can do 的態度,問題就在這;討論風險是一種cannot do 的思維,往往風險探索會背離組織的主流意見。組織要有開放的文化,讓負面言論有說出來的可能
  13. 「明確過程」有明確步驟、可預測的程序,相當於white box 。經驗過程則相當於black box,是經由不斷的觀察與驗證後,以經驗來調整輸入,進而產生滿意的輸出
  14. 風險舒緩是預先採取的一套作為,萬一風險成形,便可有效的、快速的處理風險
  15. 有風險認知的管理者,會優先考量含有重大技術風險的部分,這非常合理,不過也有違大部分管理者的本性,因為會太早暴露他們在這場競賽中的弱點。這就是為什麼對如此棘手的問題,他們總是秘而不宣,一拖再拖
  16. 如果系統有哪個部分必須仰賴技術上的突破才能完成,就該把它納入早期版本,到時候就算突破不了,應變選擇也會擁有最大的彈性。假如夠早,也許私下承受一點損失即可;反之,若把相同的挫折放到專案後期,影響層面將會擴大到每一個人
  17. 漸進式交付是降低軟體專案風險的好方法,其是由三種artifacts所構成:
    1. 設計藍圖:顯示要識做的最低階模組或類別,以及彼此之間的關係
    2. WBS(Work Breakdown Structure):顯示要完成的工作,以及彼此之間的相依關係
    3. VAT (Version Acceptance Test):把產品的總驗收測試按照版本細分,顯示哪個測試可用在哪個中間產品上
  18. 冒險的積極程度必須由報酬而決定。你願意冒多少風險,端視你可以得到多少報酬而定
  19. 對複雜、不確定性頗高的問題,建立模型來估算各種變因對結果的敏感性,即為敏感性分析
  20. 軟體專案常會呈現規模不經濟(diseconomieis of scale)的特徵:若系統規模增加為兩倍,則實際系統開發耗費的心力會超過兩倍
  21. 擴大產品規模,成本增加的幅度就會更大;那麼縮小產品規模,便很可能可以大幅節省開支。刪除系統中屬於低價值 / 成本比的部份,也許是紓解時程和預算壓力最簡單且直接的方法
  22. 有些軟體專案,都是以專案的重要性來為死亡行軍的正當性辯護:這次的任務太重要了,請全體專案人員放棄個人生活、超量加班,就算是最後一滴血也要榨乾。但是,既然這個專案有這麼重要,為什麼公司不願意分配合理的時間與金錢來做呢?
  23. 公司很排斥將軟體專案價值量化,隱瞞做這個專案會產生的價值的期望值,如此才有可能在縮減開發成本的情況下完成專案,這是很重要的理由,「我們要把成本壓低,低到不論做出多少價值的東西都划得來」

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