В данном уроке хочу вам показать как создать web-приложение используя возможности Glassfish и EJB3.
В этом уроке хочу вас научить работать с EJB, почему сервер Glassfish, во первых мне с ним удобней работать, ну и в Glassfish мы будем хранить все настройки в нашем случае – это настройки доступа к базе данных.
Шаг 0
1. Скачиваем Glassfish.
Glassfish скачать
Теперь создаем проект в Intellij IDEA – File -> New Project -> Maven Module
2. Скачиваем MySQL Server скачать
После скачивания устанавливаем, ставим пароль root. И создаем базу, называем её devcolibri.
Шаг 1
Добавляем зависимости в pom.xml
<dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.25</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>4.2.1.Final</version> </dependency> <dependency> <groupId>org.hibernate.javax.persistence</groupId> <artifactId>hibernate-jpa-2.0-api</artifactId> <version>1.0.1.Final</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>3.0-alpha-1</version> <scope>provided</scope> </dependency> <dependency> <groupId>javaee</groupId> <artifactId>javaee-api</artifactId> <version>5</version> </dependency> <dependency> <groupId>javax</groupId> <artifactId>javaee-web-api</artifactId> <version>6.0</version> <scope>provided</scope> </dependency> </dependencies>
mysql
– нужен для получения доступа к базе данных;
org.hibernate
– будет использоваться с его контейнера entitymanager, который обеспечит удобную работу с БД;
org.hibernate.javax.persistence
– будет использоваться в связке с hibernate;
javax.servlet
– этим, мы даем возможность приложению создавать Servlet-ы;
javaee
– даст возможность реализовать клиент-сервер приложение;
javaee-web-api
– эта зависимость обеспечит возможность сделать наше приложение Web-приложением используя необходимые API;
entitymanager
– используется для работы с одной бизнес операцией, и без необходимости не открывает connection.
Пример работы с Hibernate Mapping можно посмотреть в этом уроке ‘Как работать с MySQL в Java — Hibernate XML Mapping‘
И еще нам потребуется два maven plugin-а:
<plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.5</source> <target>1.5</target> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>2.1.1</version> <configuration> <failOnMissingWebXml>false</failOnMissingWebXml> </configuration> </plugin> </plugins>
Шаг 2
Теперь давайте создадим Entity (сущность) для работы с базой данных.
Создаем класс User.java
package com.devcolibri.entity; import javax.persistence.*; @Entity(name = "users") @NamedQuery(name = "User.getAll", query = "SELECT u from User u") public class User { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE) @Column(name = "user_ID") private long id; @Column(name = "first_name", nullable = false) private String name; @Column(name = "last_name", nullable = false) private String lastName; @Column(name = "age", nullable = false) private int age; public User() { } public User(String name, String lastName, int age) { this.name = name; this.lastName = lastName; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
Дальше нам нужно создать EntityManager, но для начало настроим Glassfish.
Шаг 3
Что именно мы будем настраивать в glassfish?
Мы будем настраивать JDBC Connection.
Если вы только установили Glassfish, то он у вас уже запущен, нам нужно его остановить. Для этого идем туда где он установлен, если вы ничего не меняли, то он должен лежать в корне диска C:/glassfish4, и после в папку bin там есть файл asadmin.bat запускайте его. Появится консоль, там вы должны написать следующую команду, чтобы остановить glassfish:
stop-domain domain1
Как проверить запущен ли сервер?
Для этого откройте браузер и просто напишите в URL -> localhost:4848, если вы увидите вход в админку glassfish то сервер запущен.
После того как вы остановили сервер идем в папку C:\glassfish4\glassfish\domains\domain1\lib\ext и копируем туда MySQLJDBCDriver, его можно найти в
C:\Users\devcolibri\.m2\repository\mysql\mysql-connector-java\5.1.25\mysql-connector-java-5.1.25.jar
Это нужно Glassfish для того чтобы получать connection к базе данных, так как за все транзакции будет отвечать glassfish то ему нужен данный драйвер.
Дальше открываем asadmin.bat и запускаем сервер следующей командой:
start-domain domain1
После этого идем в браузер по URL -> localhost:4848 и логинимся admin, пароль admin.
Открываем в пункте меню вкладку JDBC -> JDBC Connection Pool.
Или вместо этого, что мы настраивали выше можно добавить в консоли asadmin.bat следующей командой эти данные.
Для JDBC Connection Pool эта (все в одну строку):
create-jdbc-connection-pool --datasourceclassname com.mysql.jdbc.jdbc2.optional.MysqlDataSource --property user=root:password=root:DatabaseName=devcolibri:ServerName=localhost:port=3306:Encoding=UTF-8 MySQL-Pool
и для JDBC Resources:
create-jdbc-resource --connectionpoolid MySQL-Pool jdbc/devcolibri
На этом настройка законченна!
Шаг 4
В проекте заходим в папку src/resources/ и создаем там новую папку META-INF и добавляем туда файл persistence.xml, теперь мы настроим наш персистенс на контейнер Glassfish-а.
<?xml version="1.0" encoding="UTF-8" ?> <persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"> <persistence-unit name="DEVMODE" transaction-type="JTA"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <jta-data-source>jdbc/devcolibri</jta-data-source> <exclude-unlisted-classes>false</exclude-unlisted-classes> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/> <property name="hibernate.hbm2ddl.auto" value="update"/> </properties> </persistence-unit> </persistence>
в строке 9 есть атрибут name=’DEV’ – это имя persistence-unit по этому имени будет фабрика будет создавать EntityManager.
В уроке ‘JPA работа с базой данных‘ уже рассматривалась работа с JPA.
Шаг 5
Создаем Bean для этого создадим класс UserBean.java и проаннотируем его аннотацией @Stateless.
Аннотация @Stateless указывает, что это будет бин без сохранения состояния между вызовами методов.
package com.devcolibri.bean; import com.devcolibri.entity.User; import javax.ejb.Stateless; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.TypedQuery; import java.util.List; @Stateless public class UserBean { // Будет инициализирован контейнером Glassfish // unitName = "DEVMODE" - это имя persistence-unit // EntityManager дает возможность выполнять CRUD запросы в БД @PersistenceContext(unitName = "DEVMODE") private EntityManager em; // Добавляем User-а В базу данных public User add(User user){ return em.merge(user); } // Получаем пользователя по id public User get(long id){ return em.find(User.class, id); } // обновляем пользователя // если User которого мыпытаемся обновить нет, // то запишется он как новый public void update(User user){ add(user); } // удаляем User по id public void delete(long id){ em.remove(get(id)); } // Получаем все пользователей с БД public List<User> getAll(){ TypedQuery<User> namedQuery = em.createNamedQuery("User.getAll", User.class); return namedQuery.getResultList(); } }
Шаг 6
Создаем Servlet который будет работать с данным бином, который мы создали выше.
Назовем его MainServlet.java он будет выводить все пользователей:
package com.devcolibri.servlet; import com.devcolibri.bean.UserBean; import com.devcolibri.entity.User; import javax.ejb.EJB; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.List; @WebServlet("/list") public class MainServlet extends HttpServlet{ // Аннотация говорит о том, // что данный объект будет инициализирован // контейнером Glassfish DI @EJB private UserBean userBean; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // Получаем список пользователей List<User> allUser = userBean.getAll(); // добавляем полученный список в request, // который отправится на jsp req.setAttribute("users", allUser); // отправляем request на jsp req.getRequestDispatcher("/list.jsp").forward(req, resp); } }
И теперь создадим jsp страницу которая будет выводить полученный список пользователей на Servlet-е.
Создадим list.jsp тут src\main\webapp\list.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <html> <head> <title>Список пользователей</title> </head> <body> <h3>Все пользователи:</h3>(<a href="add">добавить</a>) <ol> <c:forEach items="${users}" var="user"> <li> ${user.name} ${user.lastName} - ${user.age} <a href="add?edit=${user.id}">редактировать</a> | <a href="delete?id=${user.id}">удалить</a> </li> </c:forEach> </ol> </body> </html>
Шаг 7
Добавим сервлет, который будет добавлять новых пользователей, а также он будет редактировать пользователей.
Создадим сервелет AddAndEditUserServlet.java:
package com.devcolibri.servlet; import com.devcolibri.bean.UserBean; import com.devcolibri.entity.User; import javax.ejb.EJB; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/add") public class AddAndEditUserServlet extends HttpServlet { @EJB private UserBean userBean; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); req.setCharacterEncoding("UTF-8"); // если параметр null, то пользователь // пришел на страницу, чтобы создать нового, иначе // будет выполнятся редактирование существующего пользователя if(req.getParameter("edit") != null){ long id = Long.valueOf(req.getParameter("edit")); User user = userBean.get(id); req.setAttribute("user", user); } req.getRequestDispatcher("/add.jsp").forward(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); req.setCharacterEncoding("UTF-8"); String name = req.getParameter("name"); String lastName = req.getParameter("lastName"); int age = Integer.valueOf(req.getParameter("age")); // если id есть, то выполняется редактирование // а если нет id, то - это значит, что создается новый пользователь if(req.getParameter("id") != ""){ long id = Long.valueOf(req.getParameter("id")); User user = userBean.get(id); user.setAge(age); user.setLastName(lastName); user.setName(name); // обновляем пользователя userBean.update(user); } else{ // добавляем нового userBean.add(new User(name, lastName, age)); } // перенаправляем на сервлет, который выводит все пользователей resp.sendRedirect("list"); } }
и JSP для этого сервлета:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Добавление | Редактирование</title> </head> <body> <form action="add" method="post"> <label for="name">Введите имя: <input type="text" id="name" value="${user.name}" name="name" /> </label> <br /> <label for="last-name">Введите фамилию: <input type="text" id="last-name" value="${user.lastName}" name="lastName" /> </label> <br /> <label for="age">Введите возвраст: <input type="text" id="age" value="${user.age}" name="age" /> </label> <br /> <input type="hidden" name="id" value="${user.id}" /> <input type="submit" value="Сохранить" /> </form> </body> </html>
Шаг 8
И последний сервлет это для удаления пользователя, и назовем его DeleteUser.java:
package com.devcolibri.servlet; import com.devcolibri.bean.UserBean; import javax.ejb.EJB; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/delete") public class DeleteUser extends HttpServlet { @EJB private UserBean userBean; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { if(req.getParameter("id") != null && req.getParameter("id") != ""){ long id = Long.valueOf(req.getParameter("id")); userBean.delete(id); } resp.sendRedirect("list"); } }
Шаг 9
Теперь собираем проект с помощью Maven:
После этого в папке проекта появится папка target и там будет собранный проект с расширением *.war
Шаг 10
Теперь деплоим (Deploy).
Deploy – это развертывание проекта на сервере приложений.
Заходим в glassfish http://localhost:4848/ потом в меню Application -> Deploy
После удачного деплоя вы можете зайти на свое приложение:
http://localhost:8080/EJBGlassfishJPA-1.0/list
В результате получится это:
P.S. Спасибо за внимание! Надеюсь я вам помог.
ПОХОЖИЕ ПУБЛИКАЦИИ
- None Found
22 комментариев к статье "Web-приложение с использованием EJB3 + Glassfish и JPA2"
Добавить комментарий
Для отправки комментария вам необходимо авторизоваться.
В idea довольно объемная инфраструктура для создания ear приложений, было бы очень интересно почитать про концепцию работы с такими проектами в этой ide, принятый порядок подключения модулей, сборки, работу с встроенными вайзардами, инкрементное обновление ear архива и т.д. Сама ide, с не привычки немного не очевидна :) родная их дока довольно скромна на примеры, а все сторонние статьи в основном больше про мавен чем про идею, а с мавеном проблем то как раз нет, по нему книг и статей написано немерено :) Да если можно, выложите пожалуйста собранный правильно с вашей точки зрения ear проект в idea на что-нибудь вроде гитхаба, было бы интересно посмотреть :)
Есть неточность в связке между Шагом 4 и 5. Не правильно указанно имя PersistenceContext.
Спасибо за исправление. Поправил.
А куда, делся урок по сборке модульного ear архива? :)
Автор который его делал решил уйти и забрал урок :) Скоро мы напишем урок по данной теме!
Отличная статья. Очень помогла мне.
req.getParameter(“id”) != “” а может .equals() ? Скачал проект кроме добаления
primer ne rabotaet na glassfish4.0
Очень интересная статья, я не знаком с EJB, поэтому читал интересом, но к сожалению у меня запустить не получилось, и при написании своего приложения “по инструкции” и запуск ваших исходников. Сервер выдает ошибку javax.ejb.EJBException. Как считаете возможно в чем может быть проблема.
Я не тестировал на Glassfish 4 попробуйте на Glasfish 3
Да вы правы, на версии 3.1.2 все прекрасно работает, несопоставимость сервера и EJB возможно связанна с версиями данных зависимостей?
javaee
javaee-api
5
javax
javaee-web-api
6.0
provided
”
MySQLJDBCDriver, его можно найти в
C:\Users\devcolibri\.m2\repository\mysql\mysql-connector-java\5.1.25\mysql-connector-java-5.1.25.jar
”
исправьте ссыль, ведь на моём компьютере нет пользователя “devcolibri”
В строчке @Column(name = “user_ID”) – user_id подчеркиваеться красным, что за?
Весь гугл перелопатил, не найдк=у ошибку(
Пример не работает на базе postgrisql.
Внес корректировки в сущность User:
@Entity
@Table(name = “users”)
и только тогда заработало
Проблема с glassfish решена тут
https://coderwall.com/p/e5fxrw/use-hibernate-4-3-x-with-jta-on-glassfish-4
нужно поменять версию
org.hibernate
hibernate-entitymanager
4.3.0.Final
в persistence.xml указано новое значение в поле provider
org.hibernate.jpa.HibernatePersistenceProvider
и добавить в properties
…
*.war
может *.jar ?
Деплой падает с ClassNotFoundException: org.hibernate.ejb.HibernatePersistence
Glassfish 3.1.2
Делаю всё в точности с инструкцией, но при деплое валится с ошибкой: Error occurred during deployment: Exception while preparing the app : java.lang.ClassNotFoundException: org.hibernate.ejb.HibernatePersistence. В чем может быть дело?
Все работает, но при сохранении пользователя в базу данных выдает java.lang.NumberFormatException: For input string: “”.
Отрицание условия нужно поставить у if(!””.equals(req.getParameter(“id”))) в com/devcolibri/servlet/AddAndEditUserServlet.java:44
Очень полезная статья, даже в 2017 году :) спасибо кицька :*
Подскажите, как его собрать, и что размещать на хосте, не весь же проект, а то написал что мне нужно, на локале работает збс, но в сеть что выкладывать для релиза