Để thực hiện việc chuyển đổi mô hình nhƣ trên đòi hỏi phải có metamodel của UML-PP. Dựa trên mô tả của tác giả Tran.HN trong [6]
chúng tôi đã cài đặt bản metamodel cho ngôn ngữ này tuân theo chuẩn ecore của eclipse. Các bƣớc xây dựng metamodel UML-PP nhƣ sau:
Xây dựng gói Umlpp gồm ba gói: gói ProcessStructure chứa các thành tố phần mềm cùng quan hệ giữa chúng; gói ProcessPattern chứa mô tả về mẫu tiến trình và gói PatternRelationship mô tả các quan hệ sử dụng lại mẫu tiến trình
Hình IV-2 Gói Umlpp chứa các lớp của UML-PP
Chuẩn bị các gói L0, L2, LM. Do UML-PP thực hiện kế thừa từ UML theo kiểu heavy-weight, nên để tạo bản metamodel cho UML-PP, ta bắt buộc phải thực hiện trộn (merge) tất các các lớp mà
UML-PP đã thừa kế. L0, L2, LM là các gói chứa các gói con của UML cần thiết cho UML-PP
Hình IV-3 Gói L0
Hình IV-5 Gói LM
Tạo gói UmlppComplete bao gồm trộn của các gói Umlpp, L0, L2 và LM
Hình IV-6 Gói UmlppComplete là trộn các gói để tạo Umlpp metamodel
Tiến hành trộn tất cả các gói có trong UmlppComplete. Sau đó chuyển tất cả thành metamodel. Ta thu đƣợc bản metamodel của Umlpp dƣới dạng UML
Hình IV-7 Metamodel của Umlpp dƣơí dạng UML
Tiến hành chuyển bản metamodel của Umlpp dạng UML sang dạng ecore bằng sách sử dụng công cụ EMF generator model của eclipse với tùy chọn bỏ qua phần Operation Bodies
Kết quả ta sẽ thu đƣợc file UmlppComplete.ecore là bản metamodel cuối cùng của Umlpp. Bản metamodel này bao gồm các lớp của Umlpp đồng thời gồm luôn cả các lớp của UML2.0 mà Umlpp có thừa kế.
Hình IV-9 Metamodel của Umlpp
Nhận xét:
Trong quá trình xây dựng metamodel cho UMLPP, chúng tôi đã phát hiện một số chi tiết không đồng nhất hoặc không tối ƣu trong sơ đồ metamodel của tác giả nhƣ: dƣ thừa quan hệ thừa kế (ví dụ nhƣ tác giả mô tả ProcessElement thừa kế Classifier, ParameterizableElement thừa kế Classifier trong khi đó ProcessElement lại thừa kế ParameterizableElement); mâu thuẫn với các lớp và thuộc tính của UML2.0 (do trùng tên thuộc tính, tên lớp)… Trong quá trình cài đặt metamodel UML-PP, chúng tôi đã tiến hành sửa chữa và cải tiến so với mô tả của metamodel gốc (chi tiết xin kham khảo phần phụ lục A).
Mô tả: Mỗi đối tƣợng Task của UML-PP sẽ đƣợc chuyển đổi tƣơng ứng sang một hoạt động gọi thực thi một dịch vụ web của BPEL Invoke với operation là name của Task. Các thuộc tính khác của Invoke nhƣ name = Task.name, partnerLink = Task.name + "_service", portType = Task.name + "PT". Đồng thời hai Variable tƣơng ứng với input và output của Invoke sẽ đƣợc tạo ra.
Ví dụ UML-PP BPEL <invoke name="Invoke_SendEmail" operation="SendEmail" portType="SendEmail_service" partnerLink="SendEmailPL"/> <variable name="Invoke_SendEmail_InputVariable"/> <variable name="Invoke_SendEmail_OutputVariable"/> <variable name=""/> 3. UML-PP: Product BPEL: Variable
Mô tả: Các Product là tham số của Task sẽ đƣợc chuyển đổi thành nội dung chứa trong các Variable.
Ví dụ: UML-PP BPEL <assign> <copy> <from expression="IN:B|OUT:C|"/> <to variable="Invoke_A_InputVariable" part="input"/> </copy> </assign>
4. UML-PP: InitialNode
BPEL: Receive
Mô tả: Mỗi đối tƣợng InitialNode sẽ chuyển thành một Receive với thuộc tính createInstance = true để khởi tạo BPEL Process.
Ví dụ:
UML-PP BPEL
<receive name="StartFaganCodeInspection" createInstance="yes" />
5. UML-PP:FinalNode
BPEL: Reply hoặc Exithoặc callback Invoke
Mô tả: Đối tƣợng Reply sẽ đƣợc chuyển thành thẻ Reply hoặc Exit hoặc hành động Invoke callback để kết thúc tiến trình BPEL và thông báo kết quả thực thi cho dịch vụ gọi.
Ví dụ: UML-PP BPEL <invoke name="ExitFaganCodeInspection" inputVariable = "FaganCodeInspectionOutputVariable" operation = "FaganCodeInspectionCallback" />
6. UML-PP: ForkNode, JoinNode
BPEL: Flow
Mô tả: Đối tƣợng ForkNode và JoinNode sẽ đƣợc chuyển sang Flow để biểu diễn các hoạt động song song.
UML-PP BPEL <flow> <sequence> <invoke name="A"/> </sequence> <sequence> <invoke name="B"/> </sequence> </flow>
7. UML-PP: DecisionNode, MergeNode
BPEL: If, Else, ElseIf
Mô tả: Đối tƣợng DecisionNode, MergeNode sẽ đƣợc chuyển sang cấu trúc If, Else và ElseIf của BPEL. Các điều kiện sẽ đƣợc chuyển sang BPEL Condition.
Ví dụ UML-PP BPEL <if> <condition> $expression </condition> <invoke operation="A"/> <else> <invoke operation="B"/> </else> </if> 8. UML-PP: ControlFlow BPEL: Link
Mô tả: Ta có thể chuyển đổi sự phụ thuộc trƣớc sau của các Task sang BPEL Link. Khi đó Task đứng trƣớc sẽ là source của Link, và Task đứng sau là target của Link.
Ví dụ:
UML-PP BPEL
<link name="A_B"/> <invoke name="A"> <sources>
<source linkName="A_B"/> </sources>
</invoke>
<invoke name="B"> <targets>
<target linkName="A_B" /> </targets>
</invoke>
9. UML-PP: LoopNode
BPEL: While hoặc RepeatUntil
Mô tả: LoopNode có thể chuyển thành While hoặc RepeatUntil nhằm biểu diễn cấu trúc lặp.
UML-PP BPEL <while> <condition> $Expression </condition> <invoke operation="A"/> </while>
10. UML-PP: ProcesssPatternBinding, ProcessPatternApplying. Để chuyển đổi các quan hệ ProcessPatternBinding, ProcessPattern- Applying sang BPEL, chúng tôi đề nghị hai hƣớng tiếp cận nhƣ sau:
Cách 1)
Dùng ATL và giải thuật đƣợc mô tả trong [6] để unfold tất cả các quan hệ sử dụng lại trong mô hình UMLPP gốc (bao gồm binding, applying). Mô hình UMLPP đã unfold sẽ đƣợc tiếp tục dùng ATL để chuyển sang mô hình BPEL căn cứ vào các luật từ 1-9 ở trên.
Ưu điểm của hướng tiếp cận này là mô hình BPEL sau khi chuyển đổi có thể thực thi ngay được do chỉ bao gồm các hoạt động Invoke. Tuy nhiên, ngữ nghĩa sử dụng lại trong tiến trình phần mềm sẽ không còn.
Cách 2)
Chuyển các quan hệ dùng lại vào trong thẻ extensionActivity:
BPEL hỗ trợ thẻ <extensionActivity> dùng để vào mục đích mở rộng BPEL. Do ta có thể tự do tạo các thẻ tùy ý trong thẻ <extensionActivity> nên ta có thể chuyển tất cả các quan hệ dùng lại trong UML-PP vào trong <extensionActivity> nhƣ cấu trúc sau: <extensionActivity>
<reuseActivity>
<bindingActivity name="DesignReview" /> <boundPattern name="FaganCodeInspection"> <!--Qui trình BPEL dạng abstract giải pháp -->
<process name=”Fagan Code Inspection”> ... </process> </boundPattern> <reuseParameters> <reuseParamete parameter="Artifact" value="DesignModel"/> .... </reuseParameters> <reuseActivity> </extensionActivity>
Ƣu điểm cách hai là lƣu giữ lại đƣợc ngữ nghĩa thực thi nhƣng do các bộ máy thực thi không hỗ trợ hiểu các thẻ đƣợc đề cập trong
<extensionActivity> nên phần reuse sẽ không đƣợc thực thi (tiến trình sẽ thực thi nhƣ không có quan hệ sử dụng lại).
Các khó khăn trên là do bản thân BPEL không có bất kỳ khái niệm nào về sử dụng lại các Activity, cũng nhƣ cách để tái tổ chức hay sắp xếp lại các Activity theo một qui trình mẫu. Qui trình BPEL sau khi đƣợc tạo ra nó có tính chất cố định, không thay đổi đƣợc.
Chƣơng V
HIỆN THỰC VÀ KIỂM CHỨNG CHUYỂN ĐỔI
UML-PP SANG BPEL
Xây dựng công cụ mô hình UML-PP Các ví dụ chuyển đổi
Fagan Code Inspection Refactor Code
Modify Design
Mô hình sử dụng Pattern Binding Kiểm chứng tiến trình BPEL kết quả
Chƣơng V – HIỆN THỰC VÀ KIỂM
CHỨNG CHUYỂN ĐỔI UML-PP SANG BPEL
Trong phần này chúng tôi trình bày việc xây dựng các công cụ hỗ trợ cho việc hiện thực việc chuyển đổi UML-PP sang BPEL. Các công cụ đƣợc phát triển bao gồm: công cụ mô hình hóa tiến trình nguồn trong UML-PP, cài đặt ATL của bộ luật chuyển đổi, phần triển khai môi trƣờng thử nghiệm trong trên NetBeans 6.7.1 và thực thi trên GlassFish Server v2.1.
5.1 Xây dựng công cụ mô hình UML-PP
Sau khi đã có metamodel của UML-PP, chúng tôi tiến hành xây dựng công cụ mô hình hóa UML-PP. Công cụ mô hình hóa này đƣợc xây dựng dựa vào công nghệ GMF (Graphical Modeling Framework). Quá trình thực hiện bao gồm:
Tạo gmftool: là file mô tả thanh công cụ. Các ký hiệu trong UML- PP mà chúng tôi hỗ trợ bao gồm: InitialNode, FinalNode,
GeneralTask, GeneralProduct, ForkNode, JoinNode, DecisionNode, MergeNode, Control Flow, ObjectFlow, GuardFlow,
ProcessPattern, SolutionModel, PatternSignature, TaskParameter, ProductParameter
Hình V-1 File umlppcomplete.gmftool mô tả các công cụ
Tạo gmfgraph : là file chứa các mô tả hình vẽ cho các công cụ bao gồm các nốt, các liên kết, các nhãn trên sơ đồ. GMF cung cấp các mẫu hình cơ bản nhƣ hình tròn, ellipse… nhƣng nhà phát triển hoàn toàn có thể tuỳ biến bằng cách cài đặt các lớp hình của riêng mình
Hình V-2 File umlppcomplete.graph chứa mô tả hình biểu diễn nốt, liên kết
Tạo gmfmap: file này giúp chúng tôi ánh xạ các đối tƣợng trong thanh công cụ với hình biểu diễn và lớp, thuộc tính sẽ lƣu trữ. Nhà phát triển có thể cài đặt việc khởi tạo các đối tƣợng trong mô hình cũng nhƣ các ràng buộc tại đây.
Hình V-3 File umlppcomplete.map giúp ánh xạ công cụ, hình vẽ và lớp lƣu trữ
Hình V-4 Công cụ mô hình hóa UML-PP
Nhận xét:
Công cụ mô hình hóa UML-PP đƣợc xây dựng dƣới dạng pluggin, dễ dàng tích hợp vào môi trƣờng eclipse modeling. Hơn thế, với việc lƣu trữ dƣới định dạng XMI, các tiến trình phần mềm biểu diễn bởi UML-PP có thể đƣợc đọc bởi các công cụ mô hình phổ biến khác. Tuy nhiên, do mục đích chính của đề tài là việc khảo sát chuyển đổi mô hình tiến trình phần mềm sang mô hình nghiệp vụ nên công cụ mô hình trên còn nhiều thiếu sót nhƣ: một số ký
hiệu chƣa đúng với mô tả của tác giả (nhƣ quan hệ ProcessPatternBinding), các ràng buộc trên nốt chƣa đƣợc cài đặt đầy đủ.
5.2 Cài đặt ATL của bộ luật chuyển đổi UML-PP sang BPEL BPEL
Trong phần này, chúng tôi xin trình bày sơ lƣợc cài đặt ATL cho một số luật chuyển đổi chính đƣợc liệt kê ở mục 4.4. Mã nguồn đầy đủ có thể tìm thấy ở phần phụ lục B.
1. Chuyển đổi BehaviorModel sang Process:
-- Create Bpel process from Behavior
rule Behavior2Process { from b : MMUmlpp!BehaviorModel to p : MMBpel!Process( name <- b.name ,suppressJoinFailure <- true ,targetNamespace <- 'http://' + b.name.replace(' ','_') ,import <-
Set{thisModule.FaganCodeInspectionWSDL(b),thisModule.HumanT askWSDL(b)}
,partnerLinks <- thisModule.PartnerLinks(b) ,variables <- thisModule.Model2Variables(b) ,activity <- thisModule.Model2MainSequence(b) )
}
2. Chuyển đổi Task sang Invoke và Variable:
unique lazy rule Task2Invoke{ from t : MMUmlpp!GeneralTask to i : MMBpel!Invoke(
name <- 'Invoke_' + t.name.wtrim()
,partnerLink <- thisModule.Task2PartnerLink(t) ,operation <- thisModule.Task2Op(t)
,inputVariable <- thisModule.Task2InVariable(t) ,outputVariable <- thisModule.Task2OutVariable(t) ,portType <- thisModule.Task2PT(t)
) }
unique lazy rule Task2InVariable{ from t : MMUmlpp!GeneralTask to v : MMBpel!Variable(
name <- 'Invoke_' + t.name.wtrim() + '_' + t.name.wtrim() + '_InputVariable'
,messageType <-
thisModule.Task2RequestMessageType(t) )
}
unique lazy rule Task2OutVariable{ from t : MMUmlpp!GeneralTask to v : MMBpel!Variable(
name <- 'Invoke_' + t.name.wtrim() + '_' + t.name.wtrim() + '_OutputVariable'
,messageType <-
thisModule.Task2ResponseMessageType(t) )
}
3. Chuyển đổi Product thành Variable:
helper context MMUmlpp!GeneralTask def :
getTaskParameters() : String =
MMUmlpp!ObjectFlow->allInstances()->iterate (f;res : String = '' |
if f.target = self and
f.source.oclIsTypeOf(MMUmlpp!GeneralProduct)
then res + 'IN:' + f.source.name + '|'
else if f.source = self and
f.target.oclIsTypeOf(MMUmlpp!GeneralProduct) then res + 'OUT:' + f.target.name + '|'
else res endif endif
);
unique lazy rule Task2Assign{ from t : MMUmlpp!GeneralTask to a : MMBpel!Assign(
name <- 'Assign_' + t.name.wtrim() ,copy <- thisModule.Task2Copy(t) )
}
unique lazy rule Task2Copy{ from t : MMUmlpp!GeneralTask to c : MMBpel!Copy(
"from" <- thisModule.Task2From(t) ,"to" <- thisModule.Task2To(t) )
}
unique lazy rule Task2From{ from t : MMUmlpp!GeneralTask to f : MMBpel!From(
expression <- thisModule.Task2FromExp(t) )
}
unique lazy rule Task2FromExp{ from t : MMUmlpp!GeneralTask to f : MMBpel!Expression(
body <- t.getTaskParameters() )
}
unique lazy rule Task2To{
from t : MMUmlpp!GeneralTask to f : MMBpel!To(
variable <- thisModule.Task2InVariable(t) ,part <- thisModule.Task2Part(t)
,query <- thisModule.Task2Query(t) )}
4. Chuyển đổi ControlFlow thành Link:
unique lazy rule ControlFlow2Link{ from c : MMUmlpp!ControlFlow to l : MMBpel!Link(
name <- c.source.name + '_' + c.target.name )
}
5. Chuyển đổi ForkNode sang Flow:
unique lazy rule Fork2Flow{ from f : MMUmlpp!ForkNode to l : MMBpel!Flow( activities <- f->getBrachTasks()->collect(t | thisModule.Task2FlowSeq(t)) ) }
helper context MMUmlpp!ForkNode def : getBrachTasks() :
OrderedSet(MMUmlpp!GeneralTask) =
MMUmlpp!ControlFlow->allInstances()->select (c | c.source = self)->collect(c | c.target) ;
unique lazy rule Task2FlowSeq{ from t : MMUmlpp!GeneralTask to s : MMBpel!"Sequence"(
activities <- t->getNextTasks()->collect ( g | Sequence{thisModule.Task2Assign(g),
thisModule.Task2Invoke(g)})->flatten()) }
5.3 Cài đặt Acceleo cho chuyển đổi mô hình BPEL sang dạng BPEL XML sang dạng BPEL XML
Acceleo là bộ phát sinh mã nguồn theo đặc tả “mô hình sang mã nguồn” của OMG. Để chuyển đổi từ mô hình BPEL sang file BPEL XML có thể thực thi đƣợc, chúng tôi tiến hành tạo các file template có chứa mã nguồn truy vấn các thành phần trong mô hình. Hơn nữa, chúng tôi cũng thêm vào các cấu hình về WSDL, XSD vào file template.
Đoạn template chuyển đổi các đối tƣợng BPEL sang thẻ <invoke>, <receive>, <assign>… căn cứ vào tên lớp của các đối tƣợng là Activity:
<[p.activity.className()/] name="[p.activity.name/]">
[if (p.activity.className() = 'sequence')]
separator('\n') ] [if (a.className() = 'receive')]
<[a.className()/] name="[a.name/]"
partnerLink="[a.oclAsType(Receive).partnerLink.name/]" portType="[a.oclAsType(Receive).portType.qName/]" operation="[a.oclAsType(Receive).operation.name/]" variable="[a.oclAsType(Receive).variable.name/]" [if (a.oclAsType(Receive).createInstance->notEmpty())] createInstance="[a.oclAsType(Receive).createInstance. yesNo()/]" [/if] /> [/if]
[if (a.className() = 'assign')]
<[a.className()/] name="[a.name/]">
[for (c : Copy | a.getCopies()) separator('\n')]
<copy>
<from expression="[c.from.expression._body/]"/>
<to variable="[c.to.variable.name/]"
part="[c.to.part.name/]"
query="[c.to.query.value/]"
/> </copy>
[/for]
</assign>
[/if]
[if (a.className() = 'invoke')]
<[a.className()/] name="[a.name/]"
inputVariable = "[a.oclAsType(Invoke).inputVariable.name/]" [if (a.oclAsType(Invoke).outputVariable ->notEmpty())] outputVariable = "[a.oclAsType(Invoke).outputVariable.name/]" [/if] partnerLink = "[a.oclAsType(Invoke).partnerLink.name/]" portType = "[a.oclAsType(Invoke).portType.qName/]" operation = "[a.oclAsType(Invoke).operation.name/]" /> [/if] [/for] [/if]
5.4 Các ví dụ chuyển đổi
5.4.1 Fagan Code Inspection
Mô hình Fagan Code Inspection là mô hình tiến trình dùng cho việc kiểm duyệt mã nguồn. Việc kiểm duyệt bao gồm các hành động lên kế hoạch (Planning) với tham số đầu vào là mã nguồn (Source Code), xem xét tổng quan (Overview), chuẩn bị (Preparing) sau đó tiến hành thanh tra mã nguồn (Inspection Meeting), thay đổi mã nguồn (Rework) và kiểm tra (Follow Up). [Hình V-5] là mô hình Fagan Code Inspection đƣợc biểu diễn bằng UML- PP.
Hình V-5 Mô hình Fagan Code Inspection
Việc chuyển đổi mô hình Fagan Code Inpsection UML-PP sang mô hình BPEL đƣợc thực hiện lần lƣợt qua các bƣớc:
Chuyển đổi đối tƣợng BehaviorModel sang đối tƣợng BPEL Process
Khởi tạo phần đối tƣợng BPEL Import ( chứa các tham chiếu đến các file WSDL cần thiết)
Khởi tạo các đối tƣợng BPEL PartnerLink
Chuyển đổi các thành phần trong UML-PP sang BPEL Variable (nhƣ Product). Mỗi Task trong UML-PP sẽ đƣợc chuyển thành hai Variable, các tham số của Task sẽ đƣợc chuyển thành các nội dung của biến. Ví dụ, nội dung của biến PlanningIn có giá trị
’IN:Source Code’ có nghĩa tác vụ Planning nhận tham số đầu vào là Source Code
Chuyển đổi tất cả các Task thành các đối tƣợng BPEL Invoke tƣơng ứng. Đồng thời chuyển đổi thứ tự thực thi các tác vụ thành các đối tƣợng BPEL, trong mô hình Fagan Code Inspection thứ tự thực thi là đối tƣợng BPEL Sequence.
Mô hình BPEL kết quả sẽ đƣợc chuyển sang dạng file BPEL XML sử dụng Acceleo. Kết quả file BPEL XML sẽ đƣợc kiểm tra trên nền tảng NetBeans 6.7.1 và thực thi trên GlassFish Server v2.1. Nhằm mục đích thực thi chúng tôi đã tạo sẵn dịch vụ web HumanTask giả lập để thực hiện tất cả các hoạt động mà qui trình phần mềm yêu cầu.
Hình V-7 Mô hình dịch vụ web HumanActivity
5.4.2 Refactor Code
Tiến trình Refactor Code mô tả các bƣớc cần thực hiện để tiến hành chỉnh sửa mã nguồn gồm các bƣớc: xác định các vấn đề trong mã nguồn (Identify Complexity In Code), tiến hành refactor (Apply Refactor Code) sau đó thực hiện unit test (Perform Unit Test). Ở mỗi bƣớc các hoạt động đều chấp nhận đầu vào mã nguồn, tình trạng của mã nguồn sẽ đƣợc thay đổi qua các bƣớc từ inspected đến inspected + unit tested. Việc chuyển đổi sang mô hình BPEL và file BPEL XML tƣơng tự mô hình Fagan Code Inspection. Các tham số đầu vào và đầu ra của hoạt động Apply Refactor Code sẽ đƣợc chuyển sang biến và giá trị của biến nhƣ sau: ‘IN:Source Code | OUT:Source Code (inspected)’.
Hình V-9 Mô hình BPEL Refactor Code sau khi kiểm tra
5.4.3 Modify Design
Tiến trình Modify Design mô tả quá trình thay đổi bản thiết kế. Các công việc sau khi bản thiết kế đƣợc thay đổi diễn ra song song nhƣ Review
Hình V-11 Mô hình BPEL của Modify Design sau khi kiểm tra
5.4.4 Mô hình sử dụng Process Pattern Binding
[Hình V-12] mô tả một tiến trình trong đó tác vụ Code Review sử dụng lại mẫu tiến trình Fagan Code Inspection theo kiểu Process Pattern Binding. Để có thể chuyển sang đƣợc mô hình BPEL, quan hệ Process Pattern Binding sẽ