Пример простого приложения JBuilder-CORBA-Oracle

Источник: Jbuilder
Александр Лейтес

Введение

Простой пример приложения JBuilder-CORBA-Oracle, описанный в этой статье, предназначен для разработчиков, которые только начинают работу с Java и CORBA, но уже изучили основы этих технологий. В данной работе нет описания Java и CORBA, так как цель статьи - показать применение технологий Java+CORBA на практике. Читатель, интересующийся теорией, найдет всю необходимую информацию в литературе, список которой находится в конце статьи.

Пример демонстрирует:

  • Простой Java-CORBA сервер, построенный на основе VisiBroker, который легко использовать при разработке собственных CORBA-приложений.
  • Доступ к объектам этого сервера из приложения JBuilder.
  • Пример CORBA-интерфейса для навигации по таблице, вставки, редактирования и удаление записей.
  • Реализацию этого CORBA-интерфеса в JBuilder, использование простой сетки и пользовательского источника данных.

Основные характеристики примера:

Независимость от конкретной СУБД. CORBA-сервер использует для доступа к БД JDBC-драйвер, и поэтому может работать с любой СУБД для которой такой драйвер имеется.

Удобство отладки CORBA-объектов. Объекты могут использовать обычный print() для вывода отладочной информации в окно сервера.

Удобство отладки клиентских приложений. Например, утечки памяти могут быть легко обнаружены, так как сервер информирует о выделении и освобождении своих объектов. Поэтому, легко найти и устранить ошибки освобождения интерфейсов в клиентской программе, просто глядя в окно сервера, который может работать на том же компьютере.

Просмотр и редактирование результатов запросов в сетке JBuilder. Сетка является удобным инструментом для просмотра, вставки, редактирования и удаления данных. Стандартный пример ProviderResolver из JBuilder показывает, как можно использовать нестандартный источник данных в случае текстового файла, однако в данном примере показано, как применить эту возможность непосредственно к объектам CORBA. Кроме того, исправлены ошибки, которые содержит стандартный пример.

Конечно, при промышленной эксплуатации CORBA-объектов, следует использовать один из серверов приложений, имеющихся в настоящее время на рынке (например, Borland AppServer). Однако, для разработки и тестирования простых приложений, такого "минимального" сервера вполне достаточно.

Установка

Для установки и запуска примера необходимы следующие продукты:

  • VisiBroker for Java 4.5 компании Inprise
  • JBuilder 4.0 компании Inprise
  • Oracle 8
  • Oracle 8 JDBC driver: Oracle817classes12.zip (более ранний драйвер содержит ошибки)

После установки JBuilder, необходимо настроить среду для работы с VisiBroker, используя Enterprise Setup (подробности см. в документации к JBuilder). Также следует проверить, что переменная окружения CLASSPATH содержит пути ко всем необходимым драйверам и библиотекам.

Пример расположен в каталоге OraCorbaSample . Для сборки сервера необходимо зайти в каталог Ora\CorbaSample\corba-server и выполнить следующие команды:

prompt> mkserver - сборка сервера

prompt> mkuser - сборка примера

Также следует в оболочке SQL Plus от SCOTT/TIGER выполнить скрипт user\db.sql , который содержит объекты, необходимые для работы примера.

Тестирование сервера:

  • Настройте параметр JdbcURL в файле db.properties на реальный сервер сети.
  • Запустите VisiBroker Smart Agent командой osagent .
  • Запустите сервер командой server.bat .
  • Запустите клиента командой client.bat . На экране должны появиться строки из таблицы EMP , которая находится в стандартной схеме SCOTT/TIGER . Строки появляются в цикле 3 раза.

Для сборки клиента, необходимо при помощи JBuilder собрать проект

OraCorbaSample\jb-client\CORBA_Grid.jpx и запустить его. Не забудьте настроить среду JBuilder для использования VisiBroker (см. выше).

На экране должна появиться сетка с записями из таблицы EMP (служащие). Попробуйте отредактировать запись, добавить, удалить.

Описание структуры каталогов сервера

Структура каталогов сервера имеет следующий вид:

  • Database - вспомогательные классы сервера
  • DBExample - вспомогательные классы для объектов примера
  • DBObject - дополнительные интерфейсы БД

server - классы сервера

test - классы для тестирования объектов примера

user - каталог для объектов пользователя по-умолчанию

Первые три каталога создаются компилятором интерфейсов idl2java автоматически, появляются после компиляции сервера и содержат вспомогательные классы, необходимые для работы объектов совместно с VisiBroker.

Каталог server содержит классы, которые собственно и являются сервером объектов CORBA. Сервер создает и уничтожает пользовательские объекты по запросу приложения-клиента. Процесс создания пользовательских объектов описан ниже.

Каталог test содержит классы для тестирования объектов. Это необязательные программы, написанные пользователем, основным назначением которых является проверка функционирования разработанных объектов. Тестирование объектов сразу после их создания, является хорошей практикой и позволяет обнаружить ошибки на ранней стадии, до работы над реальным приложением, использующим GUI .

Каталог user является каталогом пользовательских объектов по-умолчанию. Допускается существование и других каталогов объектов, однако в этом случае нужно явно указывать путь к объекту, например MyPackage.MyObject . Каталог user также содержит класс DefaultConnection , который облегчает перенос пользовательских объектов в другую CORBA-среду.

Корневой каталог сервера содержит следующие файлы:

clean.bat - очистка каталогов

client.bat - запуск тестового клиента

mkserver.bat - компиляция сервера, очистка каталогов сервера

mkuser.bat - компиляция клиента, очистка каталогов клиента

server.bat - запуск сервера

db.properties - файл настройки сервера

Файлы client.bat, mkuser.bat не являются файлами общего назначения и нужны только для сборки и запуска конкретного примера, тогда как файлы mkserver.bat и server.bat предназначены для сборки и запуска сервера объектов.

IDL-интерфесы сервера

Интерфейсы сервера описаны в файле server\db.id l (модуль Database ) и являются ключевыми для взаимодействия с БД.

  • SessionManager - Управляет соединениями с БД, выделяя и освобождая соединения по запросу клиента. Этот интерфейс имеет только два метода: getSession() и releaseSession() , название которых говорит само за себя.
  • Session - Соединение с БД. Объекты БД выделяются в контексте сессии, которой они принадлежат. При освобождении сессии она освобождает все выделенные объекты. Методы объекта Session: commit(), rollback(), getUID(), getObject(), releaseObject() . Наибольший интерес представляют методы getObject() и releaseObject() , так как они могут выделять и освобождать любые объекты. Метод getObject() возвращает объект CORBA::Object, который преобразуется клиентским приложением в конкретный объект с помощью метода XXXHelper.narrow() (см. документацию к VisiBroker for Java). Доступ к объекту осуществляется по его имени. Имя объекта совпадает с именем класса реализации без расширения . class . Если объект расположен каталоге отличном от user , то в имени необходимо указать полную спецификацию объекта: MyPackage.MyObject . Методу releaseObject() необходимо передать ссылку на объект CORBA::Object. Метод getUID() возвращает уникальный ID записи, вызывая хранимую процедуру БД: getuid() , и передавая ей в качестве параметра имя объекта. Естественно, процедура должна быть создана заранее. Заметим, что приложение может не использовать этот метод совсем. Метод сделан для удобства разработки графических клиентских приложений, которые используют сетку для просмотра и редактирования данных. Функция getuid() для Oracle находится в файле user\db.sql и используется клиентом JBuilder.

Дополнительные объекты сервера

Интерфейсы вспомогательных объектов сервера определены в модуле DBObject файла server\db.idl и могут использоваться пользователем для упрощения разработки:

  • DBException - Исключительная ситуация.
  • BaseDataSet - Основной источник данных.
  • MultiRecordDataSet - Источник данных, который может содержать множество записей.

Следует отметить, что эти интерфейсы - тоже примеры и использовать их необязательно. Более того, их использование может вызвать необходимость изменения исходных . idl -файлов (добавление модуля DBObject ) при переносе объектов в другую среду. Однако они удобны, так как предоставляют самые основные ф-ии источника данных. Например, если объект унаследован от BaseDataSet , то сессия автоматически вызывает метод BaseDataSet.close() при удалении объекта, которым она владеет. Это может предотвратить утечку ресурсов (программист забывает закрыть/удалить объект), почти неизбежно возникающую в больших проектах.

Описание работы сервера

Класс DBServer (файл DBServer.java ) содержит ф-ию main() , которая и запускает сервер объектов. Сервер начинает свою работу с инициализации ORB. Затем сервер создает новый POA-адаптер, сервант, реализующий менеджер сессий, и активизирует сервант на созданном ранее POA. После активизации менеджера адаптера и вызова метода orb.run() , сервер ожидает запросов от клиентов в бесконечном цикле.

Запросы клиентов обслуживает сервант менеджера сессий, реализующий интерфейс SessionManager. Клиенты могут получить доступ к объектам БД только через этот интерфейс, так как остальные объекты создаются и регистрируются внутри сервера и не видны снаружи. После получения ссылки на интерфейс SessionManager, клиент вызывает метод SessionManager.getSession() для доступа к объекту Session. При вызове этого метода сервер создает сервант, реализующий интерфейс Session и активизирует его на POA-адаптере по-умолчанию. Сессия в свою очередь устанавливает JDBC-соединение с БД. Именно в контексте объекта "сессия" создаются конкретные объекты, реализующие интерфейсы для доступа к БД. Объекты создаются методом Session.getObject() . Этот метод может создавать объекты любого типа, так как возвращает объект CORBA::Object, который является предком всех CORBA-объектов. Клиент может получить конкретный объект, выполнив приведение типа при помощи метода XXXHelper.narrow() .

Сервер обслуживает пользовательские объекты, которые имеют конструктор без параметров. Это сделано для обеспечения лучшей переносимости объектов в другие среды (например, в JServer Oracle). Тогда возникает вопрос. Как пользовательским объектам передается JDBC-соединение c БД: Connection? Для этого создается специальная хэш-таблица: ConnectionTable , в которую помещаются пары объект-соединение. Элемент объект-соединение добавляется в таблицу после создания объекта, поэтому не нужно пытаться получить соединение Connection в конструкторе, так как там оно будет равняться null . Лучше поместить код получения соединения в специальный метод, и вызывать его по мере необходимости (см. EmpImpl.java). Таблица ConnectionTable является "глобальным" объектом, так как доступ к ней осуществляется при помощи статического метода ConnectionTable.getInstance() , который создает только один экземпляр таблицы и сохраняет его в статической переменной класса.

Следует отметить, что возможны различные подходы к организации работы с соединениями. Например, вместо того, чтобы устанавливать соединение при создании объекта Session, можно было бы реализовать пул соединений и организовать работу таким образом, чтобы пользовательские объекты получали соединение на время выполнения какого-либо действия с БД, и возвращали его обратно в пул, после того как это действие выполнено. В этом случае можно было бы уменьшить количество соединений с БД (кол-во клиентов > кол-во соединений), так как объекты удерживают постоянное соединение с БД только на время выполнения коротких операций. Однако, в данном примере используется подход с постоянным соединением, так как он проще и кроме того, позволяет клиенту явно управлять транзакциями.

Сессии и выделенные объекты освобождаются при помощи методов releaseSession()/releaseObject() . При этом сервер деактивизирует объект, делая его недоступным для клиента, и присваивает ссылке на объект значение null, чтобы отдать его сборщику мусора Java.

Создание пользовательских объектов

При создании пользовательских объектов следует придерживаться следующих правил:

  • Выбрать каталог, в котором будут находится объекты. По-умолчанию используется каталог user , однако пользователь может создать свой собственный каталог, с названием, характеризующим разрабатываемое приложение.
  • Создать в этом каталоге файл интерфейсов: name.idl (см. например, user\example.idl).
  • Откомпилировать получившийся . idl -файл при помощи компилятора VisiBroker idl2java .
  • Создать класс объекта (см. user\EmpImp.java). Каждый объект должен реализовывать один и только один интерфейс из .idl-файла приложения. Если интерфейс является производным от другого интерфейса, то класс должен реализовать все методы реализуемого интерфейса и его предков. Класс объекта должен быть унаследован от соответствующего серванта. Код серванта и пакет, в котором он расположен, должны появиться автоматически, после компиляции . idl -файла.
  • Откомпилировать получившийся класс с помощью компилятора VisiBroker vbjc .

Работа с пользовательскими объектами

После создания объекта, желательно выполнить его тестирование. Для тестирование объекта необходимо создать класс-приложение. Пример такого приложения находится в каталоге test : test\EmpClient.java . Это приложение тестирует объект примера EmpImpl.

Правила работы с объектом:

  • Инициализировать ORB.
  • Получить доступ к менеджеру сессий SessionManager , вызвав метод bind() : SessionManager seMgr = Database.SessionManagerHelper.bind(orb, "semgr_poa", "SessionManager".getBytes()).
  • Создать новую сессию Session с помощью вызова метода getSession(): Session mySession = seMgr.getSession("user", "passwd", autoCommitFlag).
  • Создать в контексте данной сессии требуемый объект: org.omg.CORBA.Object myObject = mySession.getObject("myPackage.myObject").
  • Выполнить приведение типа: XXX myXXX = XXXHelper.narrow(myObject) , где XXX обозначает конкретное имя интерфейса, который данный объект реализует.
  • Вызвать методы интерфейса объекта.
  • После окончания работы с объектом освободить его, вызвав метод mySession.releaseObject(myObject).
  • После завершения работы с сессией освободить объект методом seMgr.releaseSession(mySession).

Следует отметить, что для объектов расположенных в каталоге user указывать полную спецификацию объекта необязательно. Достаточно одного имени.

Метод bind() не является стандартом CORBA и реализован только в VisiBroker , однако он достаточно удобен в применении. Для лучшей переносимости следует использовать стандартный сервис имен CORBA, однако это требует запуска дополнительного модуля, реализующей этот сервис. Так как данный сервер не является только примером, то этот компонент опущен, хотя его реализация достаточно тривиальна.

Описание клиентского приложения, реализованного на JBuilder

Пример простого приложения JBuilder-CORBA-Oracle
Автор: Александр Лейтес aleytes@mail.ru
www.blacksoftcastle.com
Введение

Про CORBA и Java написано много замечательных книг (см. [1], [2], [3]), которые также содержат примеры приложений. Но когда наступает время разработать что-то реальное, сразу возникают вопросы, о которых авторы либо не пишут, либо пишут недостаточно подробно, либо информация давно устарела, что в случае с CORBA случается довольно часто. Справедливости ради, стоит отметить, что многие книги и не ставят перед собой таких целей, да и невозможно объять необъятное.

Простой пример приложения JBuilder-CORBA-Oracle, описанный в этой статье, предназначен для разработчиков, которые только начинают работу с Java и CORBA, но уже изучили основы этих технологий. В данной работе нет описания Java и CORBA, так как цель статьи - показать применение технологий Java+CORBA на практике. Читатель, интересующийся теорией, найдет всю необходимую информацию в литературе, список которой находится в конце статьи.

Прилагаются полные исходные тексты примера, которые можно использовать в собственных разработках безо всяких ограничений. (Прим: примеры находятся в ZIP-архиве статьи).

Пример демонстрирует:

Простой Java-CORBA сервер, построенный на основе VisiBroker, который легко использовать при разработке собственных CORBA-приложений.
Доступ к объектам этого сервера из приложения JBuilder.
Пример CORBA-интерфейса для навигации по таблице, вставки, редактирования и удаление записей.
Реализацию этого CORBA-интерфеса в JBuilder, использование простой сетки и пользовательского источника данных.
Основные характеристики примера:

Независимость от конкретной СУБД. CORBA-сервер использует для доступа к БД JDBC-драйвер, и поэтому может работать с любой СУБД для которой такой драйвер имеется.

Удобство отладки CORBA-объектов. Объекты могут использовать обычный print() для вывода отладочной информации в окно сервера.

Удобство отладки клиентских приложений. Например, утечки памяти могут быть легко обнаружены, так как сервер информирует о выделении и освобождении своих объектов. Поэтому, легко найти и устранить ошибки освобождения интерфейсов в клиентской программе, просто глядя в окно сервера, который может работать на том же компьютере.

Просмотр и редактирование результатов запросов в сетке JBuilder. Сетка является удобным инструментом для просмотра, вставки, редактирования и удаления данных. Стандартный пример ProviderResolver из JBuilder показывает, как можно использовать нестандартный источник данных в случае текстового файла, однако в данном примере показано, как применить эту возможность непосредственно к объектам CORBA. Кроме того, исправлены ошибки, которые содержит стандартный пример.

Конечно, при промышленной эксплуатации CORBA-объектов, следует использовать один из серверов приложений, имеющихся в настоящее время на рынке (например, Borland AppServer). Однако, для разработки и тестирования простых приложений, такого "минимального" сервера вполне достаточно.

Установка
Для установки и запуска примера необходимы следующие продукты:

VisiBroker for Java 4.5 компании Inprise: http://www.inprise.com/
JBuilder 4.0 компании Inprise
Oracle 8: http://www.oracle.com/
Oracle 8 JDBC driver: Oracle817classes12.zip (более ранний драйвер содержит ошибки)
После установки JBuilder, необходимо настроить среду для работы с VisiBroker, используя Enterprise Setup (подробности см. в документации к JBuilder). Также следует проверить, что переменная окружения CLASSPATH содержит пути ко всем необходимым драйверам и библиотекам.

Пример расположен в каталоге OraCorbaSample. Для сборки сервера необходимо зайти в каталог Ora\CorbaSample\corba-server и выполнить следующие команды:

prompt> mkserver - сборка сервера

prompt> mkuser - сборка примера

Также следует в оболочке SQL Plus от SCOTT/TIGER выполнить скрипт user\db.sql, который содержит объекты, необходимые для работы примера.

Тестирование сервера:

Настройте параметр JdbcURL в файле db.properties на реальный сервер сети.
Запустите VisiBroker Smart Agent командой osagent.
Запустите сервер командой server.bat.
Запустите клиента командой client.bat. На экране должны появиться строки из таблицы EMP, которая находится в стандартной схеме SCOTT/TIGER. Строки появляются в цикле 3 раза.
Для сборки клиента, необходимо при помощи JBuilder собрать проект

OraCorbaSample\jb-client\CORBA_Grid.jpx и запустить его. Не забудьте настроить среду JBuilder для использования VisiBroker (см. выше).

На экране должна появиться сетка с записями из таблицы EMP (служащие). Попробуйте отредактировать запись, добавить, удалить.

Описание структуры каталогов сервера
Структура каталогов сервера имеет следующий вид:

Database - вспомогательные классы сервера
DBExample - вспомогательные классы для объектов примера
DBObject - дополнительные интерфейсы БД
server - классы сервера

test - классы для тестирования объектов примера

user - каталог для объектов пользователя по-умолчанию

Первые три каталога создаются компилятором интерфейсов idl2java автоматически, появляются после компиляции сервера и содержат вспомогательные классы, необходимые для работы объектов совместно с VisiBroker.

Каталог server содержит классы, которые собственно и являются сервером объектов CORBA. Сервер создает и уничтожает пользовательские объекты по запросу приложения-клиента. Процесс создания пользовательских объектов описан ниже.

Каталог test содержит классы для тестирования объектов. Это необязательные программы, написанные пользователем, основным назначением которых является проверка функционирования разработанных объектов. Тестирование объектов сразу после их создания, является хорошей практикой и позволяет обнаружить ошибки на ранней стадии, до работы над реальным приложением, использующим GUI.

Каталог user является каталогом пользовательских объектов по-умолчанию. Допускается существование и других каталогов объектов, однако в этом случае нужно явно указывать путь к объекту, например MyPackage.MyObject. Каталог user также содержит класс DefaultConnection, который облегчает перенос пользовательских объектов в другую CORBA-среду.

Корневой каталог сервера содержит следующие файлы:

clean.bat - очистка каталогов

client.bat - запуск тестового клиента

mkserver.bat - компиляция сервера, очистка каталогов сервера

mkuser.bat - компиляция клиента, очистка каталогов клиента

server.bat - запуск сервера

db.properties - файл настройки сервера

Файлы client.bat, mkuser.bat не являются файлами общего назначения и нужны только для сборки и запуска конкретного примера, тогда как файлы mkserver.bat и server.bat предназначены для сборки и запуска сервера объектов.

IDL-интерфесы сервера

Интерфейсы сервера описаны в файле server\db.idl (модуль Database) и являются ключевыми для взаимодействия с БД.

SessionManager - Управляет соединениями с БД, выделяя и освобождая соединения по запросу клиента. Этот интерфейс имеет только два метода: getSession() и releaseSession(), название которых говорит само за себя.
Session - Соединение с БД. Объекты БД выделяются в контексте сессии, которой они принадлежат. При освобождении сессии она освобождает все выделенные объекты. Методы объекта Session: commit(), rollback(), getUID(), getObject(), releaseObject(). Наибольший интерес представляют методы getObject() и releaseObject(), так как они могут выделять и освобождать любые объекты. Метод getObject() возвращает объект CORBA::Object, который преобразуется клиентским приложением в конкретный объект с помощью метода XXXHelper.narrow() (см. документацию к VisiBroker for Java). Доступ к объекту осуществляется по его имени. Имя объекта совпадает с именем класса реализации без расширения .class. Если объект расположен каталоге отличном от user, то в имени необходимо указать полную спецификацию объекта: MyPackage.MyObject. Методу releaseObject() необходимо передать ссылку на объект CORBA::Object. Метод getUID() возвращает уникальный ID записи, вызывая хранимую процедуру БД: getuid(), и передавая ей в качестве параметра имя объекта. Естественно, процедура должна быть создана заранее. Заметим, что приложение может не использовать этот метод совсем. Метод сделан для удобства разработки графических клиентских приложений, которые используют сетку для просмотра и редактирования данных. Функция getuid() для Oracle находится в файле user\db.sql и используется клиентом JBuilder.
Дополнительные объекты сервера
Интерфейсы вспомогательных объектов сервера определены в модуле DBObject файла server\db.idl и могут использоваться пользователем для упрощения разработки:

DBException - Исключительная ситуация.
BaseDataSet - Основной источник данных.
MultiRecordDataSet - Источник данных, который может содержать множество записей.
Следует отметить, что эти интерфейсы - тоже примеры и использовать их необязательно. Более того, их использование может вызвать необходимость изменения исходных .idl-файлов (добавление модуля DBObject) при переносе объектов в другую среду. Однако они удобны, так как предоставляют самые основные ф-ии источника данных. Например, если объект унаследован от BaseDataSet, то сессия автоматически вызывает метод BaseDataSet.close() при удалении объекта, которым она владеет. Это может предотвратить утечку ресурсов (программист забывает закрыть/удалить объект), почти неизбежно возникающую в больших проектах.

Описание работы сервера
Класс DBServer (файл DBServer.java) содержит ф-ию main(), которая и запускает сервер объектов. Сервер начинает свою работу с инициализации ORB. Затем сервер создает новый POA-адаптер, сервант, реализующий менеджер сессий, и активизирует сервант на созданном ранее POA. После активизации менеджера адаптера и вызова метода orb.run(), сервер ожидает запросов от клиентов в бесконечном цикле.

Запросы клиентов обслуживает сервант менеджера сессий, реализующий интерфейс SessionManager. Клиенты могут получить доступ к объектам БД только через этот интерфейс, так как остальные объекты создаются и регистрируются внутри сервера и не видны снаружи. После получения ссылки на интерфейс SessionManager, клиент вызывает метод SessionManager.getSession() для доступа к объекту Session. При вызове этого метода сервер создает сервант, реализующий интерфейс Session и активизирует его на POA-адаптере по-умолчанию. Сессия в свою очередь устанавливает JDBC-соединение с БД. Именно в контексте объекта "сессия" создаются конкретные объекты, реализующие интерфейсы для доступа к БД. Объекты создаются методом Session.getObject(). Этот метод может создавать объекты любого типа, так как возвращает объект CORBA::Object, который является предком всех CORBA-объектов. Клиент может получить конкретный объект, выполнив приведение типа при помощи метода XXXHelper.narrow().

Сервер обслуживает пользовательские объекты, которые имеют конструктор без параметров. Это сделано для обеспечения лучшей переносимости объектов в другие среды (например, в JServer Oracle). Тогда возникает вопрос. Как пользовательским объектам передается JDBC-соединение c БД: Connection? Для этого создается специальная хэш-таблица: ConnectionTable, в которую помещаются пары объект-соединение. Элемент объект-соединение добавляется в таблицу после создания объекта, поэтому не нужно пытаться получить соединение Connection в конструкторе, так как там оно будет равняться null. Лучше поместить код получения соединения в специальный метод, и вызывать его по мере необходимости (см. EmpImpl.java). Таблица ConnectionTable является "глобальным" объектом, так как доступ к ней осуществляется при помощи статического метода ConnectionTable.getInstance(), который создает только один экземпляр таблицы и сохраняет его в статической переменной класса.

Следует отметить, что возможны различные подходы к организации работы с соединениями. Например, вместо того, чтобы устанавливать соединение при создании объекта Session, можно было бы реализовать пул соединений и организовать работу таким образом, чтобы пользовательские объекты получали соединение на время выполнения какого-либо действия с БД, и возвращали его обратно в пул, после того как это действие выполнено. В этом случае можно было бы уменьшить количество соединений с БД (кол-во клиентов > кол-во соединений), так как объекты удерживают постоянное соединение с БД только на время выполнения коротких операций. Однако, в данном примере используется подход с постоянным соединением, так как он проще и кроме того, позволяет клиенту явно управлять транзакциями.

Сессии и выделенные объекты освобождаются при помощи методов releaseSession()/releaseObject(). При этом сервер деактивизирует объект, делая его недоступным для клиента, и присваивает ссылке на объект значение null, чтобы отдать его сборщику мусора Java.

Создание пользовательских объектов
При создании пользовательских объектов следует придерживаться следующих правил:

Выбрать каталог, в котором будут находится объекты. По-умолчанию используется каталог user, однако пользователь может создать свой собственный каталог, с названием, характеризующим разрабатываемое приложение.
Создать в этом каталоге файл интерфейсов: name.idl (см. например, user\example.idl).
Откомпилировать получившийся .idl-файл при помощи компилятора VisiBroker idl2java.
Создать класс объекта (см. user\EmpImp.java). Каждый объект должен реализовывать один и только один интерфейс из .idl-файла приложения. Если интерфейс является производным от другого интерфейса, то класс должен реализовать все методы реализуемого интерфейса и его предков. Класс объекта должен быть унаследован от соответствующего серванта. Код серванта и пакет, в котором он расположен, должны появиться автоматически, после компиляции .idl-файла.
Откомпилировать получившийся класс с помощью компилятора VisiBroker vbjc.
Работа с пользовательскими объектами
После создания объекта, желательно выполнить его тестирование. Для тестирование объекта необходимо создать класс-приложение. Пример такого приложения находится в каталоге test: test\EmpClient.java. Это приложение тестирует объект примера EmpImpl.

Правила работы с объектом:

Инициализировать ORB.
Получить доступ к менеджеру сессий SessionManager, вызвав метод bind(): SessionManager seMgr = Database.SessionManagerHelper.bind(orb, "semgr_poa", "SessionManager".getBytes()).
Создать новую сессию Session с помощью вызова метода getSession(): Session mySession = seMgr.getSession("user", "passwd", autoCommitFlag).
Создать в контексте данной сессии требуемый объект: org.omg.CORBA.Object myObject = mySession.getObject("myPackage.myObject").
Выполнить приведение типа: XXX myXXX = XXXHelper.narrow(myObject), где XXX обозначает конкретное имя интерфейса, который данный объект реализует.
Вызвать методы интерфейса объекта.
После окончания работы с объектом освободить его, вызвав метод mySession.releaseObject(myObject).
После завершения работы с сессией освободить объект методом seMgr.releaseSession(mySession).
Следует отметить, что для объектов расположенных в каталоге user указывать полную спецификацию объекта необязательно. Достаточно одного имени.

Метод bind() не является стандартом CORBA и реализован только в VisiBroker, однако он достаточно удобен в применении. Для лучшей переносимости следует использовать стандартный сервис имен CORBA, однако это требует запуска дополнительного модуля, реализующей этот сервис. Так как данный сервер не является только примером, то этот компонент опущен, хотя его реализация достаточно тривиальна.

Описание клиентского приложения, реализованного на JBuilder

Клиентское приложение, написанное на JBuilder использует компонент JdbTable для просмотра и редактирования записей таблицы EMP . При этом, используется пользовательский источник данных EmpProvider , унаследованный от стандартного класса JBuilder: Provider . Для сохранения отредактированных данных используется класс EmpResolver , унаследованный от стандартного класса JBuilder: Resolver . Реализация этих классов во многом повторяет реализацию классов ProviderBean и ResolverBean из примера ProviderResolver , который поставляется вместе с JBuilder, однако, вместо чтения текстового файла используются вызовы методов интерфейса объектов.

Имеется также еще одно небольшое отличие: для получения уникального идентификатора записи, используется метод Session.getUID() , описанный ранее. Дело в том, что пример ProviderResolver содержит ошибку, которая не позволяет ввести новую запись, сохранить ее, а затем обновить без перезапроса данных. Причина ошибки: ROWID записи формируется при пересылке данных в файл и не сохраняется в сетке. Поэтому программа не знает, какую запись ей обновлять. Для устранения этого недостатка, в примере CORBA_Grid определяется событие источника данных - inserted() , которое происходит после добавления в сетку новой записи. Внутри этого события новой записи присваивается уникальный идентификатор: recordUID = Session.getUID("object_name").

Замечания

  • Описанная модель является примером и поэтому имеет существенные недостатки. Например, получение новой строки данных с помощью вызова метода next() не является эффективным, так как приводит к неоправданному росту сетевого траффика и замедлению работы приложения. Передача ограниченных массивов данных могла бы решить эту проблему. Вторым примером является получение всех данных сразу, что также неэффективно, да и не нужно на практике. JdbcTable имеет ряд методов, которые позволяют извлекать данные по требованию, например, когда пользователь доходит до последней записи при прокрутке.
  • В приложениях, которые предназначены для работы в Интернет, следует по возможности избегать интерфейсов, которые используют сетки данных, таблицы со связями master-detail и т.п., так как при доступе к данным через Интернет, это работает довольно долго. Разработка приложений, не использующих сетки, ничем не отличается (с точки зрения CORBA) от разработки приложений, которые их используют.
  • Не следует передавать строки данных как wstring . В типе данных CORBA wstring каждый символ кодируется двумя байтами (UNICODE), что приводит к неоправданному росту количества передаваемых по сети данных. Более эффективным способом является передача строк как массива octet , который является потоком байтов, и достаточен для хранения русских символов. В примере показана эта возможность (см. example.idl ).

Список литературы

1. "Основы CORBA". Роберт Орфали, Дэн Харки, Джери Эдвардс. Издательство "МАЛИП" 1999.

2. "JAVA и CORBA в приложениях клиент-сервер". Роберт Орфали, Дэн Харки. Издательство "Лори" 2000.

3. "Вопросы создания CORBA-приложений" Александр Цимбал


Страница сайта http://test.interface.ru
Оригинал находится по адресу http://test.interface.ru/home.asp?artId=3457