Пакетирование компонентов
Все без исключения приложения в рамках Luther обращаются к среде J2EE и ее службам. Учитывая это ограничение, компоненты в данной среде можно пакетировать в виде элементов EJB, компонентов Java beans, отдельных библиотек классов Java, апплетов, сервлетов или произвольного сочетания перечисленных элементов. Другими словами, компонент, не являясь синонимом EJB, гем не менее допускает разные варианты пакетирования. Выбор стратегии пакетирования конкретной возможности обусловливается набором применяемых служб J2EE и решениями, уравновешивающими ряд значимых факторов (частоты межобъектного взаимодействия, местонахождения объектных экземпляров, а также необходимости применения разного рода служб J2EE — в частности, службы транзакций и службы устойчивости состояния объекта в продолжение нескольких пользовательских сеансов). К примеру, обмен данными с элементами EJB осуществляется путем удаленного вызова методов (RMI) — довольно тяжеловесного механизма взаимодействия. Некоторые контейнеры J2EE допускают оптимизацию обмена данными с элементами EJB (который в таком случае производится путем локального вызова методов); однако делается это лишь в том случае, если обмен данными происходит в рамках одной виртуальной машины Java (Java Virtual Machine, JVM). Тем не менее, поскольку оптимизация не входит в число требований к контейнерам J2EE, обмен данными между элементами EJB всегда связан с риском серьезного увеличения издержек, в связи с чем к этому вопросу следует относиться с осторожностью — если, конечно, вас заботит производительность. В качестве альтернативного решения можно создать библиотеку клaccoв Java, которая позволяет избежать удаленного вызова методов, а следовательно, и связанных с этим механизмом издержек. Впрочем, в таком случае компонентам приходится брать на себя дополнительные обязанности, которые обычно выполняются контейнерами, — в частности, связанные с созданием и удалением экземпляров компонентов. Все связанные с компонентом объекты на протяжении сеанса должны быть доступны пользователю. В этот период они могут изменяться, однако в масштабах нескольких сеансов данные должны оставаться устойчивыми и непротиворечивыми — следовательно, компоненты часто прибегают к транзакциям. К одним и тем же объектам могут обращаться сразу несколько пользователей, причем зачастую они обращаются к ним с общей целью; такие ситуации должны быть корректно обработаны. Помимо прочего, поддержка транзакций делает возможным восстановление после отказа — благодаря сохраняющейся непротиворечивости базы данных эта процедура упрощается. Как мы говорили в главе 16, модель EJB поддерживает несколько типов beans: beans-сущности (entity beans), сеансовые beans (session beans) и сеансовые beans без состояния (stateless session beans). Эти типы beans ориентированы на разные формы бизнес-логики и, соответственно, по-разному обрабатываются контейнерами. К примеру, bean-сущность допускает самостоятельное управление устойчивостью, которое осуществляется посредством поддерживаемых контейнером обратных вызовов (так называемая устойчивость под управлением beans, или самоуправляемая устойчивость); кроме того, эти задачи может вынолнять сам контейнер (так называемое контейнерное управление устойчивостью). В любом случае, эти операции связаны со значительными непроизводительными издержками, которые ограничивают практическое применение beans-сущностей долговременными бизнес-объектами, характеризующимися крупноблочным доступом к данным. Что делает контейнер J2EE? Приложения выказывают потребность в самых разных возможностях — например, в поддержке транзакций, безопасности и выравнивании нагрузки. Эги возможности очень сложны (многие корпорации даже организуют специальные подразделения, предназначенные исключительно для их обеспечения) и находятся за рамками любого конкретного приложения или прикладной области. Один из основных мотивов, которым руководствовалась компания Inmedius, принимая решение о создании архитектуры Luther на основе J2EE, состоял в том, что подобные характеристики реализованы в коммерческих общедоступных совместимых cJ2EE контейнерах, и, следовательно, Inmedius не пришлось реализовывать их самостоятельно. Многие из этих возможностей можно конфигурировать для конкретного элемента EJB в период размещения приложения. Есть и другая альтернатива — они могут присутствовать в контейнерах J2EE и носить прозрачный характер. В любом случае, разработчикам EJB не приходится встраивать вызовы к ним непосредственно в код; следовательно, их можно без труда сконфигурировать с учетом потребностей любого конкретного заказчика. Тем самым упрощается процесс создания компонентов EJB, независимых от конкретного приложения, и гарантируется их исполнение в рамках любых совместимых с J2EE контейнеров. ♦ EJB-контейнер осуществляет поддержку транзакций как декларативно, так и программно. Программное взаимодействие с контейнером позволяет разработчику обеспечить низкоуровневую, жестко закодированную поддержку транзакций EJB. Кроме того, с помощью дескриптора размещения разработчик может декларативно специфицировать поведение методов в рамках транзакций. Отсюда — возможность дифференциации поведения транзакций в разных приложениях, причем для этого реализация и конфигурирование непосредственно в коде EJB не требуются. ♦ J2EE предусматривает интегрированную модель безопасности, распространяющуюся как на веб, так и на EJB-контейнеры. Подобно поддержке транзакций, характеристики безопасности применяются как декларативно, так и программно. В случае написания методов с определениями полномочий, необходимых для их исполнения, разработчик может задать в дескрипторе размещения перечень пользователей (или группу пользователей), которым разрешается доступ к методам. Кроме того, с помощыо записей в дескрипторе размещения можно ассоциировать с методами права доступа. Это, опять же, позволяет приложению определять произвольные полномочия в рамках методов компонентов, причем сами компоненты при этом переписывать не требуется. ♦ Наконец, EJB-контейнер обеспечивает прозрачное выравнивание нагрузки. Создание и управление экземплярами EJB осуществляется контейнером в период исполнения — при необходимости они создаются, активируются, пассивируются и удаляются. Если обращений к данному элементу EJB давно не поступало, его можно пассивировать — при этом его данные сохраняются а постоянном устройстве хранения, а экземпляр удаляется из памяти. Таким способом контейнер фактически выравнивает нагрузку в масштабе всех экземпляров в контейнере, регулирует потребление ресурсов и оптимизирует производительность системы. Что делает разработчик компонентов? Разработчик компонента создает для него клиентское представление, или интерфейс прикладного программирования, а также реализацию компонента. В отношении простых элементов EJB его действия ограничиваются написанием всего лишь трех классов: home-интерфейса, remote-интерфейса и класса реализации. Кроме того, разработчик компонента составляет определение типов данных, выставляемых напоказ клиентам через интерфейс прикладного программирования. Они реализуются как дополнительные классы и во многих случаях принимают форму объектов значения (value objects), которые посредством интерфейса прикладного программирования передаются элементу EJB и извлекаются из него. Пример повторно используемого компонента: компонент технологического управления В этом разделе мы рассмотрим один из повторно используемых компонентов возможностей, разработанных для библиотеки компонентов Inmedius, связанные с ним проблемы и принятые решения. Компонент технологического управления — крупнейший из всех созданных на сегодняшний момент компонентов архитектуры — иллюстрирует процесс конструирования, пакетирования и введения в архитектуру Luther компонентов общих возможностей.
|