在 Biztalk 编排中异步调用 Web 服务






4.97/5 (13投票s)
2006年2月4日
13分钟阅读

135402

1682
在本文中,我将向您展示如何使用 Biztalk 异步调用 Web 服务。我们将使用两个业务流程和一些概念,例如端口参数和端口的极性反转。
引言
一段时间前,我正在使用 Biztalk Server 开发一个解决方案,但发现关于如何异步调用 Web 服务(或任何其他进程)的信息非常少。在 Biztalk 文档中进行了一些搜索后,我发现了一个有趣的解决方案,它由两个业务流程和一个作为参数从一个业务流程传递到另一个业务流程的端口组成。为了说明这个解决方案,我将使用一个假设的场景,利用 Northwind 数据库。
场景
假设您为一家大公司工作,该公司使用遗留系统处理订单。公司现在正计划更换系统,但新系统需要一年时间才能投入运行。公司目前使用 Biztalk 作为其集成平台,您是一名 Biztalk 开发人员。由于您的公司需要扩大业务,并且不能等到新系统准备就绪,您的老板给您分配了一项新任务。
“我们对遗留系统的查询支持非常有限。目前,我们的销售人员只能查询某一天的订单,而不能查询某个日期范围内的订单。这些信息对我们至关重要,因为为了增加销售额,我们的销售人员需要获得整月甚至整年的信息,以便分析趋势。我需要您创建一个 Biztalk 流程,能够接收一个日期范围,并查询我们遗留系统中该范围内的每一天的订单。这个 Biztalk 流程将返回该范围内的所有订单作为结果。”
这听起来像是 Biztalk 的一项简单任务,不是吗?幸运的是,遗留系统的人员已经创建了一个 Web 服务层,这样您就可以查询遗留系统中特定日期的订单。
为了模拟遗留系统的 Web 服务,我创建了一个简单的 Web 服务,它查询 Northwind 数据库中的信息。Web 服务的源代码可在文章中找到。
架构
在我们开始构建 Biztalk 解决方案之前,我们需要了解我们的订单查询过程将如何工作。下图显示了解决方案将如何工作
当最终用户应用程序向 Biztalk 服务器发送 XML 请求时,该过程开始。此请求将包含我们需要在遗留系统中查询的日期范围。当消息到达 Biztalk 时,它会为该范围内的每个日期生成另一个业务流程的一个实例(在图中,有 7/1/1996、7/2/1992、7/3/1996 和 7/4/1996 的业务流程实例)。第二个业务流程使用遗留系统的 Web 服务查询特定日期的订单。请注意,所有这些业务流程都是异步生成的。每个业务流程处理完毕后,它会将响应返回给主业务流程。请注意,主业务流程中的循环一结束,我们就会启动另一个循环,等待我们生成的每个业务流程的响应。收到所有消息后,我们将它们聚合到一个消息中并返回给最终用户应用程序。使用这种方法,查询日期范围所需的时间将与查询单一天所需的时间大致相同,因为我们的业务流程会同时为每一天启动对遗留系统的新查询。
由于我们没有最终用户应用程序,我们将使用 XML 文件来模拟最终用户应用程序。
创建项目
我们将从创建 Biztalk 项目开始。启动 Visual Studio 并创建一个名为 BTSOrderQuery 的新 Biztalk Server 项目。您需要向项目添加两个引用。第一个是引用 BTSUtils 库。该库包含一个用于聚合 XML 消息的通用类。您可以在文章随附的 ZIP 文件中找到该项目。另一个引用是对我们遗留系统的 Web 服务的 Web 引用(也可以在单独的 .zip 文件中下载)。只需单击“引用”,添加 Web 引用,然后输入您安装 Web 服务的 URL(在我的例子中是 https:///legacyorder/orderquery.asmx)。
创建架构
我们将在项目中创建的第一个项目是用于向 Biztalk Server 发送查询请求的架构。右键单击解决方案资源管理器中的项目,然后选择“添加新项...”选项。选择“架构”作为项类型,并将其命名为 OrderRequest.xsd。
打开您刚刚创建的架构(如果它尚未打开),并将其“目标命名空间”属性更改为“http://nwtraders”(单击 <Schema> 访问此属性)。更改目标命名空间后,将根元素的“节点名称”属性更改为 OrderRequest。
现在,在根元素中添加两个子字段(右键单击“OrderRequest”元素并选择“插入...子字段元素”),分别命名为 StartDate
和 EndDate
。将这两个元素的数据类型都更改为 xs:dateTime
。
为了完成我们的架构,右键单击 StartDate
,选择“提升”选项,然后选择“显示提升”。确保屏幕左侧选择了“StartDate
”,然后单击“添加”。现在,选择“EndDate
”字段并再次单击“添加”。屏幕应如下图所示。单击“确定”关闭此对话框
将这些字段提升为“区分字段”将允许我们在业务流程代码中访问它们。在过程结束时,您的架构应如下图所示
创建主业务流程
现在我们有了架构和引用,我们将创建主业务流程。右键单击项目,选择“添加新项...”选项,然后选择“业务流程”。将其命名为“OrderRequestMain”。
打开“业务流程视图”窗口(如果看不到“业务流程视图”窗口,请转到“视图”菜单,“其他窗口”,然后选择“业务流程视图”),然后右键单击“消息”文件夹,并选择“新建消息”选项。将消息名称更改为“msgOrderRequest
”,并将“消息类型”属性更改为“架构...”,“BTSOrderQuery.OrderRequest
”。创建另一个名为“msgOrders
”的消息,并将其消息类型选择为“Web 消息类型”,“BTSOrderQuery.localhost.OrderQuery_.GetOrders_response
”。
从工具箱中,将“接收”形状拖到业务流程设计器区域,并将其命名为“RcvOrderQuery
”。将其消息属性更改为“msgOrderRequest
”,将其激活属性更改为“True”。
在业务流程视图中,右键单击“变量”文件夹并选择“新建变量”。将变量命名为“oAgreg
”,并将其数据类型选择为“.NET 类”,“BTSUtils.Aggregator
”。我们将使用此类将所有查询的结果聚合到一个消息中。创建另一个类型为 datetime 的变量 dtDate
。将“表达式”形状拖到“接收”形状下方,并在其中输入以下表达式。这将初始化我们查询的第一个日期的变量。将“循环”形状拖到业务流程设计器中,位于“表达式”形状下方。将其表达式属性更改为以下表达式
System.DateTime.Compare(dtDate, msgOrderRequest.EndDate) <= 0
现在在循环形状内添加一个“启动业务流程”形状,并在其下方(也在循环形状内)添加一个“表达式”形状。在表达式形状中,添加以下表达式
dtDate = dtDate.AddDays(1);
复制业务流程中的第一个表达式形状,并将其粘贴到我们的循环下方(这将把日期变量重置为我们的新循环)。现在拖动另一个循环形状,并使用我们用于另一个循环的相同表达式属性。在这个循环中,添加一个接收形状和一个表达式形状。在接收形状中,选择 msgOrders
作为其消息属性。在表达式形状中,添加以下代码
oAgreg.Aggregate(msgOrders.GetOrdersResult,
"/ns0:Result/ns0:Orders", "/ns0:Result/ns0:Orders/ns0:Order");
上面的表达式使用通用聚合器将每一天的结果组合成一个消息。为了完成我们的主业务流程,在我们创建的最后一个循环下方拖动一个“消息构造”形状。选择 msgOrders
作为要构造的消息。在这个“消息构造”中,拖动一个“消息赋值”形状并添加以下代码
msgOrders.GetOrdersResult = oAgreg.GetAggregatedDocument();
GetAggregatedDocument
返回作为 Aggregate
方法调用中的参数传递的文档的聚合版本。现在我们有了聚合消息,我们需要将其发送给最终用户。在消息构造下方拖动一个发送形状,并将其消息属性选择为 msgOrders
。
此时,您的业务流程应如下图所示
创建端口
现在,我们需要创建端口来接收和发送我们的消息。右键单击业务流程设计器左侧的端口平面,然后选择“新建配置端口”。在第一个屏幕上单击“下一步”。在下一个屏幕上,键入“rpIN”作为接收端口的名称,然后单击“下一步”。
在下一个屏幕上,键入“rpINType”作为端口类型,然后单击“下一步”。确保选择了“我将始终接收...”选项,单击“下一步”,然后单击“完成”。将创建一个新端口。将此端口连接到业务流程中的第一个接收形状。
让我们创建第二个端口(将接收来自其他业务流程的消息的端口)。右键单击端口表面,现在在业务流程的右侧,然后选择“新建配置端口”。在第一个屏幕上单击“下一步”。在下一个屏幕上,键入“rpOrders”作为接收端口的名称,然后单击“下一步”。在下一个屏幕上,键入“rpOrdersType”作为端口类型,然后单击“下一步”。确保选择了“我将始终接收...”选项,并选择“直接”作为“端口绑定”选项。在直接绑定选项中,选择“自关联”。单击“下一步”,然后单击“完成”。我们在这里使用自关联选项 Biztalk,我们将把这个端口作为参数传递给我们的另一个业务流程(哎呀!),通过选择此选项,我们确保响应将定向到正确的业务流程。将此端口连接到第二个循环内的接收形状。
现在是最后一个端口。右键单击业务流程设计器左侧的端口平面,然后选择“新建配置端口”。在第一个屏幕上单击“下一步”。在下一个屏幕上,键入“spOUT”作为接收端口的名称,然后单击“下一步”。在下一个屏幕上,键入“spOUTType”作为端口类型,然后单击“下一步”。确保选择了“我将始终发送...”选项,单击“下一步”,然后单击“完成”。将创建一个新端口。将此端口连接到业务流程中的最后一个发送形状。
创建端口后,我们的业务流程应如下图所示。
创建第二个业务流程
第二个业务流程负责查询我们遗留系统的 Web 服务以获取特定日期,并将结果返回给主业务流程。第二个业务流程比第一个简单。让我们从创建新的业务流程文件开始。在“解决方案资源管理器”中,右键单击 Biztalk 项目并选择“添加新项...”。选择“业务流程”并将其命名为“BTSQueryLegacy”。
与其他业务流程不同,此业务流程将由参数而不是接收形状激活。转到业务流程视图,然后右键单击“业务流程参数”选项。选择“新建变量参数”。将参数的名称属性更改为 dtOrder
,并将其数据类型更改为“datetime”。
为了调用遗留 Web 服务,我们需要创建请求和响应消息。在“业务流程视图”窗口中创建名为 msgReq
和 msgResp
的消息。对于请求消息,从“Web 消息类型”中选择“BTSOrderQuery.localhost.OrderQuery_.GetOrders_request
”作为其“消息类型”属性。对于响应消息,从“Web 消息类型”中选择“BTSOrderQuery.localhost.OrderQuery_.GetOrders_response
”作为其“消息类型”属性。调用 Web 服务所需的另一个步骤是在业务流程中创建 Web 端口。将“端口”形状从工具箱拖到端口平面区域的右侧。在端口创建向导中,单击“下一步”。键入“wsLegacy
”作为端口名称,然后单击“下一步”。在下一个屏幕中,选择“使用现有端口类型”,展开“Web 端口类型”并选择“BTSQuery.localhost.OrderQuery_.OrderQuery
”。单击“下一步”两次,然后单击“完成”。
现在让我们向业务流程添加一些形状。将“消息构造”形状拖到业务流程中,并选择“msgReq
”消息作为要构造的消息。将“消息赋值”形状拖到构造形状内,并在其中键入以下表达式
msgReq.date = dtOrder;
这将创建一个请求消息,其中包含作为参数接收的订单日期。现在将发送形状拖到消息构造下方,并选择“msgReq
”作为其消息。将发送形状链接到端口表面区域右侧的 Web 端口。将接收形状拖到发送形状下方,并选择“msgResp
”作为其消息。也将其链接到 Web 端口(在响应槽中)。
使用端口参数
现在我们需要将响应发送回主业务流程。为此,我们将使用端口参数。选择“新建配置端口参数”,在第一个屏幕上单击“下一步”。在下一个屏幕上,选择 spOrders
作为端口参数名称,然后单击“下一步”。在下一个屏幕上,选择“使用现有端口类型”选项,并选择“BTSOrderQuery.rpOrdersType
”作为端口类型。现在,单击“下一步”。在下一个屏幕上,将“端口方向”选项更改为“我将始终从该端口发送消息”。
将端口作为参数传递给另一个业务流程是唯一可以更改端口“极性”的有效情况,将其从接收端口更改为发送端口。这里使用的概念与回调函数非常相似。我们将主业务流程的接收端口传递给特定业务流程(回调函数)。当特定业务流程完成其工作时,它会将响应发送到作为参数接收的端口(调用回调函数以通知调用者)。
将发送形状拖到业务流程中最后一个接收形状下方,并选择 msgResp
作为其消息。将此形状连接到作为参数接收的端口(spOrders
)。在此过程结束时,您的业务流程应如下图所示
最后步骤
唯一缺少的是主业务流程中特定形状(启动业务流程形状)的一个属性。打开主业务流程并找到启动业务流程形状。在“调用业务流程”属性中,选择“BTSOrderQuery.BTSQueryLegacy
”。在“参数”选项中单击 (...) 按钮。将打开一个新窗口,现在设计器可以传递所需的参数。只需单击“确定”关闭对话框。
为了测试我们的解决方案,您需要为 Biztalk 程序集创建一个强名称。您可以使用 sn.exe 工具来完成此操作。完成此操作后,将解决方案部署到您的 Biztalk Server,然后使用 FILE 适配器创建接收和发送端口以测试我们的解决方案。我使用以下消息测试了解决方案
<ns0:OrderRequest xmlns:ns0="http://nwtraders">
<StartDate<1996-07-04T00:00:00.000-00:00</StartDate>
<EndDate<1996-07-10T00:00:00.000-00:00</EndDate>
&</ns0:OrderRequest>
结果
如果您将测试消息放入文件接收端口(您可以使用 1996 年 7 月 1 日至 1996 年 7 月 30 日之间的任何日期),Biztalk 将在输出文件夹中放置一条包含合并结果的消息。如果您在文件删除时检查 Health and Activity Monitoring (HAT),您会看到主业务流程确实为您的订单查询请求中的每个日期生成了另一个业务流程,如下图所示
这就是您如何使用 Biztalk 进行异步调用。使用两个业务流程并将端口作为参数传递解决了所有问题。希望您喜欢这篇文章!:)