Multi-application solutions

For many scenarios, it is useful to group functionality into separate BizTalk applications (or services) for reuse in other applications. For example, you might put generic purchase order functions into at purchase order BizTalk application. You can then build business processes in one or more different BizTalk applications that uses the functions from the purchase order application.

After a while, you typically ends up with a graph of BizTalk applications depending on each other. That is good because you have only implemented everything once. However, this creates a deployment challenge. If you have explicit dependencies, the BizTalk applications have to be deployed in the correct order. If you make changes to an application that others depends on, you first have to undeploy all the other applications before you can update yours. Then redeploy the rest of the applications again.

If you use the deployment scripts and techniques found in this guide, the problem described above is not that painful anymore, because when you deploy, everything is removed and installed again in the correct order.

However, for large solutions, deployment can be time consuming. Sometimes you also want to update one application without reinstalling everything. This is especially true during development.

By designing the applications to use “loose” dependencies, we can overcome these problems. As an added bonus, your application will become easier to test.

What to avoid

If you use the “Start Orchestration” or “Call Orchestration” shapes in BizTalk, you create a hard dependency on the other orchestration. If the other orchestration lives in a different BizTalk application, these two applications will also have a hard dependency. It will also be a hard dependency, if you add a reference to another BizTalk application in Visual Studio in order to use schemas or maps from that application.

Loose coupling

You cannot avoid hard dependencies completely. You will need at least one application that contains common schemas. For two applications to communicate in a loosely manner, they must share the same schemas. This typically done by creating a “Common” BizTalk application. All BizTalk application has a dependency on the “Common” application, but not on each other. Applications communicate by sending messages to the BizTalk message box and receives them by using subscriptions.

Let us use the following simple scenario as an example.

We have a client application that talks to a business process by sending a message, and gets a reply back as another message. While running, the business process needs to look up additional information by sending a request to a service.

SubService.png

Both the “Business process” and the “Service” can be implemented as BizTalk applications. Look at the sample applications in the source code. The “Service” is the “Contoso.Math” BizTalk application. Just to have some sample data to work with, the service returns a Fibonacci sequence of the length specified in the request. The “Business process” is implemented in the “Contoso.Samples” application. The application simply goes through the list returned from the service and squares the numbers.

The interesting part is how “Business process” talks to the “Service”.

First, look at the service, located in the “GenerateFibonacci.odx” orchestration.

The orchestration uses a "request-response" port to receive a message. The response message is generated by a C# class library and sent back through the request-response port.

Loose1.png

The important thing here is to create the port using “Direct binding”.

Loose2.png

Select the receive shape and note, that even if the “Filter Expression” is blank in Visual Studio, a filter is still created on the message type. In most cases, you do not need to specify additional filters.

Loose3.png

The message schemas are referenced from the “Contoso.Common” application.

Loose4.png

Now, switch to the “Contoso.Samples” solution, and open the “SquareFibonacciSequence.odx” orchestration.

Loose5.png

On the left, a request-response port handles the request from the client application. It was created the same way as we did for the service in the previous example. However, in this case the message schemas are contained within the application. That is because they are not used by other BizTalk applications. The client uses them.

On the right are the ports for calling GenerateFibonacci service. Notice that there are two one-way direct bound ports. One for the request and the one for the response.

Loose6.png

Important! The calling orchestration does not know anything about how the service is implemented. The only thing the caller knows is that it should call the service by publishing a message to the BizTalk message box, and that a reply will arrive in the message box at some point in the future. Never assume that the service is implemented in a particular way, it might change in the future.

To call the service, the orchestration uses the messages defined by the schemas in the “Contoso.Common” application. When the orchestration sends a request, it is important the reply get back to the same orchestration instance. BizTalk keeps track of this by using a “Correlation Set”. A correlation set is made from some information in the message that is unique for each request. In order for BizTalk to match the reply with the request, the same information has to be returned in the response message.

In this case, we use the “UnitOfWorkID” element for correlation. To use this element in a correlation set, we need a “Property Schema”. First, create a property schema, and add the properties needed for correlation. In this case, there is only one, and we have used the same name as the element from the messages.

Loose7.png

Assign the same property schema to both the request and reply message, and promote the “UnitOfWorkID” element.

Loose8.png

In the caller orchestration, first define a new correlation type that uses the property schema we just created. Then, create a new correlation set based in that type.

Loose9.png

Select the “Send” shape and set the “Initializing Correlation Set”.

Loose10.png

Then, select the “Receive” shape and set the “Following Correlation Set” to the same correlation set.

Loose11.png

Now, you are ready to run. The orchestration will now be able to call the service without an explicit reference.

Last edited Mar 14, 2014 at 1:33 PM by hallis, version 17