blob: d9d2c56e349b752382d4ce107e67e0310bf756f2 [file] [log] [blame]
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
= Учебный курс по электронной коммерции NetBeans. Добавление классов сущностей и сеансных компонентов
:jbake-type: tutorial
:jbake-tags: tutorials
:jbake-status: published
:icons: font
:syntax: true
:source-highlighter: pygments
:toc: left
:toc-title:
:description: Учебный курс по электронной коммерции NetBeans. Добавление классов сущностей и сеансных компонентов - Apache NetBeans
:keywords: Apache NetBeans, Tutorials, Учебный курс по электронной коммерции NetBeans. Добавление классов сущностей и сеансных компонентов
1. link:intro.html[+Введение+]
2. link:design.html[+Проектирование приложения+]
3. link:setup-dev-environ.html[+Настройка среды разработки+]
4. link:data-model.html[+Проектирование модели данных+]
5. link:page-views-controller.html[+Подготовка представлений страниц и сервлета контроллера+]
6. link:connect-db.html[+Подключение приложения к базе данных+]
7. *Добавление классов сущностей и сеансных компонентов*
8. link:manage-sessions.html[+Управление сеансами+]
9. link:transaction.html[+Интеграция транзакционной бизнес-логики+]
10. link:language.html[+Добавление поддержки языков+]
11. link:security.html[+Обеспечение безопасности приложений+]
12. link:test-profile.html[+Тестирование и профилирование+]
13. link:conclusion.html[+Заключение+]
image::../../../../images_www/articles/68/netbeans-stamp-68-69.png[title="Содержимое на этой странице применимо к IDE NetBeans, версии 6.8 и 6.9"]
В этом учебном курсе рассмотрены технологии link:http://java.sun.com/products/ejb/[+Enterprise JavaBeans+] (EJB) и link:http://java.sun.com/javaee/technologies/persistence.jsp[+Java Persistence+] (JPA). Используются необходимые для разработки в Java EE мастеры среды IDE. Это:
* *Мастер создания классов сущностей из базы данных*Для каждой выбранной таблицы базы данных создается класс сущности, сохраняющий состояние при помощи JPA, с аннотациями именованных запросов, полями, соответствующими столбцам и отношениями, соответствующими внешним ключам.
* *Мастер сеансных компонентов для классов сущностей*Создает фасад сеанса EJB для каждого класса сущностей с основными методами доступа.
Эти два мастера предоставляют эффективный способ быстрого создания модели для приложения. При рассмотрении link:design.html#mvcDiagram[+диаграммы MVC+] для создаваемого приложения можно увидеть место расположения сеансных компонентов EJB и классов сущностей JPA в его структуре.
image::images/mvc-diagram.png[title="Диаграмма MVC приложения AffableBean"]
Создаваемые в этом разделе классы сущностей создают представление базы данных `affablebean` в форме Java. Каждый класс сущностей представляет таблицу базы данных, а экземпляры классов сущностей соответствуют записям, _сохраняемым_ в базе данных. Бизнес-логика приложения инкапсулируется сеансными компонентами, которые могут использоваться как классы _фасада_, предоставляющие доступ CRUD (создание, чтение, обновление, удаление) к записям (см. ниже), или могут содержать код, реализующий характерные для приложения действия. Пример такого использования приведен в разделе link:transaction.html[+Раздел 9: интеграция транзакционной бизнес-логики+].
Можно просмотреть интерактивную демонстрацию приложения, которое создается в этом учебном курсе: link:http://dot.netbeans.org:8080/AffableBean/[+Демонстрация приложения электронной коммерции NetBeans+]
|===
|Программное обеспечение или материал |Требуемая версия
|link:https://netbeans.org/downloads/index.html[+IDE NetBeans+] |Набор Java, версия 6.8 или 6.9
|link:http://www.oracle.com/technetwork/java/javase/downloads/index.html[+Комплект для разработчика на языке Java (JDK)+] |версия 6
|<<glassFish,Сервер GlassFish>> |v3 или Open Source Edition 3.0.1
|link:http://dev.mysql.com/downloads/mysql/[+Сервер базы данных MySQL+] |Версия 5.1
|link:https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot3.zip[+Проект AffableBean+] |снимок 3
|===
*Примечания:*
* The IDE NetBeans requires the Java Development Kit (JDK) to run properly. Если указанные материалы не установлены, JDK следует загрузить и установить в первую очередь.
* The IDE NetBeans Java Bundle includes Java Web and EE technologies, which are required for the application you build in this tutorial.
* The IDE NetBeans Java Bundle also includes the GlassFish server, which you require for this tutorial. Можно link:https://glassfish.dev.java.net/public/downloadsindex.html[+загрузить сервер GlassFish отдельно+], но версия, предоставляемая с NetBeans, имеет преимущество, так как автоматически зарегистрирована в среде IDE.
* Этот учебный курс можно выполнять без выполнения предыдущих. Для этого обратитесь к link:setup.html[+инструкциям по настройке+], в которых описана подготовка базы данных и настройка подключений между IDE, GlassFish, и MySQL.
[[whatEJB]]
== Общие сведения о технологиях EJB и JPA
До сих пор проект, который создавался в процессе этого учебного курса, можно было запустить на веб-сервере с контейнером сервлетов, таком как Apache Tomcat. Пока использовались только технологии JSTL и сервлетов, а подключение к базе осуществлялось напрямую через JDBC. Теоретически можно продолжать разработку с применением только этих технологий и вручную писать код для всех аспектов приложения, включая многопоточное исполнение, транзакции и безопасность. Однако компоненты EJB и классы сущностей JPA позволяют сосредоточиться на бизнес-логике приложения, используя проверенные и протестированные решения. В следующих разделах рассматриваются данные технологии и их роль в разработке для Java EE.
* <<ejb,JavaBeans Enterprise>>
* <<jpa,Сохранение состояния Java>>
[[ejb]]
=== JavaBeans Enterprise
На официальной link:http://java.sun.com/products/ejb/[+странице продукта EJB+] технология EnterPrise JavaBeans описана как "компонентная архитектура клиент-сервер", которая "позволяет быстро и легко разрабатывать распределенные транзакционные безопасные и переносимые приложения." При применении EJB все службы, предоставляемые этой технологией, остаются прозрачными для разработчика, избавляя его от утомительного и часто приводящего к ошибкам добавления кода заготовок. Для новичка в разработке для Java EE потребность в EJB для веб-приложения Java неочевидна. В книге Дебу Панды, Реза Рахмана и Дерека Лейна (Debu Panda, Reza Rahman и Derek Lane) link:http://www.manning.com/panda/[+EJB 3 в действии (EJB 3 In Action)+] роль EJB четко сформулирована:
[NOTE]
====
_Многие считают, что технология EJB не требуется для разработки сравнительно простых веб-приложений небольшого размера, но это далеко от действительности. Никто не начинает постройку дома с нуля. Постройка начинается с покупки материалов или найма подрядчика. Точно так же неэффективно разрабатывать приложение уровня предприятия с нуля. Большинство приложений на стороне сервера имеют много общего: бизнес-логику, управление состоянием приложения, сохранение и извлечение информации из реляционной базы данных, управление транзакциями, обеспечение безопасности, выполнение асинхронной обработки, интеграцию систем и так далее.
Контейнер EJB предоставляет эти функциональные возможности в виде встроенных, поэтому компоненты EJB могут использовать их в приложении. Это освобождает разработчика от необходимости изобретать велосипед. Например, при написании модуля обработки кредитных карт в веб-приложении необходимо создать большой объем сложного и приводящего к ошибкам кода для управления транзакциями и контроля безопасности доступа. Можно избежать этого, используя декларативные транзакции и службы безопасности контейнера EJB. Эти службы доступны компонентам EJB при развертывании в контейнере EJB, как и многие другие. Это позволяет создавать высококачественные многофункциональные приложения гораздо быстрее, чем можно подумать._^<<footnote1,[1]>>^
====
EJB можно рассматривать как компоненты или как классы Java, включенные в проект, а также как _платформу_, предоставляющую множество служб, связанных с уровнем предприятия. Некоторое службы, использованные в этом учебном курсе, описаны в книге link:http://www.manning.com/panda/[+EJB 3 в действии+] следующим образом:
* *Создание пула:*для каждого компонента EJB платформа EJB создает пул совместно используемых клиентами экземпляров компонента. В любой момент времени каждый экземпляр из пула может использоваться только одним клиентом. После завершения обслуживания клиента экземпляр возвращается в пул для повторного использования вместо уничтожения и восстановления сборщиком мусора.
* *Многопоточная ориентированность:* EJB делает все компоненты ориентированными на многопоточное исполнение и высокопроизводительными. Это означает, что серверные компоненты можно писать так же, как и однопоточные настольные приложения. Сложность компонента не имеет значения. Многопоточное исполнение обеспечивается технологией EJB.
* *Транзакции:* EJB поддерживает управление объявленными транзакциями, которое позволяет добавить транзакционное поведение к компонентам путем настройки, а не программирования. В результате можно сделать транзакционным любой метод компонента. При нормальном завершении метода EJB подтверждает транзакцию и сохраняет сделанные методом изменения. В противном случае выполняется откат транзакции. Транзакции EJB, управляемые контейнером, продемонстрированы в разделеlink:transaction.html[+Раздел 9: интеграция транзакционной бизнес-логики+].
* *Безопасность:* EJB поддерживает интеграцию с интерфейсом API службы проверки подлинности и авторизации Java (JAAS), поэтому теперь легче выстроить безопасность и защитить приложения, используя несложные настройки, вместо того, чтобы загромождать программу кодами безопасности. ^<<footnote2,[2]>>^В разделе 11:link:security.html#secureEJB[+Обеспечение безопасности приложений+]была продемонстрирована аннотация <a href="http://download.oracle.com/javaee/6/api/javax/annotation/security/RolesAllowed.html" target="_blank"`@RolesAllowed` EJB.
[[jpa]]
=== Сохранение состояния Java
В контексте Java Enterprise _сохранение состояния_ это автоматическое сохранение данных из объектов Java в реляционной базе данных. link:http://java.sun.com/javaee/technologies/persistence.jsp[+Интерфейс API сохранения состояния Java+] (Java Persistence API, JPA) — технология объектно-реляционного сопоставления (ORM), позволяющая приложению прозрачным для разработчика образом управлять данными в объектах Java и реляционной базе данных. Это означает, что можно применить JPA к проекту, добавив и настроив набор классов (_сущностей_), соответствующих модели данных. После этого приложение сможет получать доступ к этим сущностям как при прямом доступе к базе данных.
Преимущества использования JPA:
* Для выполнения статических и динамических запросов в JPA используется собственный язык запросов, схожий с SQL. При использовании языка запросов Java Persistence Query Language (JPQL) приложения можно переносить между базами данных различных поставщиков.
* Можно избежать написания низкоуровневого кода JDBC/SQL.
* JPA предоставляет прозрачные службы для кэширования данных и оптимизации производительности.
[[whatSession]]
== Общие сведения о сеансных компонентах
Сеансные компоненты уровня предприятия вызываются клиентом для выполнения конкретных бизнес-операций. Слово _сеансные_ означает, что экземпляры компонентов доступны в течение "периода обработки". link:http://jcp.org/aboutJava/communityprocess/final/jsr318/index.html[+Спецификация EJB 3.1+] описывает следующие характеристики типичного сеансного объекта:
* Выполнение для одного клиента
* Способность работать с транзакциями
* Обновление данных в основной базе данных
* Отсутствие прямого представления общих данных из базы данных несмотря на возможность использования и обновления таких данных
* Непродолжительное время существования
* Удаление при сбое контейнера EJB Для продолжения вычислений клиент должен повторно установить сеансный объект.
EJB предоставляет три вида сеансных компонентов: _с поддержкой состояния_, _без поддержки состояния_ и _одноэкземплярные_. Следующие определения взяты из link:http://download.oracle.com/docs/cd/E17410_01/javaee/6/tutorial/doc/index.html[+учебного курса Java EE 6+].
* поддержкой состояния:* состояние компонента сохраняется между вызовами методов. "Состояние" это значения переменных экземпляра. Поскольку клиент взаимодействует с компонентом, это состояние часто называют _диалоговым_.
* *Без поддержки состояния:* такие компоненты используется для операций, происходящих в течение одного вызова метода. При завершении выполнения метода состояние, зависящее от клиента, не сохраняется. Компонент без сохранения состояния не поддерживает диалоговое состояние с клиентом.
* *Одноэкземплярный:* одноэкземплярный сеансный компонент создается в приложении в единственном числе и существует в течение всего жизненного цикла приложения. Одноэкземплярные сеансные компоненты созданы для ситуаций, в которых один экземпляр компонента уровня предприятия совместно и одновременно используется клиентами.
Дополнительные сведения о сеансных компонентах EJB приведены в документе link:http://download.oracle.com/docs/cd/E17410_01/javaee/6/tutorial/doc/gipjg.html[+Учебный курс Java EE 6: общие сведения о сеансных компонентах+].
Для разработки приложения электронной коммерции в этом учебном курсе используются только сеансные компоненты без сохранения состояния.
[[specification]]
== Спецификации и реализации
Технологии EJB и JPA определены в следующих спецификациях:
* link:http://jcp.org/en/jsr/summary?id=317[+Сохранение состояния Java+]
* link:http://jcp.org/en/jsr/summary?id=318[+JSR 318: Enterprise JavaBeans 3.1+]
Указанные спецификации определяют данные технологии. При этом для применения технологии в проекте нужна _реализация_ спецификации. После утверждения спецификации в нее включается ссылочная реализация, которая является свободной реализацией технологии. Если такая концепция вызывает удивление, можно рассмотреть следующую аналогию: музыкальная композиция (т.е. ноты на странице) определяет музыкальное произведение. Когда музыкант заучивает композицию и записывает ее исполнение, происходит _интерпретация_ произведения. Таким образом, музыкальная композиция напоминает техническую спецификацию, а процесс записи музыки перекликается с реализацией спецификации.
Подробные сведения о технических спецификациях Java и их формальной стандартизации приведены в link:intro.html#jcp[+описании Java Community Process+].
На странице загрузки окончательной редакции спецификаций EJB и JPA находятся ссылки на следующие примеры реализации:
* *JPA:* link:http://www.eclipse.org/eclipselink/downloads/ri.php[+http://www.eclipse.org/eclipselink/downloads/ri.php+]
* *EJB:* link:http://glassfish.dev.java.net/downloads/ri[+http://glassfish.dev.java.net/downloads/ri+]
Примеры реализации спецификации JPA называются _поставщиками сохранения состояния_, а поставщиком сохранения состояния, который был выбран в качестве эталонной реализации для спецификации JPA, версия 2.0, является link:http://www.eclipse.org/eclipselink/[+EclipseLink+].
Ссылка на пример эталонной реализации EJB также приведет на страницу, где упомянуты не только реализации EJB, но и все примеры реализации, предоставленные link:https://glassfish.dev.java.net/[+проектом GlassFish+]. Причиной является то, что проект GlassFish предоставляет эталонную реализацию спецификации link:http://jcp.org/en/jsr/summary?id=316[+JSR 316+] для платформы Java EE 6. Сервер приложений GlassFish, версия 3 (или версия с открытым исходным кодом), который используется в данном учебном курсе для создания проекта по интернет-коммерции, содержит эталонные реализации всех технологий, разработанных в проекте GlassFish. В связи с этим такой сервер приложений называют _контейнером_ Java EE 6.
Контейнер Java EE содержит три необходимых компонента: веб-контейнер (например, сервлет), контейнер EJB и поставщик сохранения состояния. Сценарий развертывания приложения электронной коммерции показан на диаграмме. Классы сущностей, создаваемые в этой главе, управляются поставщиком сохранения состояния. Создаваемые в этой главе сеансные компоненты управляются контейнером EJB. Представления отображаются страницами JSP, которые управляются веб-контейнером.
image::images/java-ee-container.png[title="Будучи контейнером Java EE, GlassFish в.3 содержит веб-контейнеры и контейнеры EJB и EclipseLink, поставщик сохраняемости"]
[[addEntity]]
== Добавление классов сущностей
Вначале используйте мастер создания классов сущностей из базы данных в среде IDE для создания классов сущностей на основе схемы `affablebean`. При выполнении этого действия мастеру требуется поставщик сохранения состояния.
1. Откройтеlink:https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot3.zip[+снимок проекта+] в среде IDE. В IDE нажмите Ctrl-Shift-O (âŚ�-Shift-O в Mac) и перейдите к местоположению на компьютере, где был распакован загруженный файл.
2. Нажмите сочетание клавиш CTRL+N (⌘-N на компьютере Mac) для открытия мастера создания файлов.
3. Выберите категорию "Сохранение состояния" и затем "Классы сущностей из базы данных". Нажмите кнопку "Далее".
4. На втором экране мастера "Таблицы базы данных" выберите в списке источников данных `jdbc/affablebean`. Выпадающий список заполняется зарегистрированными на сервере приложений источниками данных.
При выборе источника данных `jdbc/affablebean` среда IDE сканирует базу данных и перечисляет таблицы в панели "Доступные таблицы".
image::images/entity-from-database.png[title="Выберите доступный источник данных для чтения IDE в таблицах баз данных"]
[start=5]
. Нажмите кнопку "Добавить", а затем - кнопку "Далее".
[start=6]
. Step 3 of the Entity Classes from Database wizard differs slightly between IDE NetBeans 6.8 and 6.9. В зависимости от используемой версии IDE выполните следующие шаги.
* <<68,IDE NetBeans 6.8>>
* <<69,IDE NetBeans 6.9>>
[[68]]
==== IDE NetBeans 6.8
image::images/entity-classes-68.png[title="NetBeans 6.8 - классы сущностей из мастера баз данных, Step 3: Классы сущностей"]
1. Введите *название сущности* в поле "Пакет". После завершения работы мастера будет создан новый пакет для классов сущностей.
2. Нажмите кнопку "Создать блок сохранения состояния". Будет открыто диалоговое окно "Создание блока сохранения состояния".
image::images/create-pu.png[title="Используйте диалоговое окно 'Создание блока сохранения состояния' для создания файла persistence.xml"]
_Блок сохранения состояния_ ссылается на набор классов сущностей приложения. Описанное выше диалоговое окно создает файл `persistence.xml`, который используется поставщиком сохранения состояния для определения параметров блока сохранения состояния. Обратите внимание, что для проекта по умолчанию выбран сервер EclipseLink (JPA 2.0). Оставьте для стратегии генерирования таблиц значение `Нет`. Это предотвращает изменения базы данных поставщиком сохранения состояния. Например, если требуется, чтобы поставщик сохранения состояния удалил базу данных, а затем снова создал ее на основе классов сущностей, можно выбрать стратегию `Удалить и создать`. Теперь каждый раз при развертывании проекта будет выполняться это действие.
[start=3]
. Нажмите кнопку "Создать".
[start=4]
. Отобразится третий экран "Классы сущностей". Обратите внимание, что имена классов сущностей зависят от таблиц базы данных. Например, сущность `CustomerOrder` связана с таблицей базы данных `customer_order`. Также обратите внимание, что по умолчанию выбран параметр "Создание аннотаций именованных запросов для сохраняемых полей". В этом учебном курсе будут использованы различные именованные запросы.
[start=5]
. Продолжение смотрите ниже в <<step7,шаге 7>>.
[[69]]
==== IDE NetBeans 6.9
image::images/entity-classes-69.png[title="NetBeans 6.9 - классы сущностей из мастера баз данных, Step 3: Классы сущностей"]
1. Введите *название сущности* в поле "Пакет". После завершения работы мастера будет создан новый пакет для классов сущностей.
2. Обратите внимание:
* имена классов сущностей зависят от таблиц базы данных. Например, сущность `CustomerOrder` связана с таблицей базы данных `customer_order`.
* Параметр "Создать аннотации именованных запросов для сохраняемых полей" выбирается по умолчанию. В этом учебном курсе будут использованы различные именованные запросы.
* Флажок "Создать блок сохранения состояния" установлен по умолчанию. _Блок сохранения состояния_ это набор классов сущностей приложения. Сохранение состояния определяется файлом настройки `persistence.xml`, который используется поставщиком сохранения состояния. Включение этого параметра означает, что мастер создает также файл `persistence.xml` и заполняет его параметрами по умолчанию.
[start=7]
. Нажмите кнопку "Завершить". Классы сущностей JPA будут созданы на основе таблиц базы данных `affablebean`. Классы сущностей можно просмотреть в окне "Проекты", развернув только что созданный пакет `entity`. Обратите внимание, что новый блок сохранения состояния появляется в узле "Файлы настройки".
image::images/entity-classes.png[title="Узлы для сущностных классов можно будет увидеть в окне Projects ("Проекты")."]
Обратите внимание, что был создан дополнительный класс сущностей `OrderedProductPK`. Таблица `ordered_product` в модели данных использует составной первичный ключ, состоящий из первичных ключей таблиц `customer_order` и `product`. Ознакомьтесь с разделом link:data-model.html#manyToMany[+Проектирование модели данных — создание связей "многие ко многим"+]. Поэтому поставщик сохранения состояния создает отдельный класс сущностей для составного ключа и _внедряет_ его в сущность `OrderedProduct`. Для просмотра класса откройте его в редакторе `OrderedProduct`. Чтобы показать, что внедряемый класс является составным первичным ключом, в JPA используется аннотация `@EmbeddedId`.
[source,java]
----
public class OrderedProduct implements Serializable {
private static final long serialVersionUID = 1L;
*@EmbeddedId*
protected OrderedProductPK orderedProductPK;
----
Нажмите сочетание клавиш CTRL+ПРОБЕЛ на аннотации `@EmbeddedId` для вызова документации по интерфейсу API.
image::images/embedded-id.png[title="Для вызова документации по API нажмите сочетание клавиш CTRL+ПРОБЕЛ."]
[start=8]
. Откройте в редакторе блок сохранения состояния (`persistence.xml`). Для блоков сохранения состояния в среде IDE, кроме представления XML, доступно представление "Проектирование". Представление "Проектирование" позволяет удобно вносить изменения в параметры проекта, касающиеся управления поставщиком сохранения состояния.
image::images/persistence-unit.png[title="Представление проектирования AffableBeanPU единицы сохранения"]
[start=9]
. Чтобы открыть представление XML, выберите вкладку "XML" в верхней части блока сохранения состояния `AffableBeanPU`. Добавьте в файл следующее свойство.
[source,xml]
----
<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, чтобы получить представление о журналировании и список всех значений журнала, в разделе link:http://wiki.eclipse.org/EclipseLink/Examples/JPA/Logging[+"Как настроить журналирование"+]
[[addSession]]
== Добавление сеансных компонентов
В этом разделе для создания _фасада сеанса_ каждого созданного класса сущностей будет использован мастер среды IDE "Сеансные компоненты для классов сущностей". В каждом сеансном компоненте будут содержаться основные методы доступа к соответствующему классу сущностей.
_Фасад сеанса_ это шаблон проектирования, рекомендуемый link:http://java.sun.com/blueprints/enterprise/index.html[+программе Enterprise BluePrints+]. Как указано в документе link:http://java.sun.com/blueprints/corej2eepatterns/Patterns/SessionFacade.html[+Core J2EE Pattern Catalog+], этот компонент пытается решить общие проблемы, возникающие в многопоточном приложении, например:
* Жесткие связи, приводящие к прямой зависимости между клиентскими и бизнес-объектами.
* Излишние вызовы методов между клиентом и сервером, приводящие к проблемам производительности сети.
* Недостаточная общность стратегий доступа клиентов, что вызывает недопустимое использование бизнес-объектов.
Фасад сеанса маскирует взаимодействие основных бизнес-объектов и создает уровень служб, предоставляющий только необходимые функциональные возможности. Это позволяет скрыть от клиента сложную схему взаимодействия участников. Таким образом, сеансный компонент (т.е. фасад сеанса) управляет взаимодействием бизнес-объектов. Сеансный компонент также управляет жизненным циклом участников, создавая, находя, редактируя и удаляя их в соответствии с рабочим процессом.
1. Нажмите сочетание клавиш CTRL+N (⌘-N на компьютере Mac) для открытия мастера создания файлов.
2. В категории "Сохранение состояния" выберите "Сеансные компоненты для классов сущностей".
image::images/session-beans-for-entity-classes.png[title="Выберите компоненты Beans сеанса для классов сущностей для создания фасадного сеанса для модели сохраняемости"]
[start=3]
. Нажмите кнопку "Далее".
[start=4]
. Второй экран "Классы сущностей". Обратите внимание, что все классы сущностей проекта перечислены слева в разделе "Доступные классы сущностей". Нажмите кнопку "Добавить все". Все классы сущностей перемещаются вправо в раздел "Выбранные классы сущностей".
[start=5]
. Нажмите кнопку "Далее".
[start=6]
. Третий экран "Созданные сеансные компоненты". Введите *session* в качестве имени пакета.
image::images/generated-session-beans.png[title="Укажите местоположение загруженных исходных файлов в папке в "Source"."]
*Примечание.* Мастер может использоваться для создания локальных и удаленных интерфейсов к сеансным компонентам. Программирование сеансных компонентов с интерфейсами предпочтительнее (например, скрытие взаимодействия бизнес-объектов за интерфейсом позволяет отделить клиента от бизнес-логики, а при необходимости можно реализовать несколько вариантов интерфейса приложения). В то же время рассмотрение этого процесса выходит за рамки данного учебного курса. Обратите внимание, что версии EJB до 3.1 _требуют_ реализации интерфейса для каждого сеансного компонента.
[start=7]
. Нажмите кнопку "Завершить". В среде IDE создаются сеансные компоненты для каждого класса сущностей проекта. В окне "Проекты" разверните новый пакет `session` для просмотра сеансных компонентов.
|===
|Net Beans, версия 6.8 |Net Beans, версия 6.9
|image::images/projects-window-session-beans.png[title="Изучите проект CalculatorClientApp в окне "Проекты". "] |image::images/projects-window-session-beans-69.png[title="Изучите проект CalculatorClientApp в окне "Проекты". "]
|===
*Примечание.* Как показано выше, IDE NetBeans 6.9 обеспечивает незначительные усовершенствования аналогично созданию мастером компонентов сеансов для классов сущностей фасадных классов. А именно, код-заготовка, общий для всех классов, складывается в абстрактный класс, названный `AbstractFacade`. Работая в версии 6.9, откройте любой из созданных фасадных классов (кроме класса `AbstractFacade`). Видно, что этот класс расширяет `AbstractFacade`.
[start=8]
. Откройте сессионный фасад в редакторе, например в `ProductFacade`. Все редактируемые сессионные фасады создают link:http://java.sun.com/javaee/6/docs/api/javax/persistence/EntityManager.html[+`EntityManager`+], используя аннотацию link:http://download.oracle.com/javaee/6/api/javax/persistence/PersistenceContext.html[+`@PersistenceContext`+].
[source,java]
----
@PersistenceContext(unitName = "AffableBeanPU")
private EntityManager em;
----
Аннотация `@PersistenceContext` используется для добавления в класс интерфейса `EntityManager`, управляемого контейнером. Другими словами, контейнер EJB проекта GlassFish используется для открытия и закрытия интерфейсов `EntityManager`, когда это необходимо. Элемент `unitName` указывает блок сохранения состояния `AffableBeanPU`, который был определен в файле `persistence.xml` приложения.
`EntityManager` (диспетчер сущностей) внутренний компонент интерфейса API сохранения состояния Java, отвечающий за сохранение состояния в базе данных. В книге link:http://www.manning.com/panda/[+EJB 3 в действии+] `EntityManager` описан следующим образом:
[NOTE]
====
_Интерфейс JPA `EntityManager` управляет сущностями в терминах реального обеспечения служб сохранения состояния. Когда сущности сообщают поставщику JPA о своем сопоставлении с базой данных, они не сохраняют свое состояние самостоятельно. Интерфейс `EntityManager` считывает метаданные ORM для сущности и производит операции сохранения состояния._
====
Теперь приложение содержит модель сохранения состояния базы данных `affablebean` в форме классов сущностей JPA. Также оно содержит фасад сеанса, состоящий из компонентов уровня приложения, используемых для доступа к классам сущностей. В следующем разделе показан способ доступа к базе данных при помощи сеансных компонентов и классов сущностей.
[[access]]
== Доступ к данным при помощи EJB
В link:connect-db.html[+предыдущей главе учебного курса+] показан способ доступа к базе данных путем настройки источника данных в GlassFish, добавления ссылки на ресурс к описателю развертывания приложения и использования тега JSTL `<sql>` на страницах JSP приложения. Это важный способ, поскольку он позволяет быстро настроить прототипы, включающие в себя данные из базы данных. Тем не менее, такой способ не подходит для средних и крупных приложений или приложений, управляемых командой разработчиков, так как сложен в расширении и поддержке. Более того, при разработке многоуровневого приложения или соблюдении шаблона MVC не следует хранить код доступа к данным в внешнем интерфейсе. Использование компонентов уровня предприятия с моделью сохранения состояния позволяет более полно следовать шаблону MVC благодаря разделению компонентов представления и модели.
Следующая инструкция описывает использование сеансных компонентов и компонентов сущностей в проекте `AffableBean`. В примере будет удален код доступа к данным JSTL, написанный ранее для страницы-указателя и страницы категории. Вместо них будут использованы методы доступа к данным сеансных компонентов, а данные будут храниться в контекстных переменных, которые доступны из внешнего интерфейса. Для начала отредактируем страницу-указатель, а затем - более сложную страницу категории.
* <<index,страница-указатель>>
* <<category,страница категории>>
[[index]]
=== страница-указатель
На странице-указателе требуются данные о четырех категориях продуктов. При текущих настройках теги JSTL `<sql>` запрашивают в базе данных сведения при каждом запросе к странице-указателю. Поскольку эта информация редко изменяется, с точки зрения производительности разумнее выполнить запрос только раз после того, как приложение будет запущено, и сохранить данные в атрибуте на уровне приложения. Этого можно добиться, добавив данный код в принадлежащий классу `ControllerServlet` метод `инициализации`.
1. В окне "Проекты" дважды щелкните узел "Исходные пакеты" > `controller` > `ControllerServlet`, чтобы открыть его в редакторе.
2. Объявите экземпляр `CategoryFacade` и примените к нему аннотацию `@EJB`.
[source,java]
----
public class ControllerServlet extends HttpServlet {
*@EJB
private CategoryFacade categoryFacade;*
...
}
----
После добавления аннотации `@EJB` контейнер EJB создает экземпляр переменной `categoryFacade` с EJB `CategoryFacade`.
[start=3]
. С помощью подсказок среды IDE добавьте операторы импорта для следующих классов:
* `javax.ejb.EJB`
* `session.CategoryFacade`
При нажатии Ctrl-Shift-I (⌘-Shift-I в Mac) требуемые импорты автоматически добавляются к используемому классу.
[start=4]
. Добавьте в класс следующий метод `init`. Веб-контейнер инициализирует сервлет, вызывая свой метод `init`. Это происходит только один раз после загрузки сервлета и до начала обработки запросов.
[source,java]
----
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). (The image below displays the popup that appears using IDE NetBeans 6.8.)
image::images/method-signature.png[title="Подведите мышь к методу, удерживая клавишу Ctrl для просмотра его подписи."]
Щелкните гиперссылку для перехода к методу.
[start=5]
. С помощью подсказки среды IDE добавьте аннотацию `@Overrides` Метод `init` определяется надклассом `HttpServlet` и сервлетом `GenericServlet`.
image::images/override.png[title="С помощью подсказки среды IDE добавьте аннотацию @Overrides "]
Добавление аннотации не обязательно, но дает следующие преимущества:
* Позволяет компилятору проверить, действительно ли переопределяется метод, который предполагается переопределить.
* Улучшает удобство восприятия, поскольку становится ясно, какие методы в исходном коде переопределяются.
Дополнительные сведения об аннотациях приведены в курсе link:http://download.oracle.com/javase/tutorial/java/javaOO/annotations.html[+Учебные курсы по Java: аннотации+].
[start=6]
. После создания в контексте приложения атрибута, содержащего список категорий, измените страницу-указатель таким образом, чтобы использовался этот атрибут.
Дважды щелкните узел "Веб-страницы" > `index.jsp` в окне "Проекты", чтобы открыть файл в редакторе.
[start=7]
. Закомментируйте (или удалите) оператор `<sql:query>` в начале файла. Для закомментирования кода в редакторе выделите код, затем нажмите Ctrl-/ (⌘-/ в Mac).
image::images/commented-out.png[title="Нажмите Ctrl-/ для закомментирования фрагмента кода в редакторе"]
[start=8]
. Отредактируйте открывающий тег `<c:forEach>` так, чтобы его атрибут `items` указывал на новый атрибут контекста приложения `categories`.
[source,java]
----
<c:forEach var="category" items="*${categories}*">
----
[start=9]
. Откройте дескриптор развертывания веб-проекта. Нажмите сочетание клавиш ALT+SHIFT+O (CTRL+SHIFT+O в Mac OS) и в диалоговом окне "Переход к файлу" введите `web`, затем нажмите кнопку "ОК".
image::images/go-to-file.png[title="С помощью диалогового окна "Переход к файлу" быстро откройте файлы в редакторе"]
[start=10]
. Закомментируйте (или удалите) запись `<resource-ref>`. Эта запись требовалась для определения тегами `<sql>` источника данных, зарегистрированного на сервере. Теперь для доступа к базе данных используется JPA, и источник данных `jdbc/affablebean` уже был указан в блоке сохранения состояния. Подробные сведения представлены выше в разделе <<pu,Представление проектирования поставщика сохранения состояния проекта>>.
Выделите всю запись `<resource-ref>`, затем нажмите Ctrl-/ (⌘-/ в Mac).
[source,xml]
----
*<!-- *<resource-ref>
<description>Connects to database for AffableBean application</description>
<res-ref-name>jdbc/affablebean</res-ref-name>
<res-type>javax.sql.ConnectionPoolDataSource</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref> *-->*
----
[start=11]
. Выполните проект. Нажмите кнопку 'Запустить проект' ( image::images/run-project-btn.png[] ). В браузере откроется страница-указатель проекта, и отобразятся все четыре категории и изображения.
image::images/index-page.png[title="Убедитесь в том, что к базе данных добавлены новые таблицы."]
[[category]]
=== страница категории
Для верного отображения link:design.html#category[+страницы категории+] требуются три элемента данных:
1. *данные о категориях:* для кнопок категорий в левом столбце;
2. *выбранная категория:* выбранная категория выделяется в левом столбце и ее имя отображается над таблицей продуктов;
3. *данные о продуктах в выбранной категории:* для отображения продуктов в таблице.
Рассмотрим отдельно каждый элемент данных.
* <<categoryData,данные о категориях>>
* <<selectedCategoryData,выбранная категория>>
* <<productData,данные о продуктах в выбранной категории>>
[[categoryData]]
==== данные о категориях
Для получения данных о категориях можно повторно использовать атрибут в контексте приложения `categories`, созданный для страницы-указателя.
1. Откройте `category.jsp` в редакторе и закомментируйте (Ctrl-/; ⌘-/ в Mac) операторы JSTL `<sql>`, указанные в верхней части файла.
image::images/comment-out-sql.png[title="Закомментируйте операторы JSTL <sql> на странице категорий"]
[start=2]
. Отредактируйте открывающий тег `<c:forEach>` так, чтобы его атрибут `items` указывал на атрибут контекста приложения `categories`. Эта же операция была проведена в файле `index.jsp`.
[source,java]
----
<c:forEach var="category" items="*${categories}*">
----
[start=3]
. Выполните проект для проверки текущего состояния страницы категории. Нажмите кнопку 'Запустить проект' ( image::images/run-project-btn.png[] ). После отображения страницы-указателя в браузере щелкните одну из категорий. Кнопки категорий в левом столбце отображаются и работают ожидаемым образом.
image::images/category-page-left-column.png[title="Кнопки категорий в левом столбце отображаются и работают ожидаемым образом."]
[[selectedCategoryData]]
==== выбранная категория
Чтобы извлечь выбранную категорию, можно использовать переменную `categoryFacade`, созданную ранее для поиска `Category`, чей идентификатор совпадает со строкой запроса.
1. Откройте в редакторе `ControllerServlet`. Если он уже открыт, нажмите сочетание клавиш CTRL+TAB и выберите его во всплывающем списке.
2. Начните реализовывать функциональность по принятию выбранной категории Найдите комментарий `TODO: Implement category request` (Сделать: реализовать запрос категории), удалите его и добавьте следующий код (выделен *полужирным шрифтом*).
[source,java]
----
// if category page is requested
if (userPath.equals("/category")) {
*// get categoryId from request
String categoryId = request.getQueryString();
if (categoryId != null) {
}*
// if cart page is requested
} else if (userPath.equals("/viewCart")) {
----
В этом запросе вызовом функции `getQueryString()` извлекается идентификатор запрашиваемой категории.
*Примечание.* Логика определения выбранной категории кнопками левого столбца уже реализована в `category.jsp` с использованием выражения EL, что сравнимо с вызовом `getQueryString()` в сервлете. Выражение EL: `pageContext.request.queryString`.
[start=3]
. Добавьте в оператор `if` следующую строку кода.
[source,java]
----
// 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`.
[start=4]
. Щелкните метку ( image::images/editor-badge.png[] ) на левой границе для использования подсказки в редакторе для объявления `selectedCategory` как локальной переменной в методе `doGet`.
image::images/local-variable.png[title="Использование подсказок редактора для объявления локальных переменных"]
Поскольку `selectedCategory` имеет тип `Category`, который не был ранее импортирован в класс, среда IDE автоматически добавляет выражение импорта для `entity.Category` в начало файла.
[start=5]
. Чтобы поместить полученный объект `Category` в контекст запроса, добавьте следующую строку.
[source,java]
----
// 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);*
}
----
[start=6]
. Переключитесь в редакторе к файлу `category.jsp`. Для этого нажмите сочетание клавиш CTRL+TAB и выберите его во всплывающем списке.
[start=7]
. Найдите текст `<p id="categoryTitle">` и внесите следующие изменения.
[source,xml]
----
<p id="categoryTitle">
<span style="background-color: #f5eabe; padding: 7px;">*${selectedCategory.name}*</span>
</p>
----
Теперь используется атрибут `selectedCategory`, помещенный в контекст запроса в `ControllerServlet`. С помощью "`.name`" в выражении EL вызывается метод `getName` в данном объекте `Category`.
[start=8]
. Переключитесь обратно на окно браузера и обновите страницу категорий. Теперь на странице отображается имя выбранной категории.
image::images/category-page-selected-category.png[title="Теперь на странице отображается имя выбранной категории."]
[[productData]]
==== данные о продуктах в выбранной категории
Для того чтобы получить все продукты из выбранной категории, используется принадлежащий сущности `Category` метод `getProductCollection()`. Запустите вызов этого метода для `selectedCategory`, чтобы получить коллекцию всех `Product`, связанных с `selectedCategory`. Далее сохраните коллекцию продуктов в контексте запроса как атрибут и, наконец, сошлитесь на контекстный атрибут из представления страницы `category.jsp`.
1. Добавьте следующий оператор в код `ControllerServlet`. Это выражение управляет запросом категории.
[source,java]
----
// if category page is requested
if (userPath.equals("/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);
*// get all products for selected category
categoryProducts = selectedCategory.getProductCollection();*
}
----
Здесь вызов `getProductCollection` позволяет получить коллекцию всех продуктов `Product`, связанных с выбранной категорией `selectedCategory`.
[start=2]
. Используйте подсказку редактора для определения `categoryProducts` в качестве локальной переменной для метода `doGet`.
image::images/local-variable2.png[title="Использование подсказок редактора для объявления локальных переменных"]
[start=3]
. Поместите коллекцию продуктов `Product` в контекст запроса, чтобы ее можно было извлечь из внешнего интерфейса приложения.
[source,java]
----
// if category page is requested
if (userPath.equals("/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);
// get all products for selected category
categoryProducts = selectedCategory.getProductCollection();
*// place category products in request scope
request.setAttribute("categoryProducts", categoryProducts);
}*
----
[start=4]
. Откройте в редакторе `category.jsp` и внесите в таблицу запросов следующее изменение.
[source,java]
----
<table id="productTable">
<c:forEach var="product" items="*${categoryProducts}*" varStatus="iter">
----
Тег `<c:forEach>` теперь ссылается на набор `categoryProducts`. Цикл `c:forEach` теперь выполняется для каждого объекта `Product`, содержащегося в коллекции, и извлекает соответствующие данные.
[start=5]
. Для запуска проекта нажмите клавишу F6 (или сочетание клавиш fn+F6 в Mac OS) В браузере перейдите к странице категории и обратите внимание, что для каждой категории отображаются все продукты.
image::images/category-page-product-table.png[title="Убедитесь в том, что к базе данных добавлены новые таблицы."]
Этот учебный курс краткое введение в технологии JPA и EJB. Также здесь описана роль спецификаций Java и использование примеров их реализации в сервере приложений GlassFish. Показано, как создать набор классов сущностей JPA, предоставляющих реализацию базы данных проектов на уровне Java. Затем в соответствии с шаблоном _фасад сеанса_ показано создание набора сеансных компонентов EJB, которые расположены выше уровнем, чем классы сущностей, и предоставляют удобный доступ к ним. Наконец, проект `AffableBean` изменен для того, чтобы использовать новые сеансные компоненты и сущности для доступа к базе данных. Это требовалось в странице-указателе и странице категорий.
You can download link:https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot4.zip[+snapshot 4+] of the `AffableBean` project, which corresponds to state the project after completing this unit using IDE NetBeans 6.9.
В следующей главе будет рассмотрено управление сеансами и запоминание приложением действий пользователя, который перемещается по сайту. Это ключевой момент при реализации механизма "покупательской корзины" в приложениях электронной коммерции.
link:/about/contact_form.html?to=3&subject=Feedback: NetBeans E-commerce Tutorial - Adding Entity Classes and Session Beans[+Мы ждем ваших отзывов+]
[[seeAlso]]
== Дополнительные сведения
=== Материалы по NetBeans
* link:../../../trails/java-ee.html[+Учебная карта по Java EE и Java Web+]
* link:../javaee-intro.html[+Введение в технологию Java EE +]
* link:../javaee-gettingstarted.html[+Начало работы с приложениями для Java EE+]
* link:../secure-ejb.html[+Создание безопасных компонентов уровня предприятия в Java EE+]
* link:../javaee-entapp-ejb.html[+Создание приложения уровня предприятия с помощью EJB 3.1+]
* link:../jpa-eclipselink-screencast.html[+Использование поддержки JPA с EclipseLink+] [экранная демонстрация]
* link:../../screencasts.html[+Video Tutorials and Demos for IDE NetBeans 6.x+]
* link:http://refcardz.dzone.com/refcardz/netbeans-java-editor-68[+Работа с кодом в редакторе Java IDE NetBeans: справочник+]
=== Ресурсы по EJB
* *Страница продукта:* link:http://java.sun.com/products/ejb/[+Технология Enterprise JavaBeans +]
* *Загрузка спецификации:* link:http://jcp.org/aboutJava/communityprocess/final/jsr318/index.html[+JSR 318: EJB 3.1 Final Release+]
* *Пример реализации:* link:http://glassfish.dev.java.net/downloads/ri[+http://glassfish.dev.java.net/downloads/ri+]
* *Официальный форум:* link:http://forums.sun.com/forum.jspa?forumID=13[+Enterprise Technologies — Enterprise JavaBeans+]
* *Учебный курс Java EE 6:* link:http://download.oracle.com/docs/cd/E17410_01/javaee/6/tutorial/doc/bnblr.html[+Часть IV. Компоненты уровня предприятия+]
=== Ресурсы по JPA
* *Страница продукта:* link:http://java.sun.com/javaee/technologies/persistence.jsp[+Java Persistence API+]
* *Загрузка спецификации:* link:http://jcp.org/aboutJava/communityprocess/final/jsr317/index.html[+JSR 317: Java Persistence 2.0 Final Release+]
* *Пример реализации:* link:http://www.eclipse.org/eclipselink/downloads/ri.php[+http://www.eclipse.org/eclipselink/downloads/ri.php+]
* *Учебный курс по Java EE 6:* link:http://download.oracle.com/docs/cd/E17410_01/javaee/6/tutorial/doc/bnbpy.html[+Часть VI. Сохранение состояния+]
=== Ресурсы по GlassFish
* link:https://glassfish.dev.java.net/docs/index.html[+Документация GlassFish v3+]
* link:http://www.sun.com/offers/details/GlassFish_Tomcat.html[+Изучение GlassFish в Tomcat+]
* link:https://glassfish.dev.java.net/javaee5/persistence/persistence-example.html[+Проект GlassFish. Пример использования Java Persistence+]
* link:http://docs.sun.com/app/docs/doc/820-7759[+Первые шаги: введение в платформу Java EE+]
* link:https://glassfish.dev.java.net/downloads/ri/[+Загрузка примеров реализации+]
=== Технические статьи
* link:http://www.theserverside.com/news/1363656/New-Features-in-EJB-31[+Новые возможности EJB 3.1+]
* link:http://www.ibm.com/developerworks/java/library/j-ejb1008.html[+Практические рекомендации по EJB: безопасность компонентов сущностей+]
* link:http://java.sun.com/blueprints/corej2eepatterns/Patterns/SessionFacade.html[+Core J2EE Patterns - Фасад сеанса+]
* link:http://www.ibm.com/developerworks/websphere/library/techarticles/0106_brown/sessionfacades.html[+Правила и шаблоны фасадов сеанса+]
* link:http://www.oracle.com/technology/sample_code/tech/java/j2ee/designpattern/businesstier/sessionfacade/readme.html[+Пример приложения шаблона проектирования - фасад сеанса+]
* link:http://www.ibm.com/developerworks/websphere/library/bestpractices/using_httpservlet_method.html[+Практические рекомендации: использование метода `init` объекта HttpServlet+]
=== Книги
* link:http://www.amazon.com/Beginning-Java-EE-GlassFish-Second/dp/143022889X/ref=dp_ob_title_bk[+Начало работы с Java EE 6 с GlassFish 3+]
* link:http://www.amazon.com/Java-EE-GlassFish-Application-Server/dp/1849510369/ref=sr_1_1?s=books&ie=UTF8&qid=1281888153&sr=1-1[+Java EE 6 с сервером приложений GlassFish 3+]
* link:http://www.apress.com/book/view/1590598954[+Pro IDE NetBeans 6 Rich Client Platform Edition+]
* link:http://www.amazon.com/Real-World-Patterns-Rethinking-Practices/dp/0557078326/ref=pd_sim_b_4[+Испытанные приемы пересмотра шаблонов Java EE Real World+]
* link:http://www.amazon.com/Patterns-Enterprise-Application-Architecture-Martin/dp/0321127420/ref=sr_1_1?s=books&ie=UTF8&qid=1281985949&sr=1-1[+Шаблоны архитектуры корпоративных приложений+]
* link:http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215/ref=sr_1_1?s=books&ie=UTF8&qid=1281985959&sr=1-1[+Разработка на основе доменов: сложность отслеживания в основе программного обеспечения+]
== Ссылки
1. <<1,^>> Адаптация link:http://www.manning.com/panda/[+EJB 3 в действии+] Глаза 1, раздел 1.1.2: EJB как платформа.
2. <<2,^>>EJB предоставляет множество других служб. Более подробный список приведен в книге link:http://www.manning.com/panda/[+EJB 3 в действии+], глава 1, раздел 1.3.3: получение функциональных возможностей с помощью служб EJB.