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

Упростите интеграцию Ajax и Java EE

Автор: Патрик Гэн
IBM
Опубликовано: 21.10.2008

С ростом популярности Ajax наступает необходимость развеять мифы относительно этой популярной технологии и разобраться со всеми проблемами, которые могут возникнуть во время ее использования.

Ajax – это довольно новое понятие (хотя некоторые говорят, что это старая технология в новом обличии), которое наделало много шума в различных сообществах Web-разработчиков, включая Java EE. Технология Ajax делает работу с приложениями более удобной, устраняя необходимость бесчисленных перечитываний Web-страниц. И, кроме того, Ajax сближает серверную и клиентскую части кода и предоставляет пользователю практически бесшовный интерфейс. Ajax позиционируется как один из главных инструментов, который поможет интернету подняться на новый уровень (Web 2.0).

Как прилежные Java EE-разработчики, вы, вероятно, читали множество статей с практическими рекомендациями по использованию Ajax, и, возможно, вас взволновала предоставляемая им возможность усовершенствования ваших работ. Но каким же все-таки образом модель асинхронной передачи данных впишется в ваши Java EE приложения?

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

Недостатки схемы адресации

Довольно долго Java-сообщество усердно применяет для Web-ориентированной разработки приложений паттерны проектирования. Одним из наиболее используемых является паттерн Модель-Представление-Контроллер (Model-View-Controller – MVC). Несколько фреймворков с открытым кодом, например, Apache Struts, основаны на этом паттерне и следующей из него архитектуре (см. Ресурсы). Достоинства MVC включают в себя разделение ответственности и уменьшение количества избыточного кода.

Разделение ответственности позволяет каждому разработчику сфокусироваться на конкретной роли в заданном проекте приложения при помощи использования заранее оговоренных интерфейсов.

Например, разработчики модели сосредотачиваются на таких технологиях, как JDBC, компонентах Enterprise JavaBeans (EJB) или Java-классах, взаимодействующих с основными data-persistence технологиями.

Разработчики представлений сосредотачиваются на технологии JavaServer Pages (JSP), библиотеках тегов и других технологиях, связанных с представлением данных.

Уровень контроллера отделяет уровень модели от представления и, одновременно, является связующим звеном между ними, сохраняя четкое разделение ответственности. Рисунок 1 иллюстрирует архитектуру MVC:


Рисунок 1. Архитектура MVC.

Внедрение Ajax в Web-приложения Java EE имеет значение для разделения ответственности (а потому и при разделении ролей разработчиков). В некоторых случаях применение Ajax может породить пересылку большого количества JavaScript-кода обратно на JSP-страницу, отображаемую в браузере. Таблица 1 демонстрирует уровень представления MVC, не использующий Ajax, и показывает количество необходимого кода, в предположении, что уровень контроллера представлен сервлетами, а уровень представления – технологией JSP. (Я объясню различие между синхронными и асинхронными запросами в следующем разделе, Решение дилемм разработки).

Таблица 1. MVC без Ajax: Количество кода, связанного с типичной последовательностью уровня представления.

Последовательность Описание Требуется код?
Перед вызовом синхронного запроса Код скриптлета требуется при подготовке к отправке формы. Нет.
Вызов синхронного запроса Отправка формы инициализируется нажатием кнопки или ссылки; значения элемента DOM автоматически переводятся в HttpRequest (посредством GET или POST). Нет: все, что требуется – способ вызова отправки данных страницы.
Прием ответа на синхронный запрос После завершения обработки программой-сервером объект обычно отсылается обратно в JSP (через HttpRequest или сохраненным в HttpSession). На этом этапе объект доступен в JSP посредством использования HttpRequest или HttpSession (с помощью скриптлета или какой-либо библиотеки тегов), и требуются минимальные усилия по созданию скриптов для отображения содержимого объекта. Да: минимум скриптлетов.

Сравним Таблицу 1 с Таблицей 2, которая описывает уровень представления, использующий Ajax, так же предполагая, что уровень контроллера представлен сервлетами, а уровень представления – технологией JSP.

Таблица 2. MVC с Ajax: Количество кода, связанного с типичной последовательностью view-уровня.

Последовательность Описание Требуется код?
Перед вызовом асинхронного запроса Код JavaScript требуется для получения значений DOM элементов, необходимых для вызова Ajax. Да
Вызов асинхронного запроса Код JavaScript требуется для создания XMLHTTPRequest и ассоциирования (заранее собранных) значений DOM-элементов и XMLHTTPRequest.send(). Да
Прием ответа на асинхронный запрос После завершения исполнения серверного кода JavaScript-код требуется для получения результата (из XML-потока ответа) и преобразования значений в соответствующие DOM-элементы. Да

Как видите, количество скриптов в уровне представления при использовании Ajax увеличивается. Это влечет за собой три существенных недостатка:

У вас есть несколько способов избежать этих недостатков дизайна или, хотя бы, смягчить их:

Решение дилемм разработки

При использовании Ajax в разработке сетевых Java-приложений важно полностью осознавать разницу между синхронной и асинхронной коммуникационными моделями (см. Ресурсы). Недостаточная поддержка асинхронной коммуникационной модели может негативно отразиться на разработке клиентской части, интеграции с Web-фреймворками, использовании библиотек тегов, использовании IDE и работе потоков.

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

Рисунок 2 является диаграммой последовательности, иллюстрирующей традиционную модель синхронной передачи данных. Обратите внимание на последовательности серверных операций – процесс отправки формы от клиента и обработка ее на сервере тесно связаны.


Рисунок 2. Последовательность синхронной передачи данных.

В модели асинхронной передачи данных взаимодействие между браузером (через Web-пользователя) и Web-сервером, сервером приложений или Web-приложением не связаны. Во время обработки пары запрос/ответ, пользователь может продолжать использовать браузер. Как только обработка запроса будет завершена, асинхронный ответ (от Web-сервера, сервера приложений или Web-приложения) будет передан обратно на страницу клиента. Обычно, в течение этого процесса, вызов не влияет на действия пользователей; им нет необходимости ждать ответа.

Диаграмма последовательностей на рисунке 3 иллюстрирует асинхронную модель взаимодействия. Первая отправка данных (которые затем будет обрабатывать сервер) и первый ответ сервера выделены кружочками. Эти последовательности не связаны. В иллюстрации также обращается внимание на тот важный факт, что здесь, скорее всего, возникнет несколько потоков отправки.

Влияние клиентской части

При внедрении Ajax в Web-приложение команда разработчиков должна учитывать ряд потенциальных проблем, в основном связанных с генерацией HTML-страницы, и ее взаимодействием с браузером. Эти проблемы хорошо описаны в статье Криса Лаффры (Chris Laffra) Рассматривая Ajax, состоящей из двух частей (см. Ресурсы). Необходимо отметить несколько важных вещей:


Рисунок 3. Последовательность асинхронной передачи данных.


Рисунок 4. Последовательность управления синхронным запросом.

Интеграция с сетевыми структурами

Вполне естественны попытки интегрировать Ajax-разработку с выбранным Web-фреймворком Java EE. Но пока еще не все Java EE Web-фреймворки предоставляют поддержку асинхронной модели передачи данных. Чтобы понять последствия этого факта, вам нужно понять, каким образом сервлеты организуют синхронную и асинхронную передачу данных. Рисунок 4 показывает традиционную последовательность управления синхронным запросом.

Java EE Web-разработчикам рисунок 4 должен показаться довольно знакомым. Сначала запрос от браузера управляется контроллером service(). Этот сервлет получает любое необходимое значение из HttpRequest (параметр или атрибут). Как только контроллер завершает обработку, её результат отсылается обратно в HttpRequest (или HttpSession), и RequestDispatcher передает управление обратно на страницу.

Рисунок 5 показывает последовательность обработки асинхронного запроса.


Рисунок 5. Последовательность обработки асинхронного запроса.

Последовательность на рисунке 5 немного отличается от синхронной. Сначала запрос от браузера обрабатывается сервлетом контроллера service(). Этот сервлет получает любое значение, которое ему нужно, из HttpRequest (параметр или атрибут). Но когда контроллерная обработка завершена, должно быть указано, что тип контента HttpServletResponse – XML. Также, результат обработки должен быть выведен с помощью PrintWriter. Здесь использование RequestDispatcher игнорируется.

Дело в том, что как раз эта (асинхронная) последовательность не поддерживается в большинстве Java EE Web-фреймворков, что усложняет интеграцию с Ajax. Портлеты и фреймворки JavaServer Faces (JSF), которые не поддерживают асинхронную модель передачи данных, сталкиваются с той же проблемой.

Есть несколько вариантов выхода из этой ситуации:

Использование библиотек тегов

Использование библиотек тегов при разработке Web-приложений очень распространено. Как и многие Web-фреймворки Java EE, некоторые библиотеки тегов в настоящее время не поддерживают асинхронную модель, не оставляя вам возможности перевести данные, отправленные через XMLHttpRequest, в HttpServletRequest (и наоборот). По сути, библиотеки, которые не поддерживают асинхронную передачу данных, становятся бесполезными на время вызова Ajax XMLHttpRequest. Варианты такие:

Разработка и отладка с IDE

Для отладки JavaScript придумано множество инструментов, помогающих разработчикам в создании JavaScript-решений. Однако традиционные среды разработки Java не позволяют исследовать значения в XMLHTTPRequest и других параметрах Ajax.

Одно из решений – использование AJAX Toolkit Framework (ATF) (см. Ресурсы). ATF – это дополнение к Eclipse с усовершенствованными инструментами редактирования JavaScript, такими, как проверка синтаксиса во время редактирования, встроенный браузер Mozilla, встроенный браузер DOM и встроенный JavaScript-отладчик. Кроме того, ATF включает в себя функцию Personality Builder, которая помогает при создании элементов IDE для произвольных run-time сред Ajax.

Проблемы работы потоков

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

Если Web-приложение поддерживает как синхронные, так и асинхронные модели взаимодействия, могут возникнуть проблемы в случае, когда его работа неправильно проанализирована и спланирована. В приложении, которое поддерживает обе модели передачи данных, может возникнуть путаница с вызовами на данной странице (то есть, исключительно синхронные, исключительно асинхронные и смесь синхронных и асинхронных). Как и в сценарии «многократного щелчка», асинхронный вызов может обрабатываться немного медленнее. И пользователь, если приложение не предотвращает этого, может вызвать синхронный запрос во время обработки асинхронного потока, поскольку страница не обновляется и поэтому не предотвращает дальнейшую активность на странице. Конечный результат – то, что эти два процесса обработаны одновременно. Даже если они не вызваны нажатием одной и той же кнопки или ссылки, такие ситуации могут вызывать проблемы поточной работы (подобно проблеме «многократного щелчка») в коде программы сервера.

В качестве примера возьмем страницу перевода средств в банковском приложении, показанную на Рисунке 6:


Рисунок 6. Транзакционный пример.

В этом примере кнопка Transfer Funds (Перевод средств) порождает Ajax-запрос. Ссылка Logout порождает синхронный запрос. Если нетерпеливый или неопытный пользователь нажмет последовательно кнопку и ссылку «Logout» (предполагается, что обе ссылки имеют одинаковый путь в коде), в конечном счете, может произойти эффект гонки.

Есть два способа избежать этой ситуации. Первый – это клиентское решение. Используйте JavaScript для того, чтобы, как только ссылка или кнопка была нажата, запретить дальнейшие попытки отправки формы до тех пор, пока текущий поток не будет обработан. Второе решение состоит в том, чтобы разрешить многократные отправки потоков, полагаясь на синхронизацию с серверной частью, чтобы избежать эффекта гонки. Если для решения этой проблемы вы выбрали синхронизацию, не забудьте, что Web-компоненты Java EE (сервлеты, портлеты, JSF и т.д.) являются многопоточными. Будьте осторожны с синхронизацией больших кусков кода (особенно кода, относящегося к циклу обработки запроса/ответа). Неправильное использование синхронизации может превратить приложение в однопоточное, уменьшая его производительность.

Преодоление проблем производительности

Использование Ajax может влиять на выполнение Web-приложений, основанных на Java EE. Возможность добавления дополнительных потоков по запросу может повлиять на два элемента.

Во-первых, возможно воздействие на пул потоков сервлет-контейнера. Это средство определяет максимально возможное число потоков, которые могут быть запущены в Web-контейнере одновременно. Для каждого запроса клиента нужен один поток. Однако запрос клиента не обязательно равен запросу пользователя. Браузеру может потребоваться несколько клиентских запросов на один пользовательский. Например, несколько клиентских запросов могут быть необходимы, чтобы осуществить операцию пользователя «отправить форму» (submit) (которая содержит в себе отправку значения полей формы, получение gif-файлов, получение файлов JavaScript, и получение файлов CSS). Если разрешено параллельно отправлять синхронные и асинхронные запросы, то такая ситуация означает использование еще одного потока (для Ajax-запроса) на каждый запрос пользователя. Хотя возможная необходимость добавления еще одного потока на каждый пользовательский запроса не кажется страшной, последствия этого становятся очевидными во время процесса загрузки приложения (когда каждый дополнительный поток на пользовательский запрос умножается на среднее число пользователей). Очевидно, что эта ситуация может влиять на выполнение сервлет-контейнера.

Еще одно узкое место – пул соединений с БД. Типичное Web-приложение Java EE разрешает два типа последовательности пользовательского запроса: поверхностные запросы и глубокие запросы. Поверхностный запрос – это запрос, который создается из Web-страницы и исполняется на сервере, но не требует доступа к постоянному хранилищу данных (такому как база данных) для выполнения запроса. Глубокий запрос – наоборот.

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

В результате, вам может понадобиться увеличить размер пула или число соединений.

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

Java-разработчики всегда акцентировали внимание на необходимости предоставления инструментов для тестирования Java SE и Java EE кода. Так как количество JavaScript в браузерах возрастает с внедрением Ajax, то требуется надежная база для тестирования. Сейчас доступны JsUnit, Selenium, и HttpUnit (см. Ресурсы).

Эти ресурсы предоставляют инструменты для разработки тестов тех функций JavaScript, которые управляют DOM-элементами на Web-страницах. Также они позволяют группировать единичные тесты в наборы. Средство тестирования совместимости в браузере Selenium позволяет вам тестировать функции JavaScript на различных браузерах и операционных системах. Здесь используются JavaScript и Iframes для встраивания механизма тестирования в ваш браузер. Эта техника должна работать во всех браузерах, которые поддерживают JavaScript и является особенно полезной для приложений, которые поддерживают множество различных браузеров и их версий. Как Selenium, так и JsUnit поддерживают непрерывную интеграцию: вы можете встраивать как единичные тесты, так и наборы тестов JavaScript в автоматизированный процесс сборки.

Вывод

Внедрение Ajax, как и любой другой технологии, в приложение Java EE имеет свои недостатки и преимущества. Эта статья дает вам общее представление об интеграции Ajax в Web-приложения Java EE. Модель асинхронного передачи данных в Ajax достаточно сильно отличается от синхронной модели, которая традиционно используется в построении Web-приложений на Java EE. Чтобы избежать неожиданностей, заранее продумывайте потенциальные проблемы, прежде чем использовать Ajax.

Поддержка Ajax во фреймворках и утилитах Java EE продолжает совершенствоваться. Чтобы уменьшить сложность внедрения Ajax, обратите внимание на новейшие системы, поддерживающие его. За чем стоит следить, так это за основанной на JSF Apache Shale и DWR, базирующейся на сервлетах.

Ресурсы


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

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