Using MS Transaction Server 2.0 with COM Transaction Integrator 1.0

Archived content. No warranty is made as to technical accuracy. Content may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.

Angela Mills

Microsoft Corporation

On This Page

Abstract
Introduction
What is COM Transaction Integrator?
Technical Drill Down - How COMTI Extends MTS
Creating a COMTI Component
Configuring COMTI and MTS
Using a COMTI Component
Example Scenario Using COMTI
References

Abstract

This document describes how the Microsoft® COM Transaction Integrator extends Microsoft Transaction Server into the mainframe transaction processing world. It is a technical document that explains how to configure and use these products and the processes that take place "under the hood."

Introduction

This document explains how the COM Transaction Integrator (COMTI) for CICS and IMS extends Microsoft® Transaction Server into the mainframe-based transaction processing world. Shipping with SNA Server 4.0, COMTI enables application developers to easily create COM components that can expose and extend CICS and IMS transaction programs. Once created, these components can be called from many development and productivity tools such as Visual Basic®, Active Server Pages (ASP), and even Microsoft Word, enabling mainframe data and business logic to become more available and flexible.

This is a technical document that assumes a degree of knowledge about Component Object Model (COM) and Microsoft Transaction Server (MTS). (For more information on these technologies, see the References section at the end of this document.) Explanations are provided for many of the mainframe terms, so little prior knowledge of this environment is required. This document explains how COMTI integrates with and extends the functionality of Microsoft Transaction Server. Several key areas are covered.

  • How COMTI components implement COM and how COMTI enlists with the Microsoft Distributed Transaction Coordinator (DTC) to provide distributed two-phase commit support.

  • The practicalities of creating and configuring COMTI components within Microsoft Transaction Server and some of the issues and limitations involved with this version of the product.

  • How COMTI works (as an attempt to aid understanding — this knowledge is not required to build COMTI applications).

Definitions

The COMTI documentation uses several terms that may have different meanings to different people, or may be new to readers from a non-mainframe background. Brief descriptions of some of the more important terms are given below. For additional information on terminology, as well as general COM/MTS information, see the References section at the end of this document.

Transaction

A transaction is an atomic unit of work: either all the actions in a transaction are committed or none of them are. In the MTS environment, the Distributed Transaction Coordinator (DTC) coordinates a transaction.

Transaction Program (TP)

A transaction program is any CICS or IMS program that uses Advanced Program-to-Program Communication (APPC) to communicate with another TP on a peer-to-peer basis.

Transaction Coordinator

A transaction manager that coordinates transactions that span multiple resource managers. Work can be committed as an atomic transaction even if it spans multiple resource managers, potentially on separate computers.

CICS

The IBM Customer Information Control System (CICS) is a transaction manager that supports distributed online transaction processing. It uses APPC/LU 6.2.2 to communicate with other systems.

The high availability and scalability of CICS comes from its architecture. CICS is divided into separate regions or address spaces, which can execute multiple threads. A region owns resources (which include users, communications, and TPs), and entries for each resource are held in a table corresponding to the resource type.

IMS

Information Management System (IMS) is a system designed by IBM for data processing. It comprises two elements — the IMS Database Manager (IMS DB) and the IMS Transaction Manager (IMS TM). IMS TM is a message-based transaction processing system that can access data in either IMS DB or DB2 databases. Clients place messages in a queue and IMS executes the applications or TPs specified by these messages. This application will access the database and return results back to IMS TM.

COMMAREA

The Communications Area, or COMMAREA, is a term used in the mainframe world to refer to an area of memory that is accessible to different programs. It is similar to a data structure that contains both input parameters and return data.

APPC and LU 6.2

LU (logical unit) 6.2 is an IBM-architected protocol that guarantees compatibility between programs communicating with one another across a network or on the same system. Advanced Program-to-Program Communication (APPC) is an API, supported by SNA (Systems Network Architecture) Server, which provides access to the LU in a well-known and standard way.

For a TP system or program to communicate directly with another TP system using APPC, the two programs must first establish an LU 6.2 conversation with each other. LU 6.2 is the de facto standard for distributed transaction processing in the mainframe environment and is used by both CICS and IMS subsystems.

What is COM Transaction Integrator?

COM Transaction Integrator (COMTI) enables Microsoft Transaction Server (MTS) to execute applications running under CICS or IMS on an IBM MVS system. COMTI ships with SNA Server version 4.0 and comprises three main elements:

  • The Management Console snap-in for administration.

  • The Component Builder for creating COMTI components.

  • The COMTI Run-Time Proxy.

Cc723268.mtsco1(en-us,TechNet.10).gif

Figure 1: . COM Transaction Integrator (COMTI)

The COMTI Component Builder is a GUI-based stand-alone tool. It allows a developer to automatically create a type library from the COBOL declarations of an existing CICS or IMS application, or vice-versa. The type library describes the properties and methods of the COMTI component.

The COMTI run-time proxy provides the Automation server for components created by Component Builder. When methods of a COMTI component are invoked, the proxy translates them into messages that can be sent to and understood by the mainframe application. When the mainframe application returns data to the caller, the proxy translates it into a form the COMTI component can interpret.

Elements of a COMTI Transactional Application

Each of the elements in Figure 1 plays a specific role:

Client Application

The client application simply provides the presentation layer for the application or data. It can be anything capable of calling an MTS component, including an Active Server Page (ASP), a Visual Basic (VB) application, or even a Microsoft Office application.

Microsoft Transaction Server

Microsoft Transaction Server (MTS) provides the scalability engine for the COMTI component and a simple mechanism for extending the functionality of the mainframe transaction program.

MTS Component

The MTS component is a COM object that exposes the functionality of the mainframe TP as a COM interface method. It can expose all of the functionality, a subset, or a superset. The MTS component contains the transaction logic that determines when work will be committed or aborted.

COMTI Type Library

The type library is created by the COMTI Component Builder. It describes the methods and data for the mainframe TP.

COMTI Run-Time Proxy

The COMTI run-time environment provides several functions:

  • Translates between Automation and COBOL data types.

  • Translates messages to and from the mainframe.

  • Provides a generic object for MTS, the behavior of which is described by a COMTI type library for a specific instance.

Microsoft Distributed Transaction Coordinator

The Distributed Transaction Coordinator (DTC) is the part of MTS responsible for ensuring that all work within a transaction context is either committed or rolled back as an atomic unit of work, by implementing the two-phase commit protocol.

SNA Server

The Systems Network Architecture (SNA) Server provides the LU 6.2 connection between COMTI and the mainframe. COMTI ships with SNA Server.

CICS/IMS Transaction Program

The CICS or IMS TP provides access to the mainframe database and may implement some business logic.

Technical Drill Down - How COMTI Extends MTS

COMTI Run-Time Activity

The following diagram shows what happens at run-time when a COMTI method is invoked. The illustration involves a method called "CEDRBANK" being invoked on an object called "Cedar.Bank". Note that all this complexity is completely hidden from the programmer.

Cc723268.mtsco2(en-us,TechNet.10).gif

Figure 2: . COMTI run-time activity

  1. Automation client creates an object.

  2. Find out what the CLSID of "Cedar.Bank" is.

  3. Request the class factory for the "Cedar.Bank" class.

  4. Request the class factory from TAGEN.DLL.

  5. Create a "Generic COMTI Class Factory" for the class.

  6. Initialize the generic COMTI class factory for the class.

  7. Get the type library information for the class.

  8. Create a type library reader for the class.

  9. Automation client requests a new instance of the class.

  10. Call the IClassFactory::CreateInstance() method.

  11. The class factory creates a "Generic COMTI Object."

  12. Initialize the new generic COMTI object is initialized.

  13. Automation client calls a method on the new object.

  14. Get the dispatch ID for the method.

  15. Look up the dispatch ID in the type library.

  16. Invoke the method.

  17. Ask for a state machine with which to implement the method call.

  18. Create (or get from a pool) a state machine.

  19. Ask the state machine to execute the method.

Suppose the Automation client was a Visual Basic Application. It creates an instance of a COMTI component class. The programmatic ID (PROGID) of the class is "Cedar.Bank". To create the object instance, the Class ID (CLSID) is obtained by calling the COM library function CLSIDFromProgID. The class factory can then be obtained from the CLSID by calling CoGetClassObject(). Now things start to get interesting for COMTI.

The CoGetClassObject() function is called with the CLSID for "Cedar.Bank" as a parameter. The function examines the registry entries for that class and determines that the class (or at least the class factory) is implemented in TAGEN.DLL. It loads that DLL and calls its DllGetClassObject() function, passing the CLSID as a parameter. The DllGetClassObject() function then passes the call to the class factory object for the specified CLSID. Remember that Component Builder does not generate an implementation of the component, just a type library that describes the component. When TAGEN.DLL is asked to create a class factory for a class created by Component Builder, it just creates a "Generic COMTI Class Factory".

The generic class factory is then passed the Type Library ID for the component. Effectively it's saying, "make one of these when your CreateInstance() method is called". The new generic class factory reads the type library into memory and completes its initialization. The IClassFactory interface on this new class factory object is returned to the Automation client.

Within the Typelib Cache, "CreateLib" is a single-instance object (one for all COMTI components) that is a factory for the "ReadLib" objects. There is a "ReadLib" object for every COMTI class (not each instance).

The IClassFactory::CreateInstance() method is called to create an instance of the object. The class factory obtains a "Generic COMTI Object". (Note that the Generic COMTI objects are pooled). Like the generic COMTI class factory, the generic COMTI object is also given the information from the type library created by Component Builder. It uses this information to implement the object described by the type library.

The object is now ready for use. An IDispatch interface is returned to the Visual Basic application, which can finally call the methods of this interface in the usual way.

It is important to understand that the generic COMTI object is simple and does not know how to do anything specific. A "state machine" that interprets the type library and makes calls over the LU 6.2 connection to execute the appropriate CICS or IMS TP does the actual work. Like the "CreateLib" object, the "SMDisp" is a single-instance factory object for state machine objects. State machines are pooled and exist for every COMTI remote environment.

COMTI Transaction Support: The State Machine and DTC

Cc723268.mtsco3(en-us,TechNet.10).gif

Figure 3: . Transaction support in COMTI

  1. The Automation client calls an Automation method via IDispatch::Invoke().

  2. The generic object requests a new state machine from the state machine dispenser.

  3. The dispenser creates a new state machine and associates it with the LU 6.2 transport for the remote environment.

  4. The state machine dispenser then enlists the new state machine with the DTC.

  5. The ICedarSM interface is returned to the generic object.

The generic object performs several different tasks. It implements IDispatch for the client and processes method invocations. It also conforms to the MTS programming model and calls SetComplete or SetAbort, as appropriate.

The state machine dispenser is responsible for allocating a connected (and possibly enlisted) state machine that will be pooled according to the target remote environment.

The state machine's primary role is to serve the resource dispenser (ISMCedar), the generic object, and the DTC. It handles access to the conversation and transport objects and performs all parameter marshaling.

The transport object supports both transactional two-phase commit and non-transactional operations. It exposes a generic interface that is used by the COMTI run time to communicate over the LU 6.2 connection.

State Transitions

Cc723268.mtsco4(en-us,TechNet.10).gif

Figure 4: . COMTI state machine

Non-Transactional Operation

When the COMTI component has its transactional property set to "Does not support transactions" or "Supports transactions" but is not participating in a transaction context, COMTI does not enlist with the DTC. The method is invoked, the connection made, and the work done, which either succeeds or fails, and the method returns. There may be code within the TP itself that provides transactional behavior, but this is completely outwith the scope of COMTI. The upper right section of the diagram above shows the state transitions for non-transactional operations.

Transactional Operation

The lower left section of the diagram shows the state transitions for a transactional operation in COMTI. When a COMTI component has its transaction property set to "Requires a new transaction", "Requires a transaction", or "Supports a transaction" and is called within a transaction context, COMTI will enlist with the DTC to provide two-phase commit support.

The state machine is typically driven from the Idle state to the Waiting state by a COMTI generic object, and from Waiting back to Idle (via either commit or abort states) by the DTC.

COMTI does not currently support the presumed abort optimization, and in a failure situation DTC will make a decision on whether to abort or commit the transaction based upon the log entries on recovery. In MTS, it is not possible to configure timeouts on a per-method or even per-component basis. All transactions will time out and be rolled back when the globally set MTS timeout period is reached.

Creating a COMTI Component

Creating a Type Library with Component Builder

The COMTI Component Builder is effectively a parser that translates a COBOL copybook from a mainframe TP into IDL and then uses MIDL to compile this IDL into a COM type library. The COBOL wizard assists with the creation of both methods and recordsets. (Recordsets are used to access arrays of COBOL tables.)

The typical stages involved in creating a COMTI component are:

  • Create a new, empty component.

  • Specify the type library and interface names.

  • Import the COBOL declarations.

  • Specify the mainframe TP.

For example, the COBOL code below would be used to create a component with a single method called "CEDRBANK" that would take two input parameters, the account name and number, and return a single parameter, the account balance.

IDENTIFICATION DIVISION.
PROGRAM-ID. CEDRBANK.
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
LINKAGE SECTION.
01 DFHCOMMAREA.
   02  CEDARBANK-COMMAREA.
       03  NAME                   PIC X(30).
       03  ACCNUM                 PIC 9(6).
       03  ACCBAL                 PIC S9(7)V9(2) COMP-3.
PROCEDURE DIVISION.
    MOVE    777.12 TO ACCBAL.
    EXEC CICS RETURN
            END-EXEC.

The procedure for creating type libraries using Component Builder is fully documented in the COMTI online documentation.

Type Libraries and Mainframe TPs

It is important to understand the relationship between the source code for the mainframe TP and the resulting type library. The IDL for the type library generated by Component Builder for the COBOL function above is shown below.

[
 uuid(EEB4EBF1-9A63-11D0-AB6F-00AA00C1479E),
 version(1.0),
 helpstring("CedarBank sample application")
]
library Cedar
{
 importlib("STDOLE2.TLB");
 [
  uuid(EEB4EBF2-9A63-11D0-AB6F-00AA00C1479E),
  version(1.1)
 ]
 dispinterface _Bank
 {
 properties:
 methods:
long cedarbank(
   [in, out] BSTR* name,
   [in, out] BSTR* ACCNUM,
   [in, out] CURRENCY* ACCBAL);
 };
 [
  uuid(EEB4EBF3-9A63-11D0-AB6F-00AA00C1479E),
  appobject,
 ]
 coclass Bank
 {
  [default] dispinterface _Bank;
 };
}

In fact, this IDL has been simplified for the purposes of illustration. Component Builder inserts many custom attribute tags, which describe, for example, fixed length fields and whether the parameters are actually input or output.

The component, "Cedar", has a single dispatch interface called "_Bank". It has no properties (other than the standard property NewRecordset handles defining the shape of a recordset for the caller) and a single method, "cedarbank". The library and interface names were provided to Component Builder before the COBOL was imported. By default, the method name is the same as the COBOL PROGID. The three parameters to the method — NAME, ACCOUNT, and ACCBAL — reflect the contents of the COMMAREA.

Data Type Conversion

In the above example, Component Builder has made the following type conversions from COBOL to Automation data types:

PARAMETER

COBOL TYPE

AUTOMATION TYPE

NAME

PIC X(30)

String

ACCNUM

PIC 9(6)

String

ACCBAL

PIC S9(7)V9(2) COMP-3

Currency

Complete lists of data type mappings both from COBOL to Automation and from Automation to COBOL are provided in the COMTI online documentation.

Arrays and Recordsets

When importing COBOL into Component Builder, it will automatically create recordsets when a fixed or variable length table (occurs clause) is encountered. The table must conform to recordset rules — it cannot contain nested tables, which cannot be flattened, and it cannot contain arrays. (In a future version of COMTI, this default behavior will change and these will be treated as arrays of user-defined types). Below is an example of a COBOL declaration that would require a recordset as its return value in the COMTI component.

01 CUSTOMER-DATA.
    05 CUSTOMER-NUMBER                 PIC 9(9).
    05 INVOICES OCCURS 50 TIMES.                        
       10 INVOICE-NUMBER               PIC 9(9).
       10 INVOICE-DATE                 PIC 9(7) COMP-3.
       10 INVOICE-AMOUNT               PIC S9(13)V9(2) COMP-3.
       10 INVOICE-DESCRIPTION          PIC X(40).
    05 LAST-NAME                       PIC X(20).
    05 FIRST-NAME                      PIC X(20).

The resulting method would be:

GetInvoices(lCustomerNumber As Long, strLastName As String,
    strFirstName As String) As Object

The following example shows how a Visual Basic application might call this method.

Dim objInvoices As ADODB.Recordset
Dim lCustomerNumber As Long
Dim iRow As Integer
Dim iCol As Integer
Dim strLastName As String
Dim strFirstName As String
Dim Data As Variant
Set objCustomer = CreateObject("Customer.Invoicing.1")
lCustomerNumber = CLng(txtCustomerNumber)
Set objInvoices = objCustomer.GetInvoices( _
    lCustomerNumber, _
    strLastName, strFirstName)
Data = objInvoices.GetRows
grdInvoices.Rows = UBound(Data, 2) + 1
grdInvoices.Cols = UBound(Data, 1) + 1
For iRow = 0 To UBound(Data, 2)
    grdInvoices.Row = iRow
    For iCol = 0 To UBound(Data, 1)
        grdInvoices.Col = iCol
        grdInvoices.Text = Data(iCol, iRow)
    Next iCol
Next iRow

Configuring COMTI and MTS

The COMTI Remote Environment

The COMTI Remote Environment is an abstraction layer that hides the connectivity details from the component. It is simply the glue that tells COMTI what connection to use to access which mainframe TP (CICS or IMS region) for a given component. A remote environment contains three pieces of information, which are configured within SNA Server.

  • Local LU alias — An alias for the real LU name by which the Windows NT® end of the connection is known to the mainframe.

  • Remote LU alias — The name of the endpoint for the connection. For COMTI, this is typically the TP name. The remote LU alias also maps to a network name and a LU name, which is the ACBNAME of the CICS or IMS region.

  • Mode name — A set of properties that have been defined for a session.

Setting Transaction Properties on a COMTI Component

When a COMTI component is created within Component Builder, its default transaction property should be set to one of the four MTS types.

Requires a Transaction

This property may be set for a COMTI component using a mainframe TP that supports Sync Level 2. As with any MTS component, a new transaction will be created if none is in progress; otherwise, the component will enlist in the existing transaction context.

Requires a new transaction

This property may be set for a COMTI component using a mainframe TP that supports Sync Level 2. As with any MTS component, a new transaction context will always be created.

Supports transactions

This property should be set for a COMTI component using a mainframe TP that supports either transactional Sync Level 2 or nontransactional Sync Level 0. The behavior of a component that uses a TP supporting Sync Level 2 requests will be the same as a component with the transaction property of "Requires a transaction".

Does not support transactions

This property should be set for a COMTI component using a mainframe TP that supports Sync Level 0. As with any MTS component, setting this property will result in no transactional behavior.

The appropriate transaction property will depend greatly upon the type and behavior of the mainframe TP being used. Below is a summary of which transaction properties are supported by which type of mainframe TP.

PROPERTY

CICS-LINK

CICS

IMS

Requires a transaction

 

*

x

Requires a new transaction

 

*

x

Supports transactions

 

*

x

Does not support transactions

 

 

 

*CICS applications can participate in MTS transactions only if they have been written to include transactional support.

Configuring Security

To run applications on the mainframe, COMTI must be capable of passing security credentials to the mainframe. There are a number of options for configuring security on a COMTI component that can be configured by the Administrator. In the case of explicit security, however, changes must be made to the application at design time. Security options are set in MTS as properties of a package.

User Level Security

If user-level security is enabled, the COMTI run-time proxy provides the client identity to SNA Server before allocating the LU 6.2 conversation. SNA Server can then use the client's identity (the identity of the client that invoked the MTS component and resulted in the invocation of the COMTI component) to map to a mainframe credential (using the single sign-on capability of SNA Server) to authenticate itself with the mainframe.

Package-Level Security

When using package-level security, the COMTI run-time proxy uses the single sign-on support in SNA Server to authenticate itself to the host using the Windows NT security identity of the MTS package. The package containing the COMTI component must be configured in MTS to run under a Windows NT account that maps to valid mainframe credentials. This option is the most efficient security model, taking full advantage of MTS roles and integrating with both the Windows NT and mainframe security environments. This method should be used wherever possible.

Explicit Security

An administrator can allow COMTI to override the specified User ID and password and provide its own. Users can then be expressly queried for their credentials and different rights granted on both MTS and the mainframe TP. This has to be done via a callback method in the application, and the decision to use this form of security must be made at design time. An example of how to do this is given in the "Cedar Bank" demo on the SNA Server CD.

Although SNA Server and a third-party product make it possible to synchronize Windows NT and mainframe user accounts and passwords, this remains a complex and inflexible option.

Using a COMTI Component

Simple Usage

The COMTI component can be called directly or placed in a wrapper component. Either can be called from any Automation client in the usual way. An example of how the component shown earlier in "Creating a COMTI Component" is called is shown below.

Dim objBank As Object 
Dim curRetBalance As Currency
Dim rv As Long
Set objBank = CreateObject("Cedar.Bank")
rv = objBank.cedrbank(txtName, txtAccount, curRetBalance)

This same code could be used from any application that supports Visual Basic for Applications or Visual Basic Scripting Edition (VBScript). For example, the same component could be used to place data into an Excel spreadsheet, a Word document or a Web page with just a few lines of very simple code.

Wrapper Components

It is necessary to pass all input and output parameters when calling a COMTI method. This can become extremely tedious, especially when (as is the case with many mainframe TPs) there are a lot of parameters. It can be worth creating a "wrapper component" that exposes a simplified set of methods which do not require all parameters to be passed.

For example, the CedarBank method might have a wrapper with two methods — SetAccountDetails (which would take the account name and number) and GetBalance (which would return the account balance for the currently set account). The advantages of a wrapper component become more apparent in complex examples where many output parameters are being returned, such as "account balance and recent account activity".

The wrapper should create the COMTI component using the CreateInstance method of the MTS object context to ensure that any transaction context is passed from the wrapper to the COMTI component.

Extending COMTI Components

With COMTI and MTS, developers can extend transactions from the Windows NT Server environment to the mainframe. Windows-based applications using MTS can include CICS applications in MTS coordinated transactions. The example scenario presented at the end of this document shows how this can be done.

Issues and Limitations

Issues for Transactional Support

COMTI version 1.0 does not support transactions for IMS. A future version of COMTI will provide transactional support for versions of IMS that themselves support transactions (version 6.0 and later).

When a COMTI component is to be used within a transactional MTS application, the mainframe TP cannot contain explicit SYNCPOINT commands. In such an application, the DTC must have control over when an operation will commit or abort, but the explicit SYNCPOINT command would prevent this. The mainframe TP may form an atomic unit of work, but it may also, unknown to itself, form only part of a transaction. Only the DTC can know whether all work in the transaction can be committed, so only the DTC can decide to instruct COMTI to perform an SYNCPOINT. This is not an issue for components that do not form part of an MTS transaction.

Automation Limitations

Because COMTI components are called through an Automation interface, the current limitations of Automation apply to all COMTI components. The major issue here is the data type that can be supported.

Language Limitations

Although you can write applications which call COMTI components in many different languages, bear in mind that they will have different limitations that may affect how you create your COMTI component. For example, some languages limit the number of parameters on a method call, which may require the component to return a recordset instead of separate parameters.

Example Scenario Using COMTI

The Friendship Insurance sample is shipped with SNA Server 4.0. The top-level component in this sample is called ProcessClaim. This component uses other components to make changes to both DB2 and SQL Server databases as a single MTS transaction. In the example, a ProcessClaim object is created by an Active Server Page (ASP). The code for this ASP is in the Friendship Insurance tutorial directory under \WEBSTE\DEFAULT.ASP. The line of VBScript code that creates the ProcessClaim component reads:

Set myobj = Server.CreateObject("PrcClaim.ProcessClaim")

Because the ProcessClaim component is installed under MTS with the "Requires a new transaction" option set, the call to CreateObject automatically starts a transaction under the DTC. The current object context is enlisted with this new transaction.

Next the VBScript code calls myobj.ProcessClaim. A simplified and annotated version of the method code is shown below. The method takes several parameters describing an insurance claim, for example, the customer's social security number, date the incident occurred, date of birth, and amount of claim. The method allocates claim numbers and adds claim details to both DB2 and SQL Server databases.

Public Function ProcessClaim( _
    lngCustSSN As Long, dtmDateOfService As String, _
    dtmDateOfBirth As String, szIncident As Long, _
    szProvider As String, curAmount As Double,
    szComment As String) As Long

First, the current object context interface is retrieved by a call to GetObjectContext. (This function is implemented by MTS. It is a global function exported by the MTS DLL.) This object context can be used to create other objects within the same transaction context.

Dim ctxObject As ObjectContext
Set ctxObject = GetObjectContext()

The first task is the assignment of a claim number. This number is assigned by a TP executed on a mainframe. CLAIMKEY is a COMTI component created from existing CICS TP COBOL declarations using Component Builder. An instance of the CLAIMKEY component is created with the current object context, so it becomes associated with the transaction started when the ProcessClaim object was created. The call to ctxObject.CreateInstance() corresponds to steps 1 through 12 in figure 2 earlier in this document: creation of a generic COMTI object, and associating it with the type library for the CLAIMKEY component.

Dim objCK As Object, lRet As Long
Set objCK = ctxObject.CreateInstance("CLAIMSRV1.CLAIMKEY.1")

The GetNewClaimKey method of the component is used to obtain a new claim number. This corresponds to steps 13 through 19 of Figure 2, and steps 1 to 5 of Figure 3: creation of a state machine, enlistment of the state machine with the DTC, and invocation of the mainframe TP that implements the method.

lRet = objCK.GetNewClaimKey(lngClaimNo)

After the method call returns, the state machine is left in the "Waiting" state.

If the previous operation was successful, a claim summary record is then inserted into a SQL Server table. This insertion is done using another MTS component which, again, is created with the same object context to allow the transaction outcome to be controlled.

If lRet >= 0 Then
    Dim objICS As Object
    Set objICS = ctxObject.CreateInstance("ClaimsSrv.InsertClaimSummary")
    lRet = objICS.InsertClaimSummary( _
        lngClaimNo, dtmDateOfService, _
        szStatus, lngCustSSN, szProvider)
End If

If the previous operations were successful, a claim record is inserted into a DB2 table. This is done by another COMTI component, INSERTCLAIM, again created from existing CICS TP COBOL declarations. Again, an instance of the component is created with the same context. This means the creation of another COMTI generic object, but this time it is associated with the type library describing the INSERTCLAIM component. When the InsertClaim method is called, this generic object obtains another state machine, enlists it with the DTC, and executes the mainframe TP, leaving this state machine also in the "Waiting" state.

If lRet >= 0 Then
    Dim objIC As Object
    Set objIC = ctxObject.CreateInstance("CLAIMSRV2.INSERTCLAIM.1")
    lRet = objIC.InsertClaim( _
        lngClaimNo, dtmDateOfService, _
        dtmDateOfBirth, curAmount, _
        szComment, lngCustSSN, _
        szIncCode, szProvider)
End If

Finally, if everything worked, SetComplete is called. If something failed, SetAbort is called.

If lRet >= 0 Then
    ctxObject.SetComplete
Else
    ctxObject.SetAbort
End If

If SetComplete is called, the DTC goes through the commit process for each item of work enlisted for the transaction. For the state machines, this means moving through the "Preparing", "Prepared", and "Committing" states and back to "Idle".

If SetAbort is called, the DTC goes through the abort process for each item of work enlisted for the transaction. The state machines move through the "Aborting" state and back to "Idle".

Cc723268.mtscom5(en-us,TechNet.10).gif

Figure 5: . Friendship Insurance SetComplete and SetAbort scenarios

References

Box, Don. Essential COM. Addison Wesley Longman, Inc., 1998

Bernstein, Philip and Eric Newcomer. Principles of Transaction Processing. Morgan Kaufmann, 1997

Chappell, David. "How Microsoft Transaction Server Changes the COM Programming Model." (Microsoft Systems Journal, January 1998)

Gray, Steven and Rick Levano. Microsoft Transaction Server 2.0. SAMS Publishing, 1997

Rogerson, Dale. Inside COM. Microsoft Press, 1997

For general information: