blob: d4ca2068bc3ee4b44518a01c379aca746c890189 [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 четко сформулирована:
[quote]
----
_Многие считают, что технология 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 в таблицах баз данных"]
5. Нажмите кнопку "Добавить", а затем - кнопку "Далее".
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). Оставьте для стратегии генерирования таблиц значение `Нет`. Это предотвращает изменения базы данных поставщиком сохранения состояния. Например, если требуется, чтобы поставщик сохранения состояния удалил базу данных, а затем снова создал ее на основе классов сущностей, можно выбрать стратегию `Удалить и создать`. Теперь каждый раз при развертывании проекта будет выполняться это действие.
3. Нажмите кнопку "Создать".
4. Отобразится третий экран "Классы сущностей". Обратите внимание, что имена классов сущностей зависят от таблиц базы данных. Например, сущность `CustomerOrder` связана с таблицей базы данных `customer_order`. Также обратите внимание, что по умолчанию выбран параметр "Создание аннотаций именованных запросов для сохраняемых полей". В этом учебном курсе будут использованы различные именованные запросы.
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` и заполняет его параметрами по умолчанию.
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+ПРОБЕЛ."]
8. Откройте в редакторе блок сохранения состояния (`persistence.xml`). Для блоков сохранения состояния в среде IDE, кроме представления XML, доступно представление "Проектирование". Представление "Проектирование" позволяет удобно вносить изменения в параметры проекта, касающиеся управления поставщиком сохранения состояния.
image::images/persistence-unit.png[title="Представление проектирования AffableBeanPU единицы сохранения"]
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 сеанса для классов сущностей для создания фасадного сеанса для модели сохраняемости"]
3. Нажмите кнопку "Далее".
4. Второй экран "Классы сущностей". Обратите внимание, что все классы сущностей проекта перечислены слева в разделе "Доступные классы сущностей". Нажмите кнопку "Добавить все". Все классы сущностей перемещаются вправо в раздел "Выбранные классы сущностей".
5. Нажмите кнопку "Далее".
6. Третий экран "Созданные сеансные компоненты". Введите *session* в качестве имени пакета.
image::images/generated-session-beans.png[title="Укажите местоположение загруженных исходных файлов в папке в "Source"."]
*Примечание.* Мастер может использоваться для создания локальных и удаленных интерфейсов к сеансным компонентам. Программирование сеансных компонентов с интерфейсами предпочтительнее (например, скрытие взаимодействия бизнес-объектов за интерфейсом позволяет отделить клиента от бизнес-логики, а при необходимости можно реализовать несколько вариантов интерфейса приложения). В то же время рассмотрение этого процесса выходит за рамки данного учебного курса. Обратите внимание, что версии EJB до 3.1 _требуют_ реализации интерфейса для каждого сеансного компонента.
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`.
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` описан следующим образом:
[quote]
----
_Интерфейс 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`.
3. С помощью подсказок среды IDE добавьте операторы импорта для следующих классов:
* `javax.ejb.EJB`
* `session.CategoryFacade`
При нажатии Ctrl-Shift-I (⌘-Shift-I в Mac) требуемые импорты автоматически добавляются к используемому классу.
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 для просмотра его подписи."]
Щелкните гиперссылку для перехода к методу.
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: аннотации+].
6. После создания в контексте приложения атрибута, содержащего список категорий, измените страницу-указатель таким образом, чтобы использовался этот атрибут.
Дважды щелкните узел "Веб-страницы" > `index.jsp` в окне "Проекты", чтобы открыть файл в редакторе.
7. Закомментируйте (или удалите) оператор `<sql:query>` в начале файла. Для закомментирования кода в редакторе выделите код, затем нажмите Ctrl-/ (⌘-/ в Mac).
image::images/commented-out.png[title="Нажмите Ctrl-/ для закомментирования фрагмента кода в редакторе"]
8. Отредактируйте открывающий тег `<c:forEach>` так, чтобы его атрибут `items` указывал на новый атрибут контекста приложения `categories`.
[source,java]
----
<c:forEach var="category" items="*${categories}*">
----
9. Откройте дескриптор развертывания веб-проекта. Нажмите сочетание клавиш ALT+SHIFT+O (CTRL+SHIFT+O в Mac OS) и в диалоговом окне "Переход к файлу" введите `web`, затем нажмите кнопку "ОК".
image::images/go-to-file.png[title="С помощью диалогового окна "Переход к файлу" быстро откройте файлы в редакторе"]
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> *-->*
----
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> на странице категорий"]
2. Отредактируйте открывающий тег `<c:forEach>` так, чтобы его атрибут `items` указывал на атрибут контекста приложения `categories`. Эта же операция была проведена в файле `index.jsp`.
[source,java]
----
<c:forEach var="category" items="*${categories}*">
----
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`.
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`.
4. Щелкните метку ( image::images/editor-badge.png[] ) на левой границе для использования подсказки в редакторе для объявления `selectedCategory` как локальной переменной в методе `doGet`.
image::images/local-variable.png[title="Использование подсказок редактора для объявления локальных переменных"]
Поскольку `selectedCategory` имеет тип `Category`, который не был ранее импортирован в класс, среда IDE автоматически добавляет выражение импорта для `entity.Category` в начало файла.
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);*
}
----
6. Переключитесь в редакторе к файлу `category.jsp`. Для этого нажмите сочетание клавиш CTRL+TAB и выберите его во всплывающем списке.
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`.
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`.
2. Используйте подсказку редактора для определения `categoryProducts` в качестве локальной переменной для метода `doGet`.
image::images/local-variable2.png[title="Использование подсказок редактора для объявления локальных переменных"]
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);
}*
----
4. Откройте в редакторе `category.jsp` и внесите в таблицу запросов следующее изменение.
[source,java]
----
<table id="productTable">
<c:forEach var="product" items="*${categoryProducts}*" varStatus="iter">
----
Тег `<c:forEach>` теперь ссылается на набор `categoryProducts`. Цикл `c:forEach` теперь выполняется для каждого объекта `Product`, содержащегося в коллекции, и извлекает соответствующие данные.
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.