• Using Dynamic Maps in BizTalk(From CodeProject)


    Introduction to Dynamic Maps

    If you have used maps in BizTalk, by now, you must know that maps are used to transform an XML message into another format. I do not intend to go into the details about BizTalk maps here, but in essence, a map is a transformation on your existing data to the output format you desire. In this article, I will illustrate an interesting feature called Dynamic Maps in BizTalk. If you are a C++ fan like me, you would be amazed at the power of polymorphism and how a call to a function, say Shape.Draw(), differs with each derived class of Shape like Arc, Square, or Circle. So I don't have to explain why dynamic mapping is important.

    Quite often in BizTalk, you come across scenarios where you need to transform a message to an output format, which you can decide only after you know some information which is contained in the message itself, like destination recipient. This can be achieved by using maps in the ports itself, but as the number of parties grow and your exception handling requirements kick in, this route has some limitations. This is where dynamic mapping inside orchestrations make sense.

    Scenario

    For this exercise, I am building an orchestration which identifies the destination party and loads the corresponding map and sends the message to the intended recipient after the desired transformation. For this example, I have two parties ABC and XYZ.

    A Bird's Eye View of the Steps

    These are the steps for implementing our Dynamic Maps. I am assuming a working knowledge of BizTalk for the solution below, as the concept is what I intend to illustrate. You can skip these steps by downloading the source from above.

    • Create a BizTalk Project for Maps.
    • Create all Schemas and Maps.
    • Create an Orchestration Project.
    • Identify the party and load the Maps dynamically.
    • Set the Destination dynamically and route the message.
    • Deploy and GAC the DLL.
    • Testing.

    Getting Down to Business ..

    I have broken down the process into a series of logical steps.

    Step 1: Creating your Schemas and Maps Project

    You need to create a Schema and Maps project. I have all my maps and schemas in a project called Dynamic Maps. I have added three schemas to the project.

    • The Generic Schema (Common Input Schema)
    • ABC Schema (for my party ABC)
    • XYZ Schema (for my party XYZ)

    The details of the three schemas are as below. The input schema comes in with some basic information. The output schemas differ for the two parties ABC and XYZ. The three schemas are shown below.

    Right click on SubscriberInfo in the GenericSchema and do a Quick promotion. This will add a property schema to the BizTalk project.

    Now we build the two maps. Both the maps use some basic information from the sources schema, and add some additional information on the output side. I have used the Time functoid to get the submission time.

    Step 2: Signing the DLL with a Key

    You need to have a strong name for this assembly to get it loaded in the toolbox. So create a strong name and sign it. Once you have the strong key generated, reference that in the Assembly Key file value in the project properties.

    Step 3: Compile and deploy the Maps project

    From project properties in the Solution Explorer window, deploy the project. Check in GAC to see if the DLL is deployed. Note down the public key token from the file properties in GAC.

    Step 4: Build the Dynamic Maps orchestrations

    Add a new BizTalk project OrchestrationForDynamicMaps. Create a new Orchestration and name it Orch_DynamicMaps. In the Orchestration View window, create the following variables and messages. Set the value as in the table below. Leave the rest of the values as their default values.

    Message / Variable Identifier Type Comments
    Message Generic_In DynamicMaps.GenericInSchema The incoming Message
    Message Message_Out System.Xml.XmlDocument The outgoing Message
    Variable SubscriberInformation System.String Promoted Subscriber Info
    Variable tMap System.Type The Map value

    The orchestration built looks as in the figure below. The outline of steps is detailed below. You can download the source and follow the steps conceptually.

    • Add a Receive Port Receive_GenericMessage which accepts the Generic_In message declared above.
    • Add an Expression Shape Identify Subscriber and set the expression value as below:
      Collapse | Copy Code
      SubscriberInformation = 
         Generic_In(DynamicMaps.PropertySchema.SubscriberInfo );
    • Add a Decide and check if SubscriberInformation == "ABC" or SubscriberInformation == "XYZ", and a branch for termination.
    • Add an Expression Shape and name it Set Map and put the value.

      Change the public key token value to the value you noted down previously.

      Collapse | Copy Code
      tMap = System.Type.GetType("DynamicMaps.Map_ABC, 
               DynamicMaps, Version=1.0.0.0, Culture=neutral, 
               PublicKeyToken=f85be9e4dd36fb1d");
    • Add a Message Shape and do the dynamic transformation and dynamically set the Send port. These are the magic lines:
      Collapse | Copy Code
      transform (Message_Out) = tMap(Generic_In);
      Dynamic_Send(Microsoft.XLANGs.BaseTypes.Address) = 
           "FILE://C:\\Ports\\ABC\\%MessageID%.xml" ;
    • In the second branch for subscriber XYZ, we set the map to the map for XYZ and change the public key.
      Collapse | Copy Code
      tMap = System.Type.GetType("DynamicMaps.Map_XYZ, 
               DynamicMaps, Version=1.0.0.0, Culture=neutral, 
               PublicKeyToken=f85be9e4dd36fb1d");
    • Now we need to construct the message like ABC's. Alternately, you can construct the message in the Expression Shape directly, but you would need to add the construct keyword.
      Collapse | Copy Code
      construct Message_Out
      {
          transform (Message_Out) = tMap(Generic_In);
          Dynamic_Send(Microsoft.XLANGs.BaseTypes.Address) = 
                  "FILE://C:\\Ports\\XYZ\\%MessageID%.xml" ;
      }
    • Add a Send port which sends out a message of type System.Xml, and use that to send the transformed file to your desired destination.
    • Compile and deploy the project.

    Note: In essence, what we have done in the step above is to use the reflection feature in .NET and find the type of the Map. Then we use the variable and invoke the transformation by using the BizTalk internal keyword transform. BizTalk does all the hard work of loading the assembly dynamically for our use and unloading the assembly later, and all that plumbing that you otherwise need to write. Don't you love BizTalk now?

    Step 5: Testing and Output

    You can drop the two test files and you will get two different outputs for the same file based on changing the subscriber.

    I have the inputs and outputs as below:

    • Input file for party ABC

    • Output for party ABC

    • Input file for party XYZ

    • Output for party XYZ

    Step 8: A few notes on the output

    The output is self explanatory, and you will notice that for identical inputs except for the party name, the output was different based on the maps used. We used a Time functoid to generate the time, and the other values came from fixed strings. And last but not the least, I confess, I am not 22 as the example file indicates or misleads, way older than that! My wife was quick to point that one out.

    Points of Interest

    Although in this example we have used a simple Decide shape to figure out which map to load, in real life implementations, this could be a database helper class which returns the name of the map assembly from a SQL database or a similar design. This design is useful since you can add more maps and systems even after the original system has gone live. This is possible because you can add a new subscriber into the database and have a new DLL with the corresponding schema and maps. This provides a loose-coupling which is highly desired in these scenarios.

    Gotcha's

    In the declaration of the variable tMap, I could not get it to be defined as System.Type from the dropdown. I had to open the .odx file in Notepad and set it manually after choosing a random type initially.

    Exceptions

    A very common exception would be:

    Collapse | Copy Code
    Error in accessing the part data or one of its fragments. 
    The part or fragment may not exist in the database.

    When this happens, make sure you have both the assemblies deployed and they are present in the GAC. Also check that the ports are created and the Receive port uses an XML transmit pipeline and the Send port uses a pass-through transmit pipeline. If that did not solve the problem, ping me at the BizTalk cafe forums. I would be glad to take a look.

  • 相关阅读:
    Docker没有vi命令的解决方案
    docker-compose
    liunx 删除文件
    OPB_发票信息表(每笔结算生成一条数据) opb_invoiceinfo
    OPB_发票明细表(每一类药品生成一条数据) opb_invoicedetail
    工程启动类
    MySQL数据库启动,关闭,重启:
    linux压缩和解压缩命令
    降序限位排名
    PHP环境的塔建 防坑指南
  • 原文地址:https://www.cnblogs.com/JasonLiao/p/1984579.html
Copyright © 2020-2023  润新知