Технология Клиент-Сервер 2006'2 |
|||||||
|
Взаимодействие с СУБД – важная и существенная часть большинства приложений, и не только в архитектуре клиент-сервер. Использование API для взаимодействия с СУБД характерно и для серверов приложений (даже в случае использования компонентной модели EJB), и для клиентских приложений – для временного хранения данных на стороне клиента, например, в случае невозможности поддержания непрерывного соединения с сервером.
Как и любая другая Java-ориентированная технология, J2EE в качестве основного инструмента взаимодействия с РСУБД полагается на JDBC, точнее, JDBC версии 2.1 и выше.
Для понимания механизма взаимодействия WAS CE c СУБД необходимо знать основы JDBC.
То, что JDBC построен по драйверному принципу, известно всем. К сожалению, те фундаментальные возможности JDBC, которые и позволяют этой технологии успешно взаимодействовать с другими технологиями в составе J2EE, знакомы немногим. Причина проста – эти возможности редко «попадаются на глаза». Как говорилось в эпиграфе к одной из глав книги М. Твена «Простофиля Вильсон», «на поверхности он бесполезен. Он должен находиться под землей и вдохновлять капусту».
JDBC 1.0 поддерживал только физические соединения с серверами БД. Это означало, что установка и разрыв соединения были связаны с существенными затратами ресурсов. Кроме того, не поддерживалось взаимодействие с внешними координаторами объектных транзакций – JDBC 1.0 поддерживал только локальные транзакции – транзакции на уровне одного физического соединения с БД. Наконец, менеджер соединений в JDBC 1.0 невозможно было сделать доступным для других элементов распределенной системы с помощью JNDI. Другими словами, JDBC 1.0 справлялся с задачами, характерными для архитектуры «клиент-сервер», но не удовлетворял требованиям, предъявляемым многозвенными системами.
Ответом на эти требования стала разработка стандарта JDBC 2.0 (точнее, JDBC 2.1). Основными ключевыми изменениями были следующие: менеджер соединений (интерфейс DataSource и производные от него интерфейсы) можно опубликовывать и, соответственно, получать с помощью JNDI и, самое главное, соответствующий JDBC-драйвер должен уметь поддерживать пулы соединений с СУБД, а также сопоставлять соединение с объектной распределенной (глобальной) транзакцией.
Несмотря на возможности, предоставляемые современными JDBC-драйверами, разработчикам J2EE для решения ряда задач требуется поддерживать более тесное взаимодействие с соединениями БД, нежели позволяет JDBC. Примером может служить необходимость координации глобальных (на уровне координатора объектных транзакций распределенной системы) и локальных (на уровне соединения JDBC) транзакций. Поскольку программист может самостоятельно вызывать методы API JDBC, в том числе и методы управления локальными транзакциями (такими, как setAutoCommit() или commit()), возникает возможность рассогласованного поведения при наличии глобальных транзакций. Спецификация J2EE требует, чтобы реализация предоставила возможность управления локальными транзакциями при наличии глобальных, а для этого нужно иметь возможность перехвата на уровне контейнера EJB-компонентов явного – и ошибочного – вызова разработчиком методов управления локальными транзакциями. Кроме того, драйвера JDBC 1.0 еще недавно использовались очень широко, и нужно было предусмотреть возможность их использования при работе J2EE-серверов приложений.
Был найден следующий выход: создание и поддержка пула соединений, выбор нужного вида соединения, сопоставление соединения с контекстом глобальной транзакции в большинстве случаев выполняется не JDBC-драйвером, а специальным программным модулем в составе самого J2EE-сервера приложений. Собственно драйвер используется тогда, когда нужно получить физическое соединение с СУБД, а также для поддержки распределенных транзакций (XA-транзакций).
Поскольку логика работы с пулом соединений в общем случае зависит не от вида базы данных, а от поддерживаемых видов транзакций и соединений, то возможно создать две универсальные реализации такого пула – для локальных и глобальных транзакций. Тем не менее, поскольку каждая СУБД имеет свои особенности, можно для повышения эффективности в случае, если вид СУБД известен, использовать реализацию пула, оптимизированную для работы именно с этой СУБД.
Как следствие, в состав дистрибутива WAS CE 1.0.1 входит несколько реализаций пула соединений и управления транзакциями. Работа со всеми этими реализациями происходит одинаково, поэтому в примерах мы будем использовать универсальную реализацию для поддержки локальных транзакций.
Эта реализация выполнена в виде стандартного ресурсного адаптера J2EE – модуля с расширением RAR. Этот файл имеет имя tranql-connector-1.1.rar и находится (вместе с другими реализациями пула соединений) в каталоге <install_dir>\repository\tranql\rars. Его развертывание на сервере, как и любого другого модуля, требует наличия xml-дескриптора. В этом xml-дескрипторе и указываются все необходимые для нормальной работы пула параметры.
Первый вопрос, на который должен дать ответ разработчик приложения, взаимодействующего с БД, таков: какова должна быть «область видимости» создаваемого пула соединений?
При разработке серверных приложений возможны два ответа:
Создание клиентских приложений для WAS CE – тема для отдельной статьи.
Выбор одного из этих двух вариантов никак не связан с решением проблем безопасности. Это просто выбор той из стратегий, которая наиболее адекватна поставленной задаче, и которую удобнее использовать в том или ином конкретном случае. Основные отличия связаны с самой процедурой создания и регистрации пула. Кроме того, в случае создания пула на уровне приложения он существует только во время работы этого приложения.
Для нормальной работы с БД с использованием WAS CE необходимо иметь соответствующий JDBC-драйвер. JDBC-драйвера бывают разных типов – написанные на Java или с использованием native-кода, поддерживающие двухфазные (XA) транзакции и нет, обеспечивающие сетевое соединение с СУБД или требующие для работы дополнительного ПО. Сейчас в большинстве случаев используются JDBC-драйверы так называемого четвертого типа. Они поставляются в виде jar-файлов.
WAS CE содержит JDBC-драйвера для большого количества распространенных СУБД. В настоящий момент WAS CE «понимает» – т.е. либо содержит нужный драйвер, либо обеспечивает помощь в его поиске, загрузке и настройке – следующие наиболее популярные типы СУБД (это не полный список):
Разработчик может использовать доступные ODBC-драйвера (через мост JDBC-ODBC).
Кроме того, в состав WAS CE входит встроенная СУБД Derby (это клон БД Cloudscape), которая создавалась в рамках open-source проекта.
Многие из перечисленных СУБД поддерживаются как в локальном, так и в XA-режиме, т.е. режиме использования распределенных транзакций.
Несколько слов о поддержке встроенной БД Derby. Она используется сервисами самой WAS CE и готова к работе сразу после установки WAS CE. Derby поддерживается в различных режимах, в том числе режиме использования XA-транзакций. Поскольку она играет особую роль, консоль администратора в панели навигации (левая часть консоли) содержит специальный пункт – «Embedded DB». С помощью средств консоли («DBManager») пользователь может создавать новые БД, интерактивно создавать и выполнять SQL-операторы для выбранной БД Derby, а также получить список параметров настройки этой СУБД («DB Info»).
В приведенном в этой статье примере приложения будет использоваться не Derby, а бесплатная версия СУБД DB2 – DB2 Express C, которую можно бесплатно скачать с сайта IBM (http://www-306.ibm.com/software/data/db2/ udb/db2express/download.html).
JDBC-драйверы (их jar-файлы) должны находиться в каталоге repository (точнее, одном из его подкаталогов) каталога установки WAS CE. Например, JDBC-драйвер для Derby находится в каталоге <install_dir> \repository\org.apache.derby\jars, а драйвер для DB2 ExpressC – в каталоге <install_dir> \repository\com.ibm.db2\ jars.
Если разработчик хочет для создания и настройки использовать JDBC-драйвер, не входящий в комплект поставки WAS CE, то он должен поместить этот драйвер в подкаталог каталога \repository. Обратите внимание, что эксперты консоли администратора WAS CE полагаются на определенное соглашение об именах для jar-файлов. В частности, имя jar-файла обязательно должно содержать номер версии и подверсии драйвера. Например, jar-файл для драйвера DB2 ExpressC имеет имя db2jcc-8.2.jar, а jar-файл для одного из Derby-драйверов – derby-10.1.2.ibm.jar, причем номер версии отделяется от имени дефисом.
Если нужно создать пул соединений уровня сервера – т.е. пул, доступный всем приложениям этого сервера – то наиболее удобно сделать это с помощью консоли администратора, которая содержит специального мастера (wizard) для решения этой задачи. Чтобы вызвать его, в панели навигации консоли нужно выбрать пункт «Database Pools». Можно либо создавать пул соединений «с нуля» (мастер «Using the Geronimo database pool wizard»), либо импортировать готовый пул, созданный при работе с другими серверами – JBoss или Weblogic. В данной статье мы будем создавать пул соединений с DB2 ExpressC.
На первом шаге при использовании данного мастера разработчик должен выбрать имя создаваемого пула и тип используемой БД (рисунок 1).
Имя пула должно быть уникальным на сервере среди имен всех других ресурсов. Это имя появится в специфическом для WAS CE дескрипторе развертывания – там, где необходимо будет сопоставить выбранное разработчиком JNDI-имя и имя реального ресурса.
После выбора одного из поддерживаемых мастером типов БД нужно перейти к следующему этапу (рисунок 2).
Имя класса драйвера определяет сам мастер, хотя пользователь может его изменить «вручную». Jar-файл, содержащий код драйвера, нужно выбрать из списка. Если в этом списке нет соответствующего драйвера, можно попробовать найти его и загрузить с помощью мастеров консоли (кнопка «Download a driver»).
Дальнейшие параметры зависят от того, как был сконфигурирован установленный экземпляр СУБД, к которому выполняется обращение.
Наконец, на последнем шаге работы с мастером разработчик окончательно формирует нужный URL (URL формируется на основе ранее введенных данных, но здесь его можно изменить) и задает параметры – минимальный (0 по умолчанию) и максимальный (10 по умолчанию) размер пула, время ожидания (в мсек, 5000 по умолчанию) до возбуждения исключения в случае, когда пользователь запрашивает соединение, но свободных соединений в пуле нет, и время ожидания (в минутах, 15 по умолчанию) до удаления из пула неиспользуемого соединения и уменьшения его текущего размера.
После задания всех параметров имеет смысл проверить настройку пула – установить соединение с СУБД (кнопка «Test Connection»). Если все хорошо, появится страница с соответствующей информацией (рисунок 3).
Теперь можно выполнить развертывание созданного пула на сервере (кнопка «Deploy» на шаге 4 или кнопка «Skip test and deploy» на предыдущем шаге). Полезной – особенно при создании пула «вручную», о чем речь пойдет в следующем разделе – может оказаться кнопка «Show Plan» (или «Skip Test an Show Plan» на предыдущем шаге), которая приводит к отображению сгенерированного xml-дескриптора для развертываемого коннектора.
Термин «вручную» не надо понимать буквально – с учетом возможностей, предоставляемых мастерами консоли администратора. Здесь имеется в виду создание xml-файла, содержащего текст дескриптора, и некоторые манипуляции с этим файлом.
Для создания пула соединений уровня сервера приложений или корректировки параметров существующего пула всегда имеет смысл использовать консоль оператора – при этом в явном создании xml-файла дескриптора нет необходимости. Разумеется, даже при создании пула уровня сервера можно поступить иначе – создать xml-дескриптор, а затем с помощью командной строки развернуть пул на сервере. Этот подход может быть удобен, например, при использовании нетривиальных командных файлов. Командная строка для выполнения такого развертывания может выглядеть так:
java -jar bin/deployer.jar deploy <имя_файла_дескриптора>.xml \ repository/tranql/rars/tranql-connector-1.1.rar |
Данный вид командной строки подразумевает, что текущим каталогом является каталог установки WAS CE.
Явное создание xml-файла дескриптора и размещение его в EAR-архиве необходимо в случае создания пула соединений на уровне J2EE-приложения, а не сервера. Для создания такого пула нужно выполнить следующие действия:
<application xmlns="http://geronimo.apache.org/xml/ns/j2ee/application-1.0" configId="MyApplication"> <module> <connector>имя_RAR_файла.rar</connector> <alt-dd>имя_XML_дескриптора.xml</alt-dd> </module> </application> |
Теперь осталось только ознакомиться с кодом дескриптора пула соединений (его вид не зависит от области видимости пула – на уровне сервера или на уровне приложения).
Ниже приведен дескриптор, сгенерированный мастером консоли администратора для параметров, которые были указаны при интерактивной работе с консолью.
<?xml version="1.0" encoding="UTF-8"?> <connector configId="console-db-pool-MyDatabaseSource" xmlns="http://geronimo.apache.org/xml/ns/j2ee/connector-1.0"> <dep:dependency xmlns:dep="http://geronimo.apache.org/xml/ns/deployment-1.0"> <dep:uri>com.ibm.db2/db2jcc/8.2/jar</dep:uri> </dep:dependency> <resourceadapter> <outbound-resourceadapter> <connection-definition> <connectionfactory-interface> javax.sql.DataSource </connectionfactory-interface> <connectiondefinition-instance> <name> MyDatabaseSource </name> <config-property-setting name="Password"> adminpassword </config-property-setting> <config-property-setting name="Driver"> com.ibm.db2.jcc.DB2Driver </config-property-setting> <config-property-setting name="UserName"> db2admin </config-property-setting> <config-property-setting name="ConnectionURL"> jdbc:db2://localhost:50000/MYDEMODB </config-property-setting> <connectionmanager> <local-transaction/> <single-pool> <max-size>10</max-size> <min-size>0</min-size> <match-one/> </single-pool> </connectionmanager> </connectiondefinition-instance> </connection-definition> </outbound-resourceadapter> </resourceadapter> </connector> |
Обратить внимание стоит на следующее:
<...>
WAS CE предоставляет разработчикам гибкий механизм для взаимодействия со всеми наиболее распространенными реляционными СУБД с поддержкой как однофазных, так и двухфазных транзакций.
Copyright © 1994-2016 ООО "К-Пресс"