У цій статті розглянемо EJB – Enterprise JavaBeans. Ця технологія є частиною специфікації Java EE. Ми торкнемося таких питань, як:
- що таке EJB;
- якою є історія виникнення EJB;
- які є типи EJB.
Коротка історія EJB
У далекому 1996 році, коли автору цієї статті було 5 років, Java вже мала популярність серед розробників. Причиною тому були доброзичливі API, автоматичне складання сміття, і т.д. Java широко використовувалася в системах, що відповідали за бекенд. Однак, незважаючи на всі принади мови, програмісти того часу потребували певного функціоналу, ще не реалізованого в JDK. Такими потребами були:- забезпечення персистентності даних;
- цілісність транзакцій
- конкурентний доступ до даних (управління багатопоточністю);
- і, швидше за все, ще щось.
Що таке EJB
EJB у певному сенсі — збірний термін, який в залежності від контексту може мати на увазі під собою або саму технологію Enterprise JavaBeans загалом, або деякий конкретний програмний компонент (бін) Enterprise JavaBean, який є частиною технології EJB. Визначення EJB як технології наводиться на вікіпедії: Enterprise JavaBeans (також часто використовується у вигляді абревіатури EJB) - специфікація технології написання та підтримки серверних компонентів, що містять бізнес-логіку. Є частиною Java EE. Ця технологія зазвичай застосовується, коли бізнес-логіка вимагає щонайменше один з наступних сервісів, а часто всі з них:- підтримка безпеки даних (persistence): дані повинні бути в безпеці навіть після зупинки програми. Найчастіше досягається з використанням бази даних;
- підтримка розподілених транзакцій;
- підтримка паралельної зміни даних та багатопоточність;
- підтримка подій;
- підтримка іменування та каталогів (JNDI);
- безпека та обмеження доступу до даних;
- підтримка автоматизованої установки на сервер додатків;
- віддалений доступ.
Типи EJB
Резюмуємо. EJB - це звичайний Java клас, відзначений однією зі спеціальних анотацій. Такі класи називають бінами. Залежно від того, якою анотацією відзначений клас, він буде представником того чи іншого типу EJB (бінів). Є три основні типи бінів:- Message Driven Beans (біни, керовані повідомленнями);
- Entity Beans (об'єктні біни) – визначені у специфікації JPA (Java Persistence API) та використовуються для зберігання даних;
- Session Beans (сесійні біни).
- stateless (без стану);
- stateful (за допомогою поточного стану сесії);
- singleton (один об'єкт на всю програму; починаючи з версії EJB 3.1).
Session Beans
Session Beans, або сесійні біни – певний вид бінів. Вони інкапсулюють у собі бізнес-логіку, яку клієнт може програмно викликати через виклик методів цього бина. Виклик методу може виконати:- локально, іншим класом у тій же JVM, як і сесійний бін;
- віддалено, через мережу, з іншої JVM, за допомогою технології Java RMI (Remote Method Invocation).
@Stateless
. Наведемо приклад нижче:
import javax.ejb.Stateless;
@Stateless
public class StatelessEjbExample {
public String sayHi() {
return "Hi, I'm Stateless EJB!";
}
}
Сесійні біни з підтримкою поточного стану сесії (Stateful) зберігають інформацію про свій стан між зверненнями до нього від одного й того самого клієнта та завершують своє існування за явним запитом від клієнта. Досягається це за рахунок того, що статеві біни унікальні для кожного клієнта. Приклад завдання, за яке може відповідати такий тип бінів, - підтримка в актуальному стані кошика покупок в інтернет-магазині для кожного користувача. Життєвим циклом цих бінів управляє контейнер EJB. Ці біни також знищуються, коли клієнт завершує свою роботу. Подібні біни теж досить просто творити. Це Java клас, позначений інструкцією Stateful
. Приклад нижче:
import javax.ejb.Stateful;
@Stateful
public class StatefulEjbExample {
public String sayHi() {
return "Hi, I,m Stateful EJB";
}
}
Сесійні біни одинаки (singleton) ініціюються один раз за час існування програми та існують весь час "життя" програми. Такі біни розробляються для ситуацій, у яких один стан має бути поділений між усіма клієнтами. Подібно до stateless бінам, в бінах одиночках розробнику необхідно стежити за організацією потокобезпечного середовища всередині бина. Наведемо приклад Singleton Біна, який також простий у створенні як і його побратими, про які йшлося вище. Неважко здогадатися, що це Java-клас з інструкцією @Singleton
. Однак у разі необхідно бути уважним. Є дві інструкції, ідентичні за синтаксисом, але різні за призначенням і розташовані в різних пакетах:
- javax.ejb.Singleton
- javax.inject.Singleton
javax.ejb
. Приклад нижче:
import javax.ejb.Singleton;
@Singleton
public class SingletonEjbExample {
public String sayHi() {
return "Hi, I'm Singleton EJB!";
}
}
Message Driven Beans
Message Driven Beans, або MDB, або біни керовані повідомленнями, подібно до сеансових бін реалізують деяку бізнес-логіку. Але, на відміну від своїх родичів, у MDB є одна важлива відмінність. Клієнти ніколи не викликають методи MDB безпосередньо. Такі біни найчастіше виступають у ролі слухачів JMS (Java Message Service) повідомлень і є для організації асинхронного обміну повідомленнями між частинами системи. Прикладом такого повідомлення є запит на доставку товарних запасів від автоматизованої системи роздрібної торгівлі до системи управління поставками. Нижче наведемо приклад MDB Біна. На відміну від сесійних бінів, його створення трохи цікавіше:import javax.annotation.Resource;
import javax.ejb.MessageDriven;
import javax.ejb.MessageDrivenContext;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
@MessageDriven(mappedName = "jms/TestQueue")
public class MessageDrivenEjbExample implements MessageListener {
@Resource
private MessageDrivenContext messageDrivenContext;
public void onMessage(Message message) {
try {
if (message instanceof TextMessage) {
TextMessage msg = (TextMessage) message;
msg.getText();
}
} catch (JMSException e) {
messageDrivenContext.setRollbackOnly();
}
}
}
Анотація MessageDriven
робить наш клас MDB біном. Усередині анотації за допомогою JNDI (читайте про JNDI тут ) визначається ім'я JMS розсилки, слухачем якої стає наш клас. Крім цього, наш клас реалізує інтерфейс MessageListener
та його метод onMessage
. Даний метод буде викликаний, коли прийде деяке повідомлення із черги/розсилки з ім'ям, визначеним усередині анотації MessageDriven
.
Entity beans
Частиною технології EJB є JPA специфікація. JPA, або Java Persistence API – це специфікація, яка забезпечує об'єктно-реляційне відображення (ORM – Object-Relational Mapping) Java об'єктів (Entity бінів) та надає API для збереження, отримання та управління такими об'єктами. JPA дозволяє подавати дані з БД у вигляді Java-об'єктів, а також зберігати Java-об'єкти у вигляді записів у базі даних. У ролі подібного об'єкта може виступати не кожен клас, а саме Entity біни. Entity Bean - це Java клас, який відображає деяку таблицю в базі даних. Відображення (мапінг) досягається за рахунок використання спеціальних анотацій. З їхньою допомогою здійснюється зіставлення Java-класу з таблицею у базі даних, і навіть зіставлення полів Java-класу з полями таблиці БД. Наведемо приклад Entity Біна,@Entity // Делает данный класс Entity бином
@Table(name = "employee") // "Связывает" данный класс с таблицей employee в БД
public class Employee implements Serializable {
@Id // Говорит о том, что поле ниже является первичным ключом
@GeneratedValue(strategy = GenerationType.AUTO) // Определяет тип генерации значений первичного ключа
private int id;
@Column(name="name") // "Связывает" поле ниже с полем name в таблице employee в БД
private String name;
@Column (name="age") // "Связывает" поле ниже с полем age в таблице employee в БД
private int age;
// getters and setters...
}
Варто зазначити, що цей тип бінів має сенс вивчати лише у контексті вивчення специфікації JPA.
Пишемо додаток: EJB HelloWorld
У цьому розділі ми напишемо невелику Java EE HelloWorld програму, яку розгорнемо на сервері GlassFish. Перед прочитанням цієї статті настійно рекомендується прочитати статтю про налаштування локального оточення .-
Створюємо новий Maven проект у IntelliJ IDEA.
File -> New -> Project...
-
Натискаємо Next .
-
Заповнюємо параметри Maven проекту:
-
Натискаємо Finish
-
Проект створено та має таку структуру:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.codegym.lectures</groupId>
<artifactId>ejb_demo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
</dependency>
</dependencies>
</project>
Далі можна розпочинати Java-код. Наш додаток буде найпростішим. У нас буде 1 сервлет та 1 EJB. Це буде сесійний бін без збереження стану (stateless). Усередині EJB ми визначимо лише один метод, який повертатиме рядок “Hello World”. Насамперед створимо пакет com.codegym.lectures
. Потім, усередині пакету com.codegym.lectures
, створимо наш бін – DemoEJB. Код біна наведено нижче:
import javax.ejb.Stateless;
@Stateless
public class DemoEJB {
public String helloWorld() {
return "Hello world!";
}
}
Як було сказано раніше, все досить просто. Наш наступний крок — створити сервлет, який передаватиме значення з EJB як відповідь на HTTP-запит. Варто зазначити, що сервлети не належать до теми цієї статті, але для демонстрації EJB все ж таки доведеться їх використовувати. Для цього створимо новий сервлет DemoServlet
у тому пакеті, що і EJB. Його код нижче:
@WebServlet("/helloWorld")
public class DemoServlet extends HttpServlet {
@EJB
private DemoEJB ejb;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write(ejb.helloWorld());
}
}
Наведемо невеликі коментарі до коду. Анотація @WebServlet("/helloWorld")
— визначає наш клас як сервлет, який оброблятиме HTTP запити на ендпоінт /helloWorld
. У нашого класу є одне поле DemoEJB ejb
. Це наш бін, визначений раніше. Анотація над полем класу @EJB
здійснює ін'єкцію залежності (DI). Тобто. Змінна ejb автоматично ініціалізується новим екземпляром, коли це буде потрібно. Наш клас є спадкоємцем HttpServlet і перевизначає один із методів суперкласу - doGet
. Даний метод обробляє HTTP GET запити і приймає два параметри - HttpServletRequest
і HttpServletResponse
. HttpServletRequest
служить для отримання інформації про запит, що надійшов HTTP. HttpServletResponse
необхідний формування відповіді запит. Всередині методу ми отримуємо об'єкт PrintWriter
у об'єкта відповіді (HttpServletResponse
), за допомогою методу getWriter()
. Далі ми можемо записати в отриманий об'єкт деяке значення за допомогою методу write
. Чим, власне, ми і користуємося, записуючи в об'єкт PrintWriter
-а значення, отримане з визначеного нами EJB (значення - рядок "Hello World!"). Дане значення клієнт, який надіслав HTTP-запит, отримає як відповідь на свій запит. Наступним кроком є запуск програми на Java EE сервері GlassFish. Для цього створимо нову конфігурацію, як описано в статті про налаштування локального оточення . Нижче скрін готової конфігурації для поточного проекту. Переконайтеся, що у вас встановлено сервер GlassFish перед запуском: Після створення конфігурації запуску - запускаємо програму за допомогою меню Run -> Run 'ejb_demo' або за допомогою хоткеюShift+F10 . Після запуску можна побачити його логи: А також браузер, що відкрився: Все це говорить про те, що додаток працює, як замислювалося.
Висновок
У цій статті ми знайомабося з EJB – Enterprise JavaBeans. Розглянули такі питання, як:- Що таке EJB?
- Історія EJB
- Різні типи EJB
- Message Driven Beans (біни, керовані повідомленнями);
- Entity Beans (об'єктні біни) - визначені в специфікації JPA (Java Persistence API) entities та використовуються для зберігання даних;
- Session Beans (сесійні біни):
- stateless (без стану)
- stateful (за допомогою поточного стану сесії)
- singleton (один об'єкт на всю програму; починаючи з версії EJB 3.1)
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ