|
|
|||||||||||||||||||||||||||||
|
Пример простого приложения JBuilder-CORBA-OracleИсточник: Jbuilder Александр Лейтес
Введение Простой пример приложения JBuilder-CORBA-Oracle, описанный в этой статье, предназначен для разработчиков, которые только начинают работу с Java и CORBA, но уже изучили основы этих технологий. В данной работе нет описания Java и CORBA, так как цель статьи - показать применение технологий Java+CORBA на практике. Читатель, интересующийся теорией, найдет всю необходимую информацию в литературе, список которой находится в конце статьи. Пример демонстрирует:
Основные характеристики примера: Независимость от конкретной СУБД. CORBA-сервер использует для доступа к БД JDBC-драйвер, и поэтому может работать с любой СУБД для которой такой драйвер имеется. Удобство отладки CORBA-объектов. Объекты могут использовать обычный print() для вывода отладочной информации в окно сервера. Удобство отладки клиентских приложений. Например, утечки памяти могут быть легко обнаружены, так как сервер информирует о выделении и освобождении своих объектов. Поэтому, легко найти и устранить ошибки освобождения интерфейсов в клиентской программе, просто глядя в окно сервера, который может работать на том же компьютере. Просмотр и редактирование результатов запросов в сетке JBuilder. Сетка является удобным инструментом для просмотра, вставки, редактирования и удаления данных. Стандартный пример ProviderResolver из JBuilder показывает, как можно использовать нестандартный источник данных в случае текстового файла, однако в данном примере показано, как применить эту возможность непосредственно к объектам CORBA. Кроме того, исправлены ошибки, которые содержит стандартный пример. Конечно, при промышленной эксплуатации CORBA-объектов, следует использовать один из серверов приложений, имеющихся в настоящее время на рынке (например, Borland AppServer). Однако, для разработки и тестирования простых приложений, такого "минимального" сервера вполне достаточно. Установка Для установки и запуска примера необходимы следующие продукты:
После установки JBuilder, необходимо настроить среду для работы с VisiBroker, используя Enterprise Setup (подробности см. в документации к JBuilder). Также следует проверить, что переменная окружения CLASSPATH содержит пути ко всем необходимым драйверам и библиотекам. Пример расположен в каталоге OraCorbaSample . Для сборки сервера необходимо зайти в каталог Ora\CorbaSample\corba-server и выполнить следующие команды: prompt> mkserver - сборка сервера prompt> mkuser - сборка примера Также следует в оболочке SQL Plus от SCOTT/TIGER выполнить скрипт user\db.sql , который содержит объекты, необходимые для работы примера. Тестирование сервера:
Для сборки клиента, необходимо при помощи JBuilder собрать проект OraCorbaSample\jb-client\CORBA_Grid.jpx и запустить его. Не забудьте настроить среду JBuilder для использования VisiBroker (см. выше). На экране должна появиться сетка с записями из таблицы EMP (служащие). Попробуйте отредактировать запись, добавить, удалить. Описание структуры каталогов сервера Структура каталогов сервера имеет следующий вид:
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 ) и являются ключевыми для взаимодействия с БД.
Дополнительные объекты сервера Интерфейсы вспомогательных объектов сервера определены в модуле DBObject файла server\db.idl и могут использоваться пользователем для упрощения разработки:
Следует отметить, что эти интерфейсы - тоже примеры и использовать их необязательно. Более того, их использование может вызвать необходимость изменения исходных . 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. Создание пользовательских объектов При создании пользовательских объектов следует придерживаться следующих правил:
Работа с пользовательскими объектами После создания объекта, желательно выполнить его тестирование. Для тестирование объекта необходимо создать класс-приложение. Пример такого приложения находится в каталоге test : test\EmpClient.java . Это приложение тестирует объект примера EmpImpl. Правила работы с объектом:
Следует отметить, что для объектов расположенных в каталоге user указывать полную спецификацию объекта необязательно. Достаточно одного имени. Метод bind() не является стандартом CORBA и реализован только в VisiBroker , однако он достаточно удобен в применении. Для лучшей переносимости следует использовать стандартный сервис имен CORBA, однако это требует запуска дополнительного модуля, реализующей этот сервис. Так как данный сервер не является только примером, то этот компонент опущен, хотя его реализация достаточно тривиальна. Описание клиентского приложения, реализованного на JBuilder
Пример простого приложения JBuilder-CORBA-Oracle Про CORBA и Java написано много замечательных книг (см. [1], [2], [3]), которые также содержат примеры приложений. Но когда наступает время разработать что-то реальное, сразу возникают вопросы, о которых авторы либо не пишут, либо пишут недостаточно подробно, либо информация давно устарела, что в случае с CORBA случается довольно часто. Справедливости ради, стоит отметить, что многие книги и не ставят перед собой таких целей, да и невозможно объять необъятное. Простой пример приложения JBuilder-CORBA-Oracle, описанный в этой статье, предназначен для разработчиков, которые только начинают работу с Java и CORBA, но уже изучили основы этих технологий. В данной работе нет описания Java и CORBA, так как цель статьи - показать применение технологий Java+CORBA на практике. Читатель, интересующийся теорией, найдет всю необходимую информацию в литературе, список которой находится в конце статьи. Прилагаются полные исходные тексты примера, которые можно использовать в собственных разработках безо всяких ограничений. (Прим: примеры находятся в ZIP-архиве статьи). Пример демонстрирует: Простой Java-CORBA сервер, построенный на основе VisiBroker, который легко использовать при разработке собственных CORBA-приложений. Независимость от конкретной СУБД. CORBA-сервер использует для доступа к БД JDBC-драйвер, и поэтому может работать с любой СУБД для которой такой драйвер имеется. Удобство отладки CORBA-объектов. Объекты могут использовать обычный print() для вывода отладочной информации в окно сервера. Удобство отладки клиентских приложений. Например, утечки памяти могут быть легко обнаружены, так как сервер информирует о выделении и освобождении своих объектов. Поэтому, легко найти и устранить ошибки освобождения интерфейсов в клиентской программе, просто глядя в окно сервера, который может работать на том же компьютере. Просмотр и редактирование результатов запросов в сетке JBuilder. Сетка является удобным инструментом для просмотра, вставки, редактирования и удаления данных. Стандартный пример ProviderResolver из JBuilder показывает, как можно использовать нестандартный источник данных в случае текстового файла, однако в данном примере показано, как применить эту возможность непосредственно к объектам CORBA. Кроме того, исправлены ошибки, которые содержит стандартный пример. Конечно, при промышленной эксплуатации CORBA-объектов, следует использовать один из серверов приложений, имеющихся в настоящее время на рынке (например, Borland AppServer). Однако, для разработки и тестирования простых приложений, такого "минимального" сервера вполне достаточно. Установка VisiBroker for Java 4.5 компании Inprise: http://www.inprise.com/ Пример расположен в каталоге OraCorbaSample. Для сборки сервера необходимо зайти в каталог Ora\CorbaSample\corba-server и выполнить следующие команды: prompt> mkserver - сборка сервера prompt> mkuser - сборка примера Также следует в оболочке SQL Plus от SCOTT/TIGER выполнить скрипт user\db.sql, который содержит объекты, необходимые для работы примера. Тестирование сервера: Настройте параметр JdbcURL в файле db.properties на реальный сервер сети. OraCorbaSample\jb-client\CORBA_Grid.jpx и запустить его. Не забудьте настроить среду JBuilder для использования VisiBroker (см. выше). На экране должна появиться сетка с записями из таблицы EMP (служащие). Попробуйте отредактировать запись, добавить, удалить. Описание структуры каталогов сервера Database - вспомогательные классы сервера 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(), название которых говорит само за себя. DBException - Исключительная ситуация. Описание работы сервера Запросы клиентов обслуживает сервант менеджера сессий, реализующий интерфейс 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, однако пользователь может создать свой собственный каталог, с названием, характеризующим разрабатываемое приложение. Правила работы с объектом: Инициализировать ORB. Метод 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"). Замечания
Список литературы 1. "Основы CORBA". Роберт Орфали, Дэн Харки, Джери Эдвардс. Издательство "МАЛИП" 1999. 2. "JAVA и CORBA в приложениях клиент-сервер". Роберт Орфали, Дэн Харки. Издательство "Лори" 2000. 3. "Вопросы создания CORBA-приложений" Александр Цимбал Ссылки по теме
|
|