Продолжается подписка на наши издания! Вы не забыли подписаться?

Sybase PowerBuilder 9 – эволюция передачи и обработки данных в корпоративных информационных системах

Алексей Степанюк,
E-Mail: stepanyuk@sybase.ru

В настоящее время уже ни у кого не вызывает удивления тот факт, что 95% всех корпоративных информационных систем строятся на основе технологии Клиент/Сервер. Но так ли она хороша, эта технология? Позволяет ли она удобно и быстро масштабировать информационную систему? А как обстоят дела с отказоустойчивостью такой архитектуры? Что делать в том случае, если количество пользователей этой системы значительно возрастёт? Каждый из нас, конечно, может предложить различные решения, заключающиеся в увеличении производительности и повышении надежности, однако, в большинстве своём это будут решения, связанные с модернизацией существующих или покупкой новых аппаратных средств. Такой подход, как правило, является неоправданно дорогостоящим и обычно решает текущие проблемы, и не оставляет возможностей для дальнейшего развития.

А как насчет серверов приложений? По-настоящему толчком к развитию клиент/серверных технологий явилось появление промышленных серверов приложений. Возможность переноса части программного кода с клиентского рабочего места, а также с сервера баз данных, на промежуточный слой, открыла новые перспективы среды обработки данных.

Эта статья, на наш взгляд, будет интересна, программистам и системным архитекторам, вовлеченным в процесс разработки или развития корпоративных информационных систем. Основная задача статьи – показать возможность эволюционного развития клиент/серверной архитектуры до сложных многоуровневых моделей передачи и обработки данных, как в локальных вычислительных сетях, так и в Internet. Ни для кого не секрет, что именно возможность эволюционного развития представляет наибольшую ценность для программиста. Многие разработчики не раз сталкивались с проблемой изменения уже готовых, введенных в промышленную эксплуатацию систем, и представляют, насколько это трудоемкий и ответственный процесс.

Наиболее полезным для разработчиков представляется подход, продемонстрированный на конкретном, работоспособном примере программного кода. Мы не будем отступать от этой традиции и вместе с вами пройдем весь путь эволюции от создания простого клиент/серверного приложения до многозвенной архитектуры передачи и обработки данных с использованием сетевых служб (Web Services).

Выбор среды разработки, с помощью которой мы будем демонстрировать усложнение архитектуры, не случайно пал на Sybase PowerBuilder Enterprise. На протяжении последних лет PowerBuilder остается одним из лидеров среди программных средств быстрой разработки приложений (Rapid Application Development – RAD) в различных архитектурных средах. Кроме того, в состав этого пакета входят промышленный сервер приложений Sybase EAServer, полностью готовый к использованию в распределенных корпоративных сетях, и система управления базами данных для рабочих групп Sybase Adaptive Server Anywhere.

Этап первый: Клиент-Сервер

Мы начнем с создания простого приложения в архитектуре клиент/сервер, которое каждый из вас, наверное, не раз создавал, начиная новый проект. Для этого воспользуемся демонстрационной базой данных asademo.db, входящей в комплект поставки Sybase Adaptive Server Anywhere.

Рисунок 1. Приложение в технологии клиент-сервер.

Чаще всего используется описанный ниже алгоритм построения такой системы. Создается клиентское приложение, которое умеет соединяться с сервером баз данных. В среде Windows программным интерфейсом такого соединения может служить, например, механизм ODBC. Посредствам SQL-запросов клиентское приложение может манипулировать информацией, находящейся в базе данных, и предоставлять её конечному пользователю. Такая архитектура показана на рисунке 1. Архитектурной особенностью этой системы является большая концентрация программного кода на стороне клиента. Любые изменения в структуре базы данных несут за собой изменения в клиентском приложении, и наоборот. Но наша главная цель – показать развитие, поэтому приступим к созданию демонстрационного примера, основываясь на этой архитектуре.

Первым шагом на пути реализации работоспособного приложения в среде PowerBuilder будет создание рабочего пространства (Workspace), в котором находится информация обо всех файлах и библиотеках приложения. На рисунке 2 представлен результат вызова команды New из главного меню среды разработки. Здесь необходимо отметить, что рабочее пространство может содержать несколько целевых объектов(Target) для приложений различного назначения (Например, целевой объект пользовательского приложения с графическим интерфейсом или целевой объект приложения, представляющего собой компонент сервера приложений).

Рисунок 2. Создание рабочего пространства проекта.

Для того чтобы простое приложение на PowerBuilder, имеющее графический интерфейс, могло функционировать, необходимо иметь, по крайней мере, четыре объекта:

Создадим эти объекты. С помощью мастера создания приложений мы делаем сразу три объекта (Target, Library и Application). На рисунке 3 представлен мастер создания объектов в PowerBuilder с открытой закладкой Target (новый целевой объект).

Рисунок 3. Выбор мастера создания приложения.

Завершив этап создания необходимых системных объектов, мы создаем первый визуальный объект – окно. Это окно будет являться основным окном приложения. На 4 снова представлен мастер создания объектов, с открытой закладкой PB Object – новый прикладной объект для приложения.

Рисунок 4. Выбор мастера создания окна приложения.

Разработчикам клиент/серверных технологий хорошо известно, что для работы с любой системой управления базой данных необходимо установить соединение с ней. В нашем примере мы будем использовать для этой цели ODBC. При этом нам понадобится создать новый профиль соединения (Database Profile). На рисунке 5 представлен результат вызова команды Database Profile из главного меню среды разработки.

Рисунок 5. Создание нового профиля соединения с базой данных при посредстве ODBC.

Новый профиль соединения мы настроим на демонстрационную базу данных asademo.db. Назовем этот профиль asademo8. На рисунке 6 представлена форма для конфигурирования нового профиля.

Рисунок 6. Конфигурирование нового профиля
соединения с базой данных.

Для завершения создания соединения необходимо добавить в приложение невизуальный программный объект, с помощью которого мы получим возможность управлять параметрами и состоянием соединения. Для выполнения этих действий мы вновь воспользуемся (см. рисунок 7) мастером создания объектов (закладка PB Object – новый объект приложения).

Рисунок 7. Выбор мастера создания объекта соединения.

Создав объект соединения, необходимо объявить его в списке глобальных переменных (Global Variables) для того, чтобы к нему можно было обращаться из любого места программы. Сделаем это следующим образом:

obj_dbconnect db

Большинство разработчиков клиент/серверных приложений на PowerBuilder считают использование DataWindow основным способом представления информации из баз данных. Действительно, такое разнообразие функций и возможностей вы вряд ли найдете где-нибудь еще. Кстати, возможно, именно DataWindow и является причиной такой популярности PowerBuilder. При работе через DataWindow информация может представляться пользователю в самых разнообразных формах – в виде различных таблиц, графиков, этикеток и т.д. Особенность разработки с использованием DataWindow заключается в том, что нам придется иметь дело с тремя компонентами:

Для реализации нашего примера мы создадим простой объект DataWindow на основе табличного представления данных (Grid) и свяжем этот объект с таблицей Contacts базы данных. На рисунке 8 представлена форма DataWindow Painter среды разработки с загруженным в неё объектом DataWindow.

Рисунок 8. Визуальные элементы управления основного окна приложения.

Заключительным шагом в процессе визуального проектирования нашего приложения будет являться создание элементов графического пользовательского интерфейса. Что нам понадобится для отображения наших данных? Во-первых, собственно элемент управления DataWindow, в свойстве DataObject которого мы укажем ему наш объект DataWindow, сконструированный на предыдущем этапе. Во-вторых, нам необходим DropDownListBox, который в нашем случае будет содержать информацию о параметрах соединения с базой данных. Далее, по мере развития архитектуры, мы создадим другие источники получения данных, пока же DropDownListBox ограничим лишь одной строкой:

ConnectString='DSN=asademo8'

Ну и, в-третьих, самое главное, необходима кнопка, при нажатии которой наше приложение будет «наполнено» данными. Текст на кнопке будет отражать механизм получения информации, в данном случае это «ODBC». Этот подход мы сохраним на всем протяжении развития нашего приложения. Результат визуального проектирования пользовательского интерфейса показан на рисунке 8.

Итак, нам осталось написать обработчик события для нажатия кнопки “ODBC”. Код функции - обработчика приведен ниже в листинге 1.

// блок объявления переменных
Long l_result
DataStore ds
Blob blb_dataset
// создание экземпляра объекта транзакций
db = Create obj_dbconnect
// создание экземпляра объекта DataStore
ds = Create DataStore
// ассоциирование объекта транзакций со 
// строкой соединения с базой данных
SQLCA.dbparm = txt_connstr.text
// инициирование соединения с базой данных
l_result = db.of_connectdb( )
  If l_result < 0 Then
    MessageBox("Error message", "Error connecting to DB: " + 
      String(l_result))
    return -1
  End If

// ассоциирование конкретной структуры данных с DataStore 
ds.DataObject = "obj_datawindow"
// ассоциирование объекта транзакций с DataStore
ds.settransobject(SQLCA)

// извлечение информации из БД в DataStore
l_result = ds.retrieve( )
  If l_result < 0 Then
    MessageBox("Error message", "Error Retrieving Data: " + String(l_result))
    return -1
  End If

// сохранение структуры вместе с набором данных в переменную типа Blob
ds.getfullstate( blb_dataset)
// восстановление информации 
dw.setfullstate( blb_dataset)

// разрушение экземпляра объекта DataStore
Destroy ds

// завершение соединения с базой данных
db.of_disconnectdb( )
// разрушение экземпляра объекта транзакций
destroy db

return 0
Листинг 1. Текст обработчика события для кнопки “ODBC”.

Рисунок 10. Создание объекта Project для получения исполняемого exe-файла.

Одной из функциональных особенностей среды разработки PowerBuilder является встроенная поддержка средств управления конфигурациями, что значительно облегчает процесс подготовки законченного приложения. В среде PowerBuilder существуют системные объекты Projects, которые выполняют заранее определенный набор действий. Одним из примеров такого объекта может служить управление созданием исполняемого exe-файла.

После выполнения всех необходимых действий, в дереве системы (System tree) мы можем наблюдать все созданные объекты (см. рисунок 11).

Рисунок 11. Дерево объектов системы.

Теперь все готово для первого запуска нашего приложения. Если все действия были выполнены правильно, на экране мы получим пример с данными из таблицы Contacts.

Рисунок 12. Пример работающего приложения.

Архитектура клиент/сервер до определенного момента успешно решала возложенные на неё задачи, но потребности в обработке информации в корпоративных информационных системах значительно возросли, особенно в последние годы. И наша задача - показать пути решения этих проблем. Существует и другой подход к построению информационных систем, точнее сказать, к их развитию. Давайте его рассмотрим.

Этап второй: Клиент – Сервер приложений – Сервер баз данных

Следующим этапом развития Клиент/Серверных архитектур явилось появление серверов приложений, которые позволили решить ставшие уже насущными проблемы масштабируемости и обеспечения надежности информационных систем. Появилась возможность объединять серверы приложений в кластеры, в которых головной сервер оценивает нагрузку и работоспособность остальных машин кластера и равномерно распределяет запросы клиентов на получение данных из различных источников. Такая архитектура показана на рисунке 13. Архитектурной особенностью такой системы является разделение среды обработки данных на три уровня. Каждый уровень в такой архитектуре несет определенную функциональную нагрузку и призван решать вполне конкретные задачи. Первый уровень заботится о представлении информации конечному пользователю, этот уровень называют презентационным слоем системы. На нем, как правило, располагаются так называемые облегченные клиенты. Облегченными клиентами мы будем считать приложения, в которых отсутствует соединение с базой данных и большинство невизуальной бизнес-логики. Функциональной нагрузкой второго уровня является бизнес-логика информационной системы и вопросы взаимодействия с облегченные клиентами. При этом необходимо отметить, что часть функциональности облегчённых клиентов передана серверу приложений. Третий уровень, как и в архитектуре клиент/кервер, обеспечивает хранение и целостность данных.

Рисунок 13. Клиент – Сервер приложений – Сервер баз данных.

Одной из причин такой популярности трехзвенной архитектуры наряду с упомянутыми выше, является относительная легкость модернизации этой системы. Представьте себе ситуацию, при которой изменяются нормативные документы крупной компании, что влечёт за собой изменения некоторых бизнес-процессов обработки данных. В случае использования трёхзвенной архитектуры вам придется всего лишь откорректировать второй уровень, не внося изменений в пользовательское программное обеспечение и не трогая базу данных.

Но вернёмся к нашему примеру и посмотрим, каким образом можно его модифицировать для работы с использованием сервера приложений. Для этого нам понадобится установить EAServer, который, как уже отмечалось ранее, включён в комплект поставки Sybase PowerBuilder Enterprise.

В нашем примере мы будем использовать соединение, базирующееся на CORBA. Для этого нам понадобится создать новый профиль соединения (EAServer Profile). На рисунке 14 представлен результат вызова команды EAServer Profile из главного меню среды разработки.

Рисунок 14. Создание нового профиля CORBA-соединения с сервером приложений.

Новый профиль соединения мы настроим на установленный ранее сервер приложений и назовем этот профиль localhost. На рисунке 15 представлена форма для конфигурирования нового профиля.

Рисунок 15. Конфигурирование нового профиля CORBA соединения с сервером приложений.

Как и в случае с базой данных, для завершения создания соединения нам необходимо добавить программный объект в наше приложение. При этом мы получим возможность управлять параметрами и состоянием соединения. Для этой цели мы снова воспользуемся мастером создания объекта соединения (см. рисунок 16), но теперь выбираем соединение с сервером приложений.

Рисунок 16. Мастер создания объекта соединения с сервером приложений.

Создав объект соединения, нам необходимо объявить его в списке глобальных переменных (Global Variables) для получения доступа к нему из любого места программы. Добавляем его к уже имеющемуся объекту соединения с базой данных:

obj_dbconnect db
obj_easconnect as

Итак, у нас все готово для создания серверной части нашего приложения, в которую мы перенесём часть программного кода, облегчив тем самым клиентское рабочее место. Как известно, программный код, исполняющийся на серверах приложений, должен быть оформлен как компонент, разработанный по определенным правилам и основывающийся на определенных технологиях. Sybase EAServer, являясь промышленным сервером приложений, поддерживает большинство принятых на сегодняшний день стандартов создания программных компонентов, среди которых EJB, ActiveX, CORBA (С, С++, Java) и другие. Вопрос рассмотрения создания этих компонентов выходит за рамки этой статьи, поэтому мы ограничимся оформлением нашего программного кода, как NVO (non-visual object, невизуальный объект) PowerBuilder-компонент.

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

Рисунок 17. Выбор мастера создания компонента.

Здесь необходимо отметить, что существует, по крайней мере, три характеристики компонента, которые отличают его от других. Во-первых, это понятие пакета, в который будет устанавливаться компонент на сервере приложений, в нашем примере пакет называется UserPackage. Bo-вторых, это название непосредственно компонента в пакете. В примере компонент называется nvoDataWindow. Третья характеристика – это название объекта, реализующего компонент, в среде разработки, у нас - nvo_datawindow. И, наконец, главное, интерфейс, т.е. набор функций (методов), которые доступны клиентскому приложению для обращения к этому компоненту.

На первом этапе мы определяем один общедоступный (public) метод нашего приложения и одну функцию сервера приложений:

Нам осталось написать тело функции. Код для опубликованной функции приведен ниже (см. листинг 2).

// блок объявления переменных
Long l_result
// ассоциирование объекта транзакций с менеджером соединений сервера приложений
SQLCA.dbparm = "CacheName = 'asademo8'"
// инициирование соединения с БД (с использованием менеджера соединений)
l_result = db.of_connectdb( )
  If l_result <> 0 Then
    WriteJagLog("Cannot Connect to Database: " + String(l_result))
    return -1
  End If
// ассоциирование конкретной структуры данных с DataStore 
ds.DataObject = "obj_datawindow"
// ассоциирование объекта транзакций с DataStore
ds.SetTransObject (SQLCA)
// извлечение информации из БД в DataStore
l_result = ds.Retrieve()
  IF l_result < 0 THEN
    WriteJagLog("Error Retrieving Data: " + String(l_result))
    db.of_disconnectdb( )
    return -1
  END IF
//запись информации о размере набора данных в log-файл сервера приложений
WriteJagLog("DataSet: " + String(l_result))
// сохранение структуры вместе с набором данных в переменную типа Blob
ds.GetFullState(blb_dataset)
  
data = blb_dataset
// завершение соединения с БД (возвращение информации о соединении в Cache)
l_result = db.of_disconnectdb( )
  If l_result <> 0 Then
    WriteJagLog("Cannot Disconnect to Database" + String(l_result))
    return -1
  End If
    
WriteJagLog("'RetrieveData' method is called!")

return 0
Листинг 2. Текст опубликованной функции компонента.

Внимательно изучив получившийся код компоненты, мы можем более глубоко понять назначение объекта DataStore. DataStore – это специальный невизуальный вариант DataWindow, предназначенный для использования на сервере приложений. DataStore не использует возможности пользовательского интерфейса, так как отображение информации в трехуровневой архитектуре – это задача клиента, а не сервера приложений. Однако DataStore не только реализует все возможности обработки информации, предоставляемые DataWindow, но и добавляет некоторые новые. Важной особенностью при работе с DataStore является т.н. «синхронизация» (DataWindow Synchronization), то есть возможность двустороннего обмена информацией между DataStore, располагающемся на сервере приложений, и DataWindow, располагающемся на клиенте. При этом клиент и сервер могут получать друг от друга как всю обрабатываемую информацию (команды языка PowerScript GetFullState() и SetFullState()), так и только изменения, сделанные сервером или клиентом соответственно (команды GetChanges() и SetChanges()). Информация передается в виде BLOB (Binary Large Object), она включает в себя, как сам объект DataWindow, так и находящиеся в нем данные.

Но может возникнуть вопрос: а что произошло с механизмом соединения с базой данных? Во что он трансформировался? Ответом на этот вопрос служит функциональность EAServer, которая обеспечивает управление и кэширование соединений с различными базами данных. Этот механизм мы задействуем посредством выполнения двух операций. Во-первых (вторая строчка листинга 2), мы определяем имя менеджера соединений (Connection Cache). Во-вторых, в настройках профиля соединения с базой данных на закладке EAServer/MTS нам необходимо разрешить доступ по имени к менеджеру соединений из компонента (см. рисунок 18). Имя менеджера соединений для нашего примера – asademo8.

Рисунок 18. Конфигурирование профиля ODBC соединения для сервера приложений.

Мы вновь воспользуемся встроенными средствами управления конфигурациями среды разработки PowerBuilder. Во-первых, активизируем Project-объект для автоматического размещения нашего компонента на сервере приложений. Во-вторых, создадим еще один системный объект Project, который осуществит генерацию Proxy-объекта для этого компонента (см. рисунок 19).

Рисунок 19. Создание объекта Project для генерации Proxy-объекта.

Заключительным шагом в процессе развития нашего приложения на этом этапе, будет добавление новой строки в DropDownListBox, который теперь будет содержать, помимо информации о параметрах соединения с базой данных, также параметры соединения с сервером приложений:

ConnectString='DSN=asademo8'
iiop://localhost:9000

Естественно, не забудем и о кнопке для наполнения нашего приложения данными. Как мы договаривались, текст на кнопке будет отражать механизм получения информации. Пусть теперь на кнопке отображается «CORBA». Результат нашего визуального проектирования пользовательского интерфейса показан на рисунке 20.

Рисунок 20. Визуальные элементы управления основного окна приложения.

Итак, нам осталось написать обработчик события для нажатия кнопки “CORBA”. Код функции обработчика приведён ниже (см. листинг 3).

// блок объявления переменных
Long l_result
nvodatawindow cmt
Blob blb_dataset

// создание экземпляра объекта соединения с сервером приложений
as = create obj_easconnect
// объявление типа сервера
as.driver = "jaguar"
// объявление параметров соединения 
as.location = txt_connstr.text

// инициирование соединения с сервером приложений
l_result = as.ConnectToServer( )
  If l_result <> 0 Then
    MessageBox("Connection error", "Error: " + String(l_result))  
    return -1
  End If

// создание экземпляра удаленного объекта
l_result = as.CreateInstance(cmt)
If l_result <> 0 Then
  MessageBox("Creating Component error", "Error: " + String(l_result))  
  return -1
End If  

Try
  // вызов метода получения данных
  cmt.retrievedata(blb_dataset)
Catch(runtimeerror er)
  MessageBox("Method execution Error", er.getmessage())
  return -1
End Try

// восстановление информации
dw.setfullstate( blb_dataset)
// завершение соединения с сервером приложений
as.DisconnectServer()
// разрушение экземпляра объекта соединения с сервером приложений
destroy as
// разрушение экземпляра удаленного объекта
destroy cmt

return 0
Листинг 3. Текст обработчика события кнопки “CORBA”.

После выполнения всех необходимых действий в дереве системы (System tree) мы можем наблюдать все созданные нами объекты (см. рисунок 21).

Рисунок 21. Дерево объектов разрабатываемой системы.

Теперь все готово для второго запуска нашего приложения. Если все действия были выполнены правильно, то на экране мы увидим пример с данными из таблицы Contacts, полученные из компонента на сервере приложений.

Рисунок 22. Пример работающего приложения в трехзвенной архитектуре.

Трехзвенная архитектура успешно решает задачи, возложенные на информационную систему, которая «находится в пределах» локальной вычислительной сети. Но что делать, когда необходимо организовать автоматизированный обмен информацией с удаленным офисом? Или построить взаимодействие с партнерами по бизнесу? Ответить на эти вопросы мы постараемся далее.

Этап третий: Клиент – SOAP Сервер – Сервер приложений – Сервер баз данных

Представьте себе работу компании, специализирующуюся на предоставлении почтовых услуг. Главная задача такой компании – максимально быстрая доставка почтового отправления адресату. В повседневной работе компания пользуется услугами всевозможных транспортных перевозчиков, среди которых грузовые авиакомпании, железнодорожный, водный и даже автомобильный транспорт. Почтовый оператор каждый день занимается определением маршрутов движения почтовых отправлений, используя при этом расписание рейсов транспортных перевозчиков. Если для выполнения своей задачи он пользуется информацией, полученной из Сети, то таковая, скорее всего, представлена в формате HTML. Это удобно для просмотра её в броузере. Если представить, что мы создаем программу, которая должна будет обрабатывать эти данные, то компьютер воспримет HTML-страницу как строку символов разметки, а вовсе не как поток данных для последующей обработки. Хорошо, если бы информация была представлена следующим образом:

<Dataset_row>
  <id>1</id> 
  <last_name>Hildebrand</last_name> 
  <first_name>Jane</first_name> 
  <title>ma</title> 
  <street>280 Washington St.</street> 
  <city>Kanata</city> 
  <state>CA</state> 
  <zip>94608</zip> 
  <phone>5105551309</phone> 
  <fax>5105554209</fax> 
</Dataset_row>

Программные компоненты, которые могут осуществлять такой вид взаимодействия, получили название сетевых служб (Web services). Сетевые службы являются следующим этапом развития взаимодействия между клиентским приложением и сервером баз данных. Технология, которая лежит в основе такого архитектурного решения, представлена на рисунке 23.

Рисунок 23. Клиент – SOAP Сервер – Сервер приложений – Сервер баз данных.

Как мы видим, появился еще один уровень, который получил название SOAP-сервера. И может самое главное – изменился транспортный протокол. Теперь наше приложение может взаимодействовать с источником данных по HTTP и, следовательно, использовать все возможности Internet. SOAP-Сервер играет роль интерпретатора получаемых через HTTP-соединение SOAP-конвертов и вложенных в них XML-документов, преобразуя их к виду, понятному объектам на сервере приложений.

Однако давайте в очередной раз вернёмся к нашему примеру и посмотрим, как мы можем продолжить его развитие для использования в сети Internet, используя архитектуре сетевых служб.

На предыдущем этапе, когда мы строили трехзвенное взаимодействие, мы установили EAServer, который сейчас должен взять на себя дополнительную нагрузку. Архитектура сетевых служб, как мы теперь видим, требует наличия SOAP-Сервера. Для этого нам понадобится произвести дополнительные настройки EAServer’а. В окне свойств сервера приложений на закладке HTTP Config необходимо указать Web-приложение, которое будет использоваться по умолчанию (Webservices) и выделить компонент, который будет обрабатывать запросы клиента (см. рисунок 24). В поставку EAServer включён SOAP-servlet, то есть компонент, который осуществляет обработку SOAP-запросов, вызывает методы пользовательских компонентов и возвращает результат клиентскому приложению.

Как и в предыдущих случаях, подготовим новый объект соединения. Для этого нам необходимо объявить его в списке глобальных переменных (Global Variables), после чего добавить его к уже имеющимся объектам соединения с базой данных и с сервером приложений:

Рисунок. 24. Конфигурирование EAServer для работы с сетевыми службами.

obj_dbconnect db
obj_easconnect as
SoapConnection soap_as

Здесь необходимо отметить, что этот объект в отличие от предыдущих случаев не создается мастером среды PowerBuilder, а содержится в библиотеке pbsoapclient90.pbd, которую необходимо добавить в наше приложение.

Вернемся к функции retrievedata компонента (см. листинг 2), который мы создали на предыдущем этапе. Если внимательно посмотреть на текст этой функции, то мы увидим, что объект DataWindow мы передавали как Blob. Такой подход оправдывает себя, когда мы работаем в локальной вычислительной сети. Но когда дело касается Internet, мы хорошо понимаем, что фильтрация HTTP-пакетов на Proxy-Серверах различных компаний может не пропустить информацию, сериализованную из типа данных Blob. Для повышения надежности работы нашего примера мы откажемся от этого типа данных, и будем использовать простую строку, в которую поместим данные в XML-формате. Для этого создадим ещё один общедоступный метод нашего компонента:

Изменив формат данных на XML, мы получаем текст новой функции (см. листинг 4).

// блок объявления переменных
Long l_result
// ассоциирование объекта транзакций с менеджером соединений сервера приложений
SQLCA.dbparm = "CacheName = 'asademo8'"

// инициирование соединения с БД (с использованием менеджера соединений)
l_result = db.of_connectdb( )
  If l_result <> 0 Then
    WriteJagLog("Cannot Connect to Database: " + String(l_result))
    return -1
  End If
// ассоциирование конкретной структуры данных с DataStore 
ds.DataObject = "obj_datawindow"
// ассоциирование объекта транзакций с DataStore
ds.SetTransObject (SQLCA)
// извлечение информации из БД в DataStore
l_result = ds.Retrieve()
  IF l_result < 0 THEN
    WriteJagLog("Error Retrieving Data: " + String(l_result))
    db.of_disconnectdb( )
    return -1
  END IF
// запись информации о размере набора данных в log-файл сервера приложений
WriteJagLog("DataSet: " + String(l_result))
// сохранение набора данных в переменную типа String в XML формате
str_dataset = ds.Object.DataWindow.Data.XML
  
xmldata = str_dataset
// завершение соединения с БД (возвращение информации о соединении в Cache)
l_result = db.of_disconnectdb( )
  If l_result <> 0 Then
    WriteJagLog("Cannot Disconnect to Database" + String(l_result))
    return -1
  End If
    
WriteJagLog("'RetrieveXMLData' method is called!")

return 0
Листинг 4. Текст новой опубликованной функции.

Отличительной особенностью создания сетевых служб для промышленных серверов приложений является необходимость подготовки описания сетевой службы на языке WSDL (Web Service Definition Language). Это описание впоследствии будет являться необходимой составляющей для генерации в клиентском приложении Web Service Proxy-объекта, необходимого для обращения к этой сетевой службе. Поэтому следующим шагом на пути превращения нашего компонента в сетевую службу будет создание WSDL-описания. Для генерации WSDL-описания сетевой службы в EAServer мы воспользуемся одной из возможностей, предоставляемых графической утилитой управления сервером приложений Sybase Central – Web Services Toolkit (см. рисунок 25).

Рисунок 25. Создание WSDL описания сетевой службы в Sybase Central/Web Services Toolkit.

Итак, мы завершили процесс создания сетевой службы из нашего компонента, теперь мы можем вернуться к клиентской части приложения. Сервер приложений создал нам описание сетевой службы на языке WSDL, которое хранится в <JAGUAR>\Webservices\work\wsdl. Здесь <JAGUAR> – путь к дистрибутиву EAServer.

Рисунок 26. Создание объекта Project для генерации Web Service Proxy-объекта.

Мы вновь воспользуемся встроенными средствами управления конфигурациями среды разработки PowerBuilder. Во-первых, активизируем Project-объект для автоматического размещения нашего обновленного компонента на сервере приложений. Во-вторых, создадим еще один системный объект Project, который осуществит генерацию Web Service Proxy-объекта для только что созданной сетевой службы (см. рисунок 19).

Заключительным шагом в процессе развития нашего приложения на этом этапе будет добавление новой строки в DropDownListBox. В нашем случае он будет хранить еще и параметры соединения с SOAP-Сервером:

Рисунок 27. Визуальные элементы управления основного окна приложения.

ConnectString='DSN=asademo8'
iiop://localhost:9000
http://localhost:8080/WEBSERVICES/SOAP

Естественно, нужно добавить и кнопку для наполнения нашего приложения данными. Назовём её SOAP. Результат нашей работы показан на рисунке 27.

Итак, нам осталось написать обработчик события для нажатия кнопки “SOAP”. Программный код функции - обработчика приведен ниже (см. Листинг 5).

Рисунок 28. Дерево объектов разрабатываемой системы.

/

// блок объявления переменных
Long l_result
userpackage_nvodatawindowserviceport ws
String str_dataset

// создание экземпляра объекта соединения с SOAP-сервером
soap_as = Create SoapConnection

// создание экземпляра Proxy-объекта для сетевой службы
l_result = soap_as.CreateInstance(ws, "userpackage_nvodatawindowserviceport", _  
    txt_connstr.text)
  If l_result <> 0 Then
    MessageBox("Creating Webservice error", "Error: " + String(l_result))  
    Return -–1
  End If

Try
  // вызов метода получения данных
  ws.retrievexmldata(str_dataset)
Catch( SoapException er)
  MessageBox("Method execution error", er.getmessage())
  Return -1
End try
// восстановление информации из данных в XML-формате
l_result = dw.importstring(XML!, str_dataset)
  IF l_result < 0 Then
    MessageBox("Importing XML error", "Error: " + String(l_result))  
    Return -1
  End If  

// разрушение экземпляра Proxy-объекта для сетевой службы
Destroy ws
// разрушение экземпляра объекта соединения с SOAP-сервером
Destroy soap_as

Return 0
Листинг 5. Текст обработчика события кнопки “SOAP”.

После выполнения всех необходимых действий, в дереве системы (System tree) мы можем увидеть все созданные нами объекты (см. рисунок 28).

Теперь все готово для третьего запуска нашего приложения. Если все действия были выполнены правильно, на экране мы увидим пример с данными из таблицы Contacts, полученные из сетевой службы SOAP-сервера.

В заключение хотелось бы отметить, что интегрированная среда разработки Sybase PowerBuilder Enterprise 9 позволяет по-новому взглянуть на подходы к созданию и развитию информационных систем.

Рисунок 29. Пример приложения, работающего в сети Internet.

Хочется надеяться, что нам удалось на конкретном примере показать эволюционный подход к модернизации технологических решений.


Copyright © 1994-2016 ООО "К-Пресс"