Статьи

Интеграция Oracle RIB в BizTalk Server


Первоначально автор Уильям Хайнцман

Oracle RIB (Retail Information Bus) — это основанная на сообщениях платформа интеграции, предназначенная для розничных магазинов. Уровень сообщений — это служба сообщений Java, а поставщик сообщений — Oracle AQ. Одним из корпоративных решений, которое часто интегрируется с Oracle RIB, является BizTalk Server от Microsoft. В то время как JNBridge JMS Adapter для BizTalk является ключевым компонентом, обеспечивающим эту интеграцию, Oracle RIB представляет собой проблему интеграции для  автономных клиентов JMS, таких как адаптер. В этой записи блога будет рассказано, как интегрировать Oracle RIB в BizTalk Server с помощью адаптера JMS, но сначала стоит разобраться в конкретных проблемах интеграции автономных клиентов JMS .

Автономные клиенты JMS

Клиенты JMS обычно выполняются в контейнере Java EE на сервере приложений, например, в компоненте, управляемом сообщениями. Контейнер предоставляет клиенту услуги, в том числе зачисление транзакций и неявные среды именования. Общий автономный клиент JMS не выполняется в контейнере и должен явно использовать интерфейс именования и каталогов Java (JNDI) для получения фабрик соединений и мест назначения. Из-за этого автономным клиентам JMS часто требуются специальные библиотеки — файлы JAR в пути к классам — и свойства конфигурации, которые отличаются от тех, которые используются для MDB. Некоторые поставщики, такие как IBM, и некоторые продукты, такие как WebLogic, предоставляют специальный тонкий клиентJAR-файлы. Для других поставщиков необходимо выбрать подмножество файлов JAR из реализации сервера Java EE, скопировав их на клиентский компьютер JMS. В большинстве случаев поставщик фактически публикует требуемые JAR-файлы для каждой версии, в других случаях необходимо создать путь к классу по одному ClassNotFoundException за раз.

В зависимости от реализации сервера JMS автономный клиент может не иметь доступа к службе JNDI. Некоторые реализации JMS не предоставляют JNDI, вместо этого полагаясь на сервер приложений Java EE хоста для предоставления служб имен и каталогов. Если реализация JMS не интегрирована в сервер приложений, но работает как автономный посредник , все клиенты должны получать доступ к фабрикам соединений и местам назначения через собственные API-интерфейсы. Это хорошо, но это не переносимо, что является основной идеей спецификации JMS.

Oracle AQ является примером реализации JMS, которая может работать как автономный посредник или запускаться на сервере приложений Java EE, таком как Oracle WebLogic. В этом блоге будут рассмотрены оба сценария: автономный JMS-клиент, в данном случае JNBridge JMS-адаптер для BizTalk Server, подключающийся к Oracle AQ в качестве автономного посредника и в качестве поставщика услуг JMS в WebLogic. Как мы увидим, оба сценария требуют дополнительной работы для поддержки автономного клиента JMS.

Oracle AQ, настроенный как иностранный сервер в WebLogic

Вообще говоря, спецификация JMS была задумана как API, который обеспечивает общую поверхность для проприетарного промежуточного программного обеспечения обмена сообщениями. Поверхность JMS обеспечивается сервером приложений Java EE, который также предоставляет JNDI, еще один универсальный API для получения фабрик соединений и мест назначения. Обычно интеграция поставщика сообщений с JMS и JNDI на сервере приложений выполняется с помощью адаптера ресурсов Java Connection Architecture. Однако предпочтительный метод, требуемый Oracle RIB для интеграции Oracle AQ с WebLogic, заключается в настройке поставщика сообщений в качестве  стороннего сервера .

Oracle AQ использует базу данных Oracle в качестве хранилища сообщений, сопоставляя места назначения с таблицами. Из-за транзакционной природы БД в конфигурации стороннего сервера используется источник данных Java  . Источник данных автоматически обрабатывает транзакции БД, подключаясь к транзакции, обрабатываемой диспетчером транзакций Java EE, службой, предоставляемой WebLogic. Это хорошо работает, когда клиент JMS выполняется в контейнере Java EE, поскольку источник данных обеспечивает поддержку транзакций. Однако автономный клиент не может использовать источник данных, потому что нет доступного менеджера транзакций — он выполняется вне области транзакций. Хотя JMS-клиент может использовать локальные транзакции, явно вызывая commit или rollback, он не может участвовать в распределенной транзакции.

Внешний сервер с использованием источника данных

При использовании WebLogic 10.3 и Oracle AQ 11.2 настройка в качестве стороннего сервера начинается с настройки источника данных. Источник данных для БД Oracle — это оболочка с поддержкой транзакций вокруг URL-адреса подключения к базе данных. Этот снимок экрана показывает конфигурацию источника данных в WebLogic. Обратите внимание на стандартный URL-адрес соединения Oracle в верхней части с SID по умолчанию orcl .

Вот снимок экрана конфигурации стороннего сервера с использованием вышеуказанного источника данных, который был сопоставлен с именем JNDI, jms / oracleDS .

Эта конфигурация стороннего сервера будет хорошо работать для клиентов JMS, выполняющих внутри контейнеров в WebLogic. Однако если автономный клиент JMS пытается подключиться к WebLogic, это исключение выдается.

не может назначить экземпляр weblogic.jdbc.common.internal.RmiDataSource_1033_WLStub для поля oracle.jms.AQjmsConnectionFactory.data_source типа javax.sql.DataSource в экземпляре oracle.jms.AQjmsXATopicConnectionFactory

Внешний сервер с использованием URL-адреса соединения

Проблема в источнике данных. Если в конфигурации внешнего сервера не используется источник данных, а вместо этого используется URL-адрес подключения, то автономный клиент JMS сможет подключиться. На следующем снимке экрана показана конфигурация стороннего сервера с использованием URL-адреса соединения вместо источника данных.

Взаимоисключающие: требуется два внешних сервера

Теперь автономный клиент JMS может подключаться к WebLogic и получать доступ к очередям и темам Oracle AQ. Однако клиент JMS, работающий внутри контейнера в WebLogic, не может использовать эту конфигурацию стороннего сервера. Внутреннему клиенту JMS требуется источник данных для обеспечения зачисления транзакции. Решение состоит в том, чтобы настроить два внешних сервера, один из которых использует источник данных для клиентов WebLogic JMS, а другой — URL-адрес соединения для внешних автономных клиентов JMS. Каждая конфигурация стороннего сервера будет иметь свою собственную фабрику соединений с уникальным именем JNDI. Каждый сторонний сервер также будет указывать на те же очереди или темы Oracle AQ, но будет использовать уникальные имена JNDI.

Конфигурацию адаптера JNBridge JMS для BizTalk при использовании Oracle AQ, настроенного как иностранный сервер WebLogic, можно найти здесь .

Oracle AQ как автономный брокер.

Спецификация JMS является универсальным интерфейсом, но нет определенного механизма для получения фабрик соединений или мест назначения. Общий доступ обычно обеспечивается JNDI, однако спецификация не исключает не-JNDI механизма, то есть проприетарного расширения. Oracle AQ является примером реализации JMS, для которой не требуется JNDI, если он работает как автономный брокер. Однако, поскольку API для создания фабрик соединений и доступа к адресатам является закрытым, JMS-адаптер JNBridge для BizTalk может поддерживать автономный Oracle AQ, только если доступна служба JNDI.

Один из способов обойти эту проблему — написать оболочку Java, которая имитирует JNDI, но использует API Oracle AQ для создания и возврата фабрик соединений и мест назначения. JNDI требует реализации двух интерфейсов именования Java,  InitialContextFactory и Context . Когда клиенту Java EE требуется удаленный доступ к объектам в хранилище JNDI, он создает InitialContext из InitialContextFactory. Затем клиент использует InitialContext для поиска фабрик соединений и пунктов назначения. InitialContextFactory должен реализовывать метод getInitialContext (). Вот код Java для этого метода.

импорт java.util.Hashtable;
импорт java.util.Properties;
import javax.naming.Context;
import javax.naming.NamingException;
импорт java.net.URI;
открытый контекст getInitialContext (среда Hashtable <?,?>)
бросает NamingException

{

Строка dbURL =
this .getDBURL (среда);

Строка hostname =
this .getHostname (environment);
int port =
this .getPort (environment);

Строка sid =
this .getSID ();

Строка username =
this .getUsername (среда);

String password =
this .getPassword (среда);

OAQContext oaqCtx =
null ;
попытаться  {

oaqCtx =
новый OAQContext (имя хоста, имя пользователя, пароль, sid, порт);

}
catch (Exex ex) {
выбросить новое NamingException («
Невозможно создать OAQContext: » + ex.getMessage ());

}
return oaqCtx;

}

Этот метод просто анализирует объект Hashtable , среду , которая является аргументом конструктора InitialContext. Адаптер JMS для BizTalk строит объект Hashtable, заполнение его со значениями соединения, передавая ее в качестве аргумента в конструктор InitialContext в классе фабрики , где метод  getInitialContext () вызывается . Затем метод создает экземпляр OAQContext, передавая свойства соединения, где они хранятся в переменных экземпляра, и возвращает его. Объект OAQContext является реализацией интерфейса Context и поэтому должен реализовывать метод lookup () .

Вот реализация для lookup (), обратите внимание на приведение интерфейса javax.jms.Session к подклассу  AQjmsSession . Это позволяет коду вызывать собственные методы getQueue () и getTopic () .

импорт java.util.Hashtable;
импорт java.util.Properties;
импорт javax.naming.Binding;
import javax.naming.Context;
импорт javax.naming.Name;
import javax.naming.NameClassPair;
import javax.naming.NameParser;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
импорт oracle.AQ. *;
import oracle.jms. *;
импорт javax.jms. *;
публичный поиск объекта (имя String)
бросает NamingException

{

ConnectionFactory cf =
null ;

Соединение соединение =
ноль ;

Сессия сессия =
ноль ;

Object rtn =
null ;

cf =
this .getCF (имя);
if (name.equalsIgnoreCase (
«QueueConnectionFactory» ) || name.equalsIgnoreCase (
«TopicConnectionFactory» ))

{

rtn = ср;

}
еще  {
попытаться  {

connection = cf.createConnection (
это .
имя пользователя ,
это .
пароль );

session = connection.createSession (
false , Session.
AUTO_ACKNOWLEDGE );

}
catch (Exex ex) {
выбросить новое NamingException (
«Невозможно создать соединение и сеанс:« + ex.getMessage ());

}
попытаться  {

Очередь q = ((
AQjmsSession ) сеанс) .getQueue (
this .
Имя
пользователя , имя);

rtn = q;

}
catch (Exex ex) {}
if (rtn ==
null ) {
попытаться  {

Тема t = ((AQjmsSession) сессия) .getTopic (
this .
Имя
пользователя , имя);

rtn = t;

}
catch (Exex ex) {}

}

}
if (session! =
null ) {
попытаться  {

session.close ();

}
catch (JMSException e) {}

}
if (connection! =
null ) {
попытаться  {

connection.close ();

}
catch (JMSException e) {}

}
if (rtn ==
null ) {
выбросить новое NamingException (
«Невозможно найти объект:« + имя);

}
возврат ртн;

}

Закрытый метод getCF () создает  объект ConnectionFactory с использованием API Oracle AQ. Если имя объекта для поиска совпадает с именем «QueueConnectionFactory» или «TopicConnactionFactory», то возвращается соответствующая фабрика соединений. В методе lookup () , если целью поиска является имя очереди или темы, тогда для создания соединения с последующим сеансом используется фабрика соединений. Это закрытый метод getCF ().

частный ConnectionFactory getCF (имя String)
бросает NamingException

{

ConnectionFactory cf =
null ;
пытаться

{
if (name.equalsIgnoreCase (
«QueueConnectionFactory» )) {

cf = AQjmsFactory.getQueueConnectionFactory (
это .
имя хоста ,
это .
sid ,
это .
порт ,
«тонкий» );

}
еще если (name.equalsIgnoreCase (
«TopicConnectionFactory» )) {

cf = AQjmsFactory.getTopicConnectionFactory (
это .
имя хоста ,
это .
sid ,
это .
порт ,
«тонкий» );

}
еще  {

cf = AQjmsFactory.getConnectionFactory (
это .
имя хоста ,
это .
sid ,
это .
порт ,
«тонкий» );

}

}
catch (Exex ex) {
выбросить новое NamingException (
«Невозможно получить фабрику соединений OAQ:« + ex.getMessage ());

}
возврат ср;

}

Два класса,  com.jnbridge.adapters.oaq.InitialContextFactory и  com.jnbridge.adapters.oaq.OAQContext, должны быть заархивированы в файле JAR и добавлены в свойство пути класса в транспортных обработчиках BizTalk. Чтобы правильно построить URL-адрес соединения для базы данных Oracle за AQ, необходимо использовать SID Oracle . Например, этот URL-адрес подключения,

jdbc:oracle:thin:@stravinsky:1521:etude

имеет SID-имя этюда . В то время как другие значения в URL-адресе соединения могут быть получены из аргумента конструктора InitialContext, имя SID должно использовать системное свойство. Системные свойства могут быть определены и установлены с помощью аргументов виртуальной машины Java. По этой причине при настройке адаптера JMS в BizTalk свойство аргументов JVM в транспортных обработчиках BTS должно предоставлять следующий аргумент:

-Dcom.jnbridge.adapters.oaq.dbname=[OracleSID]

Для получения дополнительной информации о настройке JNBridge JMS-адаптера для BizTalk с использованием оболочки JNDI перейдите по этой ссылке .

Чтобы загрузить исходный код для оболочки JNDI, перейдите по этой ссылке .

Дополнительную информацию о настройке Oracle AQ в качестве стороннего сервера в Oracle WebLogic (хотя и с использованием источника данных) можно найти здесь .