Wednesday, September 18, 2013

การใช้งาน Message Format Language (MFL) และ File Transport



ตัวอย่าง
  • Mapping non-XML to XML
    • อ่าน CSV file แล้ว Insert เข้า Database (File transport - Proxy Service)
    • ส่ง Payload เป็น CSV แล้ว insert เข้า Database
  • Mapping XML to non-XML
    • Query database แล้ว save เป็น CSV file (File transport - Business Service)

ก่อนตัวอย่างทั้งหมด ให้สร้าง MFL file (Mapping file คล้าย XSL กับ XQ)
From
To
File name
non-XML
XML
EmployeeMessageFormat.mfl
XML
non-XML
EmployeeMessageFormat.mfl
** ในตัวอย่างสามารถใช้ file เดียวกันได้เลย
OEPE:
1) New MFL…
แก้ XML document encoding เป็น UTF-8


2) เพิ่มกลุ่มของ message เพราะอาจส่งข้อมูล Employee มากกว่า 1 คน
3) เพิ่ม Fields ที่ต้องใช้ได้แก่
a) field name ‘title’ ระบุเป็น Child ของ Group

b) field name ‘firstname’
c) field name ‘surname’
d) field name ‘ouid’
e) field name ‘birthdate’
f) field name ‘nationid’ ซึ่งเป็น field สุดท้าย ให้ปิดท้ายด้วย \n (ขึ้นบรรทัดใหม่)

4) ทดสอบ MFL transformation ด้วย CSV  
**** ข้อควรระวัง บรรทัดสุดท้ายต้องเป็นบรรทัดว่าง ด้วยการกด ENTER ไม่เช่นนั้นจะไม่สามารถ Transform CSV นั้นได้
นาย;สมชาย;แซ่ลี้;10;2013-09-16T18:01:33;1112222233333
นาง;สมศรี;วงศ์ไทย;10;2013-09-16T18:04:55;2112222233333
นาย;สมศักดิ์;จันดี;10;2013-09-16T18:09:01;3112222233333
นาง;สมหญิง;เก่งงาน;10;2013-09-16T18:13:10;4112222233333

*
กรณีไม่ \n หรือมีมากกว่า 1 จะเกิด Error





หลังจากได้ MFL file แล้วให้สร้าง XQuery transformation
สำหรับตัวอย่างที่ 1 อ่าน CSV file แล้ว Insert เข้า Database
Source
Target
File name
EmployeeMessageFormat
MergeEmployeeService1
EmployeeMessageFormat_To_MergeEmployeeService1.xq

สำหรับตัวอย่าง 3 Query database แล้ว save เป็น CSV file
Source
Target
File name
QueryEmployeeService1
EmployeeMessageFormat
QueryEmployeeService1_To_EmployeeMessageFormat.xq
WriteCSVService1
QueryEmployee
WriteCSVService1_To_QueryEmployee.xq

OEPE:
EmployeeMessageFormat_To_MergeEmployeeService1.xq
(:: pragma bea:mfl-element-parameter parameter="$employeeMessageFormat1" type="EmployeeMessageFormat@" location="../mfl/EmployeeMessageFormat.mfl" ::)
(:: pragma bea:global-element-return element="ns0:EmployeeBakCollection" location="../../Adapter/xsd/MergeEmployeeService1_table.xsd" ::)


declare namespace ns0 = "http://xmlns.oracle.com/pcbpel/adapter/db/top/MergeEmployeeService1";
declare namespace xf = "http://tempuri.org/DatabaseTX1/Service/xq/EmployeeMessageFormat_To_MergeEmployeeService1/";
declare namespace funcSQL = "http://www.v-smart.com/function/xq/funcSQL";


declare function funcSQL:nextVal() as xs:decimal {
let $val := fn-bea:execute-sql('jdbc/OSBDemoXE','value','SELECT EMP_SEQ.NEXTVAL FROM DUAL')
return $val
};


declare function xf:EmployeeMessageFormat_To_MergeEmployeeService1($employeeMessageFormat1 as element())
   as element(ns0:EmployeeBakCollection) {
       <ns0:EmployeeBakCollection>
           {
               for $Employee in $employeeMessageFormat1/Employee
               return
                   <ns0:EmployeeBak>
                   <ns0:id>{ funcSQL:nextVal() }</ns0:id>
                   <ns0:firstname>{ data($Employee/firstname) }</ns0:firstname>
                   <ns0:surname>{ data($Employee/surname) }</ns0:surname>
                   <ns0:ouId>{ xs:decimal($Employee/ouid/text()) }</ns0:ouId>
                   <ns0:birthDate>{ xs:dateTime($Employee/birthdate/text()) }</ns0:birthDate>
                   <ns0:nationalId>{ data($Employee/nationid) }</ns0:nationalId>
                       
                   </ns0:EmployeeBak>
           }
       </ns0:EmployeeBakCollection>
};


declare variable $employeeMessageFormat1 as element() external;


xf:EmployeeMessageFormat_To_MergeEmployeeService1($employeeMessageFormat1)


QueryEmployeeService1_To_EmployeeMessageFormat.xq
(:: pragma bea:global-element-parameter parameter="$queryEmployeeService1OutputCollection1" element="ns0:QueryEmployeeService1OutputCollection" location="../../Adapter/xsd/QueryEmployeeService1.xsd" ::)
(:: pragma bea:mfl-element-return type="EmployeeMessageFormat@" location="../mfl/EmployeeMessageFormat.mfl" ::)


declare namespace ns0 = "http://xmlns.oracle.com/pcbpel/adapter/db/QueryEmployeeService1";
declare namespace xf = "http://tempuri.org/DatabaseTX1/Service/xq/QueryEmployeeService1_To_EmployeeMessageFormat/";


declare function xf:QueryEmployeeService1_To_EmployeeMessageFormat($queryEmployeeService1OutputCollection1 as element(ns0:QueryEmployeeService1OutputCollection))
   as element() {
       <EmployeeMessageFormat>
           {
               for $QueryEmployeeService1Output in $queryEmployeeService1OutputCollection1/ns0:QueryEmployeeService1Output
               return
                   <Employee>
                    <title/>
                       <firstname>{ data($QueryEmployeeService1Output/ns0:EMP_FIRSTNAME) }</firstname>
                       <surname>{ data($QueryEmployeeService1Output/ns0:EMP_SURNAME) }</surname>
                       <ouid>{ xs:string($QueryEmployeeService1Output/ns0:OU_ID) }</ouid>
                       <birthdate>{ xs:string($QueryEmployeeService1Output/ns0:BIRTH_DATE) }</birthdate>
                       <nationid>{ data($QueryEmployeeService1Output/ns0:NATIONAL_ID) }</nationid>
                   </Employee>
           }
       </EmployeeMessageFormat>
};


declare variable $queryEmployeeService1OutputCollection1 as element(ns0:QueryEmployeeService1OutputCollection) external;


xf:QueryEmployeeService1_To_EmployeeMessageFormat($queryEmployeeService1OutputCollection1)


WriteCSVService1_To_QueryEmployee.xq
xquery version "1.0" encoding "Cp1252";
(:: pragma  parameter="$anyType1" type="xs:anyType" ::)
(:: pragma bea:global-element-return element="ns0:QueryEmployeeService1Input" location="../../Adapter/xsd/QueryEmployeeService1.xsd" ::)


declare namespace xf = "http://tempuri.org/DatabaseTX1/Service/xq/WriteCSVService1_To_QueryEmployee/";
declare namespace ns0 = "http://xmlns.oracle.com/pcbpel/adapter/db/QueryEmployeeService1";


declare function xf:WriteCSVService1_To_QueryEmployee($anyType1 as element(*))
   as element(ns0:QueryEmployeeService1Input) {
       <ns0:QueryEmployeeService1Input/>
};


declare variable $anyType1 as element(*) external;


xf:WriteCSVService1_To_QueryEmployee($anyType1)






*********** เริ่มต้น
ตัวอย่างที่ 1 อ่าน CSV file แล้ว Insert เข้า Database
สร้าง Proxy Service และกำหนดให้ Proxy service อ่าน CSV file จาก disk เพื่อนำมาเป็น Inbound ของ Service
แก้ไข default Service type เป็น Message Service
แก้ไขเป็น Text
แก้ไข Protocol = file และกำหนด Endpoint เป็น Directory เก็บ CSV file
กำหนด
File mask = *.csv (filter ชื่อ file ต่อท้ายด้วย .csv)
Polling interval = 10 (อ่าน file จาก Directory ทุกๆ 10 วินาที)
Read limit = 1 (หากเจอ file มากกว่า 1 file จะเปิดอ่านที่ละ file)
Uncheck Sort By Arrival (ให้อ่าน file ที่มาก่อนหรือไม่)
Post Read Action = archive (หากอ่าน file เสร็จให้ move ไปที่ Archive Directory)
Request Encoding = UTF-8 (default)
จากนั้นระบุ Stage, Archive และ Error Directory

สร้าง Message Flow
Transform_To_XML stage
Inside stage



Merge stage หรือ Insert เข้า Database
Inside stage

Completed Message Flow
ตัวอย่างที่ 2 ส่ง Payload เป็น CSV format แล้ว insert เข้า Database
สร้าง Proxy Service กำหนดให้รับ XML Payload ที่มี Value เป็น CSV string ตัวอย่าง Payload ที่ใช้ในการทดสอบ ได้แก่
<employee>นาย;สมชาย;แซ่ลี้;10;2013-09-16T18:01:33;1112222233333
นาง;สมศรี;วงศ์ไทย;10;2013-09-16T18:04:55;2112222233333
นาย;สมศักดิ์;จันดี;10;2013-09-16T18:09:01;3112222233333
นาง;สมหญิง;เก่งงาน;10;2013-09-16T18:13:10;4112222233333
</employee>

Transform_To_XML1 stage
Inside stage

*** Recommendation: OSB treats "$body/*[1]" as a special XPath that can be evaluated without invoking the XQuery engine. This is faster than specifying an absolute path pointing to the child of $body. A general XPath like "$body/Order" must be evaluated by the XQuery engine before the primary transformation resource is executed.

Merge1 stage จะเหมือนกับ Merge stage ในตัวอย่างที่ 1 เพราะมันจะต่างแค่ Stage ที่รับ Inbound และ MFL เท่านั้น











ตัวอย่างที่ 3 Query database แล้ว save เป็น CSV file
ก่อนอื่นให้สร้าง Business Service สำหรับ Write file operation ก่อน

สร้าง Proxy Service กำหนดให้ Query Database แล้ว Save เป็น CSV file ลง Disk

QueryEmployee Stage
Inside stage
Transform_To_CSV stage
Inside stage
WriteCSVFile stage
Inside stage
Completed Message Flow
ตัวอย่าง Output file คือ
test2013-09-17T10:07:00.407-07:00.txt