Dynamic Ports

You have already had a chance to see what port references look like. Dynamic ports are ports resolved at runtime using port references. We will build XLANG schedules using port references for ports that use COM components or MSMQ queues. For more discussion of dynamic ports and port references, see Chapter 10.

The case for dynamic ports based on BizTalk Messaging Services (that is, dynamic channels) is covered in Chapter 16, “Correlation—Integrating BizTalk Server Messaging and Orchestration Services.” In the case of dynamic channels, if you recall from Chapter 10, XLANG ports bound to BizTalk Messaging can be dynamic only when messages are sent out of the XLANG schedule. The port reference to resolve such a dynamic port at runtime is usually provided by a trading partner. Such a reference must contain adequate information for delivering messages from the XLANG schedule to BizTalk Messaging.

The following sections describe a schedule DynCOM.skv, which uses a dynamic port bound to a COM component and schedules Request.skv and Response.skv, which use a dynamic port bound to an MSMQ queue.

Design of DynCOM.skv

The next schedule described contains a dynamic port connected to a COM component. The schedule demonstrating this usage is shown in Figure 13.25. This schedule is called DynCom.skv.

Figure 13.25. Business process for DynCOM.skv.


In Figure 13.25, Action 1 calls the script component GenObjRef.WSC. This component constructs the COM object required by the dynamic port Port_2. Action 2 uses the dynamic port—that is, it makes the method call on the component referenced by the dynamic port. However, the method call is actually performed on the object created by the script component, which provided the object reference to the dynamic port in the first place. Figure 13.26 shows the Data page corresponding to this schedule and how this reference is passed to the dynamic port.

Figure 13.26. Data page for DynCOM.skv.


In Figure 13.26, the message pair GenObjRef_* is for the function implemented by the script component. This function takes a Prog ID for a component, constructs the component (see the “in” parameter), and returns the reference to it via the field GenObjRef_out.GenObjRef (an "out" parameter). This returned reference is used to resolve the dynamic port Port_2 by connecting the field to the Port_2 port reference.

Port_2 is bound to a dynamic instance of the class AdvOrchUtil.CMsg (refer to Listing 13.1). Action 2 calls the ShowMsgBox method of this class. The Prog ID provided to the script is AdvOrchUtil.CMsg (as it must, because of the type of the dynamic port) using the Constants message. The message box displayed contains this Prog ID and a descriptive title.

Implementing DynCOM.skv

As a first step to constructing the schedule, you need to build the script component. The script component is simple and is shown in Listing 13.17.

Listing 13.17. Code for Script Component GenObjRef.wsc
<?xml version="1.0"?>
<component>

<?component error="true" debug="true"?>

<registration
    description="Adv Orch - GenObjRef"
    progid="GenObjRef.WSC"
    version="1.00"
    classid="{3FE40B9B-2F99-4643-BBA0-1907B776F90B}"
>
</registration>

<public>
    <method name="GenObjRef">
        <PARAMETER name="ProgID"/>
    </method>
</public>

<script language="VBScript">
<![CDATA[

function GenObjRef(sProgID)
    Set GenObjRef = CreateObject(sProgID)
end function

]]>
</script>

</component>

A script component uses the XML technology and the scripting engines to construct a COM component. In Listing 13.7, the script component has a ProgID of GenObjRef.WSC and an associated class GUID. The component has one public method, called GenObjRef. The implementation of the function is contained as a script inside the CDATA section of the XML document. The function creates and returns an object using the passed in ProgID. Use the GenObjRef script component to build the schedule shown in Figure 13.25. After creating the business process, you need to drop the script component implementation shape to the right of the separator bar. Follow through the wizard steps; specify the file path and ProgID for the script component. For Port_2, use the _CMsg interface of the AdvOrchUtil component developed in Listing 13.1. Choose a dynamic instantiation; other choices are as defaults.

Caution

If you use the sample from the publisher's Web site, remember to fix the path to the script component as appropriate on your machine. Also, make sure that you either build your COM components to conform to the type library of the sample or fix the references in your schedule to use your type library.


Make all the connections on the data page as shown in Figure 13.26. The constants are shown in Table 13.4.

Table 13.4. Strings in DynCOM.Skv
NameValue
AdvOrchUtil_CMsgAdvOrchUtil.CMsg
DynPortDynamic Port

Finally, compile the schedule.

Running DynCOM.skx

When you run this schedule, you get a dialog box. The corresponding trace is shown in Listing 13.18.

Listing 13.18. DbMon Trace upon Running DynCOM.skx
2540: AdvOrchUtil.CMsg: Class_Initialize()
2540: AdvOrchUtil.CMsg: ShowMsgBox(): Msg=AdvOrchUtil.CMsg Title=Dynamic Port
2540: AdvOrchUtil.CMsg: Class_Terminate()

The dialog box has the title Dynamic Port and the message AdvOrchUtil.CMsg that was filled into the ShowMsgBox_In message on the data page. This message is displayed via the dynamic port Port_2.

This example showed the use of an interface as a port reference. You could also use a moniker, and it would work just as well. You must be careful, however, to provide a moniker that, when bound to a class instance, does in fact implement the interface expected by the dynamic port.

Building Request.skv and Response.skv

The next schedule shows the use of dynamic queues. Figure 13.27 shows a schedule called Request.skv that sends a document for processing to a queue known to all instances, named .private$AdvOrchQueue. Another schedule, Response.skv shown in Figure 13.29, sends a response back to the originating schedule instance. To receive this response, the Request.skv schedule uses a per-instance static queue shown as .private$Pvt. The last step in the schedule calls a method to show the content of the returned document. The known private queue, named .private$AdvOrchQueue, must be created by you and must be transactional for use with the schedule. The per-instance queue is created by the schedule instance when the schedule is run. The name of this per-instance queue is derived from the .private$Pvt prefix and a GUID suffix, generated at runtime.

Figure 13.27. Business process for Request.skv.


Figure 13.29. Business process for Response.skv.


When you connect the first action to send the outgoing message in 13.27, in the XML Communication Wizard, choose to Send Messages to the Queue as a String and also declare the message type as RespQ. The messages are picked up by the partner schedule using this message type. For the second action, choose to Receive String Messages from the Queue and pick up messages of the type Resp. The partner schedule sends messages of this type. Also, set the expected time that this schedule waits for the response to, say, 400 seconds, so that the schedule dehydrates when it is waiting.

To simplify the example, we are using non-XML documents. However, BizTalk internally still uses XML. For this, we must configure the Data page accordingly. This is shown in Figure 13.28.

Figure 13.28. Data page for Request.skv.


When using non-XML messages, a special field, called StringData is added to those messages. If such non-XML messages are outgoing, then the Document field must be populated with the following XML envelope:

<?xml version="1.0" ?><StringData></StringData> 

We use the Constants message for this envelope, the name of the constant used is DocumentXML. Other links show that the port reference for the private MSMQ queue is passed out in the StringData field, and the returned reference is shown in the message box. The title of the message box is filled in also with a descriptive string.

Build the Request.skv based on Figures 13.27 and 13.28 and the description here.

Figure 13.29 shows the Response.skv schedule, which retrieves the requests sent by Request.skv and sends a message back to the originating schedule instance.

The Response.skv schedule, shown in Figure 13.29, contains a While loop that runs forever. The rule named Forever contains the Visual Basic script expression of True. The body of the While loop reads messages from the .private$AdvOrchQueue queue and sends a response through the dynamic queue. By using the reference provided in the incoming message, the dynamic queue points back to the source schedule instance to send the response.

The settings in the incoming messages must match those for the outgoing messages in the sending schedule, Request.skv. Choose to receive non-XML messages of the type RespQ. Also set the receive latency high, say 500, so that the schedule dehydrates. The settings of the outgoing messages must match those for the queue in the Request.skv set up to receive the responses. Thus, choose to send non-XML messages of the type Resp.

The Data page for Response.skv is shown in Figure 13.30.

Figure 13.30. Data page for Response.skv.


For Response.skv, in Figure 13.30, you will need to again construct the XML wrapper for the non-XML document in the StringData field. The data flows show that the incoming StringData is used to resolve the dynamic queue and is returned to the sending schedule through the msgResp message. Thus, the message box in Request.skx will show the queue reference.

Build the schedules shown in Figure 13.27 and Figure 13.29. You will need to use the component AdvOrchUtil.CMsg developed in Listing 13.1. You will also have to manually create the private queue .private$AdvOrchQueue (as stated earlier).

Running Request.skx and Response.skx

To run this example, you will have to run Response.skx just once. If you have the XLANG Monitor running, you will see this looping schedule start up and promptly dehydrate waiting for requests. You can also start this schedule using the script RunResponse.vbs shown in Listing 13.19.

Listing 13.19. Run the Response.skx Schedule: Script RunResponse.vbs
Option Explicit

Dim sPath, sResp
sPath = WScript.ScriptFullName
sPath = Mid(sPath, 1, InStrRev(sPath, ""))
sResp = sPath & "Response.skx"

GetObject("sked:///" & sResp)

Listing 13.20 may be used to start three instances of the Request.skx schedule. In the XLANG Event monitor, you will see these schedules start up, dehydrate, restart, and then complete after you dismiss the dialog boxes. The dialog boxes shown contain the path of the per-instance queue created in each instance of the Request.skx started.

The GetObject call in either Listing 13.19 or Listing 13.20 uses a moniker for the schedule. The moniker used to start the schedules starts them on the local machine and in the default group manager.

Listing 13.20. Run the Request.skx Schedule: Script RunRequests.skx
Option Explicit

Dim sPath, sReq
sPath = WScript.ScriptFullName
sPath = Mid(sPath, 1, InStrRev(sPath, ""))
sReq = sPath & "Request.skx"

GetObject("sked:///" & sReq)
GetObject("sked:///" & sReq)
GetObject("sked:///" & sReq)

Listing 13.21 shows the output from the DbMon console when the two scripts RunResponse.vbs and RunRequests.vbs are run. Here you can also see what was shown in the dialog boxes.

Listing 13.21. DbMon Output from Running the RunRequests.vbs
2556: AdvOrchUtil.CMsg: Class_Initialize()
2556: AdvOrchUtil.CMsg: Class_Initialize()
2556: AdvOrchUtil.CMsg: Class_Initialize()
2556: AdvOrchUtil.CMsg: ShowMsgBox(): Msg=bztk.bztkdom.omicron.com private$
pvt{a2702811-147a-4141-8bd9-ff34fa387050} Title= Private queue port reference
2556: AdvOrchUtil.CMsg: ShowMsgBox(): Msg=bztk.bztkdom.omicron.comprivate$
pvt{65a3c661-3517-4ec3-976a-c6278615c681} Title=Private queue port reference
2556: AdvOrchUtil.CMsg: ShowMsgBox(): Msg=bztk.bztkdom.omicron.comprivate$
pvt{3e9d56b6-f568-488b-8af4-1f9876177628} Title=Private queue port reference
2556: AdvOrchUtil.CMsg: Class_Terminate()
2556: AdvOrchUtil.CMsg: Class_Terminate()
2556: AdvOrchUtil.CMsg: Class_Terminate()

In Listing 13.21, note the full port reference for the per-instance private queue for each of the schedule instances of the Request.skv. This per-instance and unique queue has the prefix pvt defined for it followed by a GUID string to generate the unique name. This port reference is the content of the StringData field in the schedules, and this port reference is used to resolve the dynamic queue in Response.skv.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset