Вы находитесь на странице: 1из 55

Module 15: Implementing Messaging Patterns

Time estimated: 105 minutes

Module objective: In this module, you will learn how to make use of additional features of BizTalk orchestrations to implement commonly used messaging patterns.
Module Overview

By gaining a deeper understanding of the features of BizTalk orchestration ports, you can design and implement more flexible messaging patterns to meet the needs of a wider array of business scenarios. This module examines the different styles of bindings that can be applied to orchestration ports. It also revisits correlation, focusing on special cases called convoy messaging patterns that arise when an orchestration is designed to receive multiple related messages.

Lesson 1: Creating Adaptable Orchestration Ports

Lesson objective:
Applying dynamic binding to orchestration ports opens new design possibilities.
Lesson Overview

BizTalk server offers five different types of port bindings that you can specify in the BizTalk Orchestration Designer. Each style of binding offers a unique set of benefits. Previous modules have covered the Specify Now and Specify Later binding types. This lesson focuses on the additional types: Dynamic, Direct and Role Links. Dynamic Binding allows you to set send port configuration settings at runtime. It accommodates scenarios in which the destination URL for a message is not known at design time. Direct Binding provides a means for orchestration ports to define custom subscriptions, opening up the possibility of communicating between orchestrations without requiring physical ports to pass the messages between them. Role Links provide a way to maintain sets of physical send and receive ports that are assigned to trading partners. Role links enable reuse of common orchestrations, making it easier to accommodate a growing number of trading partner systems.

Configuring Port Properties at Runtime

Send port configuration settings are specified at runtime.


Overview

Dynamic port binding is fairly straightforward. In this case, the orchestration is bound to a minimally configured physical send port. At runtime, the orchestration passes configuration settings as context properties of each outbound message. The settings are applied to the physical send port configuration immediately before the message is transmitted. The orchestration relies on application code to determine the send port configuration settings. The URL and settings might come from different sources, which could include a business rule, a database query, or it might even come within the content of an inbound message (e.g. a confirmation might be sent to an email address that which is provided in a purchase order message).

Communicating between Orchestrations

The three direct binding types each offer different benefits.


Overview

Applying direct binding to orchestration ports opens up possibilities that are not available with the other types of binding. Direct binding allows you to send messages to other orchestrations, while retaining the option of sending messages to physical send ports. With direct binding you can design extensibility in to your BizTalk applications. By designing your applications to maintain loose coupling between systems, you can minimize the impact required to integrate with future systems. BizTalk offers three styles of direct binding. MessageBox, Self-Correlating, and Shared Ports. MessageBox. Binding an orchestration port directly to the MessageBox offers the most flexibility amongst all of the binding styles. Directly binding to the MessageBox provides both publishers and subscribers with complete control over their interactions with a messages context properties. Consequently, rather than having to deal with fixed subscription patterns, BizTalk application designers can work at a higher level of abstraction and increase the potential for loose coupling and greater maintainability. Self-Correlating Ports. Direct binding with a self-correlating port imposes constraints that are not present when binding directly to the MessageBox, but this approach can be easier to work

with, since some of the subscription details are handled by the BizTalk runtime. In this case, one orchestration passes a port object to a second orchestration which uses the port to send messages back to the first orchestration. Shared Ports. The third direct binding option, shared ports, impose further constraints, but they offer a convenient method to implement communication between orchestrations. In this case, you configure the shared port in the port settings in the Orchestration Designer, and the compiler and BizTalk runtime handle the subscription details.

Direct Binding with the Message Box

Direct binding to the MessageBox is the most powerful option. Use it carefully.
Overview

Direct binding with the MessageBox provides unobstructed access to BizTalks publish-subscribe architecture. MessageBox direct bound ports enable an orchestration to drop messages directly into the MessageBox database without an explicit recipient, and to subscribe to messages that meet certain criteria rather than only messages that come from a particular sender. BizTalk application designers can take advantage of this binding style to create more flexible and reusable systems. Promoting the right properties, and setting up the filters is the hardest part of working with this style of binding. There can be any number of subscribers for any published message, and if there are no subscribers interested in the message at the time that it is the BizTalk runtime will throw an exception in the orchestration. Any orchestration that includes send ports bound directly to the MessageBox should implement an exception handler to account for that possibility.
Caveat

Also, think carefully about subscription filters when binding a port directly to the MessageBox, it can be easy to accidentally create a subscription filter that recursively creates orchestration instances.

An orchestration, for example, might publish a message that matches its own subscription filter. If such an orchestration receives a PurchaseOrder and later publishes a copy of the PurchaseOrder directly to the MessageBox, then a new instance of the same orchestration, along with all of the other PurchaseOrder message subscribers, will be activated to process the new copy of the message. The cycle will repeat until BizTalk runs out of resources to process the unintended orchestration instances.

Direct Binding with Self Correlation

Direct binding with self-correlation off-loads some of the correlation details to the BizTalk runtime.
Overview

Using direct binding with self-correlating ports is not as flexible as binding to the MessageBox, but it makes it easier to get the subscriptions right. The BizTalk runtime handles more of the subscription details in this case. You set up a self-correlating port by using the Orchestration Designer to configure one orchestration to start another orchestration, passing a port as a parameter. The second orchestration can use the port to send messages back to the first orchestration. Other than passing the port as a parameter in the start shape, self-correlating ports hide most of the details of the direct binding. The BizTalk runtime handles the message correlation behind the scenes with a custom correlation token that is generated by the orchestration engine. In the event that the second orchestration implements a commonly used business process, such as a credit card authorization, the option remains open for other orchestrations to make use of it by starting new instances, and passing ports of their own. The only stipulation is that the port being passed must match the parameters type definition.

Direct Binding with Shared Ports

Direct binding with shared ports hides most of the correlation details.
Overview

Direct binding with shared ports fully encapsulates the details of the underlying message correlation. imposes further constraints beyond those of self-correlation. This binding style imposes further constraints beyond those of self-correlation. All of the direct binding details are established up-front when a shared port is defined in the Orchestration Designer. When defining a shared port, you need to specify the intended sending orchestration, or the intended receiving orchestration of a message that is to be passed through the MessageBox.

Assigning Ports to Trading Partners

Role Links offer the ability to share a common business process amongst different trading partners.
Overview

When working with multiple trading partners, you probably will not be able to use the same physical send port to communicate with the entire group. You could, of course, use dynamic ports to configure URLs and other details, but that approach would most likely pose maintenance issues as the number of trading partners grows. Role links allow you separate the concerns of trading partner management and business process design. Using this approach, an orchestration has placeholders known as role links, that represent send and receive ports used to communicate with trading partners. At runtime, the orchestration specifies which trading partner it wants to communicate with, and the trading partner management system takes care of the rest. The orchestration provides an identifier, known as an alias, in a messages context, and the trading partner management system performs a look-up to determine the trading partner, and the corresponding physical send port. With role links in place, business analysts can manage trading partners, and developers can focus on developing a common implementation of the business process.

Parties. Parties are all the entities outside of BizTalk Server that interact with an orchestration. All of the partners that your organization deals with are considered parties, and your organization may have several thousand partners. The BizTalk Administration Console has a user interface that can be used to manage parties. Roles and party enlistment. Parties interact with orchestrations through roles. During development, you do not need to specify the actual party that the orchestration may interact with. An example of a role that an orchestration might use would be a shipper. The shipper would have one or two parties associated with it. When the orchestration needs to decide which shipping company to use to ship an item, it can compare the prices of the parties in the shipper role. Party enlistment is the mechanism that ties a party to a role. In BizTalk Explorer, you can enlist a party in a role, and that will enable the orchestration to interact with the party. In the example shown on the slide above, SpeedyExpress is an enrolled party in the ShipperRole of the Ordering orchestration. At runtime, the orchestration determines which shipping party should handle this order, and the Trading Partner Management system looks-up the role link to determine that the message should be sent via the Ship_SpeedyExpress send port. Service Link Type. A service link type characterizes the relationship between two services or orchestrations by defining the part played by each of the services in the relationship and specifying the port types provided by each role. Aliases. Aliases refer to the same party by different names. An organization or unit may be known by its name, by a telephone number, by an e-mail alias, by a signature certificate, or by a DUNS Number (used in some protocols), depending on who is referring to it and what protocol pis being used. BizTalk Server provides the ability to store multiple aliases for a party. Every party is given a single default alias with a name of Organization, with a qualifier as OrganizationName and value of the name of the party. This alias is always treated as the default alias. Aliases are provided as triads of name, qualifier, and value. No two parties in the same BizTalk Configuration database can have the same qualifier value pair. The alias name is used merely for convenience. You define business relationships in the Orchestration Designer using role links that contain two roles. Each of these roles represents a partner in the business relationship the orchestration is implementing. For example, you might implement an automated purchasing relationship in a purchasing role link that contains both a buyer and a seller role. You use the role link to implement two different orchestrations for both sides of the transaction. For example, the orchestration representing the buyer process implements the buyer role and uses the seller role. Conversely, the orchestration representing the seller process orchestration implements the seller role and uses the buyer role. After you create these roles, an administrator can easily package the partner orchestration and associated information in a BizTalk application for quick deployment on a partner running BizTalk Server 2010.

Choosing Partners for Role Links

Orchestrations can depend on the Trading Partner Management system to handle the details of communicating with a particular partner.
Overview

An orchestration needs a way to indicate with which trading partner that it needs to communicate. It can indicate a given trading partner to the Trading Partner Management runtime by setting a property on a role link. Since trading partners are identified by one or more aliases, the orchestration simply specifies an alias value, and which type of alias it is using. The alias must correspond to a value that a business analysts has entered using the Trading Partner Management user interface, which is provided by the BizTalk Administration Console. BizTalk Server 2010 defines the new B2B Operator Windows group that a system administrator can apply when granting access to users who need to maintain Trading Partner Management information. On the receive side, the party resolution pipeline component can use identifiers in an inbound message to attempt to identify a trading partner that is sending the message to BizTalk. The receive port accepting the message needs to have authentication enabled, and therefore the needs host to be configured as trusted.
Consumers and Providers

A role link has a SourceParty property, a DestinationParty property, and an initiating role. An initiating role is the role on which the first communication occurs, and which therefore initiates the role link by setting the value of the DestinationParty property. If the initiating role is a consumer for sending messages, you explicitly set the DestinationParty property (once and only once) in your orchestration. To do so, you set the value of the DestinationParty in the Expression shape, as in the following example, where ConfirmOrder is the name of a role link, and PartnerName and OrganizationName are parameters of a party:
ConfirmOrder(Microsoft.XLANGs.BaseTypes.DestinationParty) = new Microsoft.XLANGs.BaseTypes.Party("SpeedEx", "OrganizationName");

If the initiating role is a provider for receiving messages, the DestinationParty property is initialized automatically by the receiver. The DestinationParty is set to the provider itself. The SourceParty property is read-only, and is supplied by the party resolution pipeline component based on the security identifier (SID) of the sender or on a certificate associated with the party. The host running the pipeline component must be marked as Authentication Trusted. You can get the value of the SourceParty in the Expression shape by using the following sample code:
PartyName = Buyer_Supplier(Microsoft.XLANGs.BaseTypes.SourceParty);

Dynamic Binding Options

Dynamic binding offers benefits that Specify Now and Specify Later cannot provide.
Overview

To summarize the various dynamic binding options that BizTalk offers: Dynamic addressing relies on a predetermined subscription, but leaves options open for configuration of a physical send port. Direct binding to the MessageBox addresses the creation of subscriptions at a more abstract level. Binding directly to the MessageBox offers the most flexibility. An orchestration can decide at runtime which message context properties it wants to set for each message. This binding style is very powerful, but application designers need to think carefully about how to ensure that messages are delivered correctly. Self-correlating ports are more tightly coupled than binding directly to the MessageBox, but an orchestration can still choose at runtime from amongst a number of different orchestrations to start. It could starting more than one if necessary. This binding style makes it easier to ensure that message is delivered correctly.

Shared ports are the least flexible of the direct binding options, but they are also the easiest to set up. With this binding style, the correlation and subscription details are hidden by the designer and runtime. Role Links offer a form of dynamic binding that address the specific use case of managing subscriptions on the behalf of individual trading partners.
Conclusion

Although a message appears to go directly from one orchestration to another with direct binding, any message sent through any type of logical port always travels through the MessageBox database. Moreover, direct bound ports are only logical ports and therefore direct binding is only a design-time configuration feature. A direct bound port cannot be bound to a physical port, and you can only change the direct binding configuration at design time. One thing to keep in mind with these direct messaging options, as well as using the Start orchestration shape to asynchronously start an orchestration, is that they all use the underlying publish and subscribe model. The difference between these options is in the properties that are used for creating subscriptions and routing, and in the use cases they help solve.

Demonstration: Configuring Dynamic Ports

Learn to apply dynamic addressing and role links.


Install the Sample Application

1. In Windows Explorer, navigate to C:\AllFiles and double-click startBtServices.cmd. 2. Then, navigate to C:\AllFiles\DemoCode\Module15, and double-click SetupDynamicPorts.cmd. 3. Verify that the installation completed successfully, then close the command window.
Review the Flow of the OrderProcessing Orchestration

1. In Windows Explorer, navigate to C:\AllFiles\DemoCode\Module15\DynamicPorts and open DynamicPorts.sln. 2. In Solution Explorer, double-click the OrderProcessing.odx orchestration. This orchestration will receive an order message and branch based on the country of the shipping destination. If the shipping destination is within the UK, then the orchestration creates a shipping message, selects a trading partner to handle the shipping, and sends the shipping message. If the shipping destination is outside of the UK, then the orchestration will create a billing message, and send it to the billing department.

Examine the Dynamic Binding of the Billing Port

1. Within the ConstructBillingMessage shape, double-click the MessageAssignment shape. This Message Assignment shape copies the OrderMessage to the BillingMessage, including all of the message context properties. Then it dynamically configures the send port by setting message context properties on the BillingMessage. Notice that the first four message context properties begin with the prefix SMTP. This shape assumes that the billing message will be sent with the SMTP adapter, so it initializes a set of properties to configure an email with the billing message as an attached file. The last three message context properties configure the details of the attachment. 2. Click Cancel to close the BizTalk Expression Editor. 3. Double-click the SetDynamicAddress Expression shape. This Expression shape sets the destination URL for the billing message. In this case, the URL begins with the mailto prefix. The BizTalk runtime uses the URL prefix to determine which adapter it should use to send the message. Had the URL begun with a different prefix, like ftp, the previously configured SMTP context properties would be ignored. 4. Click Cancel to close the BizTalk Expression Editor. 5. Double-click the BillingPort shape, and in the Port Configuration Wizard, click Next three times to advance to the Port Binding page. Notice that this port is configured to send messages, the Port binding is Dynamic, and the Send pipeline is PassThruTransmit. 6. Click Cancel to close the Port Configuration Wizard.
Examine the Role Link of the Shipping Port

1. In the IsUK branch of the Decide shape, double-click the SelectParty Expression shape. Notice that this Expression shape does not set an address. Instead, it simply sets the DestinationParty property on the ShipperRole role link. The orchestration is relying on the BizTalk runtime to look up the corresponding physical send port to send a shipping message to this party. Parties are configured in the BizTalk Administration Console. Notice that the DestinationParty property is a key-value pair. In this case, the BizTalk runtime will look for a party with an OrganizationID of UP. 2. Click Cancel, then click the ShipperRole shape. The Shipper Role Link consists of a provider and a consumer. In this case, the orchestration is sending out a message first, so it acts as a provider. You can assign an orchestration send port to a role link by simply dragging and dropping the send port from the port surface to the role link shape. Notice that the ShipperPort is now simply specified as a ShippingPortType. The actual port will be assigned at runtime.
Examine the Role Link Configuration in the BizTalk Administration Console

1. In the BizTalk Administration console, under the Demos.Northwind application, click on the Role Links icon, and then in the right pane double-click Provider.

Notice the title at the top of the right-hand pane. This is where you will assign the shipper send ports to their corresponding parties. If you had defined other role link types in the orchestration, they would be configured separately. 2. Click the Unenlist button twice. 3. Click the Enlist button. 4. In the Enlist Parties dialog box, check the Federal Shipping and United Package check boxes, and then click OK. 5. In the Provider Role Link Properties dialog box, click Federal Shipping, and then click the Bind button. 6. In the Send Port list, select Shipper_FederalShipping, and then click OK. This list displays the one-way send ports that are associated with the Federal Shipping party. 7. In the Provider Role Link Properties dialog box, click United Package, and then click the Bind button. 8. In the Send Port list, select Shipper_UnitedPackage, and then click OK. This list displays the one-way send ports that are associated with the United Package party. 9. Click OK to close the Provider Role Link Properties dialog box. 10. In the left pane of the BizTalk Administration Console, click Send Ports. Notice that Shipper_FederalShipping and Shipper_UnitedPackage are simply standard ports. 11. In the left pane of the BizTalk Adminstration Console, click Parties. 12. Expand the United Package party, and double-click United Package_Profile, then in the left pane click Identities. Notice that the United Package party has an alias named OrganizationId, with the value UP. This is the alias that the orchestration used to identify this party. The Federal Shipping party has an alias named OrganizationId, with the value FS. You can add as many aliases as you need to identify a party. Examples include a D-U-N-S number, a banking number, an EIN number, or a custom identifier. 13. Click Cancel. 14. Double-click United Package, then in the left pane of the Party Properties dialog box, click Send Ports to view the ports that are assigned to the United Package party. 15. Click Cancel.
Run the Orchestration

1. In Windows Explorer, navigate to C:\AllFiles\DemoCode\Module15\DynamicPorts, and drop a copy of the ExternalOrder.xml message in C:\AllFiles\DemoCode\Northwind\Ports\FileIN. This message represents an order that is to be shipped within the UK.

2. Verify that an XML message appears in the C:\AllFiles\DemoCode\Northwind\Ports\Shippers\UnitedPackage folder. 3. Drop a copy of the ExternalOrder_NonUK.xml message in to the C:\AllFiles\DemoCode\Northwind\Ports\ FileIN folder. 4. Verify that an email message appears in the C:\inetpub\mailroot\drop folder. 5. Double-click the .eml file and notice that the billing message is attached. 6. Pause the bt10d-demo virtual machine.

Lesson 2: Receiving Multiple Related Messages

Lesson objective:
Simple correlation will break down when BizTalk receives multiple related messages simultaneously.
Lesson Overview

Correlation addresses the issue of handling subscriptions when an orchestration needs to process messages that are related to one another. Correlation was introduced in Module 9, Automating Business Processes. Simple correlation, however, is not sufficient in all cases. It is possible to encounter situations in which simple correlation breaks down, and the runtime needs to step in and coordinate at a higher level. This lesson covers these special cases, which are known as convoys.

How Correlation Works

The BizTalk runtime handles correlation by creating fine-grained subscriptions on the fly.
Overview

Correlation in orchestrations is the mechanism that enables an orchestration to receive related messages in to the same running instance. In the case of simple correlation, an orchestration sends out a message and waits for a corresponding response. Under these circumstances, the BizTalk runtime needs to watch for a specific message to return back to the orchestration. Here, the BizTalk runtime relies on the orchestration to provide a set of message context values, known as a correlation set, that it can use to create a fine-grained subscription to pick up the response message intended for the orchestration. When the matching response message arrives, the runtime delivers the message to the orchestration to continue processing, and the runtime drops the subscription.
Correlation Types and Correlation Sets

A Correlation type in an orchestration defines the set of context properties that will be used to create a subscription. A correlation set is a variable that holds instance values at runtime. The orchestration populates the set by initializing the correlation set on a send or receive shape.

Using correlation sets, the BizTalk orchestration runtime can create the very fine grained subscriptions to ensure that a message can be routed to the proper instance of an orchestration.

Orchestration Subscriptions

Activation subscriptions create a new instance of an orchestration. Instance subscriptions direct messages to an orchestration that is already running.
Overview

In BizTalk Server, there are two main types of subscriptions: activation and instance. An activation subscription is one specifying that a message that fulfills the subscription should activate, or create, a new instance of the subscriber when it is received. Examples of things that create activation subscriptions include send ports with filters or send ports that are bound to orchestrations, and orchestration receive shapes that have their "Activate" property set to true. An instance subscription indicates that messages that fulfill the subscription should be routed to an already-running instance of the subscriber. Examples of things that create instance subscriptions are orchestrations with correlated receives and request/response-style receive ports waiting for a response from BizTalk Server. Instance subscriptions are created for receive shapes that are following a correlation set, and they include the specific values that are included in the correlation set when it is initialized. The subscriber ID includes the orchestration instance ID. Instance subscriptions come into play when a correlation set is initiated, as this is when subscriptions are created for all of those ports that follow this correlation set to receive messages. Because the correlation type defines the properties to be used for correlation, the

orchestration engine can extract these properties from the message being sent or received by the initiating action. These values are then used to define subscriptions for all of the remaining actions which follow this correlation set.

Convoy Messaging Patterns

An orchestration needs the BizTalk runtime to provide additional coordination in certain cases.
Overview

Under certain conditions, an orchestration instance might receive a group of correlated messages all at the same time. In this situation, a race condition might occur, in which one of the messages in the group must initialize a correlation set in the orchestration instance before the other messages can be correlated to that orchestration instance. A convoy exists any time in which the BizTalk runtime must handle multiple related messages that could cause a race condition within an orchestration instance. Convoy patterns are correlation use cases that require special handling. In these cases, simple correlation would break down and route messages incorrectly. When dealing with convoy patterns, the runtime needs to step in to coordinate at a higher level. The Orchestration Designer recognizes convoy patterns, and it enforces constraints required by the BizTalk runtime to handle the convoy messages correctly. BizTalk handles convoy subscriptions differently than it handles other types of instance subscriptions to determine if a message should be sent to a new instance, or to a running instance.

To ensure that all of the correlated messages are received by the same orchestration instance, BizTalk Server detects the potential for such a race condition and treats these messages as a convoy. At enlistment, the runtime creates a general subscription and identifies it as part of a convoy. After filling this subscription, the messaging engine creates a temporary subscription based on the values in the predefined correlation properties. All subsequent messages that match the general subscription are evaluated against the temporary subscriptions, and those that match are routed to an existing orchestration. There are two main types of convoys: sequential convoys and parallel convoys. The main difference in the two types of convoys is the order of receipt of the items. Sequential Convoys are sets of related items that have a predefined order. The items do not have to be exactly the same, but they are all related to a specific instance of a business process. Parallel Convoys enable a business process to wait for a set of messages of different types to arrive in any order before continuing to process.
Zombie Messages

The use of convoys can result in "lost" messages which are known as zombie messages. When a non-activating receive subscription in a running orchestration matches a message in the MessageBox database, then the BizTalk runtime is obligated to deliver the message to the orchestration. Because the MessageBox does not know the business logic inside the orchestration, it simply delivers all of the messages that match the subscription to the orchestration. If any of these messages are delivered when the orchestration execution flow has passed all of the corresponding receive shapes, then the messages are suspended, becoming zombie messages. An example of a situation that creates zombies is a receive inside a loop that iterates 17 times, but 18 messages are delivered that match the receive subscription in the loop. (The MessageBox does not know that the orchestration logic only handles 17 messages.) The 18th message delivered is not consumed by the orchestration because execution flow has already exited the loop. The orchestration is completed with discarded messages (zombies), which are not resumable because the orchestration instance has already completed. You can manage zombies by using a Windows Management Instrumentation (WMI) script to query the instances with the "Suspended-NonResumable" state. In addition, the messaging engine writes an error message, "Completed with discarded messages", to the event log.

Sequential Convoys

Sequential convoys allow an orchestration to receive multiple related messages in series.


Overview

A sequential convoy occurs when multiple, related messages arrive in a series. In this case, you will need to know at design time, which type of message will arrive first. Subsequent messages do not need to be of the same time, but they will need to be correlated, and they are required to arrive through the same receive port. Since multiple messages could arrive simultaneously, the runtime needs to ensure that it takes additional precautions to handle the instance subscriptions. There are two sub-types of sequential convoys: uniform sequential convoys and non-uniform sequential convoys.
Uniform Sequential Convoy

A uniform sequential convoys consists of an orchestration receiving a series of related messages that are all of the same type. Uniform sequential convoys are handled with a single receive port having a single operation that represents a particular message type.
Non-Uniform Sequential Receives

A non-uniform sequential convoys consists of an orchestration receiving a series of related messages that may be of different types. An orchestration might, for example, receive an order header, followed by a number of related line item messages. Non-uniform sequential convoys are handled with a receive port that has multiple operations, with each operation representing a different message type.

Implementing Sequential Convoys

The sequential convoy pattern is easy to implement in the Orchestration Designer.


Overview

Determining the correct loop condition is a key part of the design of a convoy. When is it okay to break out of the receive cycle and move on with the processing?
Uniform Sequential Receives

To build a business process to handle this kind of messaging pattern, you place two successive Receive shapes into the orchestration. These must both receive the same message type from the same port. If the first Receive shape is the first shape in the orchestration, you need to set its Activate property to "True. The first Receive shape must also initialize a correlation set used for the subsequent Receive shape. The second Receive shape must follow this correlation set. A common implementation of this design pattern is in a batching scenario. This positions the second Receive shape inside a Loop shape to enable receipt of many additional messages by the business process.
Non-Uniform Sequential Receives

To implement this message pattern in a business process, position multiple Receive shapes in order inside the orchestration. If the first Receive shape is the first shape in the orchestration, you need to set its Activate property to "True. The first Receive shape in the convoy initializes a

correlation set followed by all subsequent Receive shapes. The individual messages must all originate from the same port and this port must be marked for ordered delivery. The individual message types are each associated with a separate operation inside the port.

Parallel Convoys

Parallel convoys support allow an orchestration to receive a fixed number of messages in any order.
Overview

A parallel convoy occurs any time on orchestration will wait for a known quantity of related messages that may arrive in any order. The messages may be of different types, and may arrive through one or more ports. An example would be a hospital admissions process in which an admissions message, a medical records message and a room assignment message must arrive before the business process can proceed.

Implementing Parallel Convoys

The Orchestration Designer makes it easy to implement parallel convoys.


Overview

In order to handle a parallel convoy inside an orchestration, you must use the Parallel Action shape. Add a Receive shape to each parallel branch in the shape, one for each message that you must receive. If the Parallel Action shape is the first shape in the orchestration, all of the Receive shapes inside the Parallel Action shape must have their Activate property to "True. The incoming messages may be received from different ports and be of different types. Use a correlation set to relate all the incoming messages together. Each of the Receive shapes inside the Parallel shape must initialize the correlation set.

Demonstration: Implementing Convoy Patterns

Learn to implement a non-uniform sequential convoy and a parallel convoy.


Install the Sample Application

1. Resume the bt10d-demo virtual machine. 2. In Windows Explorer, navigate to C:\AllFiles\DemoCode\Module15, and double-click SetupConvoySamples.cmd. 3. Verify that the installation completed successfully, and that it un-enlisted the ParallelConvoy orchestration, then close the command window.
Examine a Non-Uniform Sequential Convoy

1. In Windows Explorer, navigate to C:\AllFiles\DemoCode\Module15\ConvoySamples, and then double-click ConvoySamples.sln. 2. In Solution Explorer, double-click SequentialSample.odx to open the orchestration. 3. Click the Receive_InitialBill Receive shape. Notice that its Activate property is true. BizTalk will create a new instance of this orchestration when it receives a new billing message that is not related to any other billing messages being processed. 4. Click the Send_InitialAudit Send shape.

This Send shape simply sends a message to the AuditPort to allow us to see the sequence of messages that the orchestration is processing. 5. Click the Loop shape. The orchestration will loop, listening for billing and shipping messages. If it receives a billing message, it will send the message to the audit port, and then listen for another message. 6. Double-click the Done Expression shape. If the orchestration receives a shipping message, it will send the message to the audit port, set a flag to end the loop, and the orchestration will complete. 7. Click Cancel, then click the Receive_InitialBill Receive shape. Notice that this Receive shape initializes SeqCustomerCorrelation. 8. Click the Receive_BillUpdate Receive shape Notice that this Receive shape follows SeqCustomerCorrelation, and that its Activate property is false. 9. Click the Receive_Shipping Receive shape Notice that this Receive shape follows SeqCustomerCorrelation, and that its Activate property is false. When BizTalk receives a new message at the Receive_InitialBill shape, it will create two new instance subscriptions, one to listen for billing messages that correlate to the initial bill, and another to listen for shipping messages that correlate to the initial bill.
Run the Sequential Convoy Orchestration

1. In Windows Explorer, navigate to C:\AllFiles\DemoCode\Module15\ConvoySamples\Instances, and copy the BillingRequest_1.txt file to C:\AllFiles\DemoCode\Northwind\Ports\FileIN. 2. In the BizTalk Administration Console, click on BizTalk Group, and then in the center pane, click the Group Hub tab. 3. Press the F5 key to refresh the page, and notice that there is one Running service instance. 4. Click the Running service instances link. 5. In the bottom pane, double-click the highlighted service instance to view the details. 6. Click OK. 7. In Windows Explorer, copy the BillingRequest_2.txt through BillingRequest_4.txt files to C:\AllFiles\DemoCode\Northwind\Ports\FileIN. 8. Navigate to C:\AllFiles\DemoCode\Northwind\Ports\Audit, and notice that there are four billing messages so far.

9. In the BizTalk Administration Console, in the center pane, on the Running tab, click Run Query, and notice that the instance of the SequentialSample orchestration is still running. The service instance status will show either Active or Dehydrated. If the orchestration is Dehydrated, it is still running, even though BizTalk has dropped the orchestration object from memory while it waits for more messages. 10. In Windows Explorer, copy the OrderShipping.xml file from C:\AllFiles\DemoCode\Module15\ConvoySamples\Instances to C:\AllFiles\DemoCode\Northwind\Ports\FileIN. 11. Navigate to C:\AllFiles\DemoCode\Northwind\Ports\Audit, and notice the shipping message appears. 12. In the BizTalk Administration Console, in the center pane, on the Running tab, click Run Query, and notice that the instance of the SequentialSample orchestration has completed.
Demonstrate the Zombie Message Condition

1. In Windows Explorer, delete all of the messages in the C:\AllFiles\DemoCode\Northwind\Ports\Audit folder. 2. In Windows Explorer, navigate to C:\AllFiles\DemoCode\Module15\ConvoySamples, and double-click CopyAllMessages.cmd. The CopyAllMessages.cmd script copies one billing message to initiate an instance of the SequentialSample orchestration. 3. Press any key to copy the remaining billing messages and the shipping message. 4. Navigate to C:\AllFiles\DemoCode\Northwind\Ports\Audit, and notice that some number of messages appear, but not all of the messages were processed. There is a chance that all of the messages could have made it through the orchestration. If that happens, restart at step 1. 5. In the BizTalk Administration Console, in the center pane, on the Running tab, click Run Query, and notice that the instance of the SequentialSample orchestration is not listed. 6. Click the New Query tab, and in the Search For / Value list, select Suspended Service Instances, and then click Run Query. 7. Double-click the orchestration in the query result, and then click on the Error Information tab. The Error Description is The instance has completed without consuming all of its messages. The instance and its unconsumed messages have been suspended. 8. Click the Messages tab. In the Messages referenced by the service instance list, you will see billing messages that had been published to the message box, but were not processed by the orchestration. In this case, the orchestrations instance subscription for billing messages had existed when these messages were published to the message box, but when they

were to be delivered to the orchestration, the subscription was no longer in effect because the orchestration had already processed a shipping message, and had then completed. BizTalk had picked up the shipping message from the file system at the same time that it had picked up the remaining billing messages. These unconsumed messages are called zombie messages, and they are a known side effect of convoys. The possibility of zombie messages always exists when messages are submitted to BizTalk convoy over a transport that does not support ordered delivery. You can find more information on zombie message in BizTalk Server help where the condition is well documented. 9. Click OK. 10. Select all of the items in the query result, right-click on the selection and click Terminate Instances, then click Yes, and then click OK. 11. Click Run Query to verify that the service instances were terminated.
Examine a Parallel Convoy

1. In Visual Studio, in Solution Explorer, double-click ParallelConvoy.odx to open the orchestration. Notice that the Receive_Billing shape, and the Receive_Shipping shape are placed within a Parallel Actions shape. The Parallel Action shape is implemented specifically to handle parallel convoys. 2. Click the Receive_Billing Receive shape. Notice that its Activate property is true, and that it initializes CustomerCorrelationSet. 3. Click the Receive_Shipping Receive shape. Notice that its Activate property is also set to true, and that it also initializes CustomerCorrelationSet. Since either receive shape can activate a new instance of this orchestration, BizTalk can handle the arrival of these messages in any order. 4. Right-click the Parallel Action shape, then click New Parallel Branch. 5. Notice that it is possible to add additional branches that handle the arrival of additional types of messages. 6. Right-click the empty parallel branch, and then click Delete.
Run the Orchestration

1. In the BizTalk Administration Console, under the Demos.Northwind application, click Orchestrations. 2. Right-click the ConvoyOrchestrations.SequentialSample, and then click Unenlist. 3. Right-click the ConvoyOrchestrations.ParallelConvoy, and then click Start. 4. In Windows Explorer, delete all of the messages in the C:\AllFiles\DemoCode\Northwind\Ports\Audit folder.

5. In Windows Explorer, navigate to C:\AllFiles\DemoCode\Module15\ConvoySamples\Instances, and copy the BillingRequest_1.txt file to C:\AllFiles\DemoCode\Northwind\Ports\FileIN. 6. Navigate to C:\AllFiles\DemoCode\Northwind\Ports\Audit, and notice the message was processed. 7. In the BizTalk Administration Console, click BizTalk Group, then in the center pane, click the Group Hub tab, and then press the F5 key. 8. Click the Running service instances link, and notice that an instance of the ParallelConvoy orchestration is running. 9. In Windows Explorer, copy the OrderShipping.xml file from C:\AllFiles\DemoCode\Module15\ConvoySamples\Instances, to C:\AllFiles\DemoCode\Northwind\Ports\FileIN. 10. In the BizTalk Administration Console, in the center pane, on the Running tab, click Run Query, and notice that the instance of the ParallelConvoy orchestration has completed. 11. Repeat steps 4 11, but copy the OrderShipping.xml file in step 4, and copy the BillingRequest_1.txt file in step 9. 12. Shut down the bt10d-demos virtual machine.

Lab: Implementing Dynamic Messaging Patterns

Time estimated: 45 minutes Overview

In this lab you will update the Northwind ordering process to make the orchestration messaging more dynamic and add support for correlation. You will use role links to provide partner specific sending and receiving and add dynamic links to support a publish and subscribe messaging model for you orchestrations. In addition, you will use correlation to route related messages to an orchestration instance.

Start the Virtual Machine

Procedure List 1. If the Server Manager window is not already open, click on the Server Manager icon located in the task bar next to the Start button. 2. Expand Roles, Hyper-V, Hyper-V Manager. The last node to appear displays the machine name. Click on it to see the list of virtual machines available. 3. Double-click the virtual machine bt10d-15 to open a Virtual Machine Connection window. 4. Click on the Action menu in the Virtual Machine Connection window and choose Start. 5. Once the virtual machine starts, press CTRL+ALT+END. 6. Log on using the user name Administrator and the password pass@word1. 7. At the Windows Activation prompt, click Ask Me Later, then click OK.
Ensure that the BizTalk Services are started

Procedure List 1. In Windows Explorer, navigate to C:\AllFiles. 2. Double click startBtServices.cmd. 3. When prompted, press any key to close the command-line window.

Exercise 1: Use Correlation


Overview

In this part, you will message correlation to the order process. In this case, you will send a message from the order process to a shipping process, and get a response back for this particular order by correlating messages on the Order ID.
Examine the Shipping Orchestration

The shipping orchestration handles shipping requests and routes them to an appropriate shipper. Procedure List 1. In Windows Explorer, navigate to C:\AllFiles\LabFiles\Lab15\Northwind and open the Northwind.sln solution in Visual Studio. 2. Open the Shipping.odx and examine the orchestration. This orchestration receives a shipping request and then sends out a notice before replying with an acknowledgement. 3. Examine the MessageCreator.cs file in the Utilities project. This class is used by the shipping orchestration to create the acknowledgement message. It clones an XML document which contains a valid instance of the acknowledgement message type.
Set Up Schemas for Correlated Messaging

Procedure List 1. Open the MyProperties.xsd schema, and add a property named OrderIdentifier. 2. Save and close the property schema. 3. Open the ShippingRequest.xsd schema, expand the ShipRequest node and right-click the OrderID attribute and click Promote, then click Show Promotions. 4. Go to the Property Fields tab and add the Northwind.Schemas.MyProperties schema as a property schema. 5. Set the namespace prefix to prop and then add the OrderID attribute to the promoted properties. In the Property Fields list, in the Property list, select prop:OrderIdentifier. 6. Save and close ShippingRequest.xsd. 7. Repeat steps 3-5 above for the ShipmentID field in the ShipAck.xsd schema.

Add Shipping Artifacts to the Ordering Orchestration

Procedure List 1. Add the existing MapOrderToShipRequest.btm file from the C:\AllFiles\LabFiles\Lab15\Northwind\Artifacts directory to the Maps project. 2. Right-click on the Maps project and click Build. 3. Open the RouteOrder.odx orchestration. 4. In the Orchestration View, right-click the Messages node and add a new message. 5. Use the Properties window set the identifier of the message to ShipAcknowledgement. 6. Set the Message Type property by clicking Schemas, then click Northwind.Schemas.ShipAck. 7. Create another message named ShipRequest with a type of Northwind.Schemas.ShippingRequest.
Add Shapes to Communicate with the Shipping Orchestration

Procedure List 1. Delete the Shipping Destination? Decision shape. 2. Delete the ShippingUSASendPort and ShippingInternationalSendPort ports. 3. At the end of the RouteOrder orchestration add a Construct Message shape with a Transform and a Message Assignment shape inside of it. 4. Follow this by a Send shape and then a Receive shape. Set the properties as shown in the table below. Review the image that follows the table to see the intended outcome.

Property

Value Construct shape

Messages constructed Name

ShipRequest Construct ship request Transform shape

Name Map

MapOrderToShipRequest Northwind.Maps.MapOrderToShipRequest
Note: This map exists in the Northwind.Maps assembly.

Input Message Output Message

OrderMessage ShipRequest Message Assignment shape

Name Expression

AssignOrderID
ShipRequest(Northwind.Schemas.OrderIdentifier) = System.String.Format("{0:N}", System.Guid.NewGuid());

Send shape Name Message SendShipRequest ShipRequest Receive shape Name Message ReceiveShipAcknowledgement ShipAcknowledgement

5. In the orchestration view window, expand the Types node and right click Correlation Types, and then click New Correlation Type. 6. In the left pane, expand Northwind.Schemas, click OrderIdentifier then click Add, and then click OK. The Northwind.Schemas.OrderIdentifier property is now included in the correlation type. 7. Set the Identifier property on the correlation type to ShippingCorrelationType. You have defined a correlation type, which identifies which context properties will be used to correlate. In the next step, you will define a correlation set which is a container for specific data, based on this type. 8. Right click the Correlation Sets node to create a new correlation set. 9. Set the identifier property to ShippingCorrelation. 10. Set the correlation type to Northwind.Orchestrations.ShippingCorrelationType

11. On the SendShipRequest shape, set the Initializing Correlation Sets property to ShippingCorrelation. 12. On the ReceiveShipAcknowledgement shape, set the Following Correlation Sets to ShippingCorrelation. You have configured the two ports to participate in correlation. When a message is sent from the send port, it will initialize the correlation set with the values currently in the context properties. The receive shape that follows the correlation set will now have an instance subscription based on the correlation set values. 13. Right-click on the right-hand port surface, and click New Configured Port. 14. In the wizard, name the port ShippingPort and create a new port type named ShippingPortType. 15. In the next wizard pane, indicate that you will be sending messages and accept all other defaults. 16. Right-click on the right-hand port surface, and click New Configured Port. 17. In the wizard, name the port ShippingAckPort and create a new port type named ShippingAckPortType. 18. In the next wizard pane, indicate that you will be receiving messages and accept all other defaults. 19. Drag the connection points from the send and receive shapes to these new ports as appropriate.

Construct the Shipping Acknowledgement Message

Procedure List 1. Open the Shipping.odx orchestration, and inside the ConstructAck Construct Message shape, double-click the Create Ack Message Assignment shape. 2. In the BizTalk Expression Editor window, enter the following line of code, then click OK.
OrderShipAck = Northwind.Utilities.MessageCreator.CreateShipAck( OrderShipRequest(Northwind.Schemas.OrderIdentifier));

Build and Deploy the Solution

Procedure List 1. Right-click the Northwind solution, and then click Deploy Solution. The Northwind.Utilities project was already deployed to the GAC when you ran the original setup script for this lab.
Configure the Application Ports

Procedure List 1. Open the BizTalk Server Administration Console. 2. Right-click the Northwind application and click Import, then click Bindings.

3. Import the Northwind.Correlated.BindingFile.xml from the C:\AllFiles\LabFiles\Lab15\Northwind folder. 4. Examine the send and receive ports added to the application and view the configuration of the adapters. There are several File ports that will be used to send the messages between the orchestrations. 5. Right-click the Northwind application and choose Configure. 6. Configure the RouteOrder orchestration by binding the logical ports to the physical ports with the following mappings: Logical Port OrderReceivePort ShippingAckPort OrderBillingSendPort OrderAuditSendPort ShippingPort Physical Port Northwind_ReceiveOrders Northwind_ReceiveShipAck Northwind_SendToBilling Northwind_SendToAudit Northwind_ShipRequest

7. Configure the Shipping orchestration by binding the logical ports to the physical ports with the following mappings, and choosing the BizTalk Server Application as the host:

Logical Port ReceiveShippingRequestPort ShipperPort ShipAckPort

Physical Port Northwind_ReceiveShipping Northwind_SendShippingAudit Northwind_SendShippingAck

8. Both orchestrations should show green check marks when all of the configuration is complete. 9. Apply the changes and exit the configuration dialog.
Test the Solution

Procedure List 1. Right-click the Northwind application, and then click Start. 2. Copy the OrderExternal.xml file from the C:\AllFiles\LabFiles\Lab15 directory to the C:\AllFiles\LabFiles\Ports\OrderIN directory. 3. Open the C:\AllFiles\LabFiles\Ports\Audit directory and validate that the shipping notice arrives. 4. To view the detailed steps, disable the Northwind_ReceiveShipAck_File and Northwind_ReceiveShipping_File receive locations.

5. Submit a message, and you should find it waiting in C:\AllFiles\LabFiles\Ports \shipping\requests. 6. Enable the Northwind_ReceiveShipping_File receive location and then you should find the acknowledgement in the C:\AllFiles\LabFiles\Ports \shipping\acknowledgments folder. 7. Enable the Northwind_ReceiveShipAck_File location and the process should complete.

Exercise 2: Using Role Links for Messaging


Overview

In this part, you will create a role link to identify the shipper role in the business process. Later, you will define the parties which can play this role for this given process. This will allow the actual send port to be chosen dynamically based on some data that identifies the party currently playing that role.
Define a Role Link in the Shipping Orchestration

Procedure List 1. Open the Shipping.odx orchestration 2. Right-click in the right-hand port surface, and click New Role Link, and then click Next. 3. In the wizard, name the role link ShipperRoleLink and create a new role link type named ShipperRoleLinkPortType. 4. Specify that the orchestration will be playing the role of consumer indicating that the orchestration will be consuming the role link by sending the first message. 5. Click Finish. 6. Drag the ShipperPort to the provider space of the role link to indicate the port type consumed by the orchestration as part of the role. Notice that instead of ShipperPort the port is now called ShipperPortType. This is because the role link is our logical entity now, and the port type is just that, a type.

Set the Destination Party

The orchestration must set the destination party for the role link so the appropriate send port can be selected. Procedure List 1. Using the orchestration view, add a new variable named shipperIdentifier of type string. 2. Drag an Expression shape from the toolbox and add it to the orchestration just before the SendToChosenShipper shape. 3. Set the name of the Expression shape to DetermineShipper and double-click the Expression shape to edit the code. 4. Add the following code to the Expression shape which defines the shipper, and then sets the destination party for the role link:
shipperIdentifier = "Federal Shipping"; ShipperRoleLink(Microsoft.XLANGs.BaseTypes.DestinationParty) = new Microsoft.XLANGs.BaseTypes.Party( shipperIdentifier, "OrganizationName");

Note that in this scenario we hard code the shipper name. In a real scenario, you would use business rules to dynamically determine the shipper. We use the shipper

name, but when defining parties, any custom identifier can be created as an alias for that party and used to set the destination part. For example, your internal customer id, or a DUNS number. 5. Your orchestration should look similar to the image below:

6. Build the solution and fix any problems that arise. 7. Right click the solution and choose Deploy Solution.

Exercise 3: Define Parties


Overview

In this part you will define the configuration related to the roles and send ports for the orchestration. You will create physical send ports for each shipper and then enlist or link them to the role link you defined in the business process.
Create the Send Ports for the Shippers

Procedure List 1. In Windows Explorer, validate that the folder c:\AllFiles\LabFiles\ports\shippers exists. 2. Within the folder above, are three folders representing the three shippers: Federal Shipping, Speedy Express and United Package. 3. Open the BizTalk Server Administration Console and navigate to the Northwind application node. 4. Add three static one-way send ports to represent three different shippers. The configuration information is below:

Send Port: Shipper_United Transport Type Address Pipeline Send Port: Shipper_Speedy Transport Type Address Pipeline Send Port: Shipper_Federal Transport Type Address Pipeline FILE c:\AllFiles\LabFiles\Ports \shippers\ FederalShipping passthrough FILE c:\AllFiles\LabFiles\Ports \shippers\SpeedyExpress passthrough FILE c:\AllFiles\LabFiles\Ports\shippers\UnitedPackage passthrough

5. Start all three send ports after they are created.


Define the Shippers and Assign Send Ports

Procedure List 1. Right-click the Parties node and create a new party. 2. Name the party Federal Shipping and then use the send port pane to select the Shipper_Federal send port.

3. Repeat the above two steps to create parties named Speedy Express and United Package associated to their respective send ports.
Enroll the Parties in the Orchestration Shipper Role

Procedure List 1. Click the Role Links node in the Northwind application 2. Double-click the Provider item and then click the Enlist button. 3. Check all three shippers and click OK 4. Highlight each party and click the Bind button, then select the appropriate send port to bind to the NotifyShipper operation. 5. Be sure you have configured all shippers.
Test the Solution

Procedure List 1. Right-click the Northwind application and choose Start to start all send ports and orchestrations. 2. Copy the OrderExternal.xml file from the C:\AllFiles\LabFiles\Lab15 directory to the c:\AllFiles\LabFiles\Ports\OrderIN\ directory. 3. Test the output by checking the FederalShipping directory to see if the shipping acknowledgement appears.

Exercise 4: Use Direct Messaging Ports


Overview

In this part you will create a dynamic shared port between the two orchestrations. This will continue to use a publish and subscribe model of messaging, but will not require that messages be passed through an external intermediary like the file system used in the first part of the lab. The messaging will all be done at the message box layer.
Configure a Dynamic Port

In this section, you will change the shipping request and acknowledgment ports to a single dynamic port Procedure List 1. In Visual Studio, open the RouteOrder.odx orchestration. 2. Delete the ShippingPort and ShippingpAckPort from the design surface. 3. In the orchestration view, under the Types heading, delete the ShippingAckPortType and ShippingPortType. 4. Right-click on the right-hand port surface, and click New Configured Port, and then click Next. 5. In the Name box enter ShippingPort and then click Next. 6. Click Create a new port type, and in the Port Type Name box, enter ShippingPortType, then click Request-Response, and then click Next. 7. On the port binding page, in the Port direction of communication list, click Ill be sending a request and receiving a response, then in the Port binding list, click Direct. 8. Click the radio button labeled To send messages to other orchestrations, select this port here and in those orchestrations. 9. From the drop down, choose the Northwind.Orchestrations.RouteOrder. ShippingPort, then click Next, and then click Finish. 10. In the orchestration view, delete the ShippingCorrelation and ShippingCorrelationType. You wont need these correlation items now that you will be using direct messaging. The messages will be correlated based on internal correlation values leveraging the port information and orchestration instance ids. 11. Use the green connection points to hook the SendShipRequest and ReceiveShipAcknowledgement shapes to the new port. 12. Build the solution and fix any problems.

Update the Shipping Orchestration to Use the Dynamic Port

Procedure List 1. Open the Shipping orchestration 2. Delete the ReceiveShippingRequestPort and ShipAckPort ports from the design surface. 3. From the orchestration view, delete the ReceiveShippingRequestPortType and ShipAckPortType 4. Right-click on the left-hand port surface, and click New Configured Port, and then click Next. 5. In the wizard, name the port RequestShippingReceivePort, and then click Next. 6. For the port type, choose to use the existing Northwind.Orchestrations.ShippingPortType. 7. In the port binding page of the wizard, specify that you will be receiving and then sending, and choose Direct for the port binding. 8. Click the radio button labeled To receive messages from other orchestrations, select this port here and in those orchestrations. 9. From the drop down, choose: Northwind.Orchestrations.RouteOrder. ShippingPort, then click Next, and then click Finish.

10. In the orchestration designer, drag the connection points from the new port to the receive and send shapes appropriately. 11. Your completed orchestration should look similar to the following:

12. Build your solution and fix any compiler errors. 13. Right-click the Northwind solution, and then click Deploy Solution. 14. Test by dropping the OrderExternal.xml file into the c:\AllFiles\LabFiles\Ports\OrderIN\ directory. 15. Check the c:\AllFiles\LabFiles\Ports\Shippers\FederalShipping directory for the output.

Course Evaluation
Your evaluation of this workshop will help Microsoft understand the quality of your learning experience. Please work with your training provider to access the workshop evaluation form. Microsoft will keep your answers to this survey private and confidential and will use your responses to improve your future learning experience. Your open and honest feedback is very valuable.

Вам также может понравиться