| // |
| // 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) && (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+]. |
| |