// 
//     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.
//

= Создание приложения J2EE с помощью EJB 3.1
:jbake-type: tutorial
:jbake-tags: tutorials 
:jbake-status: published
:icons: font
:syntax: true
:source-highlighter: pygments
:toc: left
:toc-title:
:description: Создание приложения J2EE с помощью EJB 3.1 - Apache NetBeans
:keywords: Apache NetBeans, Tutorials, Создание приложения J2EE с помощью EJB 3.1

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

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

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

* link:javaee-gettingstarted.html[+Начало работы с приложениями Java EE+]

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

* <<intro,О приложении J2EE NewsApp>>
* <<Exercise_1,Создание проекта приложения J2EE>>
* <<Exercise_2,Написание кода модуля EJB>>
* <<Exercise_2a,Создание класса сущностей>>
* <<Exercise_2b,Создание управляемого сообщениями компонента>>
* <<Exercise_2c,Создание фасада сеанса>>
* <<Exercise_3,Написание кода веб-модуля>>
* <<Exercise_3a,Создание единичного сеансного компонента>>
* <<Exercise_3b,Создание сервлета ListNews>>
* <<Exercise_3c,Создание сервлета PostMessage>>
* <<Exercise_4,Выполнение проекта>>
* <<Exercise_5,Загрузка проекта решения>>
* <<Exercise_6,Устранение проблем>>

*Для работы с этим учебным курсом требуется следующее программное обеспечение и ресурсы.*

|===
|Программное обеспечение или материал |Требуемая версия 

|link:https://netbeans.org/downloads/index.html[+IDE NetBeans+] |Версия 7.2, 7.3, 7.4, 8.0, Java EE 

|link:http://www.oracle.com/technetwork/java/javase/downloads/index.html[+Комплект для разработчика на языке Java (JDK)+] |версия 7 или 8 

|GlassFish Server Open Source Edition 3.1.2.2 |3.x, 4.x 
|===

*Предпосылки*

Предполагается, что читатель обладает базовыми знаниями по следующим технологиям или опытом программирования с их использованием:

* Программирование на Java
* IDE NetBeans

Можно загрузить link:https://netbeans.org/projects/samples/downloads/download/Samples/JavaEE/NewsAppEE6.zip[+готовый проект в виде архива ZIP+].


== О приложении J2EE NewsApp

В этом руководстве приводится несложный пример создания многоуровневого приложения Java EE 6 с именем NewsApp. В приложении NewsApp используется несколько функций, внедренных в спецификации Java EE 6.

Структура приложения NewsApp, как правило, соответствует следующим уровням.

* *Веб-уровень.* Веб-уровень содержит логику представления приложения и запускается на сервере Java EE. В приложении NewsApp веб-уровень представлен веб-модулем и содержит сервлеты, через которые осуществляется доступ к бизнес-логике в модуле EJB.
* *Бизнес-уровень.* Приложения бизнес-уровня также выполняются на серверах Java EE и содержат бизнес-логику приложения. В приложении NewsApp бизнес-уровень представлен модулем EJB. Модуль EJB содержит код для обработки запросов от клиентов веб-уровня и для управления транзакциями и способами сохранения объектов в базе данных.
* *EIS-уровень.* EIS-уровень - это надежный уровень хранения приложения. В приложении NewsApp этот уровень представлен базой данных для сохранения сообщений.

При сборке приложения J2EE в среде IDE модуль EJB и модуль веб-приложения упаковываются в архивный файл EAR, который затем развертывается на сервере. Затем доступ к приложению обычно получается из *клиентского уровня.* Уровень клиента является средой, в которой клиент запускается и часто является веб-браузером в локальной системе пользователя.

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

Подробные сведения о структуре приложений J2EE Java EE см. в главе link:http://download.oracle.com/javaee/6/tutorial/doc/bnaay.html[+Распределенные многоуровневые приложения+] в link:http://download.oracle.com/javaee/6/tutorial/doc/[+руководстве по Java EE 6, часть I+].


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

Цель этого упражнения состоит в создании проекта приложения J2EE NewsApp. Для создания приложения J2EE, содержащего EJB-модуль и веб-модуль, используется мастер создания проекта.

1. Выберите 'Файл' > 'Создать проект' (Ctrl-Shift-N; ⌘-Shift-N в Mac) в главном меню.
2. В категории "Java EE" выберите приложение J2EE и нажмите "Далее".
3. Введите имя проекта *NewsApp* и укажите местоположение проекта.
4. Снимите флажок "Использовать отдельную папку", если он установлен.
(В рамках этого руководства копирование библиотек проекта в отдельную папку нецелесообразно, поскольку совместное использование библиотек с другими пользователями или проектами не требуется.)
Нажмите кнопку "Далее".


. В качестве сервера выберите сервер GlassFish, а в качестве версии Java EE укажите Java EE 6 или Java EE 7.


. Выберите пункты "Создать модуль EJB" и "Создать модуль веб-приложения". Нажмите кнопку "Завершить".

image::images/new-entapp-wizard.png[title="Мастер создания проектов"]

После нажатия кнопки "Готово" среда IDE создает три проекта: NewsApp, NewsApp-ejb и NewsApp-war При разворачивании узла NewsApp в окне "Проекты" можно увидеть, что проект приложения J2EE не содержит исходные файлы. Все исходные файлы содержатся в двух модулях, созданных мастером и выведенных в узле "Модули Java EE".

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

image::images/ejb-projectswindow.png[title="Окно 'Проекты', в котором отображается структура приложения"] 


== Написание кода модуля EJB

В этом упражнении будет создан класс сущностей, управляемый сообщениями компонент и фасад сеанса в модуле EJB. Также будет создана единица сохранения состояния для обеспечения контейнера информацией об источнике данных и о способах управления сущностями, а также ресурсы службы передачи сообщений Java (Java Message Service, JMS), используемые управляемым сообщениями компонентом.


=== Создание класса сущности

В этом упражнении будет создан класс сущностей  ``NewsEntity`` . Класс сущностей – это простой класс Java, как правило, соответствующий таблице в базе данных. При создании класса сущностей в среде IDE для определения класса как класса сущностей добавляется аннотация  ``@Entity`` . После создания класса в нем создаются поля для представления требуемых данных в таблице.

Каждый класс сущностей должен иметь первичный ключ. При создании класса сущностей в среде IDE добавляется аннотация  ``@Id``  для объявления, какое поле необходимо использовать в качестве первичного ключа. Также в среде IDE добавляется аннотация  ``@GeneratedValue``  и указывается стратегия создания ключей для первичного идентификатора.

Для создания класса  ``NewsEntity``  выполните следующие действия.

1. Щелкните правой кнопкой мыши модуль EJB в окне "Проекты" и выберите "Создать > Прочее" для открытия мастера создания файла.
2. Выберите "Класс сущностей" из категории "Сохранение состояния" и нажмите "Далее".
3. В поле "Имя класса" введите *NewsEntity*.
4. В поле Package ("Пакет") введите *ejb*.
5. В мастере создания класса сущностей оставьте тип первичного ключа  ``Long`` .
6. Выберите команду "Создать блок сохранения состояния". Нажмите кнопку "Далее".
7. Оставьте имя блока сохранения состояния по умолчанию.
8. Для Поставщика сохранения состояния выберите  ``EclipseLink (JPA2.0)(по умолчанию)`` .
9. В поле "Источник данных" укажите источник данных (например, выберите  ``jdbc/sample`` , если необходимо использовать JavaDB).
10. Убедитесь в том, что для блока сохранения состояния используется интерфейс API транзакций Java и что для стратегии создания таблиц установлено значение "Создать", т. е. таблицы на основе классов сущностей создаются при развертывании приложения.

image::images/new-pu-wizard.png[title="Панель 'Поставщик и база данных'"]



. Нажмите кнопку "Завершить".

При нажатии кнопки "Завершить" в среде IDE будет создан файл  ``persistence.xml``  и класс сущностей  ``NewsEntity.java`` .  ``NewsEntity.java``  будет открыт средой IDE в редакторе исходного кода.

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

1. Добавьте к классу следующие объявления полей:

[source,java]
----

private String title;
private String body;
----


. Щелкните правой кнопкой мыши в редакторе исходного кода, выберите пункт "Вставить код" (Alt-Insert; Ctrl-I на Mac) и выберите пункт "Методы получения и установки", чтобы открыть диалоговое окно "Создать методы получения и установки".


. В диалоговом окне выберите поля  ``body``  и  ``title`` . Нажмите кнопку "Создать".

image::images/ejb-gettersetter.png[title="Диалоговое окно 'Создание методов получения и установки'"]

При нажатии кнопки "Создать" в среде IDE добавляются методы получения и установки для полей.



. Сохраните изменения в  ``NewsEntity.java`` .

 ``NewsEntity.java``  можно закрыть.

Для получения подробных сведений о классах сущностей см. главу link:http://java.sun.com/javaee/6/docs/tutorial/doc/bnbpz.html[+Введение в интерфейс API сохранения состояния Java+] в link:http://download.oracle.com/javaee/6/tutorial/doc/[+Руководство по Java EE 6. Часть I+].


=== Создание управляемого сообщениями компонента

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

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

1. Щелкните правой кнопкой мыши модуль EJB в окне "Проекты" и выберите "Создать > Прочее" для открытия мастера создания файла.
2. В категории "Enterprise JavaBeans" выберите тип файла "Компонент, определяемый сообщениями". Нажмите кнопку "Далее".
3. В поле "Имя EJB" введите *NewMessage*.
4. В раскрывающемся списке "Пакет" выберите  ``ejb`` .
5. Для открытия диалогового окна "Добавление адресата сообщения" нажмите кнопку "Добавить" рядом с полем "Адресат проекта".
6. В диалоговом окне "Добавление адресата сообщения" введите *jms/NewMessage* и выберите "Очередь" для типа адресата. Нажмите кнопку "ОК".
7. Подтвердите, что адресат проекта выбран правильно. Нажмите кнопку "Завершить".

image::images/ejb-newmessage.png[title="Мастер создания компонентов, управляемых сообщениями"]

При нажатии кнопки "Завершить" в редакторе исходного кода откроется класс компонента  ``NewMessage.java`` . При этом в среде IDE добавляется аннотация  ``@MessageDriven``  и свойства настройки для класса.


[source,java]
----

       
@MessageDriven(mappedName = "jms/NewMessage", activationConfig =  {
        @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
        @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue")
    })
public class NewMessage implements MessageListener {
----

Аннотация  ``@MessageDriven``  указывает на то, что данный компонент является управляемым сообщениями, а также определяет ресурс JMS, используемый компонентом. При создании класса в среде IDE отображаемое имя ресурса ( ``jms/NewMessage`` ) определяется на основе имени класса ( ``NewMessage.java`` ). Ресурс JMS привязан к имени JNDI адресата, от которого в компонент поступают сообщения. Мастер создания управляемых сообщениями компонентов также добавляет в файл  ``glassfish-resources.xml``  информацию о ресурсах JMS. Для указания ресурсов JMS не требуется настраивать дескрипторы развертывания. Если в среде IDE для развертывания приложения на сервере GlassFish выбрать операцию "Выполнить", то ресурсы JMS создаются на сервере при развертывании.

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

1. Введите в класс ресурс  ``MessageDrivenContext``  посредством добавления к классу следующего аннотированного поля (выделено полужирным шрифтом):

[source,java]
----

public class NewMessage implements MessageListener {

*@Resource
private MessageDrivenContext mdc;*
----


. Добавьте диспетчер сущностей в класс, щелкнув правой кнопкой мыши в коде и выбрав 'Вставить код' (Alt-Insert, Ctrl-I в Mac) и выбрав 'Использовать диспетчер сущностей' из всплывающего меню. В среде IDE к исходному коду добавляется следующая аннотация  ``@PersistenceContext`` .

[source,java]
----

@PersistenceContext(unitName = "NewsApp-ejbPU")
private EntityManager em;
----
Кроме того, в среде IDE создается следующий метод  ``persist`` .

[source,java]
----

public void persist(Object object) {
    em.persist(object);
}
----


. Для изменения имени на  ``save``  измените метод  ``persist`` . В результате метод должен выглядеть следующим образом:

[source,java]
----

public void *save*(Object object) {     
    em.persist(object);
}
----


. Измените метод  ``onMessage``  путем добавления следующих строк кода (выделено полужирным шрифтом) в тело метода.

[source,java]
----

public void onMessage(Message message) {
    *ObjectMessage msg = null;
    try {
        if (message instanceof ObjectMessage) {
            msg = (ObjectMessage) message;
            NewsEntity e = (NewsEntity) msg.getObject();
            save(e);            
        }
    } catch (JMSException e) {
        e.printStackTrace();
        mdc.setRollbackOnly();
    } catch (Throwable te) {
        te.printStackTrace();
    }*
}
----


. Щелкните правой кнопкой мыши в редакторе и выберите 'Исправить выражения импорта' (Alt-Shift-I; ⌘-Shift-I в Mac) для создания необходимых операторов импорта. Сохраните изменения.

NOTE:  При создании операторов импорта необходимо *убедиться в импорте библиотек  ``javax.jms``  и  ``javax.annotation.Resource`` *.

Подробные сведения об управляемых сообщениями компонентах приведены в главе link:http://java.sun.com/javaee/6/docs/tutorial/doc/gipko.html[+Что такое управляемый сообщениями компонент?+] в link:http://download.oracle.com/javaee/6/tutorial/doc/[+руководстве по Java EE 6. Часть I+].


=== Создание фасада сеанса

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

Для создания фасада сеанса выполните следующие действия:

1. Щелкните модуль EJB правой кнопкой мыши и выберите команду "Создать" > "Другие".
2. Из категории "Сохранение состояния" выберите "Сеансные компоненты для классов сущностей". Нажмите кнопку "Далее".
3. Из списка доступных классов сущностей выберите  ``ejb.NewsEntity``  и нажмите кнопку "Добавить", чтобы переместить класс на панель "Выбранные классы сущностей". Нажмите кнопку "Далее".
4. Убедитесь в том, что для параметра "Пакет" установлено значение  ``ejb`` . Нажмите кнопку "Завершить".

image::images/ejb-sessionforentity.png[title="Мастер создания компонентов, управляемых сообщениями"]

При нажатии кнопки "Готово" среда IDE создает класс фасада сеанса  ``NewsEntityFacade.java``  и  ``AbstractFacade.java``  и открывает файлы в редакторе. Как видите из созданного кода, аннотация  ``@Stateless``  используется для объявления  ``NewsEntityFacade.java``  в качестве простого сеансного компонента без сохранения состояния. Также в среде IDE добавляется аннотация  ``PersistenceContext``  для внедрения ресурса непосредственно в элемент сеансного компонента. Класс  ``NewsEntityFacade.java``  расширяет класс  ``AbstractFacade.java`` , который содержит бизнес-логику и управляет транзакцией.

NOTE:  Удаленный интерфейс все еще является обязательным, если доступ к компонентам будет осуществляться с использованием удаленных клиентов.

Для получения подробных сведений о сеансных компонентах см. главу link:http://java.sun.com/javaee/6/docs/tutorial/doc/gipjg.html[+Что такое сеансный компонент?+] в link:http://download.oracle.com/javaee/6/tutorial/doc/[+руководстве по Java EE 6, часть I+].


== Написание кода веб-модуля

В примере в этом разделе будет создано два сервлета в веб-модуле. Сервлет ListNews извлекает сообщения из базы данных через фасад сущностей в модуле EJB. Сервлет PostMessage используется для отправки сообщений JMS.

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


=== Создание единичного сеансного компонента

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

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

Для создания единичного сеансного компонента выполните следующие действия.

1. Для открытия мастера создания файла щелкните веб-модуль правой кнопкой мыши и выберите "Создать" > "Другие".
2. Выберите "Сеансный компонент" в категории Enterprise JavaBeans. Нажмите кнопку "Далее".
3. В поле "Имя EJB" введите *SessionManagerBean*.
4. В качестве имени параметра "Пакет" введите *ejb*.
5. Выберите "Единичный". Нажмите кнопку "Завершить".

image::images/ejb-newsingleton.png[title="Создание отдельного компонента в мастере создания компонентов сеансов"]

При нажатии кнопки "Завершить" в среде IDE будет создан класс единичного сеансного компонента, который откроется в редакторе. При этом в среде IDE добавляется аннотация  ``@Singleton``  к классу для объявления единичного сеансного компонента. В мастере также создается аннотация  ``@LocalBean``  для класса.


[source,java]
----

@Singleton
@LocalBean
public class SessionManagerBean {

}
----

1. Создайте аннотацию  ``@WebListener``  для класса и реализуйте  ``HttpSessionListener`` .

[source,java]
----

@Singleton
@LocalBean
*@WebListener*
public class SessionManagerBean *implements HttpSessionListener*{

}
----

Аннотация  ``@WebListener``  является частью интерфейса API сервлета 3.0 и позволяет реализовать прослушивающий процесс непосредственно в коде.

При реализации  ``HttpSessionListener``  в среде IDE в поле отображается предупреждение.



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

image::images/ejb-implementabstract.png[title="Подсказка редактора о реализации абстрактных методов"]

В среде IDE добавляются методы  ``sessionCreated``  и  ``sessionDestroyed`` .



. Добавьте статическое поле  ``counter``  и установите начальное значение на  ``0`` .

[source,java]
----

@LocalBean
@WebListener
public class SessionManagerBean implements HttpSessionListener{
    *private static int counter = 0;*
----


. Измените созданные тела методов  ``sessionCreated``  и  ``sessionDestroyed``  для увеличения значения поля при запуске нового сеанса и для уменьшения значения при завершении сеанса. Значение сохраняется в поле  ``counter`` .

[source,java]
----

public void sessionCreated(HttpSessionEvent se) {
    *counter++;*
}

public void sessionDestroyed(HttpSessionEvent se) {
    *counter--;*
}
----


. Добавьте следующий метод, возвращающий текущее значение поля  ``counter`` .

[source,java]
----

public int getActiveSessionsCount() {
        return counter;
    }
----

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



. Сохраните изменения.

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


[source,java]
----

@Singleton
@LocalBean
@WebListener
public class SessionManagerBean implements HttpSessionListener {
    private static int counter = 0;

    public void sessionCreated(HttpSessionEvent se) {
        counter++;
    }

    public void sessionDestroyed(HttpSessionEvent se) {
        counter--;
    }

    public int getActiveSessionsCount() {
        return counter;
    }

}
----

Подробные сведения об единичных сеансных компонентах см. в главе link:http://java.sun.com/javaee/6/docs/tutorial/doc/gipjg.html[+Что такое сеансный компонент?+] в link:http://download.oracle.com/javaee/6/tutorial/doc/[+руководстве по Java EE 6, часть I+].


=== Создание сервлета  ``ListNews`` 

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

1. Щелкните проект веб-модуля правой кнопкой мыши и выберите "Создать" > "Сервлет".
2. В поле "Имя класса" введите *ListNews*.
3. В качестве имени параметра "Пакет" введите *web*. Нажмите кнопку "Завершить".

При нажатии кнопки "Готово" класс  ``ListNews.java``  будет открыт в редакторе исходного кода. В редакторе исходного кода выполните следующие шаги.

1. Щелкните правой кнопкой мыши в редакторе исходного кода, выберите пункт "Вставить код" (Alt-Insert; Ctrl-I на Mac) и выберите пункт "Вызов компонента EJB".
2. В диалоговом окне "Вызов компонента EJB" разверните узел NewsApp-ejb и выберите NewsEntityFacade. Нажмите кнопку "ОК".

В среде IDE добавляется аннотация  ``@EJB``  для ввода компонента EJB.



. Используйте диалоговое окно "Вызов компонента EJB" еще раз для ввода компонента SessionManagerBean в узел NewsApp-war.

В коде можно увидеть следующие аннотации для ввода двух компонентов EJB.


[source,java]
----

@WebServlet(name = "ListNews", urlPatterns = {"/ListNews"})
public class ListNews extends HttpServlet {

    @EJB
    private SessionManagerBean sessionManagerBean;
    @EJB
    private NewsEntityFacade newsEntityFacade;
                
----

Кроме того, можно увидеть, что аннотация  ``@WebServlet``  используется для объявления класса сервлета и для указания имени сервлета. Аннотация  ``@WebServlet``  является частью интерфейса API сервлета 3.0, представленного в спецификации Java EE 6. Сервлеты можно определить с помощью аннотации вместо дескриптора развертывания в  ``web.xml`` . Приложение NewsApp не содержит  ``web.xml`` .



. В методе  ``processRequest``  добавьте следующий код (выделено полужирным шрифтом) для возврата к текущему сеансу или создания нового.

[source,java]
----

protected void processRequest(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
        *request.getSession(true);*
        response.setContentType("text/html;charset=UTF-8");
----


. Добавьте следующий код (выделен жирным шрифтом) к методу  ``processRequest``  для вывода сообщений и добавления ссылки на сервлет PostMessage. (При необходимости удалите знак комментария для кода в методе.)

[source,xml]
----

out.println("<h1>Servlet ListNews at " + request.getContextPath () + "</h1>");

*List news = newsEntityFacade.findAll();
for (Iterator it = news.iterator(); it.hasNext();) {
    NewsEntity elem = (NewsEntity) it.next();
    out.println(" <b>"+elem.getTitle()+" </b><br />");
    out.println(elem.getBody()+"<br /> ");
}
out.println("<a href='PostMessage'>Add new message</a>");*

out.println("</body>");
                    
----


. Добавьте следующий код (выделено полужирным шрифтом) для получения и отображения количества пользователей/открытых сеансов.

[source,xml]
----

out.println("<a href='PostMessage'>Add new message</a>");

*out.println("<br><br>");
out.println(sessionManagerBean.getActiveSessionsCount() + " user(s) reading the news.");*

out.println("</body>");
                    
----


. Нажмите сочетание клавиш Ctrl+Shift+I для создания обязательных операторов импорта для класса. При создании операторов импорта может потребоваться *импортировать библиотеки  ``java.util`` *.


. Сохраните измененный файл.


=== Создание сервлета  ``PostMessage`` 

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

1. Щелкните проект веб-модуля правой кнопкой мыши и выберите "Создать" > "Сервлет".
2. В поле "Имя класса" введите  ``PostMessage`` .
3. Для имени параметра "Пакет" введите  ``web``  и нажмите "Завершить".

При нажатии кнопки "Готово" в редакторе исходного кода будет открыт класс  ``PostMessage.java`` . В редакторе исходного кода выполните следующие шаги.

1. Используйте аннотации для ввода ресурсов  ``ConnectionFactory``  и  ``Queue``  путем добавления следующих объявлений полей (выделено полужирным шрифтом):

[source,java]
----

@WebServlet(name="PostMessage", urlPatterns={"/PostMessage"})
public class PostMessage extends HttpServlet {                
    *@Resource(mappedName="jms/NewMessageFactory")
    private  ConnectionFactory connectionFactory;

    @Resource(mappedName="jms/NewMessage")
    private  Queue queue;*
----


. Теперь создадим код для передачи сообщения JMS путем добавления в метод  ``processRequest``  следующих строк кода, выделенных полужирным шрифтом:

[source,java]
----

response.setContentType("text/html;charset=UTF-8");

// Add the following code to send the JMS message
*String title=request.getParameter("title");
String body=request.getParameter("body");
if ((title!=null) &amp;&amp; (body!=null)) {
    try {
        Connection connection = connectionFactory.createConnection();
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        MessageProducer messageProducer = session.createProducer(queue);

        ObjectMessage message = session.createObjectMessage();
        // here we create NewsEntity, that will be sent in JMS message
        NewsEntity e = new NewsEntity();
        e.setTitle(title);
        e.setBody(body);

        message.setObject(e);                
        messageProducer.send(message);
        messageProducer.close();
        connection.close();
        response.sendRedirect("ListNews");

    } catch (JMSException ex) {
        ex.printStackTrace();
    }
}*
                        
PrintWriter out = response.getWriter();
                    
----


. Добавьте следующие строки (выделены жирным шрифтом) к методу  ``processRequest`` , чтобы добавить веб-форму добавления сообщения. (При необходимости, уберите знак комментария для вывода кода HTML)

[source,xml]
----

out.println("Servlet PostMessage at " + request.getContextPath() + "</h1>");

// The following code adds the form to the web page
*out.println("<form>");
out.println("Title: <input type='text' name='title'><br/>");
out.println("Message: <textarea name='body'></textarea><br/>");
out.println("<input type='submit'><br/>");
out.println("</form>");*

out.println("</body>");
                
----


. Нажмите сочетание клавиш Ctrl+Shift+I для создания обязательных операторов импорта для класса.

NOTE:  При выборе библиотек для импорта для  ``Connection`` ,  ``ConnectionFactory`` ,  ``Session``  и  ``Queue`` , *убедитесь, что импортируются библиотеки  ``javax.jms`` *.

image::images/import-jms.png[title="Выберите библиотеки JMS в диалоговом окне 'Исправить все выражения импорта'"]



. Сохраните измененный файл.


==  Выполнение проекта

Теперь проект можно выполнить. При выполнении проекта страница с сервлетом  ``ListNews``  должна открыться в браузере. Для этого в диалоговом окне "Свойства" для приложения J2EE вводится URL-адрес. Это относительный URL-адрес, связанный с контекстным путем к приложению. После ввода относительного URL-адреса приложение можно собрать, развернуть и запустить в окне "Проекты".

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

1. В окне 'Проекты' щелкните правой кнопкой мыши узел приложения корпоративного уровня NewsApp и выберите во всплывающем меню 'Свойства'.
2. В панели "Категории" выберите "Выполнить".
3. В текстовое поле "Относительный URL-адрес" введите */ListNews*.
4. Нажмите кнопку "ОК".
5. В окне 'Проекты' щелкните правой кнопкой мыши узел приложения корпоративного уровня NewsApp и выберите 'Выполнить'.

При выполнении проекта в браузере откроется сервлет  ``ListNews`` . В нем отображается список сообщений в базе данных. При первом выполнении проекта база данных пуста, но сообщение можно добавить путем щелчка по ссылке "Добавить сообщение".

image::images/ejb-browser1.png[title="Страница сервлета ListNews"]

При добавлении сообщения с помощью сервлета  ``PostMessage``  оно передается на постоянное хранение в управляемый сообщениями компонент. Для просмотра сообщений в базе данных вызывается сервлет  ``ListNews`` . Список сообщений в базе данных, извлеченных сервлетом  ``ListNews`` , часто выводится без нового сообщения, поскольку служба передачи сообщений работает асинхронно.


== Загрузка проекта решения

Решение для данного учебного курса в виде проекта можно загрузить несколькими способами.

* Загрузите link:https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252FNewsAppEE6.zip[+архив завершенного проекта в формате zip+].
* Выполните проверку исходных файлов проекта на выходе из примеров NetBeans, выполнив перечисленные ниже действия.


. Выберите в главном меню "Группа > Subversion > Проверить".


. В диалоговом окне "Проверка" введите следующий URL-адрес репозитория:
 ``https://svn.netbeans.org/svn/samples~samples-source-code`` 
Нажмите кнопку "Далее".


. Нажмите кнопку Browse ("Обзор") для открытия диалогового окна Browse Repository Folders ("Обзор папок репозитория").


. Разверните корневой узел и выберите *samples/javaee/NewsAppEE6*. Нажмите кнопку "ОК".


. Укажите локальную папку для исходных файлов (папка должна быть пустой).


. Нажмите кнопку "Завершить".

После нажатия кнопки "Готово" среда IDE инициализирует локальную папку в качестве репозитория Subversion и выполняет проверку исходных файлов проекта на выходе.



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

*Примечания.*

* Для получения исходных файлов на редактирование требуется клиент Subversion. For more about installing Subversion, see the section on link:../ide/subversion.html#settingUp[+Setting up Subversion+] in the link:../ide/subversion.html[+Guide to Subversion in IDE NetBeans+].


== Устранение проблем

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


=== Проблема с ресурсами JMS

При создании ресурсов JMS с помощью мастера в окне вывода может появиться следующее сообщение об ошибке сервера:


[source,java]
----

[com.sun.enterprise.connectors.ConnectorRuntimeException:
                    JMS resource not created : jms/Queue]
                
----

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

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

1. Убедитесь в том, что сервер приложений запущен. Для этого разверните узел "Серверы" в окне "Службы" среды IDE. Работающий сервер обозначается зеленой стрелкой рядом с узлом сервера приложений.
2. Щелкните правой кнопкой мыши узел сервера приложений и выберите "Просмотр консоли администратора" для открытия в браузере окна входа в систему.
3. Выполните вход в систему сервера. По умолчанию используется имя пользователя  ``admin``  и пароль  ``adminadmin`` .
4. Разверните узлы "Ресурсы" и "Ресурсы JMS" в левом поле консоли администратора в браузере.
5. Щелкните ссылки "Фабрики подключений" и "Ресурсы адресатов" в левом поле и проверьте, зарегистрированы ли ресурсы на сервере; при необходимости внесите требуемые изменения. Если ресурсы не существуют, их можно создать при помощи консоли администратора.

Необходимо убедиться в том, что ресурс фабрики подключений JMS в сервлете PostMessage связан с правильным именем JNDI ресурса фабрики подключений JMS, зарегистрированного на сервере приложений Sun Java System Application Server.

На сервере Sun Java System Application Server должны быть зарегистрированы следующие ресурсы:

* ресурс адресата с именем JNDI  ``jms/NewMessage``  и типом  ``javax.jms.Queue`` ;
* ресурс фабрики подключений с именем JNDI  ``jms/NewMessageFactory``  и типом  `` javax.jms.QueueConnectionFactory`` .


link:/about/contact_form.html?to=3&subject=Feedback:%20Creating%20an%20Enterprise%20Application%20with%20EJB%203.1[+Отправить отзыв по этому учебному курсу+]



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

For more information about using IDE NetBeans to develop Java EE applications, see the following resources:

* link:javaee-intro.html[+Введение в технологию Java EE +]
* link:javaee-gettingstarted.html[+Начало работы с приложениями Java EE+]
* link:../web/quickstart-webapps.html[+Введение в разработку веб-приложений+]
* link:../../trails/java-ee.html[+Учебная карта по Java EE и Java Web+]

Дополнительные сведения об использовании корпоративных компонентов см. в link:http://docs.oracle.com/javaee/7/tutorial/doc/ejb-intro.htm[+Учебном курсе по Java EE 7+].

To send comments and suggestions, get support, and keep informed on the latest developments on the IDE NetBeans Java EE development features, link:../../../community/lists/top.html[+join the nbj2ee mailing list+].

