Writing Microsoft Transaction Server Components in Java

Paul Stafford
Developer Relations Group, Microsoft Corporation

May 1997

Click to copy the files associated with the HELLOJTX sample.

Abstract

Building applications from software components. Writing components in Java. Using transactions to ensure robustness and scalability. To many developers, these all sound like good ideas.

How about using transactions and Java components to build robust, scalable server applications? When Microsoft® Transaction Server (MTS) version 1.0 shipped in December of 1996, it became the first product to provide transactions for Java.

This article is about developing MTS application components in Java. After an overview of the process, I’ll build a simple component, step by step. Next, I’ll show two client applications and run the component under MTS. I’ll finish with some debugging tips and pointers to further information on MTS and Java.

To build and run the samples, you will need both Microsoft Transaction Server and Microsoft Visual J++™. If you don’t have MTS, you can order a free evaluation copy from http://www.microsoft.com/transaction/.

I’ll assume that you know the basics of the Component Object Model (COM), the Java programming language, and MTS programming. If you are new to MTS programming, a good place to start is the Programmer’s Guide in Microsoft Transaction Server Help. Reading Part I ("Overview and Concepts") and stepping through the tutorial in Part II ("Developing Applications in Microsoft Transaction Server") will provide more than enough background for this article.

The MTS Development Process for Java

The following is a summary of the process for creating MTS components for Java.

  1. Create the IDL for your component.

    When building MTS components in Java, the first step is to provide definitions for your COM-creatable classes ("coclasses") and for the interfaces that they implement. You do this by writing an Interface Description Language (IDL) file.

    Your interfaces must only use COM types that can be mapped to Java types. Using OLE automation compatible types and dual interfaces is a good choice. All of these types map to Java types, and a dual interface allows your component to be called from both early-binding (vtable) and late-binding (IDispatch) clients. This makes your Java server objects fully accessible from Microsoft Visual Basic® clients and various scripting languages (Visual Basic Scripting edition [VBScript], JavaScript, Active Server Pages, and so forth).

    Additionally, if you plan on using your component from VBScript, all out parameters must be of type Variant.

    For a complete table of the mapping between COM types and Java types, see "Type Mappings Between Java and COM" in the Visual J++ documentation in the MSDN Library.

  2. Generate GUIDs.

    Each interface, class, and library in an IDL file needs a COM globally unique identifier (GUID). Use the Microsoft GUID creation tool, GUIDGEN (guidgen.exe), to generate new GUIDs. You can run GUIDGEN from the command prompt or by choosing Create GUID from the Tools menu in Microsoft Developer Studio.

  3. Generate the type library file.

    The next step is to compile your IDL specification into a type library (.tlb) file. Do this by running the Microsoft IDL Compiler, MIDL (midl.exe), against your .idl file. To build MTS components, you will need version 3.01.59 or later of MIDL (version 3.01.59 ships with MTS 1.0). Earlier versions did not correctly handle IDL files with multiple custom attributes. You will need to specify multiple custom attributes when building MTS components in Java.

  4. Generate Java wrapper classes for your coclasses and interfaces.

    Next, create Java wrappers for the COM coclasses and COM interfaces described in the type library. Do this by running the Visual J++ Java Typelib Conversion Utility, JAVATLB (javatlb.exe), against the .tlb file. JAVATLB will create one wrapper class (.class file) for each coclass in the type library. It will also create a wrapper class for each interface.

  5. Generate type library summary information.

    Generate type library summary information by running JAVATLB with the /U:T option. This will create a file called summary.txt, which will provide Java declarations for each class and interface in the type library, and Java signatures for each interface method. The method signatures make handy templates when you begin writing Java classes that implement your interfaces.

  6. Run JAVAGUID against the wrapper classes.

    This step is necessary because, as stated in the MTS 1.0 Readme, "Whenever any of the MTS APIs need a parameter that is a GUID, you must pass an instance of class com.ms.com._Guid. Do not use Guid, CLSID, or IID from package com.ms.com; they will not work." MTS includes a utility, JAVAGUID, which postprocesses the .class files output by JAVATLB, making the necessary changes.

  7. Implement your classes in Java.

    For each coclass defined in your IDL, create a Java class implemention. The name of this class must match the name specified in the JAVACLASS custom IDL attribute. The class must implement all of the coclass’s interfaces. Again, using the templates from summary.txt is an easy way to get started.

  8. Compile your Java classes.

    Next, compile your Java implementations. Do this by running the Microsoft Visual J++ compiler (jvc.exe) against each Java source file; the Visual J++ compiler (JVC) will produce corresponding Java class files.

  9. Build your COM dynamic-link library (DLL).

    The next step is to take the type library, COM wrapper classes, and Java classes that you have generated so far, and gather them into a COM DLL. Do this by using the Java Executable Generator (exegen.exe). You’ll need the updated version of EXEGEN that comes with MTS—this version supports a new /D switch for creating DLLs.

  10. Deploy your DLL into Microsoft Transaction Server.

    Use the MTS Explorer to create an empty package, and then drag your file from Windows Explorer to the MTS Explorer and drop it into that package.

The Hellojtx Sample

In this section, I’ll step through the process of writing a "hello world" Microsoft Transaction Server sample in Java. The sample is called Hellojtx ("hello world" in Java, with transactions).

To build Hellojtx, you will need the EXEGEN, MIDL, and JAVAGUID tools that come with Microsoft Transaction Server. You’ll also need the JAVATLB, JVC, and GUIDGEN tools that come with Microsoft Visual J++.

In the examples below, I am using c:\src\hellojtc as the root directory for my Hellojtx project. I am assuming that all of the command-line tools except EXEGEN are in my path. If your machine is set up differently, you may need to alter the command-line entries and the build file (build.bat).

The Hellojtx IDL

Begin by writing hellojtx.idl:

// hellojtx.idl : IDL source for hellojtx.dll
//
// This file will be processed by the MIDL tool to
// produce the type library (hellojtx.tlb).
#include <MtxAttr.h>
#include <JavaAttr.h>
[
   uuid(CBD73841-C640-11d0-BD14-0080C7C1FC93),
   version(1.0),
   helpstring("Simple Microsoft Transaction Server sample, written in Java")
]
library HELLOJTXLib
{
   importlib("stdole2.tlb");
   [
      object,
      uuid(CBD73842-C640-11d0-BD14-0080C7C1FC93),
      dual,
      helpstring("IHellojtx Interface"),
      pointer_default(unique)
   ]
   interface IHellojtx : IDispatch
   {
      import "oaidl.idl";
      HRESULT SayHello([out] BSTR* pbstrResult, [out, retval] long* plRetVal);
   };
   [
      uuid(CBD73843-C640-11d0-BD14-0080C7C1FC93),
      helpstring("Hello Class"),
      JAVACLASS("Hellojtx.HelloObj"),
      PROGID("Hellojtx.Hello"),
      TRANSACTION_REQUIRED
   ]
   coclass CHellojtx
   {
      [default] interface IHellojtx;
   };
};

The Hellojtx server will implement one COM-creatable class:

[
   uuid(CBD73843-C640-11d0-BD14-0080C7C1FC93),
   helpstring("Hello Class"),
   JAVACLASS("Hellojtx.HelloObj"),
   PROGID("Hellojtx.Hello"),
   TRANSACTION_REQUIRED
]
coclass CHellojtx
{
   [default] interface IHellojtx;
};

The very long number is the globally unique COM identifier (GUID) for this class. Clients written in C or C++ will ask for the class by this GUID. Other clients prefer shorter, more readable names. Visual Basic clients will ask for the Programmatic Identifier (ProgID) specified in the PROGID custom IDL attribute (Hellojtx.Hello). Most humans also prefer ProgIDs, so I will call this class Hellojtx.Hello.

When JAVATLB creates a Java wrapper for this class, it will get the name of the wrapper class, CHellojtx.class, from the IDL coclass entry.

When we write a Java implementation for Hellojtx.Hello, we must match the JAVACLASS attribute. We’ll name our Java class HelloObj.class and place it in the Hellojtx package.

When we use the MTS Explorer to deploy our component, it will see the TRANSACTION_REQUIRED attribute and mark our component as needing a transaction. Alternatives to TRANSACTION_REQUIRED are TRANSACTION_SUPPORTED, TRANSACTION_NOT_SUPPORTED, and TRANSACTION_REQUIRES_NEW. This example does not in fact need to use transactions, but is marked as requiring one to show you how it’s done.

Hellojtx.Hello components implement one interface, IHellojtx:

[
   object,
   uuid(CBD73842-C640-11d0-BD14-0080C7C1FC93),
   dual,
   helpstring("IHellojtx Interface"),
   pointer_default(unique)
]
interface IHellojtx : IDispatch
{
   import "oaidl.idl";
   HRESULT SayHello([out] BSTR* pbstrResult, [out, retval] long* plRetVal);
};

The IHellojtx interface has one method, SayHello (the methods it inherits from IDispatch are not shown in the IDL). The types specified in the SayHello signature are all COM types; JAVATLB will map these types to native Java types.

Hellojtx GUIDs

I used GUIDGEN to create fresh GUIDs for the HELLOJTXLib library, the IHellojtx interface, and the CHellojtx coclass. For your own projects, remember to create new GUIDs!

Run MIDL

Run midl.exe against Hellojtx.idl:

C:\src\hellojtx>MIDL hellojtx.idl

This will create the type library file hellojtx.tlb. You can use the OLE Object Viewer application (oleview.exe) to examine the contents of the type library.

Run JAVATLB

Run javatlb.exe against hellojtx.tlb:

C:\src\hellojtx>JAVATLB /d . /p Hellojtx /p:b- hellojtx.tlb

The "/d ." option tells JAVATLB to use the current directory as the root directory for class file output. Keeping the files under the current directory makes them a little easier to work with for the rest of the build steps.

The "/p" option specifies Hellojtx as the Java package for the new classes.

JAVATLB creates two new Java class files, one for the coclass and one for the interface. Java requires that file names match class names, so JAVATLB names the files CHellojtx.class and IHellojtx.class. Java also requires that directory names match package names, so JAVATLB puts the files into the Hellojtx subdirectory.

CHellojtx.class is a COM class wrapper. Java clients will use CHellojtx to create instances of the Hellojtx.Hello COM class. For example:

// Code in Java client
IHellojtx hello = (IHellojtx) new CHellojtx();

When the Microsoft Virtual Machine for Java loads CHellojtx.class, it will recognize that it is a wrapper and invoke the COM creation application programming interface (API) CoCreateInstance to instantiate an instance of the Hellojtx.Hello COM class.

IHellojtx.class is a COM interface wrapper. At run time, the Java virtual machine (VM) will use this class to map incoming calls from COM clients to method calls on the Java class Hellojtx.HelloObj.

Generate summary.txt

This step is optional. Create type library summary information for Hellojtx by running JAVATLB with the "/U:T" option, as follows:

C:\src\hellojtx>JAVATLB /U:T hellojtx.tlb

Which returns:

import hellojtx.*;

This output shows that Java clients can import the Hellojtx package by using the "import hellojtx.*" statement.

Here is the content of summary.txt:

public class hellojtx/CHellojtx extends java.lang.Object
{
}
public interface hellojtx/IHellojtx extends com.ms.com.IUnknown
{
   public abstract int SayHello(java.lang.String[]);
}

Here we see how JAVATLB maps COM types specified in the IDL to Java types. Recall that in the IDL, we used COM types in the SayHello signature:

HRESULT SayHello([out] BSTR* pbstrResult, [out, retval] long* plRetVal);

Since Java only supports input parameters, JAVATLB generates an array of String objects to implement the BSTR out parameter. The SayHello Java implementation will set the first element of the array to return an output string to its caller. JAVATLB uses this same technique on all out parameters specified in the IDL.

JAVATLB maps the retval parameter plRetVal to an Integer return value.

Note   "JAVATLB /U:T" outputs summary.txt, along with new .class files, to a directory in the Java class path. On my machine, it puts these files in c:\winnt\java\trustlib\hellojtx. To avoid having multiple copies of class files lying around my system, I delete them from this directory and copy summary.txt back to the root directory of my project.

Run JAVAGUID

Postprocess the new class files by running javaguid.exe. JAVAGUID can be run only from the command line and only from the same directory as its target files. Change to the Hellojtx subdirectory, and then invoke JAVAGUID:

C:\src\hellojtx>cd Hellojtx
C:\src\hellojtx\Hellojtx>JAVAGUID CHellojtx.class IHellojtx.class
C:\src\hellojtx\Hellojtx>cd ..

JAVAGUID does not create any new files. It edits its target files, finding each reference to a COM GUID and changing it to com.ms.com._Guid. It also adds a static public final member to each class, representing the _Guid for that class. Clients use these members when calling the MTS IObjectContext.CreateInstance method.

Implement HelloObj

Now it’s time to write the Java class that implements the IHellojtx.Hello coclass. The class name and package for this class must match the name previously specified in the JAVACLASS IDL attribute: Hellojtx.HelloObj. Java filenames must match class names, so create a new file, HelloObj.class, in the Hellojtx subdirectory:

// Simple Microsoft Transaction Server sample application, written in Java
// Copyright (C) 1997 Microsoft Corporation
// All rights reserved.
package Hellojtx;
import com.ms.mtx.*;
public class HelloObj implements IHellojtx
{
   public int SayHello(String[] result)
   {
      try
      {
         result[0] = "Hello from simple MTS Java sample";
         MTx.GetObjectContext().SetComplete();
         return 0;
      }
 
      catch(Exception e)
      {   
         MTx.GetObjectContext().SetAbort();
         return -1;
      }
   }
}

Sticking to tradition, SayHello returns a simple "Hello" message. Notice again how we use an array of Strings to return the out parameter.

Before returning, SayHello calls SetComplete to let MTS know that it is done with it’s work, and that it’s happy—the work it’s just done can be committed:

   MTx.GetObjectContext().SetComplete();

Now, this component does not really need to use a transaction. It’s not doing any work on shared, durable backend data. It’s not calling any Resource Managers. I’m just using a transaction as an example. Using the MTS Explorer Transaction Statistics pane, you’ll be able to see this component triggering transactions when it runs under MTS.

Compile CHelloObj.java

Next, compile the CHelloObj implementation:

C:\src\hellojtx>JVC Hellojtx\HelloObj.java

This will produce the file HelloObj.class. This class contains the Java byte codes that will be interpreted by the Java VM at run time. Because HelloObj belongs to the Hellojtx package, HelloObj.class must be in the Hellojtx subdirectory.

Build hellojtx.dll

Now we have all of the pieces that we need: a type library, a wrapper class for the IHellojtx interface, and a Java class that implements the Hellojtx.Hello COM class. It’s time to gather all the pieces into a COM DLL. Run exegen.exe from the command prompt in the root directory:

C:\src\hellojtx>C:\MTX\TOOLS\EXEGEN /d /r /out:hellojtx.dll hellojtx.tlb *.class

The "/d" switch tells EXEGEN to build a DLL and the "/out" switch tells it to name this DLL hellojtx.dll. The "/r" switch will cause EXEGEN to recurse into the Hellojtx subdirectory, where it will pick up our three class files (CHellojtx.class, IHellojtx.class, and HelloObj.class). EXEGEN will place copies of the class files in the resource fork of hellojtx.dll.

At run time, hellojtx.dll will be the COM server for the Hellojtx.Hello class. However, it will delegate this task to the Java VM.

The Microsoft Virtual Machine for Java (msjava.dll) knows how to be an InProc COM server. To implement the Hellojtx.Hello class, the VM will interpret the byte codes in the HelloObj Java class. To map incoming COM method calls to Java method calls, it will use the IHellojtx interface wrapper. It finds both of these classes in hellojtx.dll’s resource fork.

Note   CHellojtx.class does not actually need to be included in the DLL—at run time, the Java VM does not need to load the wrappers for COM classes that a DLL implements.

Deploy hellojtx.dll into Microsoft Transaction Server

Fire up the MTS Explorer and create a new package named "hellojtx". If you’ve never created a new MTS package, see "Creating and Configuring Packages" in Microsoft Transaction Server Help (Administrator's Guide, Using the Transaction Server Explorer).

Next, select hellojtx.dll in the Windows Explorer, drag it, and drop it into the empty package. That’s it! The MTS Explorer does all the work of configuring the new component.

Create a build file

It might seem that this process has a lot of steps. However, only two of the steps require writing code: creating the IDL and implementing the Java classes. Two steps involve simple use of a GUI tool: creating the GUIDs and deploying the DLL into MTS.

The rest of the steps—running MIDL, JAVATLB, JAVAGUID, JVC, and EXEGEN—can be automated. For example, here is the batch file I used for building Hellojtx:

MIDL hellojtx.idl
JAVATLB /d . /p Hellojtx /p:b- hellojtx.tlb
cd Hellojtx
JAVAGUID CHellojtx.class IHellojtx.class
cd ..
JVC Hellojtx\HelloObj.java
C:\MTX\TOOLS\EXEGEN /d /r /out:hellojtx.dll hellojtx.tlb *.class

Clients for Hellojtx

Before we can see the Hellojtx.Hello component run under Microsoft Transaction Server, we need to build some clients. I’ll describe two clients: one written in Java and one written in Visual Basic.

The Java client

The source code for the Java client consists of a single Java file, Client.java:

import Hellojtx.*;
 
public class Client
{
   public static void main(String args[])
      {
      IHellojtx myHello;
      String strRet[] = { "" };
      int nRet;
 
      try
         {
         myHello = (IHellojtx) new CHellojtx();
         System.out.println("Calling SayHello..");
         nRet = myHello.SayHello(strRet);
         System.out.println("nRet = " + nRet);
         System.out.println("strRet = " + strRet[0]);
         }
      catch (Throwable t)
         {
         System.out.println("Exception: " + t.toString());   
         t.printStackTrace();
         System.exit(0);
         }
      try
         {
         System.out.println("Hit any key to exit..");
         System.in.read();
         myHello = null;
         System.gc();
         }
      catch (Exception e)
         {
         }
      }
}

Client imports the Hellojtx package:

import Hellojtx.*;

This allows Client to omit the package name when referring to IHellojtx and CHellojtx.

Now we come to an important point. Here is the correct way for Client to create and call a Hellojtx.Hello component:

IHellojtx myHello;
myHello = (IHellojtx) new CHellojtx();
nRet = myHello.SayHello(strRet);

Client creates a Hellojtx.Hello component by using the Java new keyword, supplying as the argument the name specified as the coclass in the .idl file (CHellojtx). It then casts the result to an interface that the component implements (IHellojtx).

This code works because CHellojtx.class is a COM wrapper. When the Java VM loads this class, it knows to create an instance of the Hellojtx.Hello COM class. The VM handles the cast by issuing a COM QueryInterface call, asking for the IHellojtx interface.

Note   Although it might seem intuitive, specifying the object implementation class (in this example, HelloObj) as the argument to new, as follows, would not work:

// BAD code – this won’t work.
HelloObj myHello;
myHello = new HelloObj();
nRet = myHello.SayHello(strRet);

This code would cause a run-time exception such as the following:

Exception: java.lang.NullPointerException
java.lang.NullPointerException
at Hellojtx/HelloObj.SayHello
at Client.main

When a coworker and I sat down to write our first MTS component in Java, we made this mistake. We were stymied until, in desperation, we read the Microsoft Visual J++ documentation, where this caveat is called out quite clearly.

Notice once again that Client uses an array of strings to obtain the SayHello out parameter:

String strRet[] = { "<no returned data>" };
int nRet;
<other code>
nRet = myHello.SayHello(strRet);
In the second try clause, SayHello releases myHello and calls the Java garbage collector:
myHello = null;
System.gc();

These calls are optional. If Client omitted them, the Hellojtx component would be left alive until the DCOM connection timed out (by default, after six minutes). Making these calls allows the component to shut down immediately.

Building the Java client

Use the Microsoft Java compiler to build the client:

C:\src\hellojtx>jvc Client.java

Assuming it can find the Hellojtx package, JVC will create the file Client.class. If it can’t find the package, it will generate an error such as the following:

Client.java(1,8) : error J0051: Undefined package 'Hellojtx'

In this example, I’m building the client from the root directory of my project. JVC will find the classes it needs (CHellojtx.class and IHellojtx.class) in the Hellojtx subdirectory. If the client were in any other directory, it would not build.

To make the Hellojtx classes globally available, create a package on your machine’s Java class path. On my system, I would create a Hellojtx subdirectory under c:\winnt\java\trustlib, and copy CHellojtx.class and IHellojtx.class into that directory.

Note that clients do not need the HelloObj class. The Java VM needs this class at run time, and it will find the class in the resource fork of hellojtx.dll.

Running the Java client

Start the Microsoft Transaction Server Explorer. From the Tools menu, check to see whether the Microsoft Distributed Transaction Coordinator (MSDTC) is already running—if not, start the MSDTC.

Now we are ready to run the Java client using JVIEW.exe (JVIEW), the Microsoft command-line loader for Java. Here is what the result looked like on my system:

C:\src\hellojtx>jview Client
Calling SayHello..
nRet = 0
strRet = Hello from simple MTS Java sample
Hit any key to exit..

If you pause before hitting a key to exit, you can switch over to the MTS Explorer and see the Hellojtx component running. You can also use the Explorer Transaction Statistics pane to see that the component is indeed running MSDTC transactions (Figure 1).

Figure 1. Hellojtx.Hello running under Microsoft Transaction Server.

The Visual Basic client

Here is a Microsoft Visual Basic subroutine that calls a Hellojtx component:

Private Sub cmdSayHello_Click()
   Dim myHello As CHellojtx
   Dim str As String
   Dim nRet As Long
   Set myHello = CreateObject("Hellojtx.Hello")
   nRet = myHello.SayHello(str)
   MsgBox str
End Sub

Before building this code, use the Visual Basic Project References dialog box to pull in a reference to Hellojtx’s type library. It will be listed as the helpstring specified in hellojtx.idl—"Simple Microsoft Transaction Server sample, written in Java."

The only trick here is knowing which of the class’s identifiers to use when declaring the myHello variable and instantiating the object. In Visual Basic, use the coclass name specified in the .idl file (CHellojtx) when declaring a variable for the Hellojtx object. Use the ProgID specified in the PROGID custom attribute (Hellojtx.Hello) as the argument to CreateObject.

Running the clients remotely

Running the Java and Visual Basic clients remotely is much the same as running them on the same machine as Hellojtx.

Begin by using the Microsoft Transaction Server Explorer to configure Hellojtx.Hello as a remote component on the client computer. The Explorer will add all of the necessary registry entries. (If you have not installed an MTS remote component before, consult the MTS Explorer Help topic "Configuring Remote Components".)

Copy the Visual Basic executable (Client.exe) to the client machine. Make sure that MTS is running on both machines and that the MSDTC is running on the server machine. Now, run Client.exe, and it will access Hellojtx across the net.

Copy the Java class (Client.class) to the client machine. When this client runs, the Java VM will need local access to Hellojtx’s COM wrappers, so put copies of Hellojtx’s class files somewhere on the client machine’s Java class path. On my client machine, I copied CHellojtx.class and IHellojtx.class to the c:\winnt\java\trustlib\hellojtx subdirectory.

Now, use JVIEW to run the Java client, and it will access Hellojtx across the net.

Debugging

Debugging is one area where writing an MTS component in Java is a little less convenient than writing the component in C++ or Visual Basic. With current development tools, it is not possible to step through the component’s Java source code in the debugger.

One way to get debugging information as a component runs under MTS is to use "sprintf"-style debugging. For example, I could add a System.out.println call to the try clause of Hellojtx.HelloObj.SayHello:

try
{
   System.out.println("This msg is from the HelloObj implementation");
   result[0] = "Hello from simple MTS Java sample";
   MTx.GetObjectContext().SetComplete();
   return 0;
}

After rebuilding HelloObj.class and hellojtx.dll, I might expect to see "This msg is from the HelloObj implementation" in the console window the next time I used JVIEW to load the Client class. However, I actually would see the following:

C:\src\hellojtx>jview Client
Calling SayHello..
nRet = 0
strRet = Hello from simple MTS Java sample
Hit any key to exit..

Hellojtx is not running in the same process as JVIEW—it is running in a special MTS surrogate process (mtx.exe). This causes the HelloObj println output to go into the bit bucket instead of into JVIEW console window.

The solution is to configure Hellojtx to run in the process of its caller (JVIEW’s process). To do this, use the MTS Explorer. From the Activation tab of the Hellojtx Properties dialog box, configure Hellojtx to run in the client’s process (Figure 2).

Figure 2. Configuring Hellojtx.Hello to run in its client’s process.

Now reload the Client class. Hellojtx’s println calls will be visible in the output:

C:\src\hellojtx>jview Client
Calling SayHello..
This msg is from the HelloObj implementation
nRet = 0
strRet = Hello from simple MTS Java sample
Hit any key to exit..

A canonical form

The steps for building Hellojtx can serve as a model for building any MTS component written in Java.

The SayHello method, however, is a little too limited to serve as a model. Most MTS component methods are written in much the same form, no matter what programming language is used. Here is how that canonical form looks in Java:

Public int MTSJavaMethod ()
{
   IObjectContext   context;
   boolean         success = false;
   IFoo            foo = null;
 
      try
      {
         // Obtain MTS context.
         context = (IObjectContext) Mtx.GetObjectContext();
   
         // Obtain resources. for example, database connections.
 
         // Use resources.
         // Perform one piece of work for one client.
 
         // Invoke other MTS components to do some of the work.
         foo = (IFoo) context.CreateInstance(CFoo.clsid, IFoo.iid);
 
         // All went well.
         success = true;
         return 0;
      }
 
      catch (Exception e)
      {
         return -1;
      }
 
      finally
      {
         // Release resources.
         
         if (success)         // We are finished and happy.
            context.SetComplete();
         else            // We are unhappy.
            context.SetAbort();
      }
}

Where to Go from Here

As a next step, you may want to look at the Bank sample that comes with Microsoft Transaction Server. Java source code for the Bank MoveMoney and Account classes is installed in the MTX\Samples\Account.VJ\Account directory. The IMoveMoney.Perform and IAccount.Post methods implemented by these classes illustrate more complete implementations of the canonical MTS in Java form shown above.

For complete information on installing and running the Bank package, see "Validating Setup with a SQL Server Transactional Component" in the Getting Started book of Microsoft Transaction Server Help.

References