Implementing the Design
|Author's Note: To proceed past this point, you must have BizTalk Server 2006, including Developer Tools, installed on your local development environment with Visual Studio 2005. See the sidebar, Installing BizTalk Server 2006 from Part 1 of this article, for more information on installing the required development and server components.
|Whether data comes in naturally as an XML document or it is converted by brute force, orchestration can only work with serializable types or XML itself.|
Let me take a quick moment to review the work that lies ahead. First, you'll learn to create an application that encapsulates the business rules and workflow of the new Retail Operations business process. This service will be implemented as a BizTalk Server Orchestration (called SendPO.odx
) that will be exposed (at least initially) as a SOAP web service endpoint.
Create the Orchestration
As part of the design phase of the solution, you created a business process diagram (see Figure 8
) of what the SendPO workflow might look like using the ODBA. Now, to add the orchestration to Visual Studio 2005, complete the following steps:
Working with .NET Components and SOAP Services
- If it isn't already running, start Visual Studio 2005 and create a new BizTalk Server 2006 project. Figure 10 provides recommended naming for the solution and project file. This naming convention is prevalent throughout the entire solution and promotes standardization and conceptual integrity throughout the application.
|Figure 10: To create a BizTalk Project, select the Empty BizTalk Server Project template.||
|Figure 11: An orchestration exported by Orchestration Designer for Business Analysts can be added to the Visual Studio Orchestration Designer for implementation.||
- Right-click the Northwind.BusinessWorkflows.RetailOps BizTalk Server project, select Add, and then choose Existing Item. Browse to the SendPO.odx file and click Add. Figure 11 shows the orchestration you just imported. Note: If you did not use the ODBA to create the business process diagram, you must add the ODX artifact now. Refer to Figure 11, which shows the state of the newly imported orchestration.
- Notice that each ODBA Group was forward-engineered as an Orchestration Scope, and that each ODBA Action was translated as an Orchestration Group Shape. Within each Group Shape you'll see a Shape Connector Line. I'll show you how to use these stubs to wire up the components/services that the SendPO.odx orchestration will coordinate.
Before continuing, I want to point out one very important orchestration property. Recall that in BizTalk Orchestrations, there are two types of transactions: atomic and long-running. Although I'll limit the scope of this article to the successful processing of a purchase order (the happy path), there are many future enhancements (and things that can go wrong) within the order-fulfillment process that makes opting for a Long Running Transaction a good choice.
- Right-click anywhere in the Orchestration Designer and select Properties. Set the values for the Transaction Identifier and Transaction Type to SendPOTx and Long Running respectively.
With the exception of some business entities listed in Table 1 (which I will create as special C# classes) it is beyond the scope of this article to focus too much on the particulars of each service that the SendPO orchestration will coordinate.
Table 1: .NET design-time artifacts that will be implemented as part of the BizTalk Server 2006 solution.
A .NET interface that provides a contract for processing PO and managing billing and funds posting procedures.
A .NET class that implements IRetailOps.
A .NET interface that provides a contract for performing inventory operations including checking, updating, and ordering inventory, contacting shipping carriers, and recording parcel-tracking information.
A .NET class that implements IRetailManager.
A .NET interface that provides a contract for printing packing slips and shipping labels.
A .NET class that implements IPrint.
A .NET class that represents a Purchase Order entity.
A .NET class that represents an Inventory Item entity.
Table 2 shows a list of classes, SOAP endpoints, and assemblies that are provided as part of the article download.
Table 2: Packaging and deployment of the relevant artifacts that will be implemented as part of the BizTalk Server 2006 solution.
Private Assembly (IIS)
Private Assembly (IIS)
From your perspective as the reader, you will merely consume or invoke these components/services as if they've already been built (they are built in the download). It is important, however, to distinguish between the types of services that will be implemented and consumed:
This project will expose the majority of the services via vanilla .NET components. In both theory and practice, these components should adhere to the principles of component-oriented programming (Binary Compatibility, Language Independence, Location Transparency, Concurrency Management, Version Control, and Component-based Security). Whether internally, each component itself is making local intra-process calls to perform work within the CLR, or out-of-band calls across process boundaries to components that are hosted using remoting technologies such as ASP.NET Web services (SOAP), .NET remoting or Windows Communication Foundation is immaterial. As interface-based components, the implementation of each service is completely abstracted from the caller, leaving the caller to only be concerned with the contract presented.
|Author's Note: Because BizTalk Server 2006 loads all .NET resources from the Global Assembly Cache (GAC), any artifacts used as part of a BizTalk Server solution must be strongly named (you will notice a strong-name key called Northwind.snk within the Visual Studio 2005 solution that is available for download). This requirement nicely enforces the component-oriented principle of version control. See Sidebar 2, "Principles of Component-Oriented Programming," for more information on the effective use of .NET components.
The SendPO orchestration is exposed as an ASMX web service called RetailOpsService.asmx. To provide a comprehensive overview of how orchestration interacts with other pseudo-protocols on the Send side, the solution will implement the Acme.Billing.BillingService service as a SOAP web service using the BizTalk SOAP Adapter. Obviously, the decision to implement services as .NET components, custom or vendor-provided SOAP services, will vary by scenario. See Sidebar 3
, "Tenets of Service-Oriented Programming," for guiding principles for exposing applications as contract-based services.
To add the components and services to the BizTalk project, right-click the References
folder within the Northwind.BusinessWorkflows.RetailOps
project and add a reference to each relevant project, assembly, or service endpoint just as you would for a class library or other Visual Studio 2005 project type. The artifacts that will be used in this solution are listed in Table 2. The NorthwindTraders solution already contains all of the source projects so you may either reference the pre-compiled assemblies or use project references (for ease of use, the latter is used by default in the solution available for download).
Create the Domain Entities
|Author's Note: You are welcome to extend any of the components as necessary; however, for the purposes of this article, what the components are actually doing internally is not importantit is the interface/contract and the ability to coordinate their work within a workflow that is important.
Due to the graphical nature of the BizTalk design-time experience, the orchestration itself usually requires little programming (of course you must still develop components and services used in the workflow). However, you must create entities that describe the data being consumed, sent, and received. A common approach is to create domain-specific business entities using either XSD schema or .NET classes. Since many organizations will already have significant class-specific code bases, it is not always practical or necessary to strictly use XSD schema for modeling entities. In my opinion, while XSD schema has its place in messaging, the esoteric and cumbersome nature of building and maintaining the schema makes using it desirable only when higher level APIs are not available to abstract the messaging details. Thanks to .NET's rich support for serializing and de-serializing types, using classes is perfectly acceptable for creating entities within orchestration.
Now that you've added the references to pre-existing .NET components and classes used as part of the orchestration, you must create the business entities you'll use as data transfer "objects" within the solution.
- Within the NorthwindTraders solution, create a C# Class Library project called Northwind.BusinessEntities.RetailOps. This naming convention standardizes artifact naming and promotes conceptual integrity throughout the application.
- Create two new C# classes named PurchaseOrder.cs and InventoryItem.cs using Listing 1 and Listing 2 as a guide. (The downloadable code for this article contains a fully functional solution, including the class files that may also be used as a reference.) Note that as entities, these classes contain no behavior, so the only work here is to add the private members and corresponding properties, along with some special attribute decorations used by BizTalk Server.
Recall from earlier discussions on messaging and pipelines that BizTalk Server treats all messages as XML (XLANG to be precise). Whether data comes in naturally as an XML document or you convert it by brute force using a specific pipeline, orchestration can only work with serializable types or XML itself (it is actually quite possible to use binary formatting, but the default serialization behavior relies on the XML formatter). Remember from our discussion in Part 1 of this article that just because a class or message is in XML format doesn't mean that all of its fields will be automatically available to the orchestration. Fields that should be available within an orchestration instance must be marked as Distinguished.
- Add a reference to the Microsoft.XLANGs.BaseTypes.dll to the Northwind.BusinessEntities.RetailOps project (located in \Program Files\Microsoft BizTalk Server 2006), and add the following namespace to the InventoryItem and Purchase Order classes (which contains the attribute classes necessary to mark properties as Promoted or Distinguished):
- Next, decorate each class name with the Serializable attribute class:
public class InventoryItem
public class PurchaseOrder
- For each public property within each class, distinguish each property using the DistinguishedField attribute class as shown below (this will make these properties available to the BizTalk orchestration at run time):
public class InventoryItem
private int m_ItemNumber;
private decimal m_price;
public int ItemNumber
m_ItemNumber = value;
The Purchase Order class is the heart of this workflow because it will be used to store and transport order details from the client application to the Retail Operations application. As a result, you must define it as a Message at the global Scope within the orchestration.
In the Northwind.BusinessWorkflows.RetailOperations
project, double-click the SendPo.odx
file. Click the Orchestration View tab, right-click the Messages
folder and click New Message. A new Message artifact is created. Right-click the new Message artifact and click "Properties Window" or, if visible, click the Properties tab.
|Figure 12: A Message Variable is created to declare the Message type.|
Note that this is the last time I will go into such detail for bringing up artifact properties. All subsequent actions will consist of creating new artifact types or dragging shapes onto the design surface of the Orchestration Designer and setting the corresponding properties.
Under Message Type, expand .NET Classes and click "Select from Referenced Assemblies." Select Northwind.BusinessEntities.RetailOps.PurchaseOrder as the Type and enter purchaseOrderMsg
for the Name property. You can see the result of this step in Figure 12
. This step is the equivalent of creating a traditional variable declaration, except that BizTalk-distinguished variables from messages (due to the fact that each is handled a bit differently). The purchaseOrderMsg
Message Variable will be used to initialize purchase order Message data and move the message around within the orchestration.