corner imagecorner image
IDEPlatformPluginsDocs & SupportCommunityPartners
Учебный курс по электронной коммерции NetBeans. Добавление классов сущностей и сеансных компонентов

Учебный курс по электронной коммерции NetBeans. Добавление классов сущностей и сеансных компонентов

Содержимое этой страницы подходит для работы в среде IDE NetBeans версий 6.8 и 6.9

В этом учебном курсе рассмотрены технологии Enterprise JavaBeans (EJB) и Java Persistence (JPA). Используются необходимые для разработки в Java EE мастеры среды IDE. Необходимые мастеры перечислены ниже:

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

Эти два мастера предоставляют эффективный способ быстрого создания модели для приложения. При рассмотрении диаграммы MVC для создаваемого приложения можно увидеть место расположения сеансных компонентов EJB и классов сущностей JPA в в его структуре.

Диаграмма MVC приложения AffableBean

Создаваемые в этом разделе классы сущностей создают представление базы данных affablebean в форме Java. Каждый класс сущностей представляет таблицу базы данных, а экземпляры классов сущностей соответствуют записям, сохраняемым в базе данных. Бизнес-логика приложения инкапсулируется сеансными компонентами, которые могут использоваться как классы фасада, предоставляющие доступ CRUD (создание, чтение, обновление, удаление) к записям (см. ниже), или могут содержать код, реализующий характерные для приложения действия. Пример такого использования приведен в разделе Раздел 9: интеграция транзакционной бизнес-логики.

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



Программное обеспечение или ресурс Требуемая версия
Среда IDE NetBeans пакет Java, версии 6.8 или 6.9
Комплект для разработчика на языке Java (JDK) версия 6
Сервер GlassFish версия 3 или версия 3.0.1 с открытым исходным кодом
Сервер базы данных MySQL версия 5.1
Проект AffableBean снимок 3

Примечания

  • Для работы среды IDE NetBeans требуется корректная работа комплекта для разработчика на языке Java (JDK). Если все указанные выше ресурсы не установлены, JDK следует загрузить и установить в первую очередь.
  • Пакет среды Java NetBeans включает в себя технологии Java Web и EE, которые требуются для создаваемого в этом учебном курсе приложения.
  • Пакет Java среды IDE NetBeans также включает в себя сервер GlassFish, который необходим для работы с этим учебным курсом. Можно загрузить сервер GlassFish отдельно, но версия, предоставляемая с NetBeans, более удобна, так как автоматически регистрируется в среде IDE.
  • Этот учебный курс можно выполнять без выполнения предыдущих. Для этого обратитесь к инструкциям по настройке, в которых описана подготовка базы данных и настройка подключений между IDE, GlassFish, и MySQL.
  • Снимок 4 проекта AffableBean доступен для загрузки и соответствует состоянию проекта после выполнения заданий этого раздела с помощью среды IDE NetBeans, версия 6.9.

Общие сведения о технологиях EJB и JPA

До сих пор проект, который создавался в процессе этого учебного курса, можно было запустить на веб-сервере с контейнером сервлетов, таком как Apache Tomcat. Пока использовались только технологии JSTL и сервлетов, а подключение к базе осуществлялось напрямую через JDBC. Теоретически можно продолжать разработку с применением только этих технологий и вручную писать код для всех аспектов приложения, включая многопоточное исполнение, транзакции и безопасность. Однако компоненты EJB и классы сущностей JPA позволяют сосредоточиться на бизнес-логике приложения, используя проверенные и протестированные решения. В следующих разделах рассматриваются данные технологии и их роль в разработке для Java EE.

Enterprise JavaBeans

На официальной странице продукта EJB технология EnterPrise JavaBeans описана как "компонентная архитектура клиент-сервер", которая "позволяет быстро и легко разрабатывать распределенные транзакционные безопасные и переносимые приложения." При применении EJB все службы, предоставляемые этой технологией, остаются прозрачными для разработчика, избавляя его от утомительного и часто приводящего к ошибкам добавления кода заготовок. Для новичка в разработке для Java EE потребность в EJB для веб-приложения Java неочевидна. В книге Дебу Панды, Реза Рахмана и Дерека Лейна (Debu Panda, Reza Rahman и Derek Lane) EJB 3 в действии (EJB 3 In Action) роль EJB четко сформулирована:

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

Контейнер EJB предоставляет эти функциональные возможности в виде встроенных, поэтому компоненты EJB могут использовать их в приложении. Это освобождает разработчика от необходимости изобретать велосипед. Например, при написании модуля обработки кредитных карт в веб-приложении необходимо создать большой объем сложного и приводящего к ошибкам кода для управления транзакциями и контроля безопасности доступа. Можно избежать этого, используя декларативные транзакции и службы безопасности контейнера EJB. Эти службы доступны компонентам EJB при развертывании в контейнере EJB, как и многие другие. Это позволяет создавать высококачественные многофункциональные приложения гораздо быстрее, чем можно подумать.
[1]

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

  • Создание пула:для каждого компонента EJB платформа EJB создает пул совместно используемых клиентами экземпляров компонента. В любой момент времени каждый экземпляр из пула может использоваться только одним клиентом. После завершения обслуживания клиента экземпляр возвращается в пул для повторного использования вместо уничтожения и восстановления сборщиком мусора.
  • Многопоточная ориентированность: EJB делает все компоненты ориентированными на многопоточное исполнение и высокопроизводительными. Это означает, что серверные компоненты можно писать так же, как и однопоточные настольные приложения. Сложность компонента не имеет значения. Многопоточное исполнение обеспечивается технологией EJB.
  • Транзакции: EJB поддерживает управление объявленными транзакциями, которое позволяет добавить транзакционное поведение к компонентам путем настройки, а не программирования. В результате можно сделать транзакционным любой метод компонента. При нормальном завершении метода EJB подтверждает транзакцию и сохраняет сделанные методом изменения. В противном случае выполняется откат транзакции. Транзакции EJB, управляемые контейнером, продемонстрированы в разделеРаздел 9: интеграция транзакционной бизнес-логики.
  • Безопасность: EJB поддерживает интеграцию с интерфейсом API службы проверки подлинности и авторизации Java (JAAS), поэтому теперь легче выстроить безопасность и защитить приложения, используя несложные настройки, вместо того, чтобы загромождать программу кодами безопасности. [2]В разделе 11:Обеспечение безопасности приложенийбыла продемонстрирована аннотация @RolesAllowed EJB.

Сохранение состояния Java

В контексте Java Enterprise сохранение состояния — это автоматическое сохранение данных из объектов Java в реляционной базе данных. Интерфейс API сохранения состояния Java (Java Persistence API, JPA) — технология объектно-реляционного сопоставления (ORM), позволяющая приложению прозрачным для разработчика образом управлять данными в объектах Java и реляционной базе данных. Это означает, что можно применить JPA к проекту, добавив и настроив набор классов (сущностей), соответствующих модели данных. После этого приложение сможет получать доступ к этим сущностям как при прямом доступе к базе данных.

Преимущества использования JPA:

  • Для выполнения статических и динамических запросов в JPA используется собственный язык запросов, схожий с SQL. При использовании языка запросов Java Persistence Query Language (JPQL) приложения можно переносить между базами данных различных поставщиков.
  • Можно избежать написания низкоуровневого кода JDBC/SQL.
  • JPA предоставляет прозрачные службы для кэширования данных и оптимизации производительности.

Общие сведения о сеансных компонентах

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

  • Выполнение для одного клиента
  • Способность работать с транзакциями
  • Обновление данных в основной базе данных
  • Отсутствие прямого представления общих данных из базы данных несмотря на возможность использования и обновления таких данных
  • Непродолжительное время существования
  • Удаление при сбое контейнера EJB Для продолжения вычислений клиент должен повторно установить сеансный объект.

EJB предоставляет три вида сеансных компонентов: с поддержкой состояния, без поддержки состояния и одноэкземплярные. Следующие определения взяты из учебного курса Java EE 6.

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

Дополнительные сведения о сеансных компонентах EJB приведены в документе Учебный курс Java EE 6: общие сведения о сеансных компонентах.

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


Спецификации и реализации

Технологии EJB и JPA определены в следующих спецификациях:

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

Подробные сведения о технических спецификациях Java и их формальной стандартизации приведены в описании Java Community Process.

На странице загрузки окончательной редакции спецификаций EJB и JPA находятся ссылки на следующие примеры реализации:

Примеры реализации спецификации JPA называются поставщиками сохранения состояния, а поставщиком сохранения состояния, который был выбран в качестве эталонной реализации для спецификации JPA, версия 2.0, является EclipseLink.

Ссылка на пример эталонной реализации EJB также приведет на страницу, где упомянуты не только реализации EJB, но и все примеры реализации, предоставленные проектом GlassFish. Причиной является то, что проект GlassFish предоставляет эталонную реализацию спецификации JSR 316 для платформы Java EE 6. Сервер приложений GlassFish, версия 3 (или версия с открытым исходным кодом), который используется в данном учебном курсе для создания проекта по интернет-коммерции, содержит эталонные реализации всех технологий, разработанных в проекте GlassFish. В связи с этим такой сервер приложений называют контейнером Java EE 6.

Контейнер Java EE содержит три необходимых компонента: веб-контейнер (например, сервлет), контейнер EJB и поставщик сохранения состояния. Сценарий развертывания приложения электронной коммерции показан на диаграмме. Классы сущностей, создаваемые в этой главе, управляются поставщиком сохранения состояния. Создаваемые в этой главе сеансные компоненты управляются контейнером EJB. Представления отображаются страницами JSP, которые управляются веб-контейнером.

Контейнер Java EE GlassFish v3

Добавление классов сущностей

Вначале используйте мастер создания классов сущностей из базы данных в среде IDE для создания классов сущностей на основе схемы affablebean. При выполнении этого действия мастеру требуется поставщик сохранения состояния.

  1. Откройтеснимок проекта в среде IDE. В среде IDE нажмите сочетание клавиш CTRL+SHIFT+O (âŚ�+Shift+O на компьютере Mac) и откройте путь, куда был разархивирован загруженный файл.
  2. Нажмите сочетание клавиш CTRL+N (&#+N на компьютере Mac) для открытия мастера создания файлов.
  3. Выберите категорию "Сохранение состояния" и затем "Классы сущностей из базы данных". Нажмите кнопку "Далее".
  4. На втором экране мастера "Таблицы базы данных" выберите в списке источников данных jdbc/affablebean. Выпадающий список заполняется зарегистрированными на сервере приложений источниками данных.

    При выборе источника данных jdbc/affablebean среда IDE сканирует базу данных и перечисляет таблицы в панели "Доступные таблицы".
    Мастер "Классы сущностей из базы данных"
  5. Нажмите кнопку "Добавить", а затем - кнопку "Далее".
  6. Действие 3 мастера "Классы сущностей из базы данных" слегка отличается в версиях 6.8 и 6.9 среды IDE NetBeans. В зависимости от используемой версии IDE выполните следующие действия.

    Среда IDE NetBeans, версия 6.8

    Мастер "Классы сущностей из базы данных", действие 3: классы сущностей
    1. Введите название сущности в поле "Пакет". После завершения работы мастера будет создан новый пакет для классов сущностей.
    2. Нажмите кнопку "Создать блок сохранения состояния". Будет открыто диалоговое окно "Создание блока сохранения состояния".
      Диалоговое окно "Создание блока сохранения состояния"
      Блок сохранения состояния ссылается на набор классов сущностей приложения. Описанное выше диалоговое окно создает файл persistence.xml, который используется поставщиком сохранения состояния для определения параметров блока сохранения состояния. Обратите внимание, что для проекта по умолчанию выбран сервер EclipseLink (JPA 2.0). Оставьте для стратегии генерирования таблиц значение Нет. Это предотвращает изменения базы данных поставщиком сохранения состояния. Например, если требуется, чтобы поставщик сохранения состояния удалил базу данных, а затем снова создал ее на основе классов сущностей, можно выбрать стратегию Удалить и создать. Теперь каждый раз при развертывании проекта будет выполняться это действие.
    3. Нажмите кнопку "Создать".
    4. Отобразится третий экран "Классы сущностей". Обратите внимание, что имена классов сущностей зависят от таблиц базы данных. Например, сущность CustomerOrder связана с таблицей базы данных customer_order. Также обратите внимание, что по умолчанию выбран параметр "Создание аннотаций именованных запросов для сохраняемых полей". В этом учебном курсе будут использованы различные именованные запросы.
    5. Продолжение смотрите ниже в шаге 7.

    Среда IDE NetBeans 6.9

    Мастер "Классы сущностей из базы данных", шаг 3. Классы сущностей
    1. Введите название сущности в поле "Пакет". После завершения работы мастера будет создан новый пакет для классов сущностей.
    2. Обратите внимание:
      • имена классов сущностей зависят от таблиц базы данных. Например, сущность CustomerOrder связана с таблицей базы данных customer_order.
      • Параметр "Создать аннотации именованных запросов для сохраняемых полей" выбирается по умолчанию. В этом учебном курсе будут использованы различные именованные запросы.
      • Флажок "Создать блок сохранения состояния" установлен по умолчанию. Блок сохранения состояния — это набор классов сущностей приложения. Сохранение состояния определяется файлом настройки persistence.xml, который используется поставщиком сохранения состояния. Включение этого параметра означает, что мастер создает также файл persistence.xml и заполняет его параметрами по умолчанию.
  7. Нажмите кнопку "Готово". Классы сущностей JPA будут созданы на основе таблиц базы данных affablebean. Классы сущностей можно просмотреть в окне "Проекты", развернув только что созданный пакет entity. Обратите внимание, что новый блок сохранения состояния появляется в узле "Файлы настройки".
    Окно "Проекты" - классы сущностей в проекте

    Обратите внимание, что был создан дополнительный класс сущностей OrderedProductPK. Таблица ordered_product в модели данных использует составной первичный ключ, состоящий из первичных ключей таблиц customer_order и product. Ознакомьтесь с разделом Проектирование модели данных — создание связей "многие ко многим". Поэтому поставщик сохранения состояния создает отдельный класс сущностей для составного ключа и внедряет его в сущность OrderedProduct. Для просмотра класса откройте его в редакторе OrderedProduct. Чтобы показать, что внедряемый класс является составным первичным ключом, в JPA используется аннотация @EmbeddedId.
    public class OrderedProduct implements Serializable {
        private static final long serialVersionUID = 1L;
        @EmbeddedId
        protected OrderedProductPK orderedProductPK;

    Нажмите сочетание клавиш CTRL+ПРОБЕЛ на аннотации @EmbeddedId для вызова документации по интерфейсу API.

    Документация по интерфейсу API, вызванная для аннотации @EmbeddedId
  8. Откройте в редакторе блок сохранения состояния (persistence.xml). Для блоков сохранения состояния в среде IDE, кроме представления XML, доступно представление "Проектирование". Представление "Проектирование" позволяет удобно вносить изменения в параметры проекта, касающиеся управления поставщиком сохранения состояния.
    Представление "Проектирование" блока сохранения состояния AffableBeanPU
  9. Чтобы открыть представление XML, выберите вкладку "XML" в верхней части блока сохранения состояния AffableBeanPU. Добавьте в файл следующее свойство.
    <persistence-unit name="AffableBeanPU" transaction-type="JTA">
      <jta-data-source>jdbc/affablebean</jta-data-source>
      <properties>
        <property name="eclipselink.logging.level" value="FINEST"/>
      </properties>
    </persistence-unit>
    Параметр протоколирования устанавливается в значение FINEST для просмотра всего вывода поставщика сохранения состояния при запуске приложения. Это позволяет увидеть запросы SQL к базе данных, используемые поставщиком сохранения состояния, и облегчает отладку.

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


Добавление сеансных компонентов

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

Фасад сеанса — это шаблон проектирования, рекомендуемый программе Enterprise BluePrints. Как указано в документе Core J2EE Pattern Catalog, этот компонент пытается решить общие проблемы, возникающие в многопоточном приложении, например:

  • Жесткие связи, приводящие к прямой зависимости между клиентскими и бизнес-объектами.
  • Излишние вызовы методов между клиентом и сервером, приводящие к проблемам производительности сети.
  • Недостаточная общность стратегий доступа клиентов, что вызывает недопустимое использование бизнес-объектов.

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

  1. Нажмите сочетание клавиш CTRL+N (&#+N на компьютере Mac) для открытия мастера создания файлов.
  2. В категории "Сохранение состояния" выберите "Сеансные компоненты для классов сущностей".
    Мастер создания файлов: категория "Сохранение состояния", тип файла "Сеансные компоненты для классов сущностей"
  3. Нажмите кнопку "Далее".
  4. Второй экран "Классы сущностей". Обратите внимание, что все классы сущностей проекта перечислены слева в разделе "Доступные классы сущностей". Нажмите кнопку "Добавить все". Все классы сущностей перемещаются вправо в раздел "Выбранные классы сущностей".
  5. Нажмите кнопку "Далее".
  6. Третий экран "Созданные сеансные компоненты". Введите session в качестве имени пакета.
    Мастер создания сеансных компонентов для классов сущностей, третий экран "Созданные сеансные компоненты"

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

  7. Нажмите кнопку "Готово". В среде IDE создаются сеансные компоненты для каждого класса сущностей проекта. В окне "Проекты" разверните новый пакет session для просмотра сеансных компонентов.

    Net Beans, версия 6.8 Net Beans, версия 6.9
    Окно "Проекты", отображаются сеансные компоненты проекта Окно "Проекты", отображаются сеансные компоненты проекта

    Примечание. Как показано выше, в среде IDE NetBeans, версия 6.9, слегка усовершенствован способ создания фасадных классов с помощью мастера "Сеансные компоненты для классов сущностей". А именно, код-заготовка, общий для всех классов, складывается в абстрактный класс, названный AbstractFacade. Работая в версии 6.9, откройте любой из созданных фасадных классов (кроме класса AbstractFacade). Видно, что этот класс расширяет AbstractFacade.

  8. Откройте сессионный фасад в редакторе, например в ProductFacade. Все редактируемые сессионные фасады создают EntityManager, используя аннотацию @PersistenceContext.
    @PersistenceContext(unitName = "AffableBeanPU")
    private EntityManager em;
    Аннотация @PersistenceContext используется для добавления в класс интерфейса EntityManager, управляемого контейнером. Другими словами, контейнер EJB проекта GlassFish используется для открытия и закрытия интерфейсов EntityManager, когда это необходимо. Элемент unitName указывает блок сохранения состояния AffableBeanPU, который был определен в файле persistence.xml приложения.

    EntityManager (диспетчер сущностей) — внутренний компонент интерфейса API сохранения состояния Java, отвечающий за сохранение состояния в базе данных. В книге EJB 3 в действии EntityManager описан следующим образом:
    Интерфейс JPA EntityManager управляет сущностями в терминах реального обеспечения служб сохранения состояния. Когда сущности сообщают поставщику JPA о своем сопоставлении с базой данных, они не сохраняют свое состояние самостоятельно. Интерфейс EntityManager считывает метаданные ORM для сущности и производит операции сохранения состояния.

Теперь приложение содержит модель сохранения состояния базы данных affablebean в форме классов сущностей JPA. Также оно содержит фасад сеанса, состоящий из компонентов уровня приложения, используемых для доступа к классам сущностей. В следующем разделе показан способ доступа к базе данных при помощи сеансных компонентов и классов сущностей.


Доступ к данным при помощи EJB

В предыдущей главе учебного курса показан способ доступа к базе данных путем настройки источника данных в GlassFish, добавления ссылки на ресурс к описателю развертывания приложения и использования тега JSTL <sql> на страницах JSP приложения. Это важный способ, поскольку он позволяет быстро настроить прототипы, включающие в себя данные из базы данных. Тем не менее, такой способ не подходит для средних и крупных приложений или приложений, управляемых командой разработчиков, так как сложен в расширении и поддержке. Более того, при разработке многоуровневого приложения или соблюдении шаблона MVC не следует хранить код доступа к данным в внешнем интерфейсе. Использование компонентов уровня предприятия с моделью сохранения состояния позволяет более полно следовать шаблону MVC благодаря разделению компонентов представления и модели.

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

страница-указатель

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

  1. В окне "Проекты" дважды щелкните узел "Исходные пакеты" > controller > ControllerServlet, чтобы открыть его в редакторе.
  2. Объявите экземпляр CategoryFacade и примените к нему аннотацию @EJB.
    public class ControllerServlet extends HttpServlet {
    
         @EJB
        private CategoryFacade categoryFacade;
    
        ...
    }
    После добавления аннотации @EJB контейнер EJB создает экземпляр переменной categoryFacade с EJB CategoryFacade.
  3. С помощью подсказок среды IDE добавьте операторы импорта для следующих классов:
    • javax.ejb.EJB
    • session.CategoryFacade

    При нажатии сочетания клавиш CTRL+SHIFT+I (⌘+Shift+I для компьютера Mac) в класс автоматически добавляются необходимые операторы импорта.

  4. Добавьте в класс следующий метод init. Веб-контейнер инициализирует сервлет, вызывая свой метод init. Это происходит только один раз после загрузки сервлета и до начала обработки запросов.
    public class ControllerServlet extends HttpServlet {
    
        @EJB
        private CategoryFacade categoryFacade;
    
        public void init() throws ServletException {
    
            // store category list in servlet context
            getServletContext().setAttribute("categories", categoryFacade.findAll());
        }
    
        ...
    }
    Здесь метод фасадного класса findAll применяется для запроса из базы данных всех записей категории Category. Затем полученный список объектов Category устанавливается в атрибут, обозначаемый строкой categories. Размещение ссылки в ServletContext означает, что ссылка действует в контексте всего приложения.

    Чтобы быстро определить сигнатуру метода findAll, подведите указатель мышки к названию метода, удерживая при этом клавишу CTRL (⌘ на компьютере Mac). (На рисунке ниже показано всплывающее окно, которое появляется при работе в среде IDE NetBeans 6.8).

    Во всплывающем окне отображается сигнатура метода
    Щелкните гиперссылку для перехода к методу.
  5. С помощью подсказки среды IDE добавьте аннотацию @Overrides. Метод init определяется надклассом HttpServlet и сервлетом GenericServlet.
    Подсказка, отображенная в редакторе
    Добавление аннотации не обязательно, но дает следующие преимущества:
    • Позволяет компилятору проверить, действительно ли переопределяется метод, который предполагается переопределить.
    • Улучшает удобство восприятия, поскольку становится ясно, какие методы в исходном коде переопределяются.

    Дополнительные сведения об аннотациях приведены в курсе Учебные курсы по Java: аннотации.

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

    Дважды щелкните узел "Веб-страницы" > index.jsp в окне "Проекты", чтобы открыть файл в редакторе.
  7. Закомментируйте (или удалите) оператор <sql:query> в начале файла. Чтобы закомментировать код, выделите его в редакторе и нажмите сочетание клавиш CTRL+/ (⌘+/ в Mac OS).
    Отображение закомментированного фрагмента в редакторе
  8. Отредактируйте открывающий тег <c:forEach> так, чтобы его атрибут items указывал на новый атрибут контекста приложения categories.
    <c:forEach var="category" items="${categories}">
  9. Откройте дескриптор развертывания веб-проекта. Нажмите сочетание клавиш ALT+SHIFT+O (CTRL+SHIFT+O в Mac OS) и в диалоговом окне "Переход к файлу" введите web, затем нажмите кнопку "ОК".
    Диалоговое окно "Переход к файлу"
  10. Закомментируйте (или удалите) запись <resource-ref>. Эта запись требовалась для определения тегами <sql> источника данных, зарегистрированного на сервере. Теперь для доступа к базе данных используется JPA, и источник данных jdbc/affablebean уже был указан в блоке сохранения состояния. Подробные сведения представлены выше в разделе Представление проектирования поставщика сохранения состояния проекта.

    Выделите всю запись <resource-ref>, а затем нажмите сочетание клавиш CTRL+/ (⌘+/ в Mac OS).
    <!-- <resource-ref>
             <description>Connects to database for AffableBean application</description>
             <res-ref-name>jdbc/affablebean</res-ref-name>
             <res-type>javax.sql.DataSource</res-type>
             <res-auth>Container</res-auth>
             <res-sharing-scope>Shareable</res-sharing-scope>
         </resource-ref> -->
  11. Выполните проект. Нажмите кнопку "Выполнить проект" (кнопка "Выполнить проект"). В обозревателе откроется страница-указатель проекта, и отобразятся все четыре категории и изображения.
    Страница-указатель с подробностями категорий

страница категории

Для верного отображения страницы категории требуются три элемента данных:

  1. данные о категориях: для кнопок категорий в левом столбце;
  2. выбранная категория: выбранная категория выделяется в левом столбце и ее имя отображается над таблицей продуктов;
  3. данные о продуктах в выбранной категории: для отображения продуктов в таблице.

Рассмотрим отдельно каждый элемент данных.

данные о категориях

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

  1. Откройте в редакторе category.jsp и закомментируйте (сочетание клавиш CTRL+/; ⌘+/ в Mac OS) операторы JSTL <sql>, указанные в начале файла.
    Закомментированные в редакторе операторы <sql>
  2. Отредактируйте открывающий тег <c:forEach> так, чтобы его атрибут items указывал на атрибут контекста приложения categories. Эта же операция была проведена в файле index.jsp.
    <c:forEach var="category" items="${categories}">
  3. Выполните проект для проверки текущего состояния страницы категории. Нажмите кнопку "Выполнить проект" (кнопка "Выполнить проект"). После отображения страницы-указателя в обозревателе щелкните одну из категорий. Кнопки категорий в левом столбце отображаются и работают ожидаемым образом.
    Страница категории с кнопками категорий в левом столбце

выбранная категория

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

  1. Откройте в редакторе ControllerServlet. Если он уже открыт, нажмите сочетание клавиш CTRL+TAB и выберите его в всплывающем списке.
  2. Начните реализовывать функциональность по принятию выбранной категории Найдите комментарий TODO: Implement category request (Сделать: реализовать запрос категории), удалите его и добавьте следующий код (выделен полужирным шрифтом).
    // если запрашивается страница категории
    if (userPath.equals("/category")) {
    
        // получить из запроса идентификатор categoryId
        String categoryId = request.getQueryString();
    
        if (categoryId != null) {
    
        }
    
    // если запрашивается страница корзины
    } else if (userPath.equals("/viewCart")) {
    В этом запросе вызовом функции getQueryString() извлекается идентификатор запрашиваемой категории.

    Примечание. Логика определения выбранной категории кнопками левого столбца уже реализована в category.jsp с использованием выражения EL, что сравнимо с вызовом getQueryString() в сервлете. Выражение EL: pageContext.request.queryString.

  3. Добавьте в оператор if следующую строку кода.
    // get categoryId from request
    String categoryId = request.getQueryString();
    
    if (categoryId != null) {
    
        // get selected category
        selectedCategory = categoryFacade.find(Short.parseShort(categoryId));
    }
    С помощью принадлежащего классу CategoryFacadeпоискового метода возвращается объект Category, который связан с идентификатором запрашиваемой категории. Обратите внимание, что необходимо привести categoryId к типу Short, поскольку такой тип используется в поле id класса сущностей Category.
  4. Щелкните значок Значок подсказки в левом внешнем отступе, чтобы использовать подсказку редактора для объявления selectedCategory локальной переменной внутри метода doGet.
    Подсказки редактора
    Поскольку selectedCategory имеет тип Category, который не был ранее импортирован в класс, среда IDE автоматически добавляет выражение импорта для entity.Category в начало файла.
  5. Чтобы поместить полученный объект Category в контекст запроса, добавьте следующую строку.
    // get categoryId from request
    String categoryId = request.getQueryString();
    
    if (categoryId != null) {
    
        // get selected category
        selectedCategory = categoryFacade.find(Short.parseShort(categoryId));
    
        // place selected category in request scope
        request.setAttribute("selectedCategory", selectedCategory);
    }
  6. Переключитесь в редакторе к файлу category.jsp. Для этого нажмите сочетание клавиш CTRL+TAB и выберите его в всплывающем списке.
  7. Найдите текст <p id="categoryTitle"> и внесите следующие изменения.
    <p id="categoryTitle">
        <span style="background-color: #f5eabe; padding: 7px;">${selectedCategory.name}</span>
    </p>
    Теперь используется атрибут selectedCategory, помещенный в контекст запроса в ControllerServlet. С помощью ".name" в выражении EL вызывается метод getName в данном объекте Category.
  8. Переключитесь обратно на окно обозревателя и обновите страницу категорий. Теперь на странице отображается имя выбранной категории.
    На странице категории отображается имя выбранной категории

данные о продуктах в выбранной категории

Для того чтобы получить все продукты из выбранной категории, используется принадлежащий сущности Category метод getProductCollection(). Запустите вызов этого метода для selectedCategory, чтобы получить коллекцию всех Product, связанных с selectedCategory. Далее сохраните коллекцию продуктов в контексте запроса как атрибут и, наконец, сошлитесь на контекстный атрибут из представления страницы category.jsp.

  1. Добавьте следующий оператор в код ControllerServlet. Это выражение управляет запросом категории.
    // если запрашивается страница категории
    if (userPath.equals("/category")) {
    
        // получить categoryId из запроса
        String categoryId = request.getQueryString();
    
        if (categoryId != null) {
    
            // получить выбранную категорию
            selectedCategory = categoryFacade.find(Short.parseShort(categoryId));
    
            // поместить выбранную категорию в контекст запроса
            request.setAttribute("selectedCategory", selectedCategory);
    
            // получить все продукты выбранной категории
            categoryProducts = selectedCategory.getProductCollection();
        }
    Здесь вызов getProductCollection позволяет получить коллекцию всех продуктов Product, связанных с выбранной категорией selectedCategory.
  2. Используйте подсказку редактора для определения categoryProducts в качестве локальной переменной для метода doGet.
    Подсказки редактора
  3. Поместите коллекцию продуктов Product в контекст запроса, чтобы ее можно было извлечь из внешнего интерфейса приложения.
    // если запрашивается страница категорий
    if (userPath.equals("/category")) {
    
        // получаем categoryId из запроса
        String categoryId = request.getQueryString();
    
        if (categoryId != null) {
    
            // получить выбранную категорию
            selectedCategory = categoryFacade.find(Short.parseShort(categoryId));
    
            // поместить выбранную категорию в контекст запроса
            request.setAttribute("selectedCategory", selectedCategory);
    
            // получить все продукты выбранной категории
            categoryProducts = selectedCategory.getProductCollection();
    
            // поместить продукты категории в контекст запроса
            request.setAttribute("categoryProducts", categoryProducts);
        }
  4. Откройте в редакторе category.jsp и внесите в таблицу запросов следующее изменение.
    <table id="productTable">
    
        <c:forEach var="product" items="${categoryProducts}" varStatus="iter">
    Тег <c:forEach> теперь ссылается на набор categoryProducts. Цикл c:forEach теперь выполняется для каждого объекта Product, содержащегося в коллекции, и извлекает соответствующие данные.
  5. Для запуска проекта нажмите клавишу F6 (или сочетание клавиш fn+F6 в Mac OS) В обозревателе перейдите к странице категории и обратите внимание, что для каждой категории отображаются все продукты.
    Страница категорий с отображаемыми в таблице продуктами

Этот учебный курс — краткое введение в технологии JPA и EJB. Также здесь описана роль спецификаций Java и использование примеров их реализации в сервере приложений GlassFish. Показано, как создать набор классов сущностей JPA, предоставляющих реализацию базы данных проектов на уровне Java. Затем в соответствии с шаблоном фасад сеанса показано создание набора сеансных компонентов EJB, которые расположены выше уровнем, чем классы сущностей, и предоставляют удобный доступ к ним. Наконец, проект AffableBean изменен для того, чтобы использовать новые сеансные компоненты и сущности для доступа к базе данных. Это требовалось в странице-указателе и странице категорий.

Снимок 4 проекта AffableBean доступен для загрузки и соответствует состоянию проекта после выполнения заданий этого раздела с помощью среды IDE NetBeans, версия 6.9.

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



Дополнительные сведения

Материалы по среде NetBeans

Ресурсы по EJB

Ресурсы по JPA

Ресурсы по GlassFish

Технические статьи

Книги


Ссылки

  1. ^ Адаптация EJB 3 в действии Глаза 1, раздел 1.1.2: EJB как платформа.
  2. ^EJB предоставляет множество других служб. Более подробный список приведен в книге EJB 3 в действии, глава 1, раздел 1.3.3: получение функциональных возможностей с помощью служб EJB.