Mule自带例子之flight-reservation

1 配置效果图

2 应用的配置文件

  1 <?xml version="1.0" encoding="UTF-8"?>
  2 
  3 <mule xmlns:scripting="http://www.mulesoft.org/schema/mule/scripting" xmlns:vm="http://www.mulesoft.org/schema/mule/vm" xmlns:json="http://www.mulesoft.org/schema/mule/json"
  4     xmlns:ajax="http://www.mulesoft.org/schema/mule/ajax" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
  5     xmlns:spring="http://www.springframework.org/schema/beans" version="CE-3.4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  6     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
  7 http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
  8 http://www.mulesoft.org/schema/mule/ajax http://www.mulesoft.org/schema/mule/ajax/current/mule-ajax.xsd
  9 http://www.mulesoft.org/schema/mule/json http://www.mulesoft.org/schema/mule/json/current/mule-json.xsd
 10 http://www.mulesoft.org/schema/mule/vm http://www.mulesoft.org/schema/mule/vm/current/mule-vm.xsd
 11 http://www.mulesoft.org/schema/mule/scripting http://www.mulesoft.org/schema/mule/scripting/current/mule-scripting.xsd">
 12 
 13 
 14     <ajax:connector name="Ajax" serverUrl="http://0.0.0.0:9092/reservation" resourceBase="${app.home}/docroot" jsonCommented="true"    doc:name="Ajax" />
 15 
 16     <!-- 航班预定流,主要通过调用processReservation来完成航班信息的处理 -->
 17     <flow name="makeReservation">
 18         <ajax:inbound-endpoint channel="/searchFlights" connector-ref="Ajax" responseTimeout="10000" doc:name="Ajax" />
 19         <flow-ref name="processReservation" doc:name="processReservation"/>
 20     </flow>
 21 
 22     
 23     <!-- 
 24     航班预定信息处理流
 25         对航班的安排做的假设:
 26             航班号以3结尾,不可获得,直接抛出FlightUnavailableException异常
 27             航班号不是以3结尾,可进入下一步处理:
 28                 航班号以2结尾,可取得座位信息'20A';否则抛出没有座位信息异常'No seat info available',并把'No seat info available'赋给座位信息部分            
 29      -->
 30     <flow name="processReservation">
 31     
 32         <json:json-to-object-transformer returnClass="org.mule.example.ReservationRequest" doc:name="JSON to ReservationRequest" />    
 33         
 34         <!-- 把请求的负载保存到session对象中(payload的类型为ReservationRequest) -->
 35         <set-session-variable variableName="reservationRequest" value="#[payload]" doc:name="Save orignal request in Session" />
 36         
 37         <!-- 设置响应消息的负载 -->
 38         <set-payload value="#[new org.mule.example.ReservationResponse()]" doc:name="Set ReservationResponse Payload" />
 39         
 40         <!-- 把请求消息中的flighs设置到响应消息中 (payload的类型为ReservationResponse) -->
 41         <expression-component doc:name="Add request flight to response">
 42             <![CDATA[payload.setFlights(reservationRequest.flights)]]>
 43         </expression-component>
 44         
 45         <set-variable variableName="totalPrice" value="#[0]" doc:name="Initialize totalPrice" /> <!-- 设置一个totalPrice变量,值为0 -->
 46         
 47         <!-- 迭代处理payload(payload的类型为ReservationResponse,里面有请求信息flights) -->
 48         <foreach collection="#[payload.flights]" doc:name="Foreach on flights">
 49             <scripting:transformer doc:name="Search flight availability">
 50                 <scripting:script engine="Groovy"><![CDATA[
 51 if (payload.flightNumber.endsWith('3'))
 52     throw new org.mule.example.FlightUnavailableException()
 53 else
 54     payload]]>
 55                 </scripting:script>
 56             </scripting:transformer>
 57             
 58             <!-- 
 59             此处声明了一个地址为vm://acquireFlightPriceQueue VM出站端点,即把响应消息扔到了acquireSeatsInfoQueue队列
 60             而acquireSeatsInfo流,在地址vm://acquireFlightPriceQueue上等待请求
 61             exchange-pattern="request-response" 表示该VM出站端点 等待acquireSeatsInfo流给的响应
 62             -->
 63             <vm:outbound-endpoint exchange-pattern="request-response" path="acquireSeatsInfoQueue" doc:name="Acquire Seats Info"/>
 64             <!-- 再把响应消息扔到了acquireFlightPriceQueue队列,等待响应 -->
 65             <vm:outbound-endpoint exchange-pattern="request-response" path="acquireFlightPriceQueue" doc:name="Acquire Flight Price" />
 66             
 67             <!-- 更新totalPrice变量的值,把本次迭代的票价加到总价中 -->
 68             <set-variable variableName="totalPrice" value="#[totalPrice + payload.ticketPrice]" doc:name="Add price to totalPrice" />
 69         </foreach>
 70         
 71         <expression-component doc:name="Add total price to reservation">
 72             <![CDATA[payload.totalPrice = flowVars['totalPrice']]]>
 73         </expression-component>
 74         <!-- 把响应对象转换为JSON, 航班预定处理结束 -->
 75         <json:object-to-json-transformer doc:name="Object to JSON" />
 76         
 77         
 78         <!-- 异常捕获区 -->
 79         <choice-exception-strategy doc:name="Choice Exception Strategy">    
 80             <!--  -->
 81             <catch-exception-strategy when="#[exception.causedBy(org.mule.example.FlightUnavailableException)]" doc:name="Catch Exception Strategy">
 82                 <scripting:transformer doc:name="Add no avaiilability error">
 83                     <scripting:script engine="Groovy">
 84                         <![CDATA[
 85 def payload = new org.mule.example.ReservationResponse()
 86 payload.addError('There is no availability for the selected flight!')
 87 payload]]>
 88                     </scripting:script>
 89                 </scripting:transformer>
 90                 <json:object-to-json-transformer doc:name="Object to JSON" />
 91             </catch-exception-strategy>
 92             
 93             <catch-exception-strategy doc:name="Catch Exception Strategy">
 94                 <scripting:transformer doc:name="Add exception message">
 95                     <scripting:script engine="Groovy">
 96                         <![CDATA[                  
 97 def payload = new org.mule.example.ReservationResponse()
 98 payload.addError('Error processing request!')
 99 payload]]>
100                     </scripting:script>
101                 </scripting:transformer>
102                 <set-property propertyName="http.status" value="500" doc:name="Set http status 500" />
103                 <json:object-to-json-transformer doc:name="Object to JSON" />
104             </catch-exception-strategy>
105         </choice-exception-strategy>
106     </flow>
107     
108     <!-- 
109     应用启动时,该流服务随之启动,然后在vm://acquireFlightPriceQueue上等待请求
110      -->
111     <flow name="acquireSeatsInfo">
112         <!-- 在acquireSeatsInfoQueue路径上等待输入座位信息 -->
113         <vm:inbound-endpoint exchange-pattern="request-response" path="acquireSeatsInfoQueue" doc:name="VM"/>
114         
115         <!-- 使用脚本进行处理 -->
116         <scripting:component doc:name="Acquire seats info service">
117             <scripting:script engine="Groovy"><![CDATA[
118 if (payload.flightNumber.endsWith('2'))
119     payload.seatInfo = '20A'
120 else
121     throw new Exception('No seat info available')
122 payload]]></scripting:script>
123         </scripting:component>
124         
125         <!-- 异常处理 -->
126         <catch-exception-strategy doc:name="Catch Exception Strategy">
127             <expression-component doc:name="Add no seat info available message"><![CDATA[payload.seatInfo = 'No seat info available']]></expression-component>    
128         </catch-exception-strategy>
129     </flow>
130     
131     
132     <!-- 
133     
134     如:下面的path="acquireFlightPriceQueue"配置拼写不对
135 ********************************************************************************
136 Message               : There is no receiver registered on connector "connector.VM.mule.default" for endpointUri vm://acquireFlightPriceQueue
137 Code                  : MULE_ERROR-0
138 在端点地址为vm://acquireFlightPriceQueue的连接器上没有注册接收者
139 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
140 Exception stack is:
141 1. There is no receiver registered on connector "connector.VM.mule.default" for endpointUri vm://acquireFlightPriceQueue (org.mule.api.transport.NoReceiverForEndpointException)
142   org.mule.transport.vm.VMMessageDispatcher:85 (http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/api/transport/NoReceiverForEndpointException.html)
143 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
144 Root Exception stack trace:
145 org.mule.api.transport.NoReceiverForEndpointException: There is no receiver registered on connector "connector.VM.mule.default" for endpointUri vm://acquireFlightPriceQueue
146     at org.mule.transport.vm.VMMessageDispatcher.doSend(VMMessageDispatcher.java:85)
147     at org.mule.transport.AbstractMessageDispatcher.process(AbstractMessageDispatcher.java:81)
148     at org.mule.transport.AbstractConnector$DispatcherMessageProcessor.process(AbstractConnector.java:2627)
149     + 3 more (set debug level logging or '-Dmule.verbose.exceptions=true' for everything)
150 ********************************************************************************
151     航班的票价计算怪怪的,编号*2: payload.ticketPrice = Integer.valueOf(payload.flightNumber) * 2
152      -->
153     <flow name="acquireFlightPrice">
154         <vm:inbound-endpoint exchange-pattern="request-response" path="acquireFlightPriceQueue" doc:name="acquireFlightPrice"/>   
155         <expression-component doc:name="acquireFlightPrice">
156             <![CDATA[payload.ticketPrice = Integer.valueOf(payload.flightNumber) * 2]]>
157         </expression-component>
158     </flow>
159 </mule>

3 相关类定义

1)Flight -- 航班信息类

 1 package org.mule.example;
 2 
 3 import java.io.Serializable;
 4 
 5 public class Flight implements Serializable {
 6 
 7     /**
 8      * 
 9      */
10     private static final long serialVersionUID = -841916700389246787L;
11 
12     private String flightNumber;
13     private String seatInfo;
14     private Double ticketPrice;
15 
16     public String getFlightNumber() {
17         return flightNumber;
18     }
19 
20     public void setFlightNumber(String flightNumber) {
21         this.flightNumber = flightNumber;
22     }
23 
24     public String getSeatInfo() {
25         return seatInfo;
26     }
27 
28     public void setSeatInfo(String seatInfo) {
29         this.seatInfo = seatInfo;
30     }
31 
32     public Double getTicketPrice() {
33         return ticketPrice;
34     }
35 
36     public void setTicketPrice(Double ticketPrice) {
37         this.ticketPrice = ticketPrice;
38     }
39 }

2)ReservationRequest -- 请求消息负载内容类

 1 package org.mule.example;
 2 
 3 import java.io.Serializable;
 4 
 5 public class ReservationRequest implements Serializable {
 6     
 7     /**
 8      * 
 9      */
10     private static final long serialVersionUID = 3502244785792589115L;
11     
12     private Flight[] flights;
13     
14     public Flight[] getFlights() {
15         return flights;
16     }
17     
18     public void setFlights(Flight[] flights) {
19         this.flights = flights;
20     }
21 }

3)ReservationResponse 响应消息负载内容类

 1 package org.mule.example;
 2 
 3 import java.io.Serializable;
 4 import java.util.ArrayList;
 5 import java.util.List;
 6 
 7 public class ReservationResponse implements Serializable {
 8     
 9     private List<String> errors = new ArrayList<String>();
10     
11     private Flight[] flights;
12     public Double totalPrice;
13     
14     
15     public Double getTotalPrice() {
16         return totalPrice;
17     }
18     public void setTotalPrice(Double totalPrice) {
19         this.totalPrice = totalPrice;
20     }
21 
22     public List<String> getErrors() {
23         return errors;
24     }
25     public void setErrors(List<String> errors) {
26         this.errors = errors;
27     }
28 
29     public Flight[] getFlights() {
30         return flights;
31     }
32     public void setFlights(Flight[] flights) {
33         this.flights = flights;
34     }
35     
36     //------ 添加错误信息---------------------
37     public void addError(String error) {
38         errors.add(error);
39     }
40     
41     //------- 原始请求对象---------------------
42     private ReservationRequest originalRequest;
43 
44 
45     public ReservationRequest getOriginalRequest() {
46         return originalRequest;
47     }
48 
49     public void setOriginalRequest(ReservationRequest originalRequest) {
50         this.originalRequest = originalRequest;
51     }
52 }

4)FlightUnavailableException 异常类

1 package org.mule.example;
2 
3 public class FlightUnavailableException extends Exception {
4 
5 }

4 Ajax访问页面

1)index.html

 1 <!DOCTYPE html>
 2 <html>
 3 <head>
 4     <link href="flight-reservation.css" rel="stylesheet" type="text/css"/>
 5     <script type="text/javascript" src="mule-resource/js/mule.js"></script>
 6     <script type="text/javascript" src="flight-reservation.js"></script>
 7 </head>
 8 <body onload="onload();">
 9 <div class="content">
10     <div class="flightReservationHeader"> Flight Reservation System </div>
11     <div id="title"> Search Best Flight </div>
12     <div class="searchBox">
13         <form id="searchFlight">
14             <div class="cities">
15                 <div id="origin">
16                     <div>Origin</div>
17                     <select class="origin" id="originCity">
18                         <option value=""></option>
19                         <option value="BUE">Buenos Aires (BUE)</option>
20                     </select>
21                 </div>
22                 <div id="destination">
23                     <div>Destination</div>
24                     <select class="destination" id="destinationCity">
25                         <option value=""></option>
26                         <option value="MOW">Moscu (MOW) </option>
27                         <option value="HKG">Hong Kong (HKG) </option>
28                         <option value="TW">Tai Wang (TW)</option>
29                     </select>
30                 </div>
31             </div>
32         </form>
33         <div id="makeSearch">
34             <input id="searchButton" type="button" value="Search" onClick="makeSearch(dojo.byId('originCity').value, dojo.byId('destinationCity').value)">
35         </div>
36     </div>
37     <div class="response">
38         <div id="error"><div id="errorMessage"></div></div>
39         <div id="searchResults"></div>
40     </div>
41 </div>
42 </body>
43 </html>

2) flight-reservation.js

 1 function onload() {
 2     dojo.byId("error").style.display = "none";
 3     dojo.byId("searchResults").style.display = "none";
 4 }
 5 
 6 //发送航班请求
 7 function makeSearch(origin, destination) {
 8     var request="";
 9         
10     if (origin == "BUE" && destination == "MOW") 
11     {
12         
13         var request = {
14                 "flights": [
15                         {"flightNumber":912},
16                         {"flightNumber":1022},
17                         {"flightNumber":732}
18                            ]
19                     };
20         mule.rpc("/searchFlights", JSON.stringify(request), processResponse);    
21     } 
22     else if (origin == "BUE" && destination == "HKG") 
23     {
24         var request = {
25                 "flights":[
26                         {"flightNumber":822},
27                         {"flightNumber":1133}
28                           ]
29                     };
30         mule.rpc("/searchFlights", JSON.stringify(request), processResponse);
31     } 
32     else if (origin == "BUE" && destination == "TW")
33     {
34         var request = {
35                 "flights":[
36                         {"flightNumber":822},
37                         {"flightNumber":1004}
38                           ]
39                     };
40         mule.rpc("/searchFlights", JSON.stringify(request), processResponse);
41     }
42     else 
43     {
44         var request={"Invalid Request":[]};
45         mule.rpc("/searchFlights", JSON.stringify(request), processResponse);
46     }
47 }
48 
49 
50 //处理响应
51 function processResponse(message) {
52     resp = JSON.parse("[" + message.data + "]")[0];
53     
54     if(resp.errors == "") 
55     {
56         dojo.byId("error").style.display = "none";
57         dojo.byId("searchResults").style.display = "block";
58 
59         var results = "<table class='results'>";
60         results += "<th>Flight Number</th><th>Seat assignment</th><th>Price</th>"
61         
62         for(var i = 0; i < resp.flights.length;i++) 
63         {
64             results +="<tr><td>" + resp.flights[i].flightNumber + "</td><td>" + resp.flights[i].seatInfo + "</td><td>$" + resp.flights[i].ticketPrice + "</td></tr>";
65         }
66         
67         results += "<tr><td colspan='3'><div id='totalPrice'>Total price is $" + resp.totalPrice + "</div></td><tr>"
68         results += "</table>";
69 
70         dojo.byId("searchResults").innerHTML = results;
71     } 
72     else 
73     {
74         dojo.byId("error").style.display = "block";
75         dojo.byId("searchResults").style.display = "none";
76         dojo.byId("errorMessage").innerHTML = resp.errors;
77     }
78 }

3) flight-reservation.css

  1 .content {
  2     padding: 20px 0 20px 50px;
  3     width: 620px;
  4     color: #003399;
  5     background-color: #F8F8FF
  6 }
  7 
  8 .flightReservationHeader {
  9     text-align: center;
 10     font-weight: bold;
 11     padding-bottom: 20px;
 12     font-size: 1.8em;
 13 }
 14 
 15 #title {
 16     padding-top: 5px;
 17     font-weight: bold;
 18     background-color: #E8EDFF;
 19     width: 150px;
 20     height: 25px;
 21     border: 2px solid #B9C9FE;
 22     text-align: center
 23 }
 24 
 25 .searchBox {
 26     width: 550px;
 27     background-color: #E8EDFF;
 28     border: 2px solid #B9C9FE;
 29     position: relative;
 30     padding-bottom: 30px;
 31     padding-top: 20px
 32 }
 33 
 34 .cities {
 35     padding: 10px 35px 10px 35px
 36 }
 37 
 38 #origin {
 39     float: left;
 40     padding-right: 50px
 41 }
 42 
 43 .origin {
 44     width: 215px
 45 }
 46 
 47 .destination {
 48     width: 215px
 49 }
 50 
 51 #destination {
 52     float: left
 53 }
 54 
 55 #makeSearch {
 56     clear: both;
 57     padding: 20px 0 10px 40px;
 58     position: relative;
 59 }
 60 
 61 #searchButton {
 62     background-color: #B9C9FE
 63 }
 64 
 65 #error {
 66     width: 550px;
 67     height: 50px;
 68     color: #FF0000;
 69     text-align: center;
 70     background-color: #FFDAB9;
 71     border: 2px solid #FF0000;
 72     display: none
 73 }
 74 
 75 #errorMessage {
 76     padding: 10px
 77 }
 78 
 79 .response {
 80     padding-top: 30px
 81 }
 82 
 83 .response table {
 84     width: 550px;
 85 }
 86 
 87 .response table th {
 88     background: none repeat scroll 0 0 #B9C9FE;
 89     border-bottom: 1px solid #FFFFFF;
 90     border-top: 4px solid #AABCFE;
 91     color: #003399;
 92     padding: 8px
 93 }
 94 
 95 .response table td {
 96     background: none repeat scroll 0 0 #E8EDFF;
 97     border-bottom: 1px solid #FFFFFF;
 98     border-top: 1px solid transparent;
 99     color: #666699;
100     padding: 8px;
101 }
102 
103 #totalPrice {
104     float: right;
105     font-weight: bold
106 }

5 执行效果分析

1)flights编号都以'2'结尾,所以正常运行

2)该请求包含了一个以'3'结尾的航班编号,触发该航班不可得异常

3)尾号为2的航班,分配的座位都是'20A';尾号为3的航班,不可得;尾号不是2、3的航班没座位

原文地址:https://www.cnblogs.com/asnjudy/p/4593593.html