Total Pageviews

Showing posts with label webMethods. Show all posts
Showing posts with label webMethods. Show all posts

2017/09/10

[webMethods] How to invoke a Flow Service from a Java Service and get its output values

Problem
假設我要呼叫另外一個 flow service,此 flow service 沒有 input parameter,會回傳一個 output parameter,parameter name 為 isAlive

若我要透過 Java code 呼叫此 flow service,且取得其 output value 的話,該怎麼撰寫?


How-To

若呼叫 flow service 的方式是 synchronous,以下為 code snippet:
1
2
3
4
5
6
7
8
    try {
        // Invokes any service published on the server with the given input arguments.
        IData iData = Service.doInvoke("test.work", "Ping_Server", IDataFactory.create());
        // Returns a String representation of the value at the specified key.
        String isAlive = IDataUtil.getString(iData.getCursor(), "isAlive");
    } catch (Exception e1) {
     e1.printStackTrace();
    }



若呼叫 flow service 的方式是 asynchronous,以下為 code snippet:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
    try {
        // Invokes any service published on the server as a thread
        ServiceThread serviceThread = Service.doThreadInvoke("test.work", "Ping_Server", session, IDataFactory.create());
        // Returns the pipeline from the service running in this service thread.
        IData iData = serviceThread.getIData();
        // Returns a String representation of the value at the specified key.
        String isAlive = IDataUtil.getString(iData.getCursor(), "isAlive");
        loggerAsync(session, " is Alive = " + isAlive);
    } catch (Exception e) {
     e.printStackTrace();
    }

2017/09/08

[webMethods] How to invoke a Flow Service from a Java Service

Problem
如何在 Java Service 中,呼叫一個 Flow Service?

How-To
按照不同的情境 (synchronous 或 asynchronous),與有參數或無參數,需呼叫不同的 API,JavaDoc 如下:
JavaDoc for asynchronous


JavaDoc for synchronous


Examples:
1. Asynchronous and DO NOT have input parameter
    Session session = Service.getSession(); 
    Service.doThreadInvoke("test.work", "Test_Flow", session, IDataFactory.create());


2. Asynchronous and HAVE input parameter (s)
    Session session = Service.getSession(); 
    
    IData input = IDataFactory.create();
        
    IDataCursor inputCursor = input.getCursor();
    IDataUtil.put(inputCursor, "input", " test test ");
    inputCursor.destroy();
    
    Service.doThreadInvoke("test.work", "Test_Flow", session, input);


3. Synchronous and DO NOT have input parameter
    Service.doInvoke("test.work", "Test_Flow", IDataFactory.create());


4. Synchronous and HAVE input parameter (s)
    IData input = IDataFactory.create();
        
    IDataCursor inputCursor = input.getCursor();
    IDataUtil.put(inputCursor, "input", " test test ");
    inputCursor.destroy();
    
    Service.doInvoke("test.work", "Test_Flow", input);

2017/09/06

[webMethods] How to Create a Restful Service?

Problem
若我要提供一個 restful service 給另外一個系統呼叫,該如何實作?


How-To
步驟如下:
(1) 在 restful folder 下,建立一個 Rest Resource,命名為 RestTest




(2) RestTest 提供呼叫的方式為 HTTP POST


(3) 在 RestTest 中,設定一個 input parameter,parameter name 為 data


(4) 建立一個測試用的 Java Service,命名為 TestJavaService


(5) 在 TestJavaService 中,設定一個 input parameter,命名為 inputJson


(6) TestJavaService 程式邏輯為:當接收到參數值後,將 log 印到 integration server


(7) 將 TestJavaService drag and drop,放到 RestTest 中,並且將透過 restful service 中傳入的參數,傳遞到 TestJavaService  的 inputJson parameter


(8) 透過 rest client,用此 url 來進行呼叫 http://10.12.14.28:5555/rest/cctv.restful.RestTest,http method 選取 POST,在 Data Form 設定參數名稱為 data,並填入 value,按下 Send。

需注意 URL 呼叫規範為:
http://server:port/rest/FullyQualifiedResource
若是要在 URL 帶入帳號密碼,呼叫規範為:
http://username:password@server:port/rest/FullyQualifiedResource




(9) 到 integration server 的 administration console 檢查結果


Reference
[1] http://serviceorientedarchitect.com/how-to-create-a-rest-service-in-webmethods-integration-server/

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/07/07

[webMethods] How to delete threads in webMethods

Problem
假設在 OpcTest 此 package 中會執行數個 flow services

若希望在 package 被 disable 時,能把這幾個 flow services 的 threads 砍掉,該如何做?


How-To
解決方式如下,共有兩個步驟:
Step 1. 建立一個 Java Service,source code 如下:
public static final void terminationService(IData pipeline) throws ServiceException {
        IDataCursor pipelineCursor = pipeline.getCursor();
        String threadNameToKill = IDataUtil.getString(pipelineCursor, "threadNameToKill");
        pipelineCursor.destroy();
        
        if(threadNameToKill == null)
        {
            // Fill in the toppest folder name.
            // Take the OpcTest package for example, it should be "group1".
            threadNameToKill = "group1";
        }
        
        Thread current = Thread.currentThread();
        ThreadGroup root = current.getThreadGroup();
                
        while (root.getParent() != null) {
            root = root.getParent();
        }
        
        Thread [] threads = new Thread[1000];
        int count = root.enumerate(threads, true);
        
        for(int i = 0 ; i < count ; i++)
        {
            if(threads[i] instanceof ServerThread)
            {
                ServerThread temp = (ServerThread) threads[i];
                
                String threadName = temp.getName();
                
                logger( "[ Thread Name ]: " + threadName);
                if(threadName.contains(threadNameToKill))
                {
                    logger( "[ Stopping ]: " + threadName);
                    threads[i].stop();
                }
        
            }
        }       
            
    }

Step 2. 將此 Java Service 設定為 shutdown service,如此一來,當 package 被 disable 或 integration server 被 shutdown 時,都會執行此 shutdown service





2017/07/06

[webMethods] Service 'group2.test:TestSubscriber' is not operational. To run this service, first recompile the Java source.

Problem
當我在執行 Flow Service 時,出現此錯誤
1:  [ISS.0059.0001W] Interrupted [ISS.0026.9102] Service 'group2.test:TestSubscriber' is not operational.   
2:  To run this service, first recompile the Java source.  


How-To
會出現此錯誤,是因為 webMethods 沒有 compile 此 Java Service,此時要強迫 webMethods 去 compile Java Service

執行步驟:
Step 1. 打開命令提示字元,變更目錄到 [integration server directory]\instances\default\bin

Step 2. 執行 jcode 來做強迫 compile OpcTest2 此 package 下的所有 Java Services,指令如下 jcode makeall [package name]
1:  D:\SoftwareAG\IntegrationServer\instances\default\bin>jcode makeall OpcTest2  

Reference
[1] https://docs-old.servicerocket.com/display/WMFAQ/How+to+make+a+Java+service+recompiled+even+if+it+hasnt+been+changed

2017/07/04

[webMethods] 打開 Java Services 出現 source not available

Problem
當我將開發好的 package export and import 到另外一台 integration server,另外一外工程師無法看到我開發好的 Java Services,在其 designer 中出現 source not available 的錯誤,但是我卻可以看到,沒有遇到相同的問題

How-To
目前發現有兩個解決方式:
  • 由於我的 Java Services 中的程式註解有寫繁體中文,另外一位工程師可能是 Windows 語系設定與我不同的關係,導致在他的電腦中,無法看到 Java Services 的內容,當我將繁體中文的註解改成英文以後,此問題就解決了
  • 由於不明原因造成,重開 designer 之後,就可以看到 Java Service 的內容



2017/07/03

[webMethods] 如何將 export 的 package zip file,import 到另外一台 integration server

Problem
假設我們有多台 integration servers,根據不同用途分成開發機、測試機與正式機等,當我們從開發機的 integration server export 程式以後,該如何 import 到測試機 ?

How-To

前置步驟:將 package export 成 zip file


以下是 Import 執行步驟:

Step 1. 將 zip file 複製到 測試機 的 integration server 的 inbound 目錄下,路徑為 [IntegrationServer dir]\instances\default\replicate\inbound


Step 2. Login 到 Integration Server 的管理介面,點選 Packages => Management => Install inbound Releases



Step 3. 選取 Release file name,點選 Install Release


Step 4. 安裝完成後,會出現安裝成功的訊息,點選 Return to Package Management

此時,可以在 Package List 找到 ImportTest 此 Package


Refresh Designer 之後,也可以找到 ImportTest 此 package 及程式




2017/06/07

[webMethods] Global Variable

Problem
若我們有些變數是全域使用的,在 webMethods 中要設定在哪邊,才能讓所有的 Java Service、Flow Service 使用?

How-To
可以在 Integration Server 設定 global variable,步驟如下:
Step 1. 進入 Integration Server Administrator,在 Navigation panel 中選擇 Settings => Global Variables


步驟 2.  按下  Add Global Variable


步驟 3. 輸入 key (Global variable 的名字) 與 value (Global variable 的值),並按下 Save Changes



接下來,我們可以建立一個 Flow Service 來做測試
步驟1. drag and drop debugLog 此套件到 Flow Service 中,點選 Pipeline tab,並點選 message


步驟 2. 在 message 中輸入 global variable 的名字,頭尾用 % 包起來,記得要勾選 Perform global variable substitution 此選項,並按下 OK 按鈕

步驟 3. 執行此 Flow Service 進行測試



2017/06/03

[webMethods] 如何從 Java Service 中讀取 Property File

在 Java Service 中,有些設定值我希望不要 hard code 在程式中,要搬到 property file 供日後的設定之用,該如何從 Java Service 中讀取 Property File

property file 檔名為 opc_config.properties ,
內容如下:
opc.url=opc.tcp://192.168.1.1:49320
opc.retry.interval=5
opc.max.retries=5
opc.sleep.ms=5000

我目前的開發的目錄是在 Acme 的 package之下:


property file 就要放在 [IntegrationServer 安裝目錄]\instances\default\packages\Acme\resources 之下

值得注意的是,當我們在 load 此 property file 時,路徑規範是 packages\\[你的 package name]\\resources\\[你的 property file name],如 packages\\Acme\\resources\\opc_config.properties ,若沒按照此規範會出現 FileNotFoundException

Sample code 如下:

    /** 
     * The primary method for the Java service
     *
     * @param pipeline
     *            The IData pipeline
     * @throws ServiceException
     */
    public static final void PropertyFileUtils(IData pipeline) throws ServiceException {
        String config_file = "packages\\Acme\\resources\\opc_config.properties";
        
        try {
            Properties properties = loadProperties(config_file);
            
            String opcUrl = properties.getProperty("opc.url");
            String retryInterval = properties.getProperty("opc.retry.interval");
            String maxRetry = properties.getProperty("opc.max.retries");
            String sleepMs = properties.getProperty("opc.sleep.ms");
            
            logger("opcUrl = " + opcUrl);
            logger("retryInterval = " + retryInterval);
            logger("maxRetry = " + maxRetry);
            logger("sleepMs = " + sleepMs);
            
        } catch (IOException e) {
            throw new ServiceException(e);
        }
    }
    
    // --- <<IS-BEGIN-SHARED-SOURCE-AREA>> ---
    
    public static Properties loadProperties(String config_file) throws ServiceException, IOException{
        Properties properties = new Properties();
        InputStream inputStream = null;
        try {
            inputStream = new FileInputStream(config_file);
            properties.load(inputStream);
        } catch (IOException e) {
            throw new ServiceException(e);
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
        }
        return properties;
    } 
    
    public static void logger(String message) throws ServiceException {
        IData input = IDataFactory.create();
        
        IDataCursor inputCursor = input.getCursor();
        IDataUtil.put(inputCursor, "message", message);
        IDataUtil.put(inputCursor, "function", "customLogger");
        IDataUtil.put(inputCursor, "level", "INFO");
        inputCursor.destroy();
    
        try {
            Service.doInvoke("pub.flow", "debugLog", input);
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }
    
    // --- <<IS-END-SHARED-SOURCE-AREA>> ---

相同的,如果你有一些設定用的檔案如 csv 等,也可以放在 resources 目錄下,透過相同的方式皆可讀取得到

Reference
[1] https://goo.gl/EFbLkg

2017/05/10

[webMethods] IS Package Class Loaders 順序

根據 webMethods 文件
  • IS package class loaders 順序是下圖的 1.1 ~ 1.4
  • 在 runtime 的時候,順序是下圖的 2.1 ~ 2.3
  •  要注意的是,若有一個檔案同時存在於 jars 與 classes 的 folder,位於 jars folder 內的檔案擁有優先權


以 Acme package 為例子,目錄結構如下:


Reference
[1] https://goo.gl/46NgNp

2017/05/09

[webMethods] 如何在 Java Service 中印 debug log

Problem
假設我在 Java Service 中印出 debug log 來進行程式碼的 debug,該如何印

How-to
若是同步的作業,作法如下:
    public static void logger(String message) {
    
        IData input = IDataFactory.create();
        IDataCursor inputCursor = input.getCursor();
        IDataUtil.put(inputCursor, "message", message);
        IDataUtil.put(inputCursor, "function", "customLogger");
        IDataUtil.put(inputCursor, "level", "INFO");
        inputCursor.destroy();
    
        try {
            Service.doInvoke("pub.flow", "debugLog", input);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

若是非同步的作業,作法如下:
    public static void loggerAsync(Session session, String message) {
        IData input = IDataFactory.create();
        IDataCursor inputCursor = input.getCursor();
        IDataUtil.put(inputCursor, "message", message);
        IDataUtil.put(inputCursor, "function", "customLogger");
        IDataUtil.put(inputCursor, "level", "INFO");
        inputCursor.destroy();
    
        try {
            Service.doThreadInvoke("pub.flow", "debugLog", session, input);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


以下是列印 log 的呼叫方式:
    // 非同步作業的呼叫方式
    Session session = Service.getSession();
    loggerAsync(session, "Hello~ asynch log");
    
    // 同步作業的呼叫方式
    logger("Hello~ log");







2017/05/08

[webMethods] 如何在 Java Service 中呼叫另外一個 Java Service

Problem
假設我有兩個 Java Service,一個為 Test Java Service: input 參數為 name,執行時會出現 popup window 供輸入


另外一個為 HelloWorld,input parameters 有兩個,分別是 name 與 dateTime,由Test Java Service 傳送給 HellowWorld Java Service,welcomeMessage = name + "(" + dateTime + ")"



How-to
可以使用 Service.doInvoke 來呼叫其他 Service
以下是 Test Service 中的 code snippet:
public final class Test_SVC

{

    /** 
     * The primary method for the Java service
     *
     * @param pipeline
     *            The IData pipeline
     * @throws ServiceException
     */
    public static final void Test(IData pipeline) throws ServiceException {
        IDataCursor pipelineCursor = pipeline.getCursor();
        
        // Invoke the pub.date:getCurrentDateString service to get current date time
        String currentDateString = "";
        IDataUtil.put(pipelineCursor, "pattern", "yyyy/MM/dd HH:mm:ss");
        try {
            IData data = Service.doInvoke("pub.date", "getCurrentDateString", pipeline);
            currentDateString = (String) IDataUtil.get(data.getCursor(), "value");
        } catch (Exception e) {
            throw new ServiceException(e);
        }
        
        // input name
        String name = IDataUtil.getString(pipelineCursor, "name");
        IDataUtil.put(pipelineCursor, "name", name);
        
        // get current date time via pub.date:getCurrentDateString service
        IDataUtil.put(pipelineCursor, "dateTime", currentDateString);
        
        // Invoke HelloWorld service
        try {
            Service.doInvoke("acme.albert.work", "HelloWorld", pipeline);
        } catch (Exception e) {
            throw new ServiceException(e);
        }
        
        pipelineCursor.destroy();
    }
}    


以下是 HelloWorld Service 中的 code snippet:
public final class HelloWorld_SVC

{

    /** 
     * The primary method for the Java service
     *
     * @param pipeline
     *            The IData pipeline
     * @throws ServiceException
     */
    public static final void HelloWorld(IData pipeline) throws ServiceException {
        // pipeline
        IDataCursor pipelineCursor = pipeline.getCursor();
        String name = IDataUtil.getString(pipelineCursor, "name");
        String dateTime = IDataUtil.getString(pipelineCursor, "dateTime");
        logger("dateTime = " + dateTime);
        
        pipelineCursor.destroy();
                
        // pipeline
        IDataCursor pipelineCursor_1 = pipeline.getCursor();
        String welcomeMsg = "Hello~" + name + " (" + dateTime + ")";
        logger("welcome msg = " + welcomeMsg);
        IDataUtil.put( pipelineCursor_1, "welcomeMessage", welcomeMsg );
        pipelineCursor_1.destroy();     
    }
    
    // --- <<IS-BEGIN-SHARED-SOURCE-AREA>> ---  
    public static void logger(String message) throws ServiceException {
        IData input = IDataFactory.create();
        
        IDataCursor inputCursor = input.getCursor();
        IDataUtil.put(inputCursor, "message", message);
        IDataUtil.put(inputCursor, "function", "customLogger");
        IDataUtil.put(inputCursor, "level", "INFO");
        inputCursor.destroy();
    
        try {
            Service.doInvoke("pub.flow", "debugLog", input);
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }
    
    // --- <<IS-END-SHARED-SOURCE-AREA>> ---

}

執行結果:
[9987]2016-11-16 15:52:31 TST [ISP.0090.0004I] customLogger -- welcome msg = Hello~Albert (2016/11/16 15:52:31)
[9986]2016-11-16 15:52:31 TST [ISP.0090.0004I] customLogger -- dateTime = 2016/11/16 15:52:31

上述的範例是採取 synchronous 的方式去呼叫另外一個 Java Service,若要採用 asynchronous 的方式呼叫,需要改寫如下:
    Session session = Service.getSession();
    
    IData input = IDataFactory.create();
    IDataCursor inputCursor = input.getCursor();
    IDataUtil.put(inputCursor, "input", "hello");
    inputCursor.destroy();
    
    Service.doThreadInvoke("acme.albert.work.OPC", "OPC_Heartbeat_Flow", session, input);

2017/05/07

[webMethods] 在 Flow Service 中使用 Sequence 來實現 try-catch

步驟 1. 建立一個 SequenceFlow,並建立兩個輸入參數 num1 與 num2,將 num1 * num2 的結果傳送到輸出參數 result


步驟 2. 建立三個 Sequences,try-catch, try 與 catch,此三個 sequence 的 Exit on 參數分別為
* ‘Success’ for the ‘try-catch’ sequence.
* ’Failure’ for the ‘try’ sequence.
* ‘Done’ for the catch sequence.


步驟 3. 在 try-sequence 中加入 multiplyInts 進行運算


步驟 4. 在 catch-sequence 中加入 getLastError 來取得例外錯誤訊息,並加入 debugLog 將錯誤訊息印到 server log


步驟 5. 執行並驗證結果

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 並查看結果