Создание приложений из программных компонентов. Написание компонентов на Java(tm). Использование транзакций для обеспечения надежности и масштабируемости. Для многих разработчиков это звучит неплохо.
Как насчет использования транзакций и Java-компонентов для создания надежных масштабируемых серверных приложений? После выпуска в декабре 1996 года Microsoft Transaction Server 1.0 (MTS) появился первый продукт, работающий с транзакциями на Java.
Эта статья - о разработке компонентов приложений MTS на Java. После общего рассмотрения процесса мы шаг за шагом построим простой компонент. Вслед за этим мы покажем два клиентских приложения и запустим компонент под MTS. В конце мы предложим некоторые советы по отладке и ссылки на другие источники информации по MTS и Java.
Для создания и запуска примеров вам потребуется как Microsoft Transaction Server, так и Microsoft Visual J++(tm). Если у вас нет MTS, закажите бесплатную оценочную версию на www.microsoft.com/transaction.
Предполагается, что вы знаете основы Component Object Model (COM), язык программирования Java и программирование для MTS. Если вы не знакомы с программированием для MTS, хорошей стартовой точкой может стать раздел Programmer's Guide в MTS Reference. Достаточной основой для понимания этой статьи будет чтение первой части (Overview and Concepts) и выполнение упражнений из второй части (Developing Applications in Microsoft Transaction Server).
Процесс разработки для MTS с использованием Java
Создание IDL для вашего компонента.
При создании компонентов MTS на Java первым шаг необходимо в IDL файле создать определение COM-классов ("coclasses") и интерфейсов, реализуемых этими coclass-ами.
Ваши интерфейсы должны использовать только СОМ-типы, переводимые в типы Java. Хорошим выбором будет использование OLE automation совместимых типов и двойных (dual) интерфейсов. Все эти типы переводятся в типы Java. Двойной интерфейс позволяет вызывать ваш компонент как с использованием позднего связывания (early-binding (vtable)), так и с использованием позднего связывания (late-binding (IDispatch)). Это делает ваши серверные Java обекты полностью доступными для клиентов на Visual Basic или различных script-языков (например, VBScript и JavaScript).
К тому же, если вы планируете использование вашего компонента из VBScript, все out parameters должны быть типа Variant.
Полную таблицу соответствия COM-типов и типов Java можно найти в документации к Microsoft Visual J++ под названием "Type Mappings Between Java and COM."
Создайте GUID'ы.
Каждый интерфейс, класс и библиотека в файле IDL нуждается в глобально уникальном идентификаторе COM (GUID - globally unique identifier). Для создания новых GUID следует использовать guidgen.exe. GUIDGEN можно запустить из командной строки, или выбрав "Create GUID" в меню Tools в Microsoft Developer Studio.
Генерация файла библиотеки типов.
Следующий шаг - компиляция вашей IDL-спецификации в файл библиотеки типов (type library (.tlb)). Это можно сделать, запустив Microsoft IDL Compiler (midl.exe) и передав ему ваш .idl-файла файл в качестве параметра. Для компонентов MTS нужна версия MIDL 3.01.59 или более новая (версия 3.01.59 поставляется с MTS 1.0). Более ранние версии некорректно обрабатывают IDL-файлы с множественными пользовательскими атрибутами. Вам придется пользоваться множественными пользовательскими атрибутами при создании компонентов для MTS на Java.
Сгенерируйте Java wrapper классы (классы обертки) для ваших coclass-ов и интерфейсов.
Теперь создадим Java wrapper-ы для COM coclass-ов и COM-интерфесов, описанных в библиотеке типов. Java wrapper-ы создаются с помощью утилиты Visual J++ "Java Typelib Conversion Utility" (javatlb.exe) для .tlb-файла. JAVATLB создаст один wrapper класс (файл .class) для каждого coclass-а в библиотеке типов, а также wrapper класс для каждого интерфейса.
Сгенерируйте суммарную информацию по библиотеке типов.
Сгенерируйте суммарную информацию по библиотеке типов, запустив JAVATLB с ключом /U:T, результатом чего будет файл с названием summary.txt. Файл summary.txt дает Java определения для каждого класса и интерфейса в библиотеке типов, и Java описание для каждого метода интерфейса. Описания методов интерфейсов будут для вас хорошим подспорьем, когда вы начнете писать Java классы реализующие ваши интерфейсы.
Запустите JAVAGUID against the wrapper classes.
Для wrapper классов следует запустить JAVAGUID, поскольку, как сказано в MTS 1.0 Readme, "если какой-либо из MTS API нуждается в параметре GUID, вы должны передать экземпляр класса com.ms.com._Guid. Не используйте Guid, CLSID или IID из пакета com.ms.com; они небудут работать." MTS включает утилиту с названием JAVAGUID, обрабатывающую файлы .class, выдаваемые JAVATLB и производит необходимые изменения.
1. Реализуйте ваши классы на Java.
Для каждого coclass-а, определенного в вашем IDL, создайте реализацию Java-класса. Имя этого класса должно соответствовать имени, указанному в custom IDL атрибуте JAVACLASS. Класс должен реализовать все интерфейсы coclass-а. Опять-таки, проще всего использовать образцы из summary.txt.
2. Скомпилируйте Java-классы.
Скомпилируйте ваши реализации Java, применив Microsoft Visual J++ Compiler (jvc.exe) для каждого файла с исходным текстом на Java; JVC создаст соответствующий файл Java-класса.
3. Постройте свою COM DLL.
Следующий шаг - встраивание библиотеки типов, COM wrapper classes и Java-классов в COM DLL с использованием Java Executable Generator (exegen.exe). Вам потребуется обновленная версия EXEGEN, поставляемая с MTS. Эта версия EXEGEN поддерживает новый ключ /D, создающий DLL.
4. Установите ваши DLL в Microsoft Transaction Server .
Создайте пустой пакет с помощью MTS Explorer, перетащите ваш файл из Windows Explorer и бросьте его в созданный вами пакет.
Пример программы: Hellojtx
Этот раздел описывает процесс написания на Java примера "hello world" для MTS. Пример называется Hellojtx ("hello world in Java, with transactions").
Для создания Hellojtx, вам потребуются EXEGEN, MIDL и JAVAGUID, поставляемые с MTS. Вам также будут нужны JAVATLB, JVC и GUIDGEN поставляемые с Microsoft Visual J++.
В приводимых ниже примерах мы будем использовать каталог c:\src\hellojtc как корневой для проекта Hellojtx. Предполагается, что все средства командной строки кроме EXEGEN находятся там же. Если в вашем случае это не так, вам может потребоваться изменить команды, вводимые в командной строке и пакетный файл (build.bat).
Начните с написания hellojtx.idl.
Листинг 1. The Hellojtx IDL.
// hellojtx.idl : исходный IDL файл для hellojtx.dll // // Этот файл далжен быть обработан утилитой MIDL // для получения библиотеки типов (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; }; };
Сервер Hellojtx будет реализовать один COM-creatable класс:
[ uuid(CBD73843-C640-11d0-BD14-0080C7C1FC93), helpstring("Hello Class"), JAVACLASS("Hellojtx.HelloObj"), PROGID("Hellojtx.Hello"), TRANSACTION_REQUIRED ] coclass CHellojtx { [default] interface IHellojtx; };
Очень длинный номер, (CBD73843-C640-11d0-BD14-0080C7C1FC93), глобально уникальный COM идентификатор (GUID) для этого класса. Клиенты, написанные на C или C++ будут запрашивать этот класс по этому GUID. Остальные клиенты предпочитают более короткие, читаемые имена. Visual Basic будет запрашивать Programmatic Identifier (ProgID) указанный в IDL атрибуте PROGID (Hellojtx.Hello). Большинство людей также предпочитают ProgID, так что мы назовем этот класс Hellojtx.Hello.
Когда JAVATLB создает Java wrapper для этого класса, утилита конвертации библиотек типов также будет брать имя wrapper класса из точки входа IDL coclass-а (CHellojtx.class).
Когда мы пишем Java-реализацию Hellojtx.Hello, мы должны сохранять аттрибут JAVACLASS. Мы назовем наш Java-класс HelloObj.class и поместим его в пакет Hellojtx.
При использовании MTS Explorer для разворачивания нашего компонента, Explorer регистрирует атрибут TRANSACTION_REQUIRED и помечает наш компонент, как требующий транзакции. Заменой TRANSACTION_REQUIRED являются TRANSACTION_SUPPORTED, TRANSACTION_NOT_SUPPORTED и TRANSACTION_REQUIRES_NEW. Этот пример не требует использования транзакций, TRANSACTION_REQUIRED мы использовали исключительно для того, чтобы показать, как пометить ваш компонент как требующий транзакции.
Компоненты Hellojtx.Hello реализуют один интерфейс с названием 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); };
Интерфейс IHellojtx имеет один метод, названный SayHello (заметьте, что методы, наследуемые от IDispatch не показаны в IDL). Все типы, указанные в описание SayHello's - COM-типы; JAVATLB преобразует эти типы в родные Java-типы.
При создания новых GUID для библиотеки HELLOJTXLib, интерфейса IHellojtx, и CHellojtx coclass-а использовался GUIDGEN. Не забывайте создавать GUID в ваших собственных проектах!
Запустите midl.exe для Hellojtx.idl:
C:\src\hellojtx>MIDL hellojtx.idl
Это создаст файл библиотеки типов hellojtx.tlb. Для изучения содержимого библиотеки типов можно использовать OLE Object Viewer (oleview.exe).
Запустите javatlb.exe для hellojtx.tlb:
C:\src\hellojtx>JAVATLB /d . /p Hellojtx /p:b- hellojtx.tlb
Ключ /d . велит JAVATLB использовать текущий каталог как корневой каталог для создаваемого файла класса. Хранение файлов в одном каталоге несколько упрощает работу на следующих этапах. Ключ /p определяет Hellojtx как Java-пакет для новых классов.
JAVATLB создает два новых файла Java-классов, один для coclass-а и один для интерфейса. Java требует соответствия имен файлов именам классов, так что JAVATLB назовет файлы Chellojtx.class и IHellojtx.class. Так как Java вдобавок требует соответствия имен каталогов именам пакетов, JAVATLB положит файлы в подкаталог Hellojtx.
CHellojtx.class is a COM class wrapper. Java-клиенты будут использовать Chellojtx для создания реализаций класса Hellojtx.Hello. Например:
// code
in Java client
Ihellojt
x hello = (IHellojtx) new
CHellojtx();
Когда Microsoft Java Virtual Machine (Java VM) загружает CHellojtx.class, Java Virtual Machine распознает, что этот класс - wrapper (оберточный). Java Virtual Machine вызовет CoCreateInstance для создания экземпляра COM класса Hellojtx.Hello.
IHellojtx.class COM интерфейс wrapper. Во время исполнения Java VM будет использовать этот класс для переопределения вызовов COM-клиентов в вызовы методов Java класса Hellojtx.HelloObj
Этот шаг не обязателен.
Создайте файл информации о библиотеке типов для Hellojtx, запустив JAVATLB с ключом /U:T :
C:\src\hellojtx>JAVATLB /U:T hellojtx.tlb Microsoft (R) Visual J++ Java Typelib Conversion Utility Version 1.01.7048 Copyright (C) Microsoft Corp 1996. All rights reserved. import hellojtx.*;
Результат показывает, что Java-клиенты могут импортировать пакет Hellojtx, используя выражение import hellojtx.*.
Вот содержимое 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[]); }
Отсюда видно, как JAVATLB отображает COM-типы, оговоренные в IDL в Java-типы. Вспомним, что мы использовали COM-типы в IDL-описание SayHello:
HRESULT SayHello([out] BSTR* pbstrResult, [out, retval] long* plRetVal);
Поскольку Java поддерживает только input-параметры (не поддерживает возвращаемые параметры), JAVATLB создает массив сроковых объектов для того чтобы реализовать возвращаемый (out) параметр типа BSTR. JAVATLB использует эту технику для всех параметров описанных как - [out].
JAVATLB переназначает retval параметры в возвращаемые значения функций (в нашем случае параметр plRetVal переназначен в возвращаемое значение типа integer)
Примечание: JAVATLB /U:T выдает summary.txt вместе с новыми .class-файлами в каталог Java-классов. В этом примере JAVATLB помещает файлы в c:\winnt\java\trustlib\hellojtx. Чтобы избежать появления множественных копий файлов классов, уничтожьте их в этом каталоге и скопируйте summary.txt обратно в корневой каталог проекта.
Обработайте новые файлы классов утилитой javaguid.exe. JAVAGUID можно запустить только из командной строки, и только из того же каталога, что и обрабатываемые файлы. Перейдите в подкаталог Hellojtx и вызовите JAVAGUID:
C:\src\hellojtx>cd Hellojtx
C:\src\hellojtx\Hellojtx>JAVAGUID CHellojtx.class IHellojtx.class
C:\src\hellojtx\Hellojtx>cd ..
JAVAGUID не создает никаких новых файлов, а редактирует уже имеющиеся, заменяя каждую ссылку на COM GUID ссылкой на com.ms.com._Guid. JAVAGUID также добавляет static переменную в public секцию каждого класса. Эта переменная представляет собой класс _Guid. Клиент использует эту переменную при вызове метода MTS IObjectContext.CreateInstance.
Теперь самое время написать Java-класс, реализующий IHellojtx.Hello coclass. Имя класса и пакета для этого класса должны соответствовать имени, предварительно указанному в аттрибуте JAVACLASS IDL: Hellojtx.HelloObj. Имена файлов Java должны соответствовать именам классов, так что создайте новый файл HelloObj.class в подкаталоге Hellojtx.
Листинг 2. Реализация Hellojtx coclass.
// Простой пример MTS приложения, написанного на 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; } } }
SayHello возвращает простое сообщение "Hello". Обратите внимание, как мы используем массив строк для возвращения значения в out параметре.
До этого SayHello вызывает SetComplete, чтобы сообщить MTS, что работа закончена и результаты можно принять:
MTx.GetObjectContext().SetComplete();
Заметьте, что этот компонент не нуждается в использовании транзакции, поскольку не выполняет никаких действий над совместно используемыми значимыми данными. Компонент не вызывает никаких менеджеров ресурсов (за информацией о менеджерах ресурсов обращайтесь к MTS 1.0 Programmers Guide). Здесь мы используем транзакцию только чтобы показать, как разрабатывать работающие с транзакциями компоненты. В панели Transaction Statistics MTS Explorer вы можете посмотреть, как этот компонент вызывает транзакции.
Скомпилируем реализацию CHelloObj:
C:\src\hellojtx>JVC Hellojtx\HelloObj.java
Эта компиляция создаст файл HelloObj.class, содержащий байт-код Java, интерпретируемый Java VM во время исполнения. Поскольку HelloObj относится к пакету Hellojtx, HelloObj.class должен находиться в каталоге Hellojtx.
Теперь у нас имеются все составные части, необходимые для создания helppjtx DLL: библиотека типов, wrapper-класс для интерфейса IHellojtx и Java-класс, реализующий COM-класс Hellojtx.Hello. Для создания hellojtx COM DLL запустите из командной строки в корневом каталоге exegen.exe:
C:\src\hellojtx>C:\MTX\TOOLS\EXEGEN /d /r /out:hellojtx.dll hellojtx.tlb *.class
Ключ /d командует EXEGEN создать DLL, а ключ /out приказывает EXEGEN назвать эту DLL hellojtx.dll. Ключ /r заставит EXEGEN пройти по подкаталогу Hellojtx, где он обнаружит три файла классов (CHellojtx.class, IHellojtx.class и HelloObj.class). EXEGEN поместит копии файлов классов в ветку ресурсов hellojtx.dll.
При исполнении hellojtx.dll будет использовать Java VM (msjava.dll) как COM-сервер для класса Hellojtx.Hello.
Microsoft Java VM (msjava.dll) умеет прикинуться inproc COM-сервером. Для реализации класса Hellojtx.Hello VM будет интерпретировать байт-код Java-класса HelloObj. Чтобы преобразовать входящие вызовы COM-методов в вызовы методов Java, Java VM будет использовать IHellojtx интерфейс wrapper. Оба эти класса находятся в ресурсах фала hellojtx.dll.
Замечание: CHellojtx.class реально не нуждается в помещении в DLL. При исполнении Java VM не нуждается в загрузке wrappers COM-классов, реализуемых DLL.
Откройте MTS Explorer и создайте новый пакет с названием "hellojtx." Если вам не приходилось, создавать новых пакетов в MTS, просто следуйте указаниям, перечисленным в MTS Explorer Help Topics в разделе "Show me how to ... create a new empty package.".
Вслед за этим выберите hellojtx.dll в Windows Explorer, и перетащите DLL в пустой пакет. Готово! MTS Explorer выполнит всю работу по конфигурированию нового компонента.
Может показаться, что для создание Java-компонента для MTS отнимает очень много времени и сил. Однако только два из выполненных нами шагов требуют написания кода: создание IDL и реализация Java-классов. Два других шага выполняются с использованием GUI-средств: создание GUID и развертывание DLL в MTS.
Остальные шаги (запуск MIDL, JAVATLB, JAVAGUID, JVC и EXEGEN) могут быть автоматизированы с помощью batch-файла. В этом примере мы приведем batch-файл, используемый для создания Hellojtx.
Листинг 3. Batch-файл (build.bat) для 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
Прежде, чем мы сможем увидеть работу компонента Hellojtx.Hello под Microsoft Transaction Server, нужно построить какое-либо клиентское приложение. Рассмотрим написание клиента на Java и Visual Basic.
Исходный текст Java-клиента состоит из единственного Java-файла, Client.java.
Листинг 4. Реализация Java-клиента.
import Hellojtx.*; public class Client { public static void main(String args[]) { Ihellojtx myHello; String strRet[] = { "<no returned data>" }; 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.java импортирует пакет Hellojtx:
Import Hellojtx.*;
Это позволяет клиенту пропускать имя пакета
при обращениях к IHellojtx и CHellojtx.
Заставить клиента создать и вызвать компонент
Hellojtx.Hello - важный шаг в построении клиента. Вот
верный способ:
Ihellojtx myHello; MyHello = (IHellojtx) new Chellojtx(); Nret = myHello.SayHello(strRet);
Клиент создает компонент Hellojtx.Hello, используя ключевое слово new, выдавая в качестве аргумента имя, указанное как coclass в .idl-файле (CHellojtx). затем Client.java передает результат интерфейсу (в данном случае Ihellojtx).
Этот код работает, поскольку CHellojtx.class - COM wrapper. Когда Java VM загружает этот класс, она знает, что следует создать реализацию COM-класса Hellojtx.Hello.
Замечание: Хотя это и кажется очевидным, определение класса реализации объекта (например, HelloObj) как аргумента для ключевого слова Java "new" работать не будет.
// Плохой код - работать не будет. HelloObj myHello; MyHello = new HelloObj(); Nret = myHello.SayHello(strRet);
Этот код вызовет runtime exception наподобие следующей:
Exception: java.lang.NullPointerException java.lang.NullPointerException at Hellojtx/HelloObj.SayHello at Client.main
Еще раз обратите внимание, что клиент использует массива строк для получения SayHello's out параметра:
String strRet[] = { "<no returned data>" }; int nRet; <other code> nRet = myHello.SayHello(strRet);
Во втором операторе try, SayHello освобождает myHello и вызывает сборщика мусора Java (Java garbage collector):
myHello = null; System.gc();
Эти вызовы не обязательны. Если их нет, компонент Hellojtx будет жить до тайм-аута DCOM-соединения (по умолчанию, шесть минут). Наличие этих вызовов позволит немедленно уничтожить компонент.
Для этого следует использовать Microsoft Java compiler (JVC):
C:\src\hellojtx>jvc Client.java
В случае, если JVC может найти пакет Hellojtx, компилятор создаст Client.class. Если же JVC не сможет найти пакет, компилятор выдаст ошибку типа следующей:
Client.java(1,8) : error J0051: Undefined package 'Hellojtx'
В этом примере клиент создается в корневом каталоге проекта. JVC найдет нужные классы (CHellojtx.class и IHellojtx.class) в подкаталоге Hellojtx . Если классы расположены в другом каталоге, компилятор не сможет создать клиента.
Чтобы сделать классы Hellojtx общедоступными, создайте пакет в каталоге Java-класов вашей машины. В этом примере мы создадим подкаталог Hellojtx в c:\winnt\java\trustlibи скопируем туда CHellojtx.class и Ihellojtx.class.
Заметьте, что клиентам не нужен класс HelloObj. Java VM, требующая этот класс во врем выполнения, Java VM найдет его в ресурсной части of hellojtx.dll.
Запустите Microsoft Transaction Server Explorer. Убедитесь с помощью меню Tools Explorer'а, что Microsoft Distributed Transaction Coordinator (MSDTC) запущен - если нет, запустите его.
Теперь мы готовы запустить Java-клиента, используя Microsoft Command-line Loader for Java (jview.exe). Результат запуска клиента:
C:\src\hellojtx>jview Client Calling SayHello.. nRet = 0 strRet = Hello from simple MTS Java sample Hit any key to exit..
Пока вы не закрыли клиентское приложение, в MTS Explorer можно увидеть , что компонент Hellojtx работает. Убедиться, что компонент исполняет транзакции MSDTC, можно в панели Transaction Statistics .
Рис.1 Hellojtx.Hello запущен под управлением Microsoft Transaction Server.
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
До построения этого кода используйте диалог Visual Basic Project References, чтобы "втянуть" ссылку на библиотеку типов Hellojtx; ссылка будет выведена под строкой подсказки, указанной в hellojtx.idl ("Simple Microsoft Transaction Server sample, written in Java").
Единственная хитрость здесь в знании, какой из идентификаторов классов использовать при объявлении переменной myHello и реализации объекта. В Visual Basic 5.0 при объявлении переменной для объекта Hellojtx используйте имя coclass-a, указанное в .idl-файле ("CHellojtx"). В качестве аргумента для CreateObject используйте ProgID, указанный в аттрибуте PROGID ("Hellojtx.Hello").
Удаленное исполнение клиентов Visual Basic или Java очень похоже на запуск клиентов на одной машине с серверным компонентом Hellojtx.
Начните с использования Microsoft Transaction Server Explorer для конфигурирования Hellojtx.Hello как удаленного (Remote) компонента на клиентском компьютере. Explorer добавит все необходимые вхождения в реестр. (Если вы до этого не инсталлировали MTS Remote Component, обратитесь к разделу "Configuring Remote Components" в помощи к MTS Explorer).
Для запуска удаленного клиента Visual Basic:
Скопируйте исполняемый файл Visual Basic (Client.exe) на клиентскую машину. Убедитесь, что на обеих машинах запущен MTS, и что на сервере работает MSDTC. Теперь запустите Client.exe. Компонент Client свяжется с серверным компонентом Hellojtx на удаленной машине.
Для запуска удаленного клиента Java:
Скопируйте Java-класс (Client.class) на клиентскую машину. Так как Java VM нуждается при исполнении клиента в локальном доступе к Hellojtx's COM wrappers, скопируйте файлы классов Hellojtx в каталог Java-классов клиентской машины. В этом примере CHellojtx.class и IHellojtx.class были скопированы в подкаталог c:\winnt\java\trustlib\hellojtx клиентской машины.
Теперь используйте JVIEW для запуска Java-клиента, который свяжется с серверным компонентом Hellojtx, расположенным на удаленной машине.
Отладка - одна из областей, где написание компонента MTS на Java несколько менее удобно, чем на C++ или Visual Basic. Современные средства разработки не позволяют пошаговую отладку компонента, написанного на Java.
Один из способов получения отладочной информации по мере исполнения компонента под MTS заключается в использовании отладки типа "sprintf" . Например, можно добавить вызов System.out.println к оператору try в 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; }
После перестройки HelloObj.class и hellojtx.dll вы можете ожидать появления следующей строки в консольном окне при следующем использовании JVIEW для загрузки класса Client:
C:\src\hellojtx>jview Client
Calling SayHello..
nRet = 0
strRet = Hello from simple MTS Java sample
Hit any key to exit..
Однако Hellojtx и JVIEW исполняются в разных
процессах, так что ожидаемой строки вы не
увидите. Серверный компонент запускается в
особом замещающем процессе MTS (mtx.exe), заставляющем
println выдавать результат не в консольное окно JVIEW,
а в "bit bucket".
Чтобы вывести результат в консольное окно JVIEW,
нужно сконфигурировать Hellojtx для исполнения в
вызывающем его процессе (JVIEW). В панели Activation
диалога Properties Hellojtx сконфигурируйте Hellojtx на
исполнение в клиентском процессе.

Рис. 2. Конфигурация Hellojtx.Hello для
исполнения в его клиентском процессе.
Теперь перезагрузите класс Client. Вызовы Hellojtx
println будут видны:
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..
Формат компонентов MTS, написанных на Java
Этапы создания Hellojtx могут служить моделью для
создания любого серверного компонента MTS на
языке Java.
Метод SayHello, однако, может оказаться чересчур
ограниченным для использовании в качестве
модели метода компонента MTS. Следующий код
описывает общий формат методов компонентов MTS,
написанных на языке Java:
Public int MTSJavaMethod ()
{
IObjectContext context;
boolean success = false;
IFoo foo = null;
try
{
// Получаем MTS контекст
context = (IObjectContext) Mtx.GetObjectContext();
// занимаем ресурсы. для примера, соединение с базой данных.
// Используем ресурсы.
// Выполняем первую порцию работы для первого клиента
// Извлекаем другой MTS-компонент для выполнения другой работы
foo = (IFoo) context.CreateInstance(CFoo.clsid, IFoo.iid);
// все в порядке
success = true;
return 0;
}
catch (Exception e)
{
return -1;
}
finally
{
// освобождаем ресурсы
if (success) // Мы финишировали успешно
context.SetComplete();
else // Мы потерпели фиаско.
context.SetAbort();
}
}
Исходный текст примеров на
Java для MTS 1.0 Sample Bank иллюстрирует, как этот общий
формат методов Java реализован в Java-компонентах MTS.
Методы IMoveMoney.Perform и IAccount.Post, реализованные
классами ImoveMoney и Account показывают более полную
реализацию канонической формы "MTS на Java", что
и показано выше.
Исходный код Java для классов MoveMoney и Account
расположен в подкаталоге MTX\Samples\Account.VJ\Account.
Полную информацию по инсталляции и
использованию пакета Bank можно найти в Microsoft
Transaction Server Help в разделе "Validating Setup with a SQL Server
Transactional Component."