Смертельная схватка:.Net против J2EE. Архитектура корпоративных приложений. Написание кода веб-модуля

Смертельная схватка:.Net против J2EE. Архитектура корпоративных приложений. Написание кода веб-модуля

Введение

В современном быстро развивающемся мире электронного бизнеса, в который входят сложные распределенные приложения, важно, чтобы приложения предприятия выпускались на рынок как можно быстрее. Это означает, что команда разработчиков проекта не может позволить себе тратить время на разработку служб системного уровня, таких как службы удаленных соединений, присвоения имен, постоянных данных, защиты или управления транзакциями. Команда разработчиков проекта должна создать и внедрить переносимые многоразовые компоненты; заново изобретать испытанные, хорошо себя зарекомендовавшие архитектуры нерационально.

Платформа Java™ 2 Platform, Enterprise Edition (J2EE™) специально предназначена для указанной цели. Она предоставляет хорошо документированную стандартизованную среду для разработки и запуска распределенных, многоуровневых, основанных на компонентах приложений на Java. Эта среда автоматически выполняет большую часть низкоуровневой работы при создании приложения, например, настройку служб удаленных соединений, присвоения имен, постоянных данных, защиты и управления транзакциями, позволяя разработчикам сосредоточиться на бизнес-логике приложения.

Состав платформы J2EE:

  • Набор стандартов для компонентов J2EE и для платформы J2EE, на которой работают эти компоненты.
  • Эскиз проекта разработки приложения, подробно описывающий платформу J2EE и содержащий ценную информацию о том, как следует разрабатывать приложения J2EE.
  • Справочная реализация платформы J2EE, предоставленная фирмой Sun Microsystems Inc. в качестве стандарта, с которым можно сравнивать создаваемые коммерческие продукты J2EE. Справочная реализация содержит полностью готовые к использованию примеры приложений.
  • Набор тестов на совместимость, предназначенный для проверки и оценивания коммерческих реализаций J2EE относительно стандартов J2EE.

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

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

Дополнительная информация приведена в обзоре платформы J2EE фирмы Sun на Web-сайте http://java.sun.com/ . Выберите ссылку Products & APIs > Java™ 2 Platform, Enterprise Edition (J2EE™) > Overview .

Разработка J2EE в Nutshell

С точки зрения разработчика приложения:

Пример

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

Зачем нужна платформа J2EE?

Платформу J2EE удобно использовать для разработки приложения электронной коммерции на языке Java или приложения предприятия в следующих случаях:

Каждый из этих пунктов подробнее рассматривается ниже в этом разделе.

Стандартизованная, апробированная в промышленности среда

На рисунке 1 показана многоуровневая архитектура платформы J2EE, а также различные контейнеры J2EE, поддерживающие компоненты J2EE.

Рисунок 1: многоуровневая архитектура J2EE

Клиентский уровень

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

Средний уровень

Web-уровень

Компоненты Web-уровня содержат и, которые управляют взаимодействием с клиентским уровнем, изолируя клиенты от бизнес- и EIS-уровней. Клиенты отправляют запросы на Web-уровень, который обрабатывает запросы и возвращает результаты клиентам. Запросы клиентов к компонентам Web-уровня обычно приводят к запросам из Web-уровня к компонентам бизнес-уровня, которые, в свою очередь, могут приводить к запросам к EIS-уровню.

Бизнес-уровень

Компоненты бизнес-уровня - это объекты .

  • Они содержат бизнес-логику приложения.
  • Они отправляют запросы на EIS-уровень в соответствии с бизнес-логикой, обычно в ответ на запрос из Web-уровня.

EIS-уровень

EIS-уровень представляет хранимые данные приложения, часто в форме RDBMS. EIS-уровень может также состоять из устаревших систем или ERP, доступ к которым осуществляется через API архитектуры коннектора J2EE.

Дополнительная информация о API архитектуры коннектора J2EE приведена на Web-сайте http://java.sun.com/ . Выберите ссылку Products & Technologies > J2EE > J2EE Connector Architecture.

Дополнительная информация о стандартных конфигурациях развертывания J2EE приведена в разделе Концепция: конфигурации развертывания J2EE .

Серверы J2EE

Серверы J2EE - это коммерческие продукты, реализующие платформу J2EE. Примерами коммерческих серверов J2EE могут служить BEA WebLogic, Borland Enterprise Server, IBM WebSphere и iPlanet.

Термин "сервер J2EE" несколько расплывчат. Обычно имеется в виду "сервер J2EE, поддерживающий и контейнер Web, и контейнер EJB". Если использовать более точную терминологию, Web-сервер J2EE (такой как справочный Web-сервер J2EE, реализация Tomcat) поддерживает Web-контейнер; сервер приложения J2EE (или EJB) поддерживает контейнер EJB.

Контейнеры J2EE

Компоненты Web

Сервлеты Java

Технология Сервлет Java позволяет Web-серверу обрабатывать запросы, поступающие от Web-клиента, и отправлять ответы с динамическим содержимым. Для создания этого динамического содержимого сервлет Java может взаимодействовать с другими компонентами Web и EJB. Созданное содержимое может принимать форму любого текстового документа, в том числе HTML и XML. Кроме того, технологию Сервлет Java можно применять в качестве конечной точки Web-служб во взаимодействии с API JAX-RPC.

Примечание: применение технологии Сервлет Java в качестве конечной точки Web-служб - это новая функция J2EE 1.4 (JAX-RPC 1.1), не поддерживаемая в предыдущих версиях.

Дополнительная информация о сервлетах J2EE приведена на Web-сайте http://java.sun.com/ . Выберите ссылку J2EE > Blueprints .

Страницы JSP

Технология Страницы JSP основана на сервлетах Java, но вместо кода в ней применяется текст. Страница JSP обрабатывает запросы и выдает ответы, как сервлет, но ее логика контролируется прежде всего презентациями. Страница JSP содержит в основном статический HTML, определяющий формат представления данных, получаемых из других источников, таких как объекты JavaBean и EJB. Для того чтобы добавить новые возможности в JSP, разработчик компонентов Web может создавать библиотеки пользовательских тегов.

http://java.sun.com/ . Выберите ссылку J2EE > Blueprints.

Страницы HTML

Страницы HTML можно применять для поддержки пользовательских интерфейсов. Их можно определять как статические Web-страницы или создавать с помощью сервлетов и страниц JSP. Спецификация J2EE требует, чтобы Web-клиенты J2EE поддерживали показ страниц HTML.

Объекты JavaBean

API JavaBean определяет архитектуру для создания простых многоразовых компонентов. Эти компоненты можно редактировать и собирать с помощью инструментов компоновки приложения. Объекты JavaBean реализуются с помощью обычного кода Java, поэтому реализация доступна другим программистам, которым могут понадобиться эти компоненты, а также инструментам.

JavaBean не является технологией J2EE, но используется технологиями J2EE. Например, объекты EJB могут применять объекты JavaBean в качестве значений. Различия между объектами JavaBean и объектами Enterprise JavaBean описаны в разделе .

Дополнительная информация об объектах JavaBean приведена в разделе Концепция: объекты JavaBean .

Объекты Enterprise JavaBean

Спецификация объектов Enterprise JavaBean требует архитектуру для разработки и развертывания распределенных бизнес-приложений, основанных на компонентах и поддерживающих транзакции.

Компоненты, определяемые спецификацией EJB, называются объектами Enterprise JavaBean (EJB). Объекты EJB - это серверные компоненты Java, в которых вы реализуете бизнес-правила приложения.

Объекты EJB развертываются и выполняются в среде, называемой контейнером EJB; он был описан ранее в параграфе . Этот контейнер предоставляет службы , и . Архитектура EJB скрывает эти подробности, что позволяет разработчикам компонентов сосредоточиться на бизнес-логике.

Объект Enterprise JavaBean (EJB) - это совокупность, состоящая из интерфейсов Java, класса реализации EJB и файла описания XML. Интерфейсы EJB и класс реализации должны отвечать правилам, задаваемым спецификацией EJB, например, они должны реализовывать определенные интерфейсы и предоставлять определенные методы обратного вызова.

Интерфейсы EJB содержат домашние интерфейсы, предоставляющие методы поиска и создания интерфейсов EJB, и интерфейсы компонентов, предоставляющие бизнес-методы для конкретного экземпляра EJB. Это могут быть удаленные интерфейсы, т.е. те, которые можно вызывать по сети, или локальные интерфейсы, которые должны вызываться из того же процесса (точнее, из той же виртуальной машины Java). Интерфейсы EJB реализуются классами контейнера EJB, делегирующими методы классу реализации EJB. Исключение составляет метод поиска в сущностном объекте EJB, управляемом контейнером: он обрабатывается классом контейнера.

Существует три типа объектов EJB: , и .

http://java.sun.com/ . Выберите ссылку J2EE > Blueprints.

Сеансовые объекты EJB

Компонент сеансового объекта EJB предоставляет службы, реализующие бизнес-логику для клиента. Отдельный клиент может обращаться к каждому экземпляру сеансового объекта EJB через локальные или удаленные интерфейсы. Сеансовые объекты EJB могут сохранять данные в базе данных, но обычно для сохранения данных они вызывают сущностные объекты EJB, представляющие бизнес-объекты. Экземпляры сеансовых объектов EJB поддерживают временное диалоговое состояние.

У сеансового объекта EJB может быть метод getAllCustomers() , возвращающий совокупность всех заказчиков, хранящихся в базе данных. Этот сеансовый объект EJB получает информацию из сущностного объекта Customer и доставляет результаты клиенту.

Сеансовые объекты EJB без сохранения состояния могут использоваться в качестве конечной точки Web-служб, согласно спецификации JSR и EJB.

Примечание: применение сеансовых объектов EJB без сохранения состояния в качестве Web-служб - это новая функция J2EE 1.4 (JSR 109 и EJB 2.1), не поддерживаемая в предыдущих версиях.

Дополнительная информация о сеансовых объектах EJB приведена в документе Enterprise JavaBeans Specification, Version 2.1 на Web-сайте http://java.sun.com/ . Выберите ссылку Products & Technologies > J2EE > Enterprise JavaBeans .

Сущностные объекты EJB

Компонент сущностного объекта EJB предоставляет службы, реализующие бизнес-логику обработки объектов. Несколько клиентов могут обращаться к экземпляру сущностного объекта EJB параллельно через локальные или удаленные интерфейсы. Сущностные объекты EJB сохраняют данные бизнес-объектов в базах данных, и постоянно хранимым данным не грозят сбои контейнеров или клиентов.

Сущностный объект EJB может представлять заказчика, который может храниться в виде строки в таблице заказчиков в реляционной базе данных. Разработчик EJB выбирает способ постоянного хранения, в данном случае - реляционную базу данных.

Существует два типа постоянного хранения сущностных объектов EJB: постоянное хранение, управляемое EJB (BMP), и постоянное хранение, управляемое контейнером (CMP). Сущностные объекты EJB типа BMP должны реализовывать код доступа к данным, в то время как в объектах типа CMP эта функция реализуется контейнером. Реализации контейнера CMP обычно предоставляются для случая, когда постоянные данные хранятся в реляционной базе данных, хотя возможны и другие способы постоянного хранения (объектная база данных, файлы и т.п.).

Дополнительная информация о сущностных объектах EJB приведена в документе Enterprise JavaBeans Specification, Version 2.1 на Web-сайте http://java.sun.com/ . Выберите ссылку Products & Technologies > J2EE > Enterprise JavaBeans .

Управляемые сообщениями объекты EJB

Компонент управляемого сообщением объекта EJB предоставляет службу, реализующую бизнес-логику обработки сообщений. Эту службу может вызывать только контейнер; клиент не может напрямую вызывать эту службу через удаленные или локальные интерфейсы. Вместо этого, когда сообщение поступает в место назначения или конечную точку, обслуживаемую объектом EJB, контейнер вызывает экземпляр управляемого сообщениями объекта EJB, присвоенного как MessageListener месту назначения. Экземпляры управляемых сообщениями объектов EJB не обслуживают диалоговое состояние, но могут обслуживать переменные экземпляров со ссылками на ресурсы (например, соединение с базой данных) в вызовах методов.

Примечание: управляемые сообщениями объекты EJB не поддерживаются в версиях до EJB 2.0. Поддержка типов сообщений, отличных от JMS, - это новая функция спецификации EJB 2.1, поэтому они не поддерживаются в предыдущей версии.

Дополнительная информация об управляемых сообщениями объектах EJB приведена в документе Enterprise JavaBeans Specification, Version 2.0 на Web-сайте http://java.sun.com/ . Выберите ссылку Products & Technologies > J2EE > Enterprise JavaBeans .

Сравнительное описание объектов JavaBean и EJB

Несмотря на схожесть названий, объекты EJB значительно сложнее, чем обычные объекты JavaBean. И те, и другие определяют архитектуры для многоразовых компонентов, но объекты EJB добавляют необходимую поддержку для создания распределенных, многопользовательских служб. Собирать оба типа компонентов можно с помощью инструментов компоновки приложений, но для выполнения объекты EJB необходимо развертывать в контейнере EJB.

Службы (API) для компонентов J2EE

Контейнеры J2EE поддерживают все стандартные API J2SE, а также подмножество API J2EE, в зависимости от типа контейнера. Компоненты в контейнере могут обращаться к этому подмножеству. В следующей таблице даны краткие описания всех API и перечислены доступные контейнеры J2EE.

Описание

Контейнеры J2EE,
где доступны API

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

Дополнительная информация об объектах EJB приведена на Web-сайте http://java.sun.com/ . Выберите ссылку Products & Technologies > J2EE > Enterprise JavaBeans .

  • Приложение-клиент*

* только клиентские API

Служба идентификации и проверки прав доступа Java (JAAS) предоставляет службы для идентификации и проверки прав доступа пользователей, позволяющие убедиться, что у пользователей есть права на выполнение действия.

Дополнительная информация о JAAS приведена на Web-сайте http://java.sun.com/ . Выберите ссылку Products & Technologies > J2SE > Core Java > Java Authentication and Authorization Service (JAAS) .

  • Приложение-клиент

JavaBeans Activation Framework (JAF) предоставляет службы для идентификации данных и создания экземпляра JavaBean для манипулирования этими данными.

Дополнительная информация о JAF приведена на Web-сайте http://java.sun.com/ . Выберите ссылку Products & Technologies > J2SE > Desktop Java > JavaBeans > JavaBeans Activation Framework .

  • Приложение-клиент

API Java для обработки XML (JAXP) предоставляет абстрактный интерфейс для обработки документов XML, который можно применять с совместимыми синтаксическими анализаторами и преобразователями, использующими DOM SAX или XSLT.

http://java.sun.com/ . Выберите ссылку Products & Technologies > J2EE > Java API for XML Processing (JAXP) .

  • Приложение-клиент

Спецификация JAX-RPC определяет API клиента для доступа к Web-службам, а также приемы реализации конечных точек Web-служб.

Дополнительная информация о JAX-RPC приведена в разделе JAX-RPC /font>

  • Приложение-клиент

Web-службы для J2EE 1.1

Спецификация Web-служб для J2EE (JSR-109) определяет функции, которые сервер приложения J2EE
должен поддерживать для развертывания конечных точек Web-служб...

Дополнительная информация о Web-службах для J2EE приведена на Web-сайте http://jcp.org/aboutJava/communityprocess/final/jsr109/index.html

  • Приложение-клиент

API SSAJ предоставляет возможность управлять сообщениями SOAP.

Дополнительная информация о JAXP приведена на Web-сайте http://java.sun.com/ . Выберите ссылку Products & Technologies > J2EE > SOAP with Attachments API for Java (SAAJ) .

  • Приложение-клиент

Спецификация JAXR определяет API для доступа клиентов к реестрам на базе XML, таким как реестры WebXML и UDDI.

Дополнительная информация о JAXP приведена на Web-сайте http://java.sun.com/ . Выберите ссылку Products & Technologies > J2EE > Java API for XML Registries (JAXR).

  • Приложение-клиент

API JavaMail предоставляет среду, которую можно расширить для компоновки приложений почты на базе Java.

Дополнительная информация о JavaMail приведена на Web-сайте http://java.sun.com/ . Выберите ссылку Products & Technologies > J2EE > JavaMail .

  • Приложение-клиент

Java Database Connectivity (JDBC) - это API для доступа к табличным источникам данных, например базам данных SQL, электронным таблицам и простым файлам.

Дополнительная информация о JDBC приведена на Web-сайте http://java.sun.com/ . Выберите ссылку Products & Technologies > J2EE > JDBC .

  • Приложение-клиент

Служба сообщений Java (JMS) предоставляет службы асинхронной отправки сообщений для передачи данных и уведомлении о событиях. JMS позволяет применять управляемые сообщениями объекты EJB для асинхронной обработки сообщений, доставляемых в темы и очереди JMS.

Дополнительная информация о JMS приведена на Web-сайте http://java.sun.com/ . Выберите ссылку Products & Technologies > J2EE > Java Message Service .

  • Приложение-клиент

Спецификация Java Naming and Directory Interface (JNDI) предоставляет службы присвоения имен и работы с каталогами для регистрации и поиска распределенных компонентов и ресурсов. Клиентам достаточно знать зарегистрированное имя JNDI компонента или ресурса; знать фактическое расположение в сети не обязательно.

Пример: объекты EJB регистрируются в каталоге предприятия во время развертывания с помощью поля ejb-name файла описания. Клиенты J2EE находят объект EJB с помощью функции поиска JNDI. Все, что необходимо знать клиентам, - это имя, под которым объект EJB был зарегистрирован в каталоге. Функция поиска JNDI возвращает ссылку на домашний объект EJB.

Дополнительная информация о JNDI приведена на Web-сайте http://java.sun.com/ . Выберите ссылку Products & Technologies > J2SE > Core Java > Java Naming and Directory Interface (JNDI) .

  • Приложение-клиент

API транзакций Java (JTA) определяет интерфейсы для управления службами распределенных транзакций, выполняемыми в администраторе транзакций, в администраторе ресурсов, на сервере приложения и в приложении.

Дополнительная информация о JTA приведена на Web-сайте http://java.sun.com/ . Выберите ссылку Products & Technologies > J2EE > Transactions.

J2EE Connector 1.5

Service Provider Interface (SPI) архитектуры коннектора J2EE определяет стандарт для подключения ресурсов EIS к контейнеру J2EE. Адаптер ресурсов EIS (поставляемый вендором EIS) встраивается в контейнер J2EE, благодаря чему контейнер может предоставлять EIS защищенную поддержку транзакций. После этого компоненты в контейнере могут получать доступ к EIS через SPI архитектуры коннектора J2EE.

Дополнительная информация о коннекторах J2EE приведена на Web-сайте http://java.sun.com/ . Выберите ссылку Products & Technologies > J2EE > J2EE Connector Architecture.

Технология JavaServer Pages предоставляет разработчикам Web возможность создавать и обслуживать динамические Web-страницы. Страницы JSP основаны на тексте и используют теги типа XML для выполнения бизнес-логики и создания пользовательского информационного наполнения. Технология JSP позволяет делегировать бизнес-логику другим компонентам, так что в страницу JSP нужно встраивать лишь логику презентаций.

Дополнительная информация о JSP приведена на Web-сайте http://java.sun.com/ . Выберите ссылку Products & Technologies > J2EE > JavaServer Pages .

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

Дополнительная информация о сервлетах Java приведена на Web-сайте http://java.sun.com/ . Выберите ссылку Products & Technologies > J2EE > Java Servlet .

Технология Remote Method Invocation, работающая на основе Internet Inter-Orb Protocol (RMI-IIOP), позволяет компонентам Java обмениваться информацией с устаревшими компонентами CORBA, написанными на других языках, таких как C++ или Smalltalk.

http://java.sun.com/ . Выберите ссылку Products and APIs > RMI-IIOP .

  • Приложение-клиент

J2EE Management 1.0

API управления J2EE предоставляет API, с помощью которых инструменты управления могут запрашивать сервер приложения J2EE
с целью определить его текущее состояние, развернутые на нем приложения и т.п.

Дополнительная информация о RMI-IIOP приведена на Web-сайте http://java.sun.com/ . Выберите ссылку Products & Technologies > J2EE > J2EE Management Specification .

  • Приложение-клиент

API JMX применяется API J2EE Management для предоставления некоторой необходимой поддержки для управления продуктом J2EE.

Дополнительная информация о RMI-IIOP приведена на Web-сайте http://java.sun.com/ . Выберите ссылку Products & Technologies > J2SE > Core Java > Java Management Extensions (JMX) .

  • Приложение-клиент

J2EE Deployment 1.1

API развертывания J2EE определяет интерфейсы между средой выполнения инструмента развертывания и компонентами модулей, предоставляемыми сервером приложения
J2EE.

Дополнительная информация о J2EE Deployment приведена на Web-сайте http://java.sun.com/ . Выберите ссылку Products & Technologies > J2EE > J2EE Deployment Specification .

Спецификация JACC определяет контракт между сервером приложения J2EE и
провайдером стратегий проверки прав доступа.

Дополнительная информация о JACC приведена на Web-сайте http://java.sun.com/ . Выберите ссылку Products & Technologies > J2EE > Java Authorization Contract for Containers .

  • Приложение-клиент

Сборка и развертывание

Приложения J2EE состоят из файла описания приложения (application.xml) и одного или нескольких модулей J2EE, образующих приложение. Модули являются многоразовыми, переносимыми компонентами. Приложения J2EE упаковываются в архивы.ear.

Файлы описания

Файлы описания - это файлы XML, используемые в приложениях J2EE и модулях J2EE. Они предоставляют информацию о конфигурации, считываемую сервером J2EE во время развертывания. Эта информация о конфигурации позволяет серверу настроить приложение или модуль J2EE декларативно, не изменяя исходного кода или классов.

Для каждого приложения или модуля J2EE существует шаблонный тип файла описания. Шаблонные файлы описания, например ejb-jar.xml для модуля EJB, определяют информацию, которая применяется к EJB независимо от сервера, на котором он развернут. Напротив, файлы описания, связанные с конкретным сервером, задают информацию, учитываемую только на этом сервере. Таким файлам описания присваиваются имена, отражающие сервер, для которого они предназначены.

Модули J2EE

Модуль J2EE состоит из предназначенного для него файла описания и различных элементов, образующих модуль, включая:

  • Элементы, не относящиеся к Java, развернутые на Web-сервере (страницы JSP, файлы изображений, статические страницы HTML); иными словами, элементы виртуальных каталогов
  • Элементы Java, развернутые на Web-сервере (сервлеты, объекты JavaBean, классы Java)
  • Элементы, развернутые на сервере EJB (объекты EJB и поддерживающие классы Java)

Существует три вида модулей J2EE:

Приложение-клиент J2EE

Модули приложений-клиентов J2EE упаковываются в архивы.jar и содержат:

  • файл описания application-client.xml
  • файлы.class реализации приложения-клиента
Web-компонент

Модули Web-компонента упаковываются в архивы.war и содержат:

  • файл описания web.xml и файлы описания для конкретных серверов
  • страницы JSP
  • страницы HTML
  • изображения (например, .gif и.jpg)
  • файлы классов сервлетов

Если модуль - это Web-служба, то архив.war содержит:

  • файл описания webservices.xml
  • файлы классов сервлетов
  • файлы WSDL
Enterprise JavaBean

Отдельный архив JAR Enterprise JavaBean может содержать несколько объектов EJB, но их информация развертывания хранится в одном наборе файлов описания (ejb-jar.xml плюс файлы описания для конкретных серверов).

Стандартный модуль Enterprise JavaBean содержит:

  • файл описания ejb-jar.xml и файлы описания для конкретных серверов
  • файлы классов реализации EJB

Модуль Enterprise JavaBean Web-службы содержит:

  • файл описания webservices.xml
  • файлы классов реализации EJB

http://java.sun.com/ . Выберите ссылку Docs & Training > J2EE Platform, Enterprise Edition > Java Blueprints Program .

Разработка приложений J2EE

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

Роли для разработки приложений J2EE

Роли для разработки приложений перечислены в следующей таблице.

Название роли Описание

Провайдер продуктов J2EE

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

Провайдер компонентов приложений

Провайдер компонентов приложений фактически охватывает несколько ролей, например, разработчиков EJB и проектировщиков документов HTML. Эти роли отвечают за создание компонентов приложений J2EE с помощью предоставленных инструментов.

Ассемблер приложений

Ассемблер приложений создает приложение J2EE из компонентов приложения J2EE с помощью предоставленных инструментов. Приложение J2EE доставляется как файл Enterprise Archive (EAR). Ассемблер приложений также описывает все внешние зависимости приложения J2EE. Средство развертывания обрабатывает эти зависимости во время фактического развертывания приложения J2EE.

Средство развертывания

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

Системный администратор

Системный администратор отвечает за инфраструктуру среды выполнения, включающую все развернутые приложения J2EE. Эта роль выполняет задачу с помощью соответствующих инструментов, предоставляемых провайдером продукта J2EE.

Провайдер инструментов

Провайдер инструментов предоставляет инструменты, предназначенные для поддержки разработки и упаковки компонентов приложений. Эти инструменты часто соответствуют различным типам создаваемых компонентов приложений и включают IDE, например IBM VisualAge for Java и Borland JBuilder.

Провайдер компонентов системы

Провайдер компонентов системы предоставляет различные компоненты системного уровня, например адаптеры ресурсов или провайдер стратегии проверки прав доступа.


Эти роли не являются взаимоисключающими. У одного пользователя может быть несколько ролей. Эта возможность особенно полезна в небольших коллективах разработчиков и при моделировании ситуаций.

Этапы разработки приложения J2EE

В этом разделе описаны различные этапы разработки приложения J2EE, задаваемые спецификацией J2EE. Это следующие этапы:

  • Разработка компонентов
  • Приложение J2EE должно содержать хотя бы один модуль J2EE, поэтому по крайней мере один из этапов разработки компонентов обязателен. Последние два этапа всегда обязательны, поскольку необходимо собрать и развернуть все приложения J2EE.

    В следующей таблице приведены этапы разработки приложений J2EE.

    Этап разработки J2EE Задачи Выполняющая задачу роль J2EE Результат (доставляемый объект)

    Создание приложения-клиента J2EE

    • Создает код клиента и компилирует классы
    • Создает файл описания application-client.xml
    • Создает архив файлов JAR, содержащий файлы классов и XML

    Создание Web-компонента

    • Создает код сервлета и компилирует классы
    • Создает страницы JSP и HTML
    • Создает файл описания web.xml
    • Создает архив файлов Web Application Archive (WAR), содержащий файлы классов, .jsp, .html и XML

    (разработчик программного обеспечения: сервлеты; проектировщик Web: страницы JSP и страницы HTML)

    Создание объекта Enterprise JavaBean

    • Создать код EJB и откомпилировать классы
    • Создать файл описания ejb-jar.xml и файлы описания для конкретных серверов
    • Создать архив файлов JAR, содержащий файлы классов и XML

    (разработчик программного обеспечения)

    Сборка приложения J2EE

    • Создать файл описания application.xml
    • Создать архив файлов EAR, содержащий объекты EJB (JAR), Web-компоненты (WAR) и файлы XML

    Развертывание приложения J2EE

    • Добавить приложение J2EE (EAR) в среду сервера J2EE
    • Отредактировать файл описания application.xml с локальной конфигурацией среды
    • Развертывает приложение J2EE на сервере J2EE

    Установленное и настроенное приложение J2EE


    Каждый этап процесса разработки создает доставляемый объект, используемый на следующем этапе. Компоненты, создаваемые на этапах разработки компонентов, используются на этапе сборки приложения J2EE для создания архива EAR приложения J2EE. На этапе развертывания приложения J2EE архив EAR развертывается на сервере J2EE.

    Доставляемые объекты каждого этапа переносимы и не обязательно должны выполняться теми же пользователями или даже в той же среде; среда должна лишь удовлетворять требованиям платформы J2EE.

    Дополнительная информация об упаковке и развертывании J2EE приведена на Web-сайте http://java.sun.com/ . Выберите ссылку J2EE > Blueprints .

    Дополнительная информация

    Дополнительная информация о J2EE приведена в документе Sun J2EE Blueprints. Его можно найти на Web-сайте http://java.sun.com/ . Выберите ссылку J2EE > Blueprints > Guidelines: Designing Enterprise Applications with the J2EE Platform, Second Edition .

    Копия этого документа содержится также в Rational Unified Process.

    Главы документа Sun J2EE Blueprints, содержащие информацию по конкретным темам, указаны в следующей таблице.

    Концепция J2EE Глава J2EE Blueprints

    Технологии платформы J2EE

    Объекты Enterprise JavaBean

    Транзакции

    Сервлеты

    Страницы JSP

    Развертывание и упаковка

Главная > Лекция

Технологии программирования. Компонентный подход

В. В. Кулямин

Лекция 6. Архитектура распределенных приложений J2EE.

Общие принципы построения распределенных систем

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

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

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

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

      Децентрализация служб, состоящая в использовании нескольких машин для обработки поступающих запросов.

      Децентрализация данных, состоящая в использовании нескольких хранилищ данных или нескольких копий одного хранилища.

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

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

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

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

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

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

      Отказоустойчивость и способность к восстановлению после ошибок.
      Одним из достоинств распределенных систем является возможность построения более надежно работающей системы из не вполне надежных компонентов. Однако для того, чтобы это достоинство стало реальным, необходимо тщательное проектирование систем для избежания зависимости работоспособности системы от ее отдельных компонентов - иначе достоинство превращается в недостаток, поскольку в распределенной системе элементов больше и выше вероятность того, что хотя бы один элемент выйдет из строя и хотя бы один ресурс окажется недоступным.
      Еще важнее для распределенных систем уметь восстанавливаться после сбоев. Уровни этого восстановления могут быть различными - так, обычно, данные одного сеанса работы считается возможным не восстанавливать, поскольку такие данные часто мало значимы или легко восстанавливаются (если это не так - стоит серьезно рассмотреть необходимость восстановления сеансов), но так называемые постоянно хранимые (persistent) данные обычно требуется восстанавливать до последнего непротиворечивого их состояния.

Ниже перечислены основные аспекты, которые рассматривают при разработке и анализе распределенных систем.

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

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

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

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

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

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

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

Архитектура распределенных приложений на платформе J2EE

В рамках технологии J2EE бо льшая часть вопросов подобного рода решается за счет предоставления стандартных интерфейсов к механизмам, реализованных как часть функций серверов J2EE, web-серверов и серверов хранения данных, а также, за счет использования библиотек, входящих в состав J2EE,J2EE содержит набор связанных стандартов, поддерживающих их инструментов и библиотек, которые предназначены для разработки, развертывания и эксплуатации приложений, построенных в стиле многоуровневой клиент-серверной архитектуры. Большинство приложений J2EE разрабатываются в стиле трехуровневой архитектуры данные-представление-обработчик, в которой

    Аспект данных представляется сервером данных (СУБД) и набором компонентов EJB, чья связь с сервером данных обеспечивается EJB-контейнером. Компоненты EJB реализуют значимые для предметной области данного приложения операции над данными - то, что называется бизнес-логикой. При этом EJB-контейнер отвечает за поддержку взаимодействия распределенных объектов, поддержку транзакций, поддержку связи компонентов с СУБД, обеспечение защищенности и безопасности, поддержку параллелизма и управление ресурсами.

    Аспект представления реализуется Web-браузером на машине клиента, с помощью которого можно просматривать результаты обращений к системе в виде HTML страниц. Сами эти страницы чаще всего динамически генерируются по запросам клиента с помощью набора серверных страниц Java (Java Server Pages, JSP). Иногда в HTML страницы включают Java-апплеты, работающие на машине клиента и предоставляющие интерфейс, который тяжело или невозможно сделать с помощью HTML. Связь между этими апплетами и серверной частью системы тоже основывается на протоколе HTTP.

    Аспект обработки реализуется при помощи набора сервлетов (servlets) или вспомогательных компонентов, из которых строятся сервлеты. Они предстают клиенту в виде элементов управления на HTML страницах.
    И сервлеты, и JSP работают в рамках Web-контейнера, выполняющего для них те же функции, что EJB-контейнер для компонентов EJB и связывающего их с Web-сервером, который непосредственно получает и отсылает HTTP-сообщения.

Общая архитектура J2EE приложений выглядит следующим образом.

Рисунок 1. Типовая архитектура J2EE приложения.

Цветом выделены компоненты, которые надо разрабатывать, в отличии от предоставляемой платформой J2EE и поставщиками ПО поддержки инфраструктуры. Web-сервер, Web-контейнер, EJB-контейнер и хранилище данных могут быть размещены как на одной, так и на нескольких машинах, что позволяет строить более масштабируемые по производительности и, иногда, более надежные приложения.В результате J2EE предоставляет возможность создавать приложения, пользуясь уже имеющимися реализациями механизмов решения почти всех вопросов, которые возникают при создании распределенных систем.

Связь
Основную часть функций по обеспечению связи между отдельными компонентами J2EE приложения эта платформа берет на себя. Обращение к EJB компонентам из компонентов внутри Web-контейнера оформляется прозрачно, как обращение к локальным объектам.
Передача данных между отдельными компонентами J2EE приложения организуется на основе одной из реализаций протокола дистанционного или удаленного вызова методов (Remote Method Invocation, RMI).Этот протокол реализуется в виде набора классов, наследующих интерфейсы пакета java.rmi.В целом работа этого протокола организована следующим образом.Компоненты в приниципе равноправны, но в рамках одного обращения компонент, осуществляющий его, называется клиентом, а обрабатывающий - сервером. В рамках клиентского процесса, в котором работает клиент, находится заглушка (stub) серверного компонента, реализующего тот самый интерфейс, который серверный компонент предоставляет для дистанционных вызовов. В рамках того же процесса, что и серверный компонент, работает каркас (skeleton) серверного объекта.

Рисунок 2. Схема работы по протоколу RMI.

Вызов метода клиентским компонентом обрабатывается серверной заглушкой.Делается это так. Значения аргументов вызова сериализуются с тем, чтобы быть пересланы по сети (другое название процесса перевода значений аргументов в передаваемую по сети форму - маршаллинг ). При этом аргумент-ссылка на удаленный объект представляется в виде однозначно разрешимого в рамках системы идентификатора этого объекта. После этого устанавливается соединение с каркасом серверного объекта (или используется уже установленное ранее соединение), и имя вызываемого метода и значения аргументов его вызова передаются по сети.Каркас представляет собой объект, ожидающей прихода сообщений на некоторый порт. При поступлении такого сообщения, он извлекает из него имя вызываемого метода и аргументы вызова, и выполняет соответствующий вызов серверного компонента.Серверный компонент выполняет вызванный метод и возвращает результат каркасу.Каркас сериализует результат вызова и передает его в виде ответного сообщения заглушке.Заглушка извлекает результат из сообщения и возвращает его вызвавшему метод клиентскому компоненту.В качестве типов параметров и результатов методов, вызываемых удаленно, должны фигурировать только примитивные типы (boolean, char, byte, short, int, long, float, double), сериализуемые типы, реализующие интерфейс java.io.Serializable или типы самих объектов, способных быть вызванными удаленно, - все они реализуют интерфейс java.rmi.Remote.

Процессы и потоки.

Разбиение приложения на набор взаимодействующих процессов и потоков осуществляется автоматически Web- и EJB-контейнерами. Компоненты J2EE приложения, работающие в их рамках не должны реализовывать собственные отдельные потоки.

Именование.
Вопросы поддержки именования (т.е. поиска ресурсов по именам и идентификаторам) и службы каталогов (т.е. поддержки поиска ресурсов по набору значений их атрибутов) в рамках J2EE и J2SE решаются при помощи интерфейса JNDI (Java Naming and Directory Interface, Java интерфейс служб имен и каталогов).Базовые интерфейсы и классы JNDI находятся в пакете javax.namimg и его подпакетах javax.naming.directory, javax.naming.event, javax.naming.ldap.Основные сущности служб именования или каталогов, харанящие привязку ресурсов к именам и наборам атрибутов, называются контекстами .Базовый интерфейс всех контекстов определяется интерфейсом javax.naming.Context. Основные классы, его реализующие - itialContext, itialDirContext, itialLdapContext. Основные методы этого интерфейса перечислены ниже.

    void bind(String, Object) - связать данное имя с данным объектом

    Object lookup (String) - найти объект с данным именем

    void rebind(String, Object) - связать данное имя с данным объектом, даже если оно уже имеется в этом контексте

    void rename(String, String) - связать с объектом, связанным с первым именем, второе

    void unbind(String) - удалить связку объека с данным именем

    NamingEnumeration listBinding(String) - возвращает список связок имя-объект для подконтекста с указанным именем

    Context createSubcontext(String) - создать подконтекст с данным именем

    void destroySubcontext(String) - удалить подконтекст с данным именем

В дополнение к этим методам классы InitialDirContext и InitialLdapContext реализуют интерфейс контекста службы каталогов DirContext, имеющий методы void bind(String, Object, Attributes) для привязки набора атрибутов к объекту, Attributes getAttributes(String) для получения набора атрибутов объекта по указанному имени и NamingEnumeration search(String, Attributes) для поиска объектов по указанному набору атрибутов в контексте с указанным именем.При загрузке виртуальной машины механизм инициализации JNDI конструирует начальный контекст по JNDI свойствам, задаваемым во всех файлах с именем jndi.properties, находящихся в директориях, перечисленных в classpath.Стандартный набор JNDI свойств, которые могут быть установлены для Java приложения или апплета, включает

      itial (соответствует константе ITIAL_CONTEXT_FACTORY) - имя класса фабрики для создания начальных контекстов, обязательно должно быть установлено

      java.naming.provider.url (соответствует константе Context.PROVIDER_URL) - URL сервера каталогов или имен

      java.naming.dns.url (соответствует константе Context.DNS_URL) - URL для определения DNS узла, используемого для получения адреса JNDI URL

      java.naming.applet (соответствует константе Context.APPLET) - объект-апплет, используемый для получения JNDI свойств

      java.naming.language (соответствует константе Context.LANGUAGE) - список, через запятую, предпочтительных языков для использования в данной службе (пример: en-US, fr, ja-JP-kanji). Языки описываются в соответствии с RFC 1766.

Пример использования JNDI для распечатки содержимого директории c:/tmp. Для работы с файловой системой через JNDI используется реализация службы именования на основе файловой системы от Sun (http :// java . sun . com / products / jndi / serviceproviders . html ).

package ru.msu.cmc.prtech.examples;

import java.util.Properties;

import javax.naming.Binding;

import javax.naming.Context;

import itialContext;

import javax.naming.NamingEnumeration;

* @author Victor Kuliamin

public class JNDIExample

public static void main (String args)

Properties env = new Properties();

env.put(ITIAL_CONTEXT_FACTORY, "n.jndi.fscontext.RefFSContextFactory");

env.put(Context.PROVIDER_URL, "file://c:/tmp");

Context cntx = new InitialContext(env);

NamingEnumeration list = cntx.listBindings("");

while(list.hasMore())

Binding bnd = (Binding)list.next();

System.out.println(bnd.getName());

catch (NamingException e)

e.printStackTrace();

}
Синхронизация
Синхронизация работы потоков, как и само разбиение работ на потоки, выполняется автоматически.
Целостность и непротиворечивость
Целостность и непротиворечивость данных при работе J2EE приложений поддерживается с помощью механизма транзакций. Построение транзакций определяется в декларативном стиле в дескрипторах развертывания EJB компонентов, определяющих действия с данными приложения. Методы работы с EJB компонентами могут иметь различные политики работы с транзакционными контекстами: не поддерживать работу в рамках транзакции, включаться в имеющуюся транзакцию, стартовать новую, вложенную транзакцию, и т.п (см. далее).
Отказоустойчивость
Отказоустойчивость J2EE приложений не обеспечивается дополнительными средствами (такими, как репликация, надежная передача сообщений и пр.).
Защищенность
Защищенность J2EE приложения поддерживается механизмом определения ролей, доступности различных методов для ролей и политик переноса или создания ролей при совместной работе нескольких методов. Роли, политики их переноса и правила доступа различных ролдей к методам описываются в дескрипторах развертывания EJB компонентов (см. далее).

Разработка компонентов Enterprise Java Beans

После рассмотрения построения J2EE приложений в целом, перейдем к изучению техник разработки их отдельных компонентов.Компонент Enterprise Java Beans представляет собой компонент, который представляет в J2EE приложении элемент данных или внутренней, невидимой для пользователя логики приложения и для которого определен жизненный цикл в рамках рабочего процесса приложения - набор состояний через которые проходит один экземпляр такого компонента.EJB-контейнер, управляющий жизненным циклом EJB компонентов, несет ответственность за следующее.

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

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

    Он обеспечивает поддержку параллельной обработки запросов

    Он поддерживает связь между EJB компонентами и базой данных приложения и синхронизует их данные

    Он поддерживает целостность данных приложения с помощью механизма транзакций

    Он обеспечивает защищенность приложения с помощью механизма ролей, их передачи между компонентами и проверки корректности обращения в данной роли к методу компонента

Для разработки компонента EJB нужно сделать следующее.

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

    Дескриптор развертывания - xml файл в специальном формате, описывающий

    • Набор EJB компонентов приложения

      Совокупность элементов кода Java, образующих один компонент

      Связь свойств компонента с полями таблиц БД и связями между таблицами

      Набор ролей, привязку их к различным методам, а также набор правил доступа различных ролей к методам компонентов

      Политику компонентов и их методов по отношению к транзакциям

Правила создания EJB компонента, т.е. набор классов и интерфейсов, которые должны или могут быть декларированы как части его описания, зависят от вида самого компонента. Различают три вида компонентов:

    Компоненты данных (сущностные , entity beans)
    Они представляют данные приложения и основные методы работы с ними.

    Сеансовые компоненты (session beans)
    Они представляют независимую от пользовательского интерфейса и каких-либо конкретных данных логику работы приложения в рамках сеанса, называемую иногда бизнес-логикой

    (введены в EJB 2.0)
    Компоненты, управляемые сообщениями (message driven beans).
    Это вспомогательный вид компонентов, основное назначение которых - обработка асинхронных сообщений, в отличии от остальных, работающих в синхронном режиме. Клиент, вызывающий метод в компоненте данных или сеансовом компоненте, ждет, пока вызванный компонент не завершит свою работу. Компоненту же, управляемому сообщениями, можно отослать сообщение и продолжать работу сразу после окончания его передачи.

При построении компонентов разрабатываются следующие их составляющие.

    Для компонентов данных



    • Он должен наследовать интерфейс javax.ejb.EJBObject (наследующий java.rmi.Remote). Обычно такой интерфейс определяет набор свойств (свойством типа с именем считается пара методов get() и void set()), связанных с представляемыми компонентом данными. Некоторые из свойств могут быть не связаны непосредственно с каким-то хранимым в БД элементом данных, а вычислимы на основе нескольких таких элементов.



      Он должен наследовать интерфейс javax.ejb.EJBHome (наследующий java.rmi.Remote). Чаще всего такой интерфейс определяет метод создания компонента по значению первичного ключа, метод поиска компонента по значению первичного ключа, и, может быть, дополнительные методы поиска по разным комбинациям свойств.

      Класс компонента (bean class)
      Должен быть декларирован.

      В EJB 2.0 он должен быть абстрактным классом, реализующим интерфейс javax.ejb.EntityBean (в EJB 1.1 и ранее - неабстрактным классом).
      Этот класс должен реализовывать методы, декларированные в удаленном и локальном интерфейсах (но недолжен реализовывать сами эти интерфейсы!) и некоторые другие, например, методы установки значений свойств, являющихся частями первичного ключа. Свойства, соответствующие хранимым элементам данных должны быть оформлены в виде абстракных методов get и set - их взаимодействие с элементами данных автоматически поддерживается EJB контейнером (в EJB 1.1 эти методы неабстрактны и возвращают/изменяют значения соответсвующих полей, также можно поступить и в EJB 2.0, если вы не хотите использовать автоматическое управление синхронизацией с БД). Вычислимые свойства оформляются в виде неабстрактных методов.

      • public EjbCreate()
        Должен быть реализован. Устанавливает значения свойств, являющихся частями первичного ключа. Если первичный ключ составной, в качестве параметров этот метод должен использовать набор значений свойств, образующих первичный ключ.
        Должен возвращать null.
        Вызывается при создании в БД записи, соответсвующей создавемому экземпляру компонента.
        Этот метод может быть вызван контейнером на уже созданном экземпляре, находящемся в пуле, для установления его соответсвия новой записи в базе данных.
        Дополнительно, для каждого метода внешних интерфейсов с именем create(…) и результатом - локальным или удаленным интерфейсом - должен быть определен соответствующий метод EjbCreate(…) с теми же параметрами.

        public void ejbPostCreate()
        Вызывается сразу после создания соответсвтующей экземпляру компонента записи в БД.

        public void setEntityContext(javax.ejb.EntityContext)
        Вызывается сразу после инициализации экземпляра компонента, перед передачей его в пул.

        public void unsetEntityContext()
        Вызвается после удаления экземпляра компонента из пула и перед передачей его сборщику мусора для зачистки.

        public void ejbActivate()

        public void ejbPassivate()

        public void ejbLoad()
        Вызывается при загрузке данных экземпляра компонента из БД.

        public void ejbStore()
        Вызывается при сохранении данных экземпляра компонента в БД.

        public void ejbRemove()

В целом жизненный цикл компонента данных выглядит следующим образом.

Рисунок 3. Жизненный цикл компонента данных.

      Класс первичного ключа (primary key class)
      Должен быть декларирован, но в качестве такого класса может использоваться и существующий класс.
      Этот класс определяет набор данных, входящих в первичный ключ записи, соответсвующей компоненту EJB.
      Должен реализовывать интерфейс java.io.Serializable.
      Чаще всего в качестве класса первичного ключа используются библиотечные класы Integer и String.
      Необходимость в декларации своего класса возникает, только если первичный ключ составной. При этом поля этого класса должны иметь соответствующие по именам управляемые EJB контейнером свойства в классе компонента. В таком классе также должен быть определен конструктор без параметров. Кроме того, важно правильно определить методы equals() и hashCode(), чтобы контейнер мог автоматически управлять коллекциями компонентов с такими первичными ключами.


      Введен в EJB 2.0.

      о


      Введен в EJB 2.0.

Помимо синхронизации данных комопнентов и соответствующих данных БД, EJB контейнер берет на себя синхронизацию ссылок между EJB компонентами и ссылочных полей в БД.Для этого декларируются свойства (пары get и set методов), имеющие в качестве типов локальные интерфейсы компонентов, с которыми мы собираемся поддерживать связи, если связь единичная, либо коллекции (java.util.Collection), если связь множественная. Типы удаленных интерфейсов в качестве типов свойств, соответсвующих связям в БД, не поддерживаются. Если нужен доступ по связи в удаленном интерфейсе, приходится делать особый метод, возвращающий набор данных, соответсвующий связанному экземпляру, и реализовывать его в классе компонента.Пример декларации набора классов и интерфейсов для компонентов, представляющих клиентов некоторой организации, их счета и сами организации. Часть соответствующей схемы БД, включающая таблицу клиентов и связанные с ней, показана на рисунке.

Рисунок 4. Пример схемы БД.

Примеры кода удаленных интерфейсов. Они декларированы для организаций и клиентов.import java.rmi.RemoteException;import java.util.Collection;import javax.ejb.EJBObject; public interface OrganizationRemote extends EJBObject{ public String getName() throws RemoteException; public void setName(String name) throws RemoteException;}

package ru.msu.cmc.prtech.examples.ejb;

import java.rmi.RemoteException;

import javax.ejb.EJBObject;

public interface ClientRemote extends EJBObject

{ public String getFirstName() throws RemoteException; public void setFirstName(String name) throws RemoteException; public String getLastName () throws RemoteException; public void setLastName (String name) throws RemoteException; } Примеры кода локальных интерфейсов. Они декларированы для всех компонентов.package ru.msu.cmc.prtech.examples.ejb;import java.util.Collection; public interface OrganizationLocal extends EJBLocalObject{ public String getName() ; public void setName(String name); public Collection getClients() ; public void setClients(Collection clients); public void addClient(String firstName, String lastName); public void removeClient(String firstName, String lastName);}

package ru.msu.cmc.prtech.examples.ejb;

import java.util.Collection;

import javax.ejb.EJBLocalObject;

public interface ClientLocal extends EJBLocalObject{ public String getFirstName() ; public void setFirstName(String name); public String getLastName () ; public void setLastName (String name); public OrganizationLocal getOrganization() ; public void setOrganization(OrganizationLocal org);

public Collection getAccounts() ;

public void setAccounts(Collection accs);

Public void addAccount (double initialBalance);}

package ru.msu.cmc.prtech.examples.ejb;

import javax.ejb.EJBLocalObject;

public interface AccountLocal extends EJBLocalObject{ public double getBalance() ; public void setBalance(double balance); public double getCredit() ; public void setCredit(double credit) ; public int getStatus() ; public void setStatus(int status) ; public ClientLocal getClient() ; public void setClient(ClientLocal client); } Примеры кода внешних интерфейсов. Удаленные внешние интерфейсы декларированы для клиентов и организаций. Локальные внешние интерфейсы декларированы для клиентов и счетов, они содержат дополнительные методы создания компонентов. package ru.msu.cmc.prtech.examples.ejb;import java.rmi.RemoteException;import javax.ejb.EJBHome;import javax.ejb.FinderException;public interface OrganizationHomeRemote extends EJBHome{ public OrganizationRemote create (Integer id) throws CreateException, RemoteException; public OrganizationRemote findByPK(Integer id) throws FinderException, RemoteException;}package ru.msu.cmc.prtech.examples.ejb;import java.rmi.RemoteException;import javax.ejb.CreateException;import javax.ejb.EJBHome;import javax.ejb.FinderException;public interface ClientHomeRemote extends EJBHome{ public ClientRemote create (Integer id) throws CreateException, RemoteException; public ClientRemote findByPK(Integer id) throws FinderException, RemoteException;}

package ru.msu.cmc.prtech.examples.ejb;

import javax.ejb.CreateException;

import javax.ejb.FinderException;

public interface ClientHomeLocal extends EJBLocalHome

public ClientLocal create(Integer id)

throws CreateException;

Public ClientLocal createClient(String firstName, String lastName) throws CreateException; public ClientLocal findByPK(Integer id) throws FinderException;}package ru.msu.cmc.prtech.examples.ejb;import javax.ejb.CreateException;import javax.ejb.EJBLocalHome;public interface AccountHomeLocal extends EJBLocalHome{ public AccountLocal createAccount(double initialBalance) throws CreateException; public AccountLocal findByPK(Integer pk) throws FinderException; } Примеры кода классов компонентов. Показано, как реализовывать дополнительные, не поддерживаемые контейнером автоматически, методы работы со связями в классе организаций и дополнительный метод создания в классе клиентов. package ru.msu.cmc.prtech.examples.ejb;import java.util.Collection;import java.util.Iterator;import javax.ejb.CreateException;import javax.ejb.EntityBean;import itialContext;import javax.naming.NamingException;public abstract class OrganizationBean implements EntityBean{ public Integer ejbCreate(Integer pk) { setId(pk); return null; } public void ejbPostCreate(Integer pk) { } public abstract Integer getId (); public abstract void setId (Integer pk); public abstract String getName (); public abstract void setName (String name);

public abstract Collection getClients ();

Public abstract void setClients (Collection clients);

public void addClient(String firstName, String lastName)

{ InitialContext context = new InitialContext(); ClientHomeLocal clientHome = (ClientHomeLocal)context.lookup("ClientHomeLocal"); ClientLocal client = clientHome.createClient(firstName, lastName); Collection clients = getClients(); clients.add(client); } catch (NamingException e) { e.printStackTrace(); } catch (CreateException e) { e.printStackTrace(); } } public void removeClient(String firstName, String lastName) { Collection clients = getClients(); Iterator it = clients.iterator(); while(it.hasNext()) { ClientLocal client = (ClientLocal)it.next(); if(client.getFirstName().equals(firstName) && client.getLastName().equals(lastName)) { it.remove(); break; } } }}package ru.msu.cmc.prtech.examples.ejb;import javax.ejb.EntityBean;public abstract class ClientBean implements EntityBean{ public Integer ejbCreate(Integer pk) { setId(pk); return null; } public void ejbPostCreate(Integer pk) { }

public Integer ejbCreateClient(String firstName, String lastName)

setFirstName(firstName);

setLastName(lastName);

Public void ejbPostCreateClient(String firstName, String lastName) { } public abstract Integer getId (); public abstract void setId (Integer pk); public abstract String getFirstName (); public abstract void setFirstName (String name); public abstract String getLastName (); public abstract void setLastName (String name); public abstract OrganizationLocal getOrganization (); public abstract void setOrganization (OrganizationLocal org); public abstract Collection getAccounts() ; public abstract void setAccounts(Collection accs); public void addAccount(double initialBalance) { try { InitialContext context = new InitialContext(); AccountHomeLocal accountHome = (AccountHomeLocal)context.lookup("AccountHomeLocal"); AccountLocal account = accountHome.createAccount(initialBalance); Collection accounts = getAccounts(); accounts.add(account); } catch (NamingException e) { e.printStackTrace(); } catch (CreateException e) { e.printStackTrace(); } }}package ru.msu.cmc.prtech.examples.ejb;import javax.ejb.EntityBean;public abstract class AccountBean implements EntityBean{ public Integer ejbCreate(Integer pk) { setId(pk); return null; } public void ejbPostCreate(Integer pk) { } public Integer ejbCreateAccount(double initialBalance) { setBalance(initialBalance); setCredit(0.0); setStatus(0); return null; } public void ejbPostCreateAccount(double initialBalance) { } public abstract Integer getId (); public abstract void setId (Integer pk); public abstract double getBalance (); public abstract void setBalance (double balance); public abstract double getCredit (); public abstract void setCredit (double credit); public abstract int getStatus (); public abstract void setStatus (int status); public abstract ClientLocal getClient (); public abstract void setClient (ClientLocal client); }Компоненты данных могут также самостоятельно, не полагаясь на EJB контейнер упарвлять связью своих внутренних данных с записями в БД.

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

      Удаленный или дистанционный интерфейс (remote interface)
      Этот интерфейс определяет методы компонента, к которым можно обращаться извне его собственного процесса.
      Он должен наследовать интерфейс javax.ejb.EJBObject. Обычно такой интерфейс определяет набор методов, реализующих бизнес-логику, требующую манипуляций с несколькими компонентами данных.

      Удаленный внешний интерфейс (remote home interface)
      Этот интерфейс определяет методы для построения и поиска компонентов с определенными свойствами, в том числе и извне процесса, в котором они будут находится.
      Он должен наследовать интерфейс javax.ejb.EJBHome. Чаще всего такой интерфейс определяет метод создания компонента.

      Класс компонента (bean class)
      Должен быть декларирован.
      Этот класс определяет свойства компонента (обычно соответсвующие его данным) и реализацию методов удаленного и локального интерфейсов.
      Он должен быть неабстрактным классом, реализующим интерфейс javax.ejb.SessionBean.
      Этот класс должен реализовывать методы, декларированные в удаленном и локальном интерфейсах (но недолжен реализовывать сами эти интерфейсы!).
      Сеансовые компоненты могут связываться с БД, но эта связь должна быть обеспечена кодом самого класса компонента, например, с использованием JDBC. Она не поддерживается контейнером автоматически.
      Кроме того, этот класс может реализовывать служебные методы поддержки жизненного цикла (эти методы вызываются EJB контейнером на определенных фазах жизненного цикла компонента и могут быть использованы для каких-то специфических действий по мониторингу состояния компонента или управления дополнительными ресурсами, которыми контейнер не управляет автоматически).

      • public void ejbCreate(…)
        Служит для создания сеансового компонента по набору параметров, является реализацией соответсвующего метода локального или удаленного внешнего интерфейса.
        Этот метод вызывается при инициализации экземпляра компонента.

        public void setSessionContext(javax.ejb.SessionContext)
        Вызывается еще до инициализации экземпляра компонента.
        Может быть использован для чтения каких-то данных из контекста, являющихся общими для всех компонентов данного процесса.

        public void ejbActivate()
        Вызывается при активизации экземпляра компонента - вытаскивании его из пула построенных, но не готовых к работе компонентов, перед использованием для обработки пришедшего запроса.

        public void ejbPassivate()
        Вызывается при переводе экземпляра компонента из активного состояния в пул.

        public void ejbRemove()
        Вызывается перед удалением данных экземпляра компонента из БД.

Жизненный цикл сеансового компонента существенно зависит от того, имеет ли он состояние или нет. Сеансовый компонент с состоянием используется для отслеживания состояния сеанса, связанного с одним клиентским соединением. Такой компонент не может быть помещен в пул. Сеансовый компонент без состояния может быть помещен в пул - один экземпляр используется для обработки многих запросов.

Рисунок 5. Жизненный цикл сеансового компонента с состоянием.

Рисунок 6. Жизненный цикл сеансового компонента без состояния.

      Локальный интерфейс (local interface)
      Введен в EJB 2.0.
      Определяет набор методов компонента, к которым можно обращаться только из того же процесса, где этот компонент находится.
      Соответственно, с одной стороны, при работе через локальный интерфейс обеспечивается бо льшая эффективность, с другой - необходимо быть уверенным, что этот компонент управляется тем же самым EJB контейнером, что и обращающийся к нему.

      Локальный внешний интерфейс (local home interface)
      Введен в EJB 2.0.
      Определяет набор методов создания и поиска компонентов по свойствам.
      Тоже может быть использован только в рамках одного процесса с компонентом, который ищется или строится.

Пример кода сеансового компонента, реализующего метод перевода денег с одного счета клиента на другой (в принципе, этот метод мог бы быть реализован и в компоненте, представляющем клиента).

package ru.msu.cmc.prtech.examples.ejb;

import javax.ejb.EJBLocalObject;

public interface TransferLocal extends EJBLocalObject

public boolean tranfer(ClientLocal client, double sum,

AccountLocal sender, AccountLocal reciever)

TooSmallBalanceException;

package ru.msu.cmc.prtech.examples.ejb;

import javax.ejb.CreateException;

import javax.ejb.EJBLocalHome;

public interface TransferHomeLocal extends EJBLocalHome

public TransferLocal create() throws CreateException;

package ru.msu.cmc.prtech.examples.ejb;

import java.util.Collection;

import javax.ejb.SessionBean;

public abstract class TransferBean implements SessionBean

public void ejbCreate ()

public boolean tranfer (ClientLocal client, double sum,

AccountLocal sender, AccountLocal recipient)

throws IllegalArgumentException, SuspendedAccountException,

TooSmallBalanceException

if(client == null)

("Argument client is null");

else if(sender == null)

throw new IllegalArgumentException("Argument sender is null");

else if(recipient == null)

throw new IllegalArgumentException("Argument recipient is null");

Collection accounts = client.getAccounts();

if(!accounts.contains(sender))

throw new IllegalArgumentException

("sender account is not owned by the client");

else if(!accounts.contains(recipient))

throw new IllegalArgumentException

("recipient account is not owned by the client");

if(sender.getStatus() != 0)

("Suspended account is used as sender");

else if(recipient.getStatus() != 0)

throw new SuspendedAccountException

("Suspended account is used as recipient");

double senderBalance = sender.getBalance();

double recipientBalance = recipient.getBalance();

if(senderBalance + sender.getCredit() < sum)

throw new TooSmallBalanceException

("Balance of sender is insufficient for transfer");

sender.setBalance(senderBalance - sum);

recipient.setBalance(recipientBalance + sum);

catch(IllegalArgumentException e)

catch(SuspendedAccountException e)

catch(TooSmallBalanceException e)

catch(Exception e)

throw new EJBException(e);

    Для управляемых сообщениями компонентов
    Компонент, управляемый сообщениями, недоступен для удаленных вызовов через RMI, и поэтому не имеет удаленных и локальных интерфейсов. Обращения к экземпляру такого компонента организуются в виде посылки сообщений в соответствиии с интерфейсом Java Message Service (JMS), основные интерфейсы и классы которого находятся в пакете javax.jms.
    Такой компонент требует определения класса компонента, реализующего интерфейсы javax.ejb.MessageDrivenBean и javax.jms.MessageListener. Последний интерфейс требует определения метода void onMessage(Message), который разбирает содержимое пришедшего сообщения и определяет способ его обработки.
    Кроме того, требуется определить еще методы void ejbCreate() для создания компонента и void ejbRemove() для освобождения ресурсов при его удалении.
    Пример реализации класса управляемого сообщениями, использующего описанный выше сеансовый компонент для обработки асинхронных запросов на перевод денег между счетами, приведен ниже. В отличие от сеансового компонента, этот получает всю информацию о необходимом переводе в виде частей сообщения.

package ru.msu.cmc.prtech.examples.ejb;

import javax.ejb.EJBException;

import javax.ejb.MessageDrivenBean;

import javax.ejb.MessageDrivenContext;

import javax.jms.MapMessage;

import javax.jms.Message;

import javax.jms.MessageListener;

import javax.naming.Context;

import itialContext;

import javax.naming.NamingException;

public class TransferProcessorBean

implements MessageDrivenBean, MessageListener

Context context;

public void setMessageDrivenContext (MessageDrivenContext mdc)

throws EJBException

context = new InitialContext();

catch(NamingException e)

throw new EJBException(e);

public void ejbCreate()

public void onMessage (Message msg)

MapMessage message = (MapMessage)msg;

Integer clientPK = (Integer)message.getObject("Client");

Integer senderPK = (Integer)message.getObject("Sender");

Integer recipientPK = (Integer)message.getObject("Recipient");

Double sum = (Double) message.getObject("TransferSum");

ClientHomeLocal clientHome = (ClientHomeLocal) context.lookup("ClientHomeLocal");

AccountHomeLocal accountHome = (AccountHomeLocal) context.lookup("AccountHomeLocal");

TransferHomeLocal transferHome = (TransferHomeLocal)context.lookup("TransferHomeLocal");

TransferLocal transfer = transferHome.create();

ClientLocal client = clientHome.findByPK(clientPK);

AccountLocal sender = accountHome.findByPK(senderPK);

AccountLocal recipient = accountHome.findByPK(recipientPK);

transfer.tranfer(client, sum.doubleValue(), sender, recipient);

catch (Exception e)

throw new EJBException(e);

public void ejbRemove () throws EJBException

context.close();

catch (NamingException e)

Дескрипторы развертывания компонентов EJB
Помимо декларации интерфейсов и классов компонентов, для построения EJB компонента его необходимо написать дескриптор развертывания - XML файл в специальном формате, определяющий набор компонентов приложения и их основные свойства.Чаще всего дескрипторы развертывания не пушится вручную, их подготовку берут на себя специализированные инструменты для развертывания J2EE приложений. В рамках данного курса содержимое дескрипторов развертывания будет затронуто в рамках рассматрения поддержки платформой J2EE инфраструктуры распределенных бизнес-приложений и основных служб, в наличии которых такие приложения нуждаются.Дескриптор развертывания упаковывается вместе с байт-кодом классов компонентов приложения в JAR-архив, который служит для развертывания этого приложения. При развертывании такой архив помещают в выделенную директорию, используемую сервером J2EE для поиска развертываемых приложений, и сервер осуществляет развертывание (запуск приложения, поиск кода необходимых компонентов при поступлении запросов) на основании информации, предоставленной дескриптором.Начало декскриптора развертывания для набора EJB компонентов декларирует тот факт, что данный файл является дескриптором развертывания EJB компонентов и составлен в соответствии с определенной версией формата таких дескрипторов. Оно выглядит следующим образом.

    Тело дескриптора развертывания набора EJB компонентов заключено внутри тегов . Оно может содержать следующие элементы (теги XML).


    • Необязательный элемент.
      Содержит описание данное дескриптора развертывания для человека.
      Такой же элемент может содержаться внутри многих других тегов, обрамляющих описание отдельного компонента, связи, роли и пр., предоставляя описание этих соответвтующих сущностей.


      Необязателен.
      Является меткой, используемой интрументами, работающими с дескрипторами. Такой же элемент может использовтаься внутри тегов , , .

      ,
      Необязательны.
      Указывают файлы иконок внутри JAR-архива приложения, куда входит и данный дескриптор. Иконки используются для представления JAR-архива в визуальной среде разработки. Эти же элементы используются внутри элементов , , для определения иконок, представляющих отдельные компоненты.


      Обязательный элемент, должен появиться ровно один раз.
      Содержит набор описаний EJB компонентов в виде элементов , , .



      Описывает набор отношений между компонентами, которые соответствуют связям в схеме БД и автоматически поддерживаются контейнером.


      Необязателен.
      Содержит путь к JAR-файлу, содержащему классы, необходимые для работы клиентского приложения, - заглушки, удаленные интерфейсы и пр.


      Необязателен.
      Содержит элементы, описывающие правила использования компонентов - роли, политики предоставления доступа, политики создания транзакций и включения в имеющиеся транзакции и пр.

    Элементы и .
    и


    • Требуется ровно один.
      Задает имя компонента.



      Указывает полное имя удаленного внешнего интерфейса.


      Необязателен в EJB 2.0. В EJB 1.1 требуется ровно один.
      Указывает полное имя внешнего интерфейса.


      Необязателен, появился в EJB 2.0.
      Указывает полное имя локального внешнего интерфейса.


      Необязателен, появился в EJB 2.0.
      Указывает полное имя локального интерфейса.


      Требуется ровно один.
      Указывает полное имя класса компонента.

      Необязателен, используется в описании компонентов данных.
      Указывает имя поля-первичного ключа, если оно одно и связью компонента с БД управляет контейнер.


      Указывает имя класса первичного ключа. Можно отложить точное определение класса первичного ключа до развертывания, тогда в этом поле указывается java.lang.Object.

      Требуется ровно один, используется в описании компонентов данных.
      Имеет значения Bean или Container, в зависимости от того, управляется ли связь компонента с БД самим компонентом иил контейнером.


      Требуется ровно один, используется в описании компонентов данных.
      Имеет значения true или false, в зависимости от того, допускает ли компонент повторные вхождения (обращения из экземпляров компонентов, вызванных данным экземпляром, кроме него самого - автоматическое управление набором экземпляров EJB компонентов накладывает ограничения на такие вызовы, поскольку компонент не должен различать обращения клиентов; использование реентерабельных компонентов не рекомендуется).


      Необязателен, появился в EJB 2.0.
      Указывает версию спецификаций EJB, в соответствии с которой разработан компонент, что определяет способ управления этим компонентом. Может иметь значения 2.x и 1.x.


      Необязателен, появился в EJB 2.0.
      Задает уникальный идентификатор компонента для использования в запросах на языке EJB QL, который используется для описания вручную запросов к схеме данных при реализации компонента данных, самостоятельно управляющего связью с СУБД.


      Может быть несколько, используется в описании компонентов данных.
      Каждый такой элемент описывает одно поле данных, синхронизация которого с СУБД управляется EJB контейнером. Он может содержать тег с понятным человеку описанием поля и должен содержать тег с именем поля. В EJB 2.0 это имя совпадает с именем абстрактного свойства (для которого в классе компонента декларированы методы get и set), а в EJB 1.1 - с именем одного из полей класса компонента.



      Описывает элемент окружения, доступный через JNDI.
      (необязателен) и теги (обязателен), (обязателен, это может быть String или один из тпов-оберток примитивынх типов Java), (необязателен), определяющие имя, тип и значение элемента окружения. Из кода компонента значение такого элемента можно получить через интерфейс JNDI используя имя "java:comp/env/".


      Может быть несколько, необязателен.
      Предназначен для определения ссылок на другие компоненты, которые можно использовать для получения удаленного доступа к ним через JNDI.
      Такой тег может содержать тег (необязателен) и теги (обязателен), (обязателен, имеет значения Entity или Session), (обязателен, определяет имя удаленного интерфейса компонента), (обязателен, определяет имя удаленного внешнего интерфейса компонента), (необязателен, определяет имя копонента, если он описан в том же дексрипторе развертывания). Доступ к компоненту можно получить через интерфейс JNDI используя имя "java:comp/env/". Рекомендуется использовать подконтекст "ejb/".



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


      Может быть несколько, необязателен.
      Описывает ссылки на внешние ресурсы (классы фабрик ресурсов), которые можно использовать для получения к ним доступа через JNDI.
      Такой тег может содержать тег (необязателен) и теги (обязателен), (обязателен, указывет полное имя класса фабрики ресурса), (обязателен, указывает ответственного за аутентификацию ресурса - Container или Application, т.е. контейнер или смо приложение).
      Доступ к ресурсу можно получить через интерфейс JNDI используя имя "java:comp/env/". Рекомендуется использовать подконтексты
      "jdbc/" для ресурсов подключений к БД, например DataSource,
      "jms/" для ресурсов, связанных с передачей сообщений, например QueueConnectionFactory и TopicConnectionFactory,
      "mail/" для ресурсов службы JavaMail,
      "url/" для ресурсов, связанных с доступом по Интернет, например.URL.
      Если несколько компонентов в рамках одной транзакции должны работать содним ресурсом, в EJB 2.0 этот ресурс должен быть объявлен разделяемым при помощи необязательного тега , который может иметь значения Shareable и Unshareable.


      Может быть несколько, необязателен, появился в EJB 2.0.
      Описывает ссылки на дополнительные объекты, необходимые для работы с ресурсами.
      Может содержать тег (необязателен) и теги (обязателен), (обязателен, указывет полное имя класса дополнительного объекат).
      В качестве дополнительных объектов могут фигурировать, например, темы сообщений, с которыми компонент хочет работать через службу JMS.


      Может быть несколько, необязателен.
      Указывает роли безопасности, используемые данным компонентом. Они при работе приложения служат для проверки безопасности - сопоставляются с ролями, которым разрешен доступ к тому или иному методу, чтоможно проверить при помощи метода EJBContext.isCallerInRole(String).
      Может содержать тег (необязателен) и теги (обязателен), (необязателен, служит для сопоставления указанного имени роли с логической ролью, описанной в раздела ).


      Необязателен, появился в EJB 2.0.
      Определяет, какую логическую роль будет играть данный компонент при обращениях к другим компонентам. Для этого может быть использован вложенный тег для указания имени конкретной логической роли, или для указания того, что нужно использовать роль вызывающего клиента.



      Имеет значения Stateful или Stateless, в зависимости от того, с состоянием ли данный компонент или без.


      Требуется ровно один, используется в описании сеансовых компонентов.
      Имеет значения Container или Bean, в зависимости от того, управляет ли транзакциями данного компонента контейнер или он сам. В первом случае соответсвующие транзакции должны быть описаны в разделе .


      Может быть несколько, необязателен, появился в EJB 2.0.
      Используется для описания запросов, с помощью которых реализуются некоторые методы компонентов данных. Запросы описываются на языке EJB QL, привязыются к методам с пмощью тегов .
      Например


      findByName

      java.lang.String



      SELECT OBJECT(c) FROM Client c WHERE = ?1
      ]]

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


    • Требуется ровно один.
      Задает имя компонента.


      Требуется ровно один.
      Указывает имя класса компонента.

      , , , , , ,
      Все эти теги имеют то же значение, что и для сеансовых компонентов и компонентов данных.


      Селектор сообщений может использовать свойства сообщений в условынх выражениях для отбрасывания тех из них, которые не должны обрабатываться данным компонентом. Поскольку синтаксис этих выражений может конфликтовать с синтаксисом XML, их надо помещать в специальные разделы CDATA, которые не анализируются XML-процессорами.
      Например,



      Учитывается, только если компонент сам управляет транзакциями. Определяет используемый тип подтверждения получения соощений. Может иметь значения Auto-acknowledge, что означает немедленное подтверждение получения сообщения, или Dups-ok-acknowledge, если подтверждение может откладываться - это может повысить производительность, но и привести к повторным подтверждениям.


      Определяет тип подписки - на определенную очередь сообщений или на определенную тему, соответственно, javax.jms.Queue или javax.jms.Topic.

    Раздел
    Служит для описания отношений между компонентами, управляемых контейнером.
    Для каждого отношния в этот раздел вносится тег , который может иметь следующие элементы.


    • Необязателен, только один.
      Задает имя отношения.


      Обязательно два.
      Описывает одну роль в рамах отношения.


      • Определяет имя роли в рамах отношения.


        Определяет множественность - сколько экземпляров компонента могут участвовать в этой роли в рамках отношения с одним экземпляром в другой роли.
        Имеет возможные значения One или Many.


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


        Определяет имя поля, хранящего ссылки, поддерживающие данное отношение - оно задается в теге и для него в класе компонента должно быть определено абстрактное свойство с тем же именем.

    Раздел
    Этот раздел содержит дополнительные указания для сборки компонентов, в частности следующие.



    • Содержит необязательный элемент , а также приведенные ниже.
      Для компонента данных должно быть по одному такому элементу на каждый метод удаленных интерфейсов. Сеансовые компоненты, транзакциями которых управляет контейнер, также должны подчиняться этому правилу.


      • Возможно несколько.
        Содержит теги
        Может также включать элементы , и , который может иметь значения Remote, Home, Local, Local-Home, в зависимости от того, в каком интерфейсе этот метод декларирован - для поддержки возможности декларировать методы с одним именем и набором параметром в разных интерфейсах.


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

        • NotSupported
          Означает, что транзакции не распространяется на данный метод. Если он вызывается из транзакции, она приостанавливается до окончания его работы.

          Supports
          Такой метод продолжает существующую транзакцию и не создает новой, если был вызван вне транзакции.

          Required
          Такой метод продолжает существующую транзакцию и создает новую, если был вызван вне транзакции.

          RequiresNew
          Такой метод при любых обстоятельствах создает новую транзакцию, в рамках которой проходит вся его работа.

          Mandatory
          Такой метод всегда должен вызывться из транзакции. Если он вызван вне транзакции, создается исключение.

          Never
          Такой метод всегда должен вызываться вне транзакции. Он создает исключение, будучи вызван в контексте транзакции.


    • Возможно несколько, необязателен.
      Определяет роли безопасности, служащих для контроля доступа к методам компонентов.
      В каждом таком элементе могут содержаться теги (необязателен) и (обязателен, он и определяет имя роли).


      Возможно несколько, необязателен.
      Указывает правила доступа ролей, определенных в тегах , к методам компонентов.
      Содержит необязательный тег , несколько или один тег и несколько или один тег , кроме того, может присутствовать тег , который обозначает отсутствие проверки прав доступа во время работы, даже если они описаны.
      Каждый тег содержит тег , указывающий имя компонента, и , указывающий имя метода или знак *, который обозначает применение указанного атрибута ко всем методам.


      Необязателен.
      Содержит один или несколько тегов , определяющих методы, которые не должны вызываться при работе приложения. Каждый вызов такого метода создает исключительную ситуацию.

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

2.0//EN" /j2ee/dtds/ejb-jar_2_0.dtd">

OrganizationEJB

ru.anizationHomeRemote

ru.anizationRemote

ru.anizationLocal

ru.anizationEJB

id

teger

Container

false

id

name

ClientEJB

ru.msu.cmc.prtech.examples.ejb.ClientHomeRemote

ru.msu.cmc.prtech.examples.ejb.ClientRemote

ru.msu.cmc.prtech.examples.ejb.ClientHomeLocal

ru.msu.cmc.prtech.examples.ejb.ClientLocal

ru.msu.cmc.prtech.examples.ejb.ClientEJB

id

teger

Container

false

id

firstName

lastName

AccountEJB

ru.msu.cmc.prtech.examples.ejb.AccountHomeRemote

ru.msu.cmc.prtech.examples.ejb.AccountRemote

ru.msu.cmc.prtech.examples.ejb.AccountHomeLocal

ru.msu.cmc.prtech.examples.ejb.AccountLocal

ru.msu.cmc.prtech.examples.ejb.AccountEJB

id

teger

Container

false

id

balance

credit

status

Client-Organization

Organization-has-Clients

One

OrganizationEJB

clients

Client-belongs-to-an-Organization

Many

ClientEJB

organization

Client-Account

Client-has-Accounts

One

ClientEJB

accounts

Account-belongs-to-a-Client

Many

AccountEJB

client

OrganizationEJB

*

Required

ClientEJB

*

Required

AccountEJB

*

Required

administrator

user

administrator

OrganizationEJB

*

ClientEJB

*

AccountEJB

*

user

OrganizationEJB

getName

OrganizationEJB

getClients

ClientEJB

*

AccountEJB

*

Литература

    Э. Таненбаум, М. ван Стеен. Распределенные системы. Принципы и парадигмы. СПб, Питер, 2003.

    http :// java . sun . com / j 2 ee /1.4/ docs / index . html
    Документация по платформе J2EE

    Р. Монсон-Хейфел. Enterprise JavaBeans. СПб., Символ-Плюс, 2002.

    П. Аллен, Дж. Бамбара, М. Ашнаульт, Зияд Дин, Т. Гарбен, Ш. Смит. J2EE. Разработка бизнес-приложений. ДиаСофт, 2002.

Обе платформы предоставляют специальную поддержку для разработки компонентов на двух уровнях: уровне интерфейса пользователя (WebUI) и уровне связи с данными.

Пользовательский интерфейс Web -приложений основан на генерации динамических страниц HTML , содержащих данные, которые запрашивает пользователь . Уровень модели данных предоставляет приложению возможность работать с данными, обычно хранящимися в виде набора таблиц и связей между ними, как с набором связанных объектов .

Основные отличия между техниками разработки компонентов этих двух уровней, используемыми в рамках J2EE и. NET , можно сформулировать следующим образом.

  • В J2EE компоненты EJB предназначены не только для представления данных приложения в виде объектов, но и для реализации его бизнес-логики, т.е. объектов предметной области и основных способов работы с ними.

    В.NET нет специально выделенного вида компонентов, предназначенного для реализации бизнес-логики - она может реализовываться с помощью обычных классов, что часто удобнее. Это положение должно измениться с выходом EJB 3.0.

  • EJB-компоненты являются согласованным с объектно-ориентированным подходом представлением данных приложения. Работа с ними организуется так же, как с объектами обычных классов (с точностью до некоторых деталей).

    В.NET-приложениях все предлагаемые способы представления данных являются объектными обертками вокруг реляционного представления - в любом случае приходится работать с данными как с набором таблиц. В.NET нет автоматической поддержки их преобразования в систему взаимосвязанных объектов и обратно.

Уровень бизнес-логики и модели данных в J2EE

В рамках приложений, построенных по технологии J2EE , связь с базой данных и бизнес-логику, скрытую от пользователя, принято реализовывать с помощью компонентов Enterprise JavaBeans . На момент написания этой лекции последней версией технологии EJB является версия 2.1, в первой половине 2006 года должны появиться инструменты для работы с EJB 3.0 (в рамках J2EE 5.0).

Возможны и другие способы реализации этих функций. Например, бизнес-логика может быть реализована непосредственно в методах объектов пользовательского интерфейса, а обмен данными с базой данных - через интерфейс JDBC . При этом, однако, теряется возможность переиспользования функций бизнес-логики в разных приложениях на основе единой базы данных , а также становится невозможным использование автоматических транзакций при работе с данными. Транзакции в этом случае нужно организовывать с помощью явных обращений к JTA (см. предыдущую лекцию).

Компонент Enterprise JavaBeans (EJB) является компонентом, представляющим в J2EE -приложении элемент данных или внутренней, невидимой для пользователя логики приложения. Для компонентов EJB определен жизненный цикл в рамках рабочего процесса приложения - набор состояний, через которые проходит один экземпляр такого компонента. Компоненты EJB работают внутри EJB-контейнера , являющегося для них компонентной средой . Функции EJB-контейнера следующие:

  • Управление набором имеющихся EJB-компонентов , например, поддержкой пула компонентов для обеспечения большей производительности, а также жизненным циклом каждого отдельного компонента, в частности, его инициализацией и уничтожением.
  • Передача вызовов между EJB-компонентами , а также их удаленных вызовов. Несколько EJB-контейнеров, работающих на разных машинах, обеспечивают взаимодействие наборов компонентов, управляемых каждым из них.
  • Поддержка параллельной обработки запросов.
  • Поддержка связи между EJB-компонентами и базой данных приложения и синхронизация их данных.
  • Поддержка целостности данных приложения с помощью механизма транзакций.
  • Защита приложения с помощью механизма ролей: передача прав ролей при вызовах между компонентами и проверка допустимости обращения в рамках роли к методам компонентов.

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

  • Набор EJB-компонентов приложения.
  • Совокупность элементов кода на Java, образующих один компонент.
  • Связь свойств компонента с полями таблиц БД и связями между таблицами.
  • Набор ролей, правила доступа различных ролей к методам компонентов, правила передачи ролей при вызовах одними компонентами других.
  • Политику компонентов и их методов по отношению к транзакциям.
  • Набор ресурсов, которыми компоненты могут пользоваться в своей работе.

Правила создания

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

Для уменьшения стоимости и увеличения скорости проектирования и разработки корпоративного приложения платформа J2EE предлагает компонентный подход к проектированию, разработке, сборке и внедрению корпоративных приложений. Платформа J2EE предлагает модель многоуровневого распределенного приложения, возможность повторного использования компонентов, интегрированный обмен данными на основе XML, унифицированную модель безопасности и гибкое управление транзакциями. Вы не только можете выпускать на рынок инновационное решение для пользователей быстрее, чем раньше, но и Ваши платформо-независимые, основанные на компонентах J2EE-решения больше не привязаны к продуктам и API какого-либо одного производителя. Производители и пользователи обладают свободой выбора продуктов и компонентов, которые наиболее полно удовлетворяют их деловые и технологические требования.

Это руководство основано на примерах, описывающих возможности и функции, доступные в J2EE SDK версии 1.3. Вне зависимости от того, новичок Вы или опытный корпоративный разработчик, Вы найдете в примерах и сопровождающем их тексте полезную и доступную информацию для создания ваших собственных корпоративных решений.

Если Вы новичок в разработке J2EE приложений, эта глава – хорошее место для старта. В ней вы изучите архитектуру J2EE, ознакомитесь с важными соглашениями и понятиями, а также найдете собственные подходы к программированию, сборке и внедрению J2EE приложений.

В этой главе













Распределенные многоуровневые приложения

Платформа J2EE использует модель многоуровневого распределенного приложения. Логически приложение разделено на компоненты в соответствии с их функциональностью. Различные компоненты, составляющие J2EE-приложение, установлены на различных компьютерах в зависимости от их уровня в многоуровневой среде J2EE, которой данный компонент принадлежит. На рисунке 1-1 представлены два J2EE-приложения, разделенные на уровни, перечисленные в следующем списке. Части J2EE-приложения, показанные на рисунке 1-1, представлены в разделе "J2EE -компоненты".

    Компоненты клиентского уровня работают на клиентской машине.

    Компоненты Web-уровня работают на J2EE-сервере.

    Компоненты бизнес-уровня работают на J2EE-сервере.

    Программное обеспечение уровня корпоративной информационной системы (EIS) работает на EIS-сервере.

Хотя J2EE-приложение состоит из трех или четырех уровней, показанных на , многоуровневые J2EE-приложения обычно принято называть трехуровневыми, т.к. они расположены на трех различных системах: клиентский компьютер, сервер J2EE и сервер базы данных или обычный сервер. Трехуровневые приложения, работающие данным способом, расширяют стандартную архитектуру клиент-сервер, добавляя многопоточный сервер приложений между клиентской частью и сервером базы данных.


Рисунок 1. Многоуровневые приложения

J2EE-компоненты

J2EE-приложения состоят из компонентов. J2EE-компонента представляет собой законченный функциональный программный модуль, встроенный в приложение J2EE с соответствующими классами и файлами и взаимодействующий с другими компонентами. J2EE-спецификация определяет следующие J2EE-компоненты:

    Клиентские приложения и апплеты – это компоненты, работающие на клиентской машине.

    Компоненты технологии Java-сервлет и JavaServer Pages (JSP) – это Web-компоненты, работающие на сервере.

    Корпоративные компоненты – это бизнес-компоненты, работающие на сервере.

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

J2EE-клиенты

J2EE-клиентом может быть Web-клиент или клиент приложения.

Web-клиенты

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

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

Апплеты

Web-страница, полученная от Web-уровня, может включать в себя встроенный апплет. Апплет - это небольшое клиентское приложение, написанное на языке Java и выполняющееся на установленной в Web-браузере виртуальной машине Java. Однако системы клиента могут потребовать Java- Plug-in и файл политики безопасности для того, чтобы апплет успешно выполнялся в Web-браузере.

Web-компоненты являются более предпочтительным API для создания клиентской Web-программы, т.к. на системах клиента не требуется никаких дополнений и файлов политики безопасности. К тому же Web-компоненты предоставляют более ясную модульную структуру приложения, т.к. обеспечивают способ отделения программного кода приложения от кода оформления Web-страниц.

Клиенты приложения

Клиент J2EE-приложения работает на клиентской машине и обеспечивает пользователей возможностью работать с задачами, требующими более богатого пользовательского интерфейса, чем тот, который предоставлен языками разметки страниц. Они обычно имеют графический пользовательский интерфейс, созданный при помощи Swing или AWT API, хотя, безусловно, возможен и интерфейс командной строки.

Клиенты приложения имеют непосредственный доступ к корпоративным компонентам, исполняющимся на бизнес-уровне. Тем не менее, клиент приложения J2EE может открыть HTTP соединение для коммуникации с сервлетом, работающим на Web-уровне, если существуют такие требования к приложению.

Архитектура компонентов JavaBeans

Уровни сервера и клиента могут также включать компоненты, основанные на архитектуре компонентов JavaBeans, для управления потоком данных между клиентом приложения или апплетом и компонентами, выполняющимися на сервере J2EE, либо компонентами сервера и базой данных. Компоненты JavaBeans не считаются компонентами J2EE согласно спецификации J2EE.

Компоненты JavaBeans содержат переменные экземпляра и методы get и set для доступа к данным в переменных экземпляра. Компоненты JavaBeans, используемые таким образом, обычно просты по дизайну и реализации, но должны быть согласованы с правилами именования и дизайна, определенными в архитектуре компонентов JavaBeans.

Коммуникации сервера J2EE

Уровень корпоративной информационной системы

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

J2EE-контейнеры

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

Контейнерные сервисы

Контейнеры являются интерфейсом между компонентом и низкоуровневыми платформо-зависимыми функциональными возможностями, поддерживающими компонент. До того, как Web-компонент, корпоративный компонент или компонент клиентского приложения может быть выполнен, он должен быть скомпонован в J2EE-приложение и размещен внутри своего контейнера.

Процесс компоновки включает в себя определение установок контейнера для каждого компонента в J2EE-приложении и для самого J2EE-приложения. Установки контейнера настраивают внутреннюю поддержку, обеспечиваемую J2EE-сервером, которая включает в себя такие сервисы как безопасность, управление транзакциями, JNDI-поиск и удаленную связь. Вот некоторые из основных положений:

    Модель безопасности J2EE позволяет сконфигурировать Web-компонент или корпоративный компонент так, что доступ к системным ресурсам разрешается только авторизованным пользователям.

    Модель транзакции J2EE позволяет вам определять взаимосвязи между методами, которые составляют простую транзакцию, так, что все методы в одной транзакции интерпретируются как один модуль.

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

    Модель удаленного доступа J2EE управляет низкоуровневыми взаимосвязями между клиентами и корпоративными компонентами. После того, как корпоративный компонент создается, клиент вызывает его методы так, как если бы они находились на той же виртуальной машине.

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

Контейнер также управляет неконфигурируемыми сервисами, такими как время жизни корпоративного компонента и сервлета, ресурсный пул (объединение ресурсов) связи с БД, персистенция данных, доступ к API J2EE-платформы, описанным в разделе "J2EE API". Хотя сохраняемость данных является неконфигурируемым сервисом, J2EE-архитектура позволяет замещать сохраняемость, управляемую контейнером, при помощи включения соответствующего кода в реализацию вашего корпоративного компонента в тех случаях, когда вы желаете получить больший контроль, чем обеспечиваемый по умолчанию. Например, Вы можете использовать персистенцию, управляемую компонентом, для реализации Ваших собственных методов поиска или для создания пользовательского кэша базы данных.

Типы контейнеров

Процесс размещения устанавливает компоненты J2EE-приложения в J2EE-контейнеры, как показано на

J2EE-сервер: является частью времени исполнения J2EE-приложения. J2EE-сервер предоставляет EJB и Web-контейнеры.

Корпоративный EJB-контейнер: управляет исполнением корпоративных компонентов для J2EE-приложений. Корпоративные компоненты и их контейнер выполняются на J2EE-сервере.

Web-контейнер: управляет исполнением JSP-страницы и сервлетов для J2EE-приложения. Web-компоненты и их контейнер выполняются на J2EE-сервере.

Контейнер клиентского приложения: управляет исполнением компонентов клиентского приложения. Клиентские приложения и их контейнер выполняются на клиенте.

Контейнер апплетов: управляет выполнением апплетов. Состоит из web-броузера и Java- plug-in, выполняющихся на клиенте совместно.



Рисунок 5. J2EE-сервер и контейнеры

Пакетирование

J2EE-компоненты упаковываются раздельно и связываются в J2EE-приложение. Каждый компонент, его файлы, такие как GIF и HTML-файлы, или сервисные классы на сервере и дескриптор размещения компонуются в модуль и добавляются в J2EE-приложение. J2EE-приложение состоит из одного или нескольких модулей корпоративных компонентов, web-компонентов или компонентов клиентского приложения. Окончательное корпоративное решение может использовать одно J2EE-приложение или состоять из двух и более J2EE-приложений в зависимости от требований проекта.

J2EE-приложение и каждый из его модулей имеет собственный дескриптор размещения. Дескриптор размещения является XML-документом с расширением.xml, описывающим установки размещения компонента. Дескриптор размещения модуля корпоративного компонента, например, описывает атрибуты транзакции и уровень безопасности для корпоративного компонента. Т.к. информация дескриптора размещения является описательной, она может меняться без изменения исходного кода компонента. Во время выполнения J2EE-сервер читает дескриптор размещения и соответствующим образом обрабатывает компонент.

J2EE-приложение со всеми своими модулями поставляется в файле корпоративного архива (EAR). EAR-файл является стандартным Java-архивом (JAR) с расширением.ear. В GUI-версии J2EE SDK Вы сначала создаете EAR-файл и добавляете JAR и WAR (Web Archive) файлы в EAR. Если Вы используете средства пакетирования командной строки, Вы сначала создаете JAR и WAR файлы, а затем создаете EAR. J2EE SDK инструменты описаны в разделе "Инструменты".

    Каждый EJB JAR-файл содержит дескриптор размещения, файлы корпоративных компонентов и связанные с ними файлы.

    Каждый JAR-файл клиентского приложения содержит дескриптор размещения, файлы классов клиентского приложения и связанные с ними файлы.

    Каждый WAR-файл содержит дескриптор размещения, файлы Web-компонентов и связанные с ними ресурсы.

Использование модулей и EAR-файлов делает возможной компоновку нескольких различных J2EE-приложений, используя некоторые из тех же самых компонентов. Никакое дополнительное кодирование не требуется; это вопрос компоновки различных J2EE-модулей в EAR-файлы.

Роли в разработке ПО

Модули повторного использования дают возможность разделить процесс разработки и размещения приложения на отдельные составляющие, так что разные люди и компании могут выполнять различные части процесса.

Первые две фазы включают приобретение и инсталляцию J2EE-приложения и инструментов. Когда программное обеспечение приобретено и установлено, J2EE-компоненты могут быть разработаны поставщиками компонентов приложения, скомпонованы сборщиками приложения и размещены установщиками. В большой организации каждая из этих фаз может выполняться различными специалистами или их группами. Такое разделение труда работает, потому что на каждой фазе создается переносимый файл, являющийся входным для следующей фазы. Например, на фазе разработки компонента приложения разработчик корпоративного компонента создает EJB JAR-файлы. На фазе компоновки приложения другой разработчик компонует эти файлы в J2EE-приложение и сохраняет его как EAR-файл. На фазе размещения приложения системный администратор на сайте пользователя использует EAR-файл для инсталляции J2EE-приложения на J2EE-сервере.

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

Поставщик J2EE-продукта

Поставщиком J2EE-продукта является компания, которая проектирует и продает J2EE-платформу, наборы API и другие средства, определенные в спецификации J2EE. Обычно поставщики продукта – это продавцы операционной системы, системы управления базами данных, сервера приложений или Web-сервера, которые поставляют J2EE-платформу согласно спецификации J2EE.

Поставщик инструмента

Поставщик инструмента – это компания или человек, который создает средства разработки, компоновки и пакетирования, используемые поставщиками компонентов, компоновщиками и установщиками. Для более детальной информации о средствах, доступных в J2EE SDK версии 1.3, смотри раздел "Инструменты".

Поставщик компонента приложения

Поставщиком компонента приложения является компания или человек, который создает Web-компоненты, корпоративные компоненты, апплеты или клиентские приложения для использования в J2EE-приложениях.

Разработчик корпоративного компонента

Разработчик корпоративного компонента выполняет следующие задачи по созданию EJB JAR-файла, содержащего корпоративный компонент:

    Описывает дескриптор установки.

    Собирает class-файлы и дескриптор установки в EJB JAR-файл.

Разработчик Web-компонента

Разработчик Web-компонента выполняет следующие задачи по созданию WAR-файла, содержащего Web-компонент:

    Создает и компилирует исходный код сервлета.

    Создает JSP и HTML-файлы.

    Описывает дескриптор установки для Web-компонента.

    Собирает.class, .jsp, .html-файлы и дескриптор установки в WAR-файл.

Разработчик клиентского приложения J2EE

Разработчик клиентского приложения выполняет следующие задачи по созданию JAR-файла, содержащего клиентское приложение J2EE:

    Создает и компилирует исходный код.

    Описывает дескриптор установки для клиента.

    Собирает.class-файлы и дескриптор установки в JAR-файл.

Компоновщик приложения

Компоновщик приложения - это компания или человек, который получает JAR-файлы компонента приложения от поставщика компонента и компонует их в EAR-файл J2EE-приложения. Компоновщик или установщик может редактировать дескриптор установки непосредственно, или используя инструменты, которые корректно добавляют XML-тэги в диалоговом режиме. Разработчик программного обеспечения выполняет следующие задачи по созданию EAR-файла, содержащего J2EE-приложение:

    Собирает EJB JAR и WAR-файлы, созданные на предыдущих этапах, в EAR-файл J2EE-приложения.

    Описывает дескриптор установки для J2EE-приложения.

Установщик приложения и администратор

Установщик приложения и администратор – это компания или человек, который конфигурирует и устанавливает J2EE-приложение, администрирует вычислительную и сетевую инфраструктуру, в которой работают J2EE-приложения, и следит за рабочим окружением. В его обязанности входит также настройка управления транзакциями, настройка атрибутов безопасности, а также определение связей с базами данных.

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

Установщик/системный администратор выполняет следующие задачи по инсталляции и конфигурированию J2EE-приложения:

    Добавляет EAR-файл J2EE-приложения, созданный на предыдущем этапе, на J2EE-сервер.

    Конфигурирует J2EE-приложение под рабочее окружение, изменяя дескриптор установки J2EE-приложения.

    Проверяет корректность содержимого EAR-файла и его соответствие спецификации J2EE.

    Инсталлирует EAR-файл J2EE-приложения на J2EE-сервере.

Программное обеспечение

J2EE SDK – некоммерческое практическое определение платформы J2EE и спецификация, свободно распространяемые Sun Microsystems для демонстрации, апробирования и обучения. J2EE SDK включает в себя сервер приложений J2EE, Web-сервер, реляционную базу данных, набор J2EE API и полный набор инструментов для разработки и установки. J2EE SDK можно загрузить с

Цель J2EE SDK – позволить поставщикам продукта определить, что должна делать их реализация в конкретных условиях, и запустить набор тестов совместимости J2EE для проверки соответствия этих продуктов спецификации. Они также могут запускать свои J2EE-приложения на J2EE SDK для проверки полной переносимости всех J2EE-продуктов и инструментов.

Доступ к базам данных

Реляционная база данных обеспечивает постоянное место хранения данных приложения. Для реализации J2EE не требуется поддержки определенного типа базы данных. Это означает, что базы данных, поддерживаемые различными J2EE-продуктами, могут быть разными. Список баз данных, поддерживаемых в данной реализации, приведен в Release Notes, включенном в J2EE SDK.

J2EE API

Для запуска J2EE SDK необходимо наличие: Java 2 Platform, Standard Edition (J2SE) SDK, которая предоставляет основные API для создания J2EE-компонентов, основные инструменты разработки и виртуальную машину Java. J2EE SDK предоставляет описанные ниже API, используемые в J2EE-приложениях.

Технология Enterprise JavaBeans 2.0

Корпоративный компонент представляет собой код с полями и методами, реализующий модули бизнес-логики. Корпоративный компонент можно представить в виде строительного блока, который может использоваться как самостоятельно, так и совместно с другими компонентами, для исполнения бизнес-логики на J2EE-сервере.

Существует три вида корпоративных компонентов: сессионные компоненты, компоненты управления данными, управляемые сообщениями компоненты. Корпоративные компоненты часто взаимодействуют с базами данных. Одним из преимуществ компонентов управления данными является то, что вы не должны писать никакого SQL-кода или использовать JDBC API непосредственно для выполнения операций доступа к базе данных, т.к. EJB-контейнер сделает это за вас. Однако, если вы по какой-либо причине меняете установленную по умолчанию персистенцию, управляемую контейнером, то вы должны использовать JDBC API. Также, если необходимо, чтобы сессионный компонент имел доступ к базе данных, требуется использование JDBC API.

JDBC API 2.0

JDBC API позволяет вызывать SQL-команды из методов языка программирования Java. JDBC API используется также в корпоративных компонентах при изменении установленной по умолчанию персистенции, управляемой контейнером, или при обращении к базе данных из сессионного компонента. При персистенции, управляемой контейнером, операции доступа к базе данных обрабатываются контейнером, т.е. реализация корпоративного компонента не содержит кода JDBC или SQL-команд. Также, возможно использование JDBC API в сервлете или JSP-странице для прямого доступа к базе данных, минуя корпоративный компонент.

JDBC API состоит из двух частей: интерфейса прикладного уровня, используемого компонентами приложения для доступа к базе данных, и интерфейса поставщика сервиса, используемого для подключения JDBC-драйвера к J2EE-платформе.

Технология Java Servlet 2.3

Технология Java Servlet позволяет определить классы сервлетов. Класс сервлета расширяет возможности серверов, доступные хост-приложениям при использовании ими модели программирования "запрос - ответ". Хотя сервлеты могут отвечать на запросы любого типа, они обычно используются в приложениях, поддерживаемых Web-серверами.

Технология JavaServer Pages 1.2

Технология JavaServer Pages позволяет встраивать фрагменты кода сервлета прямо в текстовые документы. JSP-страница представляет собой текстовый документ, который содержит два типа текста: статичные шаблонные данные, которые могут быть представлены в любом текстовом формате, таком как HTML, WML и XML, а также JSP-элементы, которые определяют способ построения динамичного содержимого страницы.

Java Message Service 1.0

JMS представляет собой стандарт обмена сообщениями, позволяющий компонентам J2EE-приложения создавать, посылать, принимать и читать сообщения. Он обеспечивает двустороннее, надежное, асинхронное распределенное соединение. Дополнительную информацию по JMS можно получить в руководстве по Java Message Service на

Java Naming and Directory Interface 1.2

JNDI обеспечивает функции имен и каталогов. Интерфейс предоставляет приложениям методы для стандартных операций с каталогами, таких как назначение атрибутов объектам и поиск объектов по их атрибутам. Используя JNDI, J2EE-приложение может сохранять и восстанавливать любые типы именованных Java-объектов.

Поскольку JNDI не зависит от какой бы то ни было специализированной реализации, приложения могут использовать JNDI для доступа к многочисленным сервисам имен и каталогов, включая такие сервисы, как LDAP, NDS, DNS и NIS. Это позволяет J2EE-приложениям сосуществовать с традиционными приложениями и системами. Дополнительную информацию по JNDI можно получить в онлайн-руководстве по JNDI на

Java Transaction API 1.0

Java Transaction API (JTA) обеспечивает стандартный интерфейс для разделенных транзакций. J2EE-архитектура обеспечивает автоматическую фиксацию транзакции по умолчанию для управления фиксацией и откатом транзакций. Автофиксация означает, что любые другие приложения, просматривающие данные, будут видеть обновленные данные после каждой операции чтения или записи в базу данных. Однако если приложение выполняет две отдельные операции доступа к базе данных, зависящие друг от друга, необходимо использовать JTA API для разграничения целостной транзакций, включающей обе операции, на начало, откат и фиксацию.

JavaMail API 1.2

Приложение J2EE может использовать JavaMail API для отправления e-mail сообщений. JavaMail API состоит из двух частей: интерфейса прикладного уровня, используемого компонентами приложения для отправления почты, и интерфейса поставщика сервиса. J2EE-платформа включает JavaMail вместе с поставщиком сервиса, что позволяет компонентам приложения отправлять Интернет-почту.

JavaBeans Activation Framework 1.0

JavaBeans Activation Framework (JAF) используется JavaMail. Он предоставляет стандартные сервисы для определения типа произвольных частей данных, инкапсулирует доступ к ним, разрешает операции над ними, и создает соответствующий JavaBeans-компонент для выполнения этих операций.

Java API for XML Processing 1.1

XML – это язык для представления текстовых данных таким образом, чтобы эти данные могли быть прочитаны и обработаны любой программой или инструментом. Программы и инструменты могут генерировать XML-документы, которые могут быть прочитаны и обработаны другими программами и инструментами. Java API for XML Processing (JAXP) поддерживает обработку XML-документов, используя DOM, SAX и XSLT. JAXP позволяет приложениям анализировать и преобразовывать XML-документы независимо от особенностей реализации XML-обработки.

Например, J2EE-приложение может использовать XML для построения отчетов. Различные компании, получив отчеты, могут обрабатывать данные, способом, наиболее соответствующим их требованиям. Одна компания может передать XML-данные в программу, преобразующую XML в HTML для публикации в Web. Другая компания может обработать XML-данные для создания презентации. Третья компания может прочитать XML-данные в свое J2EE-приложение для обработки.

J2EE Connector Architecture 1.0

J2EE Connector Architecture используется поставщиками J2EE-инструментов и системными интеграторами для создания адаптеров ресурсов, поддерживающих доступ к информационной системе предприятия. Эти адаптеры могут быть включены в любой J2EE-продукт. Адаптер ресурса - это программный компонент, позволяющий компонентам J2EE-приложения иметь доступ и взаимодействовать с базовым менеджером ресурсов. Т.к. адаптер ресурса специфичен для своего менеджера ресурсов, обычно существуют различные адаптеры для каждого типа базы данных или информационной системы предприятия.

Java Authentication and Authorization Service 1.0

Java Authentication and Authorization Service (JAAS) предоставляет возможность приложению J2EE аутентифицировать и авторизовывать определенного пользователя или группу пользователей.

JAAS – это Java-версия стандартной системы подключаемого модуля аутентификации PAM (Pluggable Authentication Module), которая расширяет архитектуру безопасности платформы Java 2 поддержкой пользовательской авторизации.

Упрощенная системная интеграция

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

Набор J2EE API обеспечивает системную интеграцию и интеграцию приложений при помощи:

    Унифицированой прикладной модели на всех уровнях посредством корпоративных компонентов.

    Упрощенного механизма запросов и ответов посредством JSP-страниц и сервлетов.

    Надежной модели безопасности посредством JAAS.

    Интеграции обмена XML-данными посредством JAXP.

    Упрощенного взаимодействия систем посредством архитектуры J2EE-коннектора.

    Простого взаимодействия с базой данных посредством JDBC API.

    Интеграции корпоративных приложений посредством управляемых сообщениями компонентов и JMS, JTA и JNDI.

Вы можете узнать больше об использовании J2EE-платформы для построения интегрированных бизнес-систем, прочитав "J2EE-технология на практике" на

Инструменты

Реализация J2EE предоставляет средства размещения приложения и набор скриптов для компоновки, проверки и размещения J2EE-приложений, а также управления средой разработки и рабочим окружением. Смотрите приложение В, в котором содержится информация об инструментах.

Инструмент размещения приложения

J2EE-реализация предоставляет инструмент размещения приложения (deploytool) для компоновки, проверки и размещения J2EE-приложений. Существует две версии: командная строка и GUI.

GUI-версия включает мастера для:

    Пакетирования, конфигурирования и размещения J2EE-приложений.

    Пакетирования и конфигурирования корпоративных компонентов.

    Пакетирования и конфигурирования Web-компонентов.

    Пакетирования и конфигурирования клиентских приложений.

    Пакетирования и конфигурирования адаптеров ресурсов.

Кроме того, информация о конфигурации может быть установлена для каждого типа компонента или модуля на закладке "inspector".

Скрипты

Таблица 1-1 содержит список скриптов, включенных в J2EE-реализацию и позволяющих выполнить действия из командной строки.

Таблица 1. J2EE-скрипты

Скрипт Описание

Запуск и остановка J2EE-сервера

Запуск и остановка базы данных по умолчанию

Добавление JDBC-драйверов, JMS-назначений и мастеров соединений для различных ресурсов

Создание общих и персональных ключей и генерация сертификата X509

Импорт файлов сертификата. Добавление и удаление J2EE пользователей из списка аутентификации и авторизации для J2EE-приложения

Пакетирование компонентов J2EE-приложения в EAR, EJB JAR, JAR и WAR-файлы

Проверка корректности EAR, EJB JAR, JAR и WAR-файлов и соответствия их J2EE-спецификации

Запуск клиентского приложения J2EE

Удаление всех размещенных приложений с J2EE-сервера

В наше время существует множество вариантов построения Java-приложений и задачи их конфигурирования решаются по разному.
В статье будут рассмотрены техники и особенности конфигурирования J2SE и J2EE приложений с применением стандартных средств JDK, а также альтернативы этим способам.

J2SE

java.util.Properties
Классический вариант конфигурирования приложений - применение класса java.util.Properties . Внутри все очень просто - по сути это расширение интерфейса java.util.Map с возможностью сохранения и инициализации значений по-умолчанию.

Минусов несколько:

  • Отсутствует типизация - getProperty возвращает только String;
  • Отслеживание изменений в файле конфигурации не поддерживается (т.е. при изменении никаких событий порождено не будет и приложение ничего о них не узнает);
  • Работа только с одним файлом. N файлов = N экземпляров Properties.

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

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

На все это можно возразить: «Можно же просто добавить перечитывание файла настроек и подсистему генерации событий» - да, это так, только все это уже сделано и сделано до мелочей, которые кажутся неочевидными сейчас, но всегда обязательно проявляются.
В следующей статье я расскажу о Commons Configuration и том, как обозначенные выше проблемы там решаются.
А пока - рассмотрим типовые варианты конфигурирования J2EE-приложений.

J2EE-EJB3

Инжекция ресурса
Один из наиболее простых вариантов конфигурирования EJB-приложений заключается в использовании дескриптора развертывания (ejb-jar.xml):
< enterprise-beans >
< session >
< ejb-name > MyService
< env-entry >
< env-entry-name > myProperty
< env-entry-type > java.lang.String
< env-entry-value > 100500




В дескрипторе мы указываем имя (env-entry-name), тип (env-entry-type) и значение параметра (env-entry-value), после чего производим его инжекцию при помощи аннотации :

@Resource(name = "myProperty" )
private String myProperty;
@PostConstruct
public void postConstruct() {
System.out .println("myProperty = " + myProperty);
}

Данный подход позволяет работать с параметрами следующих типов:

  • java.lang.String
  • java.lang.Boolean
  • java.lang.Byte
  • java.lang.Character
  • java.lang.Double
  • java.lang.Float
  • java.lang.Integer
  • java.lang.Long
  • java.lang.Short

К минусам стоит отнести то, что изменение параметров приводит к редеплою приложения, что, в свою очередь, приводит к некоторому периоду неработоспособности.
Политика редеплоя зависит от настроек сканера изменений дескрипторов приложений на сервере приложений.
Так, например, в случае с сервером приложений JBoss 5.x-6.x изменение ejb-jar.xml гарантированно приводит к редеплою (если, конечно, сканер не выключен и редеплой производится вручную, через JMX-консоль).

Использование внешнего файла настроек

Существует очень полезный документ - ограничения технологии EJB . В этом документе есть четкие показания к неиспользованию файловых ресурсов. Показания следующие:

  • Файловый ресурс не является транзакционным;
  • Файлы не являеются подходящим местом для хранения бизнес-данных, поскольку существуют вне компетенции сервера приложений и не обеспечивают должного уровня поддержки механизмов блокировок.

Тем не менее, использование файлов в роли read-only источников данных допустимо, когда они находятся внутри EE-приложений. Дело в том, что в случае кластерного развертывания EE-приложение будет одинаковым на всех узлах.

Таким образом мы приходим к классическому варианту использования java.util.Properties внутри EE-приложений:

@Stateless(mappedName = "BackendService" )
public class BackendServiceBean implements BackendServiceLocal {

private static final String P_PROPERTIES = "myProperties.properties" ;

private static final Logger logger = LoggerFactory.getLogger(BackendServiceBean.class );

@EJB
private DataRepositoryLocal dataRepository;

@Resource(name = "remoteURL" )
private String remoteURL;

private Properties properties;

@PostConstruct
private void init(){
InputStream propertiesResource = null ;
try {
propertiesResource = getClass().getResourceAsStream(P_PROPERTIES);
properties = new Properties();
properties.load(propertiesResource);
} catch (Exception e) {
logger.error("Error" , e);
}finally {
if (propertiesResource !=null ){
try {
propertiesResource.close();
} catch (Exception e) {
logger.error("Error" , e);
}
}
}
}

public Properties getProperties() {
return properties;
}


Минусы те-же, что и обозначенные ранее у J2SE и java.util.Properties. Плюс к этому - мы находимся в контексте J2EE и не можем просто добавить некий поток, отслеживающий изменения файлов и генерирующий события (т.к. потоки в J2EE-приложении создавать нельзя).
Кто-то может сказать: «Надо перечитывать.properties файл каждый раз, когда приложение вызывает getProperty у нашего properties-proxy-объекта». Да, это можно сделать, но в этом случае следует забыть о высокой производительности приложения - отрытие файла на чтение, его загрузка в буфер, парсинг и создание экземпляра Properties будет вносить ощутимую задержку в обработку.
Правильный вариант применения такого решения - хранение исключительно статических read-only настроек.

Другие варианты

Описанные ранее варианты обладают недостатком - коректная работа обеспечивается только со статическими параметрами. Если требуется получение всегда актуального значения какого-либо параметра, то нужно искать другие варианты.

Для J2EE приложений такими вариантами могут быть:

  • Получение настроек из БД (причем занесением в БД занимается другое приложение - например админка-конфигуратор);
  • Запрос настроек у удаленного компонента-поставщика (например с именем ConfigurationProvider).

Как для J2EE, так и для J2SE-приложений можно применять различные фреймворки/создавать свои собственные, заточенные под решение задач конфигурирования.

J2EE-Servlets

При конфигурировании сервлетов мы имеем дело с дескриптором web.xml, в котором задаются необходимые нам параметры:
< web-app version ="2.5" xmlns ="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation ="http://java.sun.com/xml/ns/j2ee java.sun.com/xml/ns/j2ee/web-app_2_5.xsd" >


< context-param >
< param-name > myContextParam1
< param-value > value1

< context-param >
< param-name > myContextParam2
< param-value > value2


< filter >
< filter-name > myFilter
< filter-class > net.universe.filter.EntityAccessFilter
< init-param >
< param-name > checkType
< param-value > ldap

< init-param >
< param-name > myParam
< param-value > true


< servlet >
< servlet-name > MyServlet
< servlet-class > net.universe.servlet.MyServlet
< init-param >
< param-name > servletParam1
< param-value > paramValue1

< load-on-startup > 1


Настройка заключается в изменении элементов конфигурации param-value. После изменений и сохранения файла у нас также происходит редеплой приложения с последующим периодом его неработоспособности. Этот способ конфигурирования, как и вариант с ejb-jar.xml, наиболее подходит для параметров, которые не предполагается изменять по ходу работы приложения. Техники по работе с runtime-настройками здесь аналогичны применяемым в случае с EJB - базы данных, JNDI и т.п…

Общее для всех

System.getProperty
Общим, для всех перечисленных способов конфигурирования, является применение системных параметров передающихся в строке запуска Java-приложения:
java -DmyProperty1=myPropertyValue1 -DmyProperty2=myPropertyValue2 -jar myapp.jar

После этого параметры конфигурации можно взять при помощи класса java.lang.System:
String string = System.getProperty("myProperty1");

Данный способ ограниченно применим в контексте работы с J2EE - при работе в кластерном режиме системная переменная может не приехать на все узлы. Почему «может» - потому что, например, у сервера приложений JBoss есть служба SystemPropertiesService и фрагменты по ее конфигурированию можно включить в наше EE-приложение (т.е. в итоге «системная» переменная окажется на всех узлах, т.к. будет в конфигурационных файлах в составе приложения).

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

Также можно отметить альтернативу такому подходу - применение аспектно-ориентированного программирования/инъекций в байт-код. Эти техники позволяют оставить неизменным исходное приложение, но требуют более высокого уровня квалификации разработчика, особенно когда речь идет о динамическом внедрении AOP-перехватчиков (interceptors) на работающей продакшен системе.

JMX

JMX является удобным средством много для чего, в том числе и для конфигурирования приложений. Можно комбинировать применение java.util.Properties/Commons Configuration и выставленного MBean-а с методами установки/получения значений наших параметров (при установке - с последующим делегированием к properties.setProperty).
Подобное решение может успешно применяться там, где нет доступа к файлам конфигурации, но есть доступ к MBeanServer-у по сети.

Минусы у такого подхода следующие:

  • JMX подсистема в J2SE приложениях по-умолчанию выключена;
  • Допустимо применение только простых типов параметров (сложные тоже можно, но тогда управлять через jconsole уже не получится);
  • В контексте J2EE работа с JMX может приобретать весьма замысловатые формы. Так, например, микроядро JBoss 4.x-6.x использует в своей основе JMX и попытка получить дерево MBean-ов в утилите jconsole приведет, с высокой долей вероятности, к ее зависанию/очень медленной работе.

На этом пока все.

В ближайшее время будет завершена статья о библиотеке Commons Configuration, которая значительно расширяет возможности по работе с конфигурационными файлами в J2SE и J2EE приложениях.

Спасибо за внимание!



просмотров