Это то, что я всегда думал. Ну, не больше, сейчас. Позвольте мне поделиться своим опытом.
Несколько недель назад я начал думать о переносе устаревшего приложения spring + hibernate + tomcat на новую платформу:
SAP NetWeaver Cloud . Я знаю, о чем вы думаете, придурки: этот пост ухудшается. Он начинается с Java EE, не совсем вызывающий, и теперь входит в SAP , а не просто вундеркинд… Пожалуйста, дайте мне еще десять минут!
Конфигурация весеннего слоя моего старого приложения была основана на xml (она была написана до появления аннотаций в игре). Я боялся перспективы погрузиться в — мой собственный — ужас XML снова.
Затем появился этот твит:
и через несколько дней эта документация . И я попробовал это. И это сработало. И я передумал о Java EE. В блоге Билла Водопроводчика есть пост, который точно описывает мои мысли после этого опыта.
Так много с бла бла бла. Давайте начнем кодировать! Если вы спешите, клонируйте полное приложение по адресу https://github.com/cthiebaud/adventscloud.
Перед тем как вырезать и вставить как сумасшедший, давайте кратко опишем, о чем код ниже Мы создадим и развернем в облаке (бесплатно) крошечное веб-приложение, которое:
1. входит в систему пользователя (извините, вам понадобится учетная запись SAP Community Network , не волнуйтесь, это бесплатно),
2. при входе в систему скажите «привет» остальному миру от имени пользователя,
3. при последующих входах в систему вместо того, чтобы снова и снова говорить «привет», просто сохраните в базе данных, сколько было сказано «привет», и
4. вот и все.
Для этого нам понадобится один интерфейс Java, три класса Java, одна страница сервера Java, а также последний штрих в файлах persistence.xml (для конфигурации базы данных) и web.xml (для мастера ограничения безопасности).
Для краткости, пакеты, импорт, получатели и установщики опущены в коде ниже. Но, как только что сказано, полный исходный код доступен @ github
Напишите один Hello.java POJO (полный класс здесь ):
|
1
2
3
4
5
6
7
8
|
public class Hello { private Long id; private String username; private Integer counter; private Timestamp when; // ... getters and setters ...} |
Совершенно очевидно: для каждого username этот POJO будет хранить в counter сколько раз пользователь нажимал index.jsp нашего приложения и when было в последний раз.
Аннотируйте это Hello.java POJO с аннотациями JPA (полный класс здесь ):
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
@Entity@Table(name="T_HELLO")@NamedQueries( { @NamedQuery(name = "allHellos", query = "select h from Hello h"), @NamedQuery(name = "helloFromUsername", query = "select h from Hello h where h.username = :username")})public class Hello { @Id @GeneratedValue private Long id; @Column(name="A_USER", unique=true, nullable=false) private String username; @Column(name="A_COUNTER", nullable=false) private Integer counter; @Version @Column(name="A_TIMESTAMP", nullable=false) private Timestamp when; public Hello() { this.counter = 1; } // ... getters and setters ...} |
Напишите один интерфейс HelloDao.java, который обращается к POJO (полный интерфейс здесь )
|
1
2
3
4
5
6
7
|
@Localpublic interface HelloDao { List<hello> getAll(); Hello fromUsername(String username); Hello save(Hello hello);} |
Напишите один HelloBean.java, аннотированный аннотациями EJB, который реализует интерфейс HelloDao (полный класс здесь ):
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
@Statelesspublic class HelloBean implements HelloDao { @PersistenceContext private EntityManager em; @Override public List<hello> getAll() { @SuppressWarnings("unchecked") List<hello> hellos = (List<hello>)em.createNamedQuery("allHellos").getResultList(); Collections.sort(hellos, new Comparator<hello>() { @Override public int compare(Hello o1, Hello o2) { return o2.getWhen().compareTo(o1.getWhen()); // latest first } }); return hellos; } @Override public Hello fromUsername(String username) { Query query = em.createNamedQuery("helloFromUsername"); query.setParameter("username", username); Hello hello = null; try { hello = (Hello)query.getSingleResult(); } catch (NoResultException ignored) { } return hello; } @TransactionAttribute @Override public Hello save(Hello hello) { hello = em.merge(hello); return hello; }} |
Напишите один фильтр Java Servlet 3 HelloFilter.java, который: 1. увеличивает счетчик при входе в систему, и 2. предоставляет экземпляр HelloBean на странице Java Server, которая скоро появится (полный класс здесь ):
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
@WebFilter("/index.jsp")public final class HelloFilter implements Filter { @EJB HelloDao helloDao; @Override public void init(FilterConfig fConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { try { request.setAttribute("helloDao", helloDao); String username = ((HttpServletRequest)request).getRemoteUser(); Hello hello = helloDao.fromUsername(username); if (hello == null) { hello = new Hello(); hello.setUsername(username); } else { hello.setCounter(hello.getCounter()+1); } hello = helloDao.save(hello); chain.doFilter(request, response); } finally { request.removeAttribute("helloDao"); } } @Override public void destroy() { }} |
NB. Выделено жирным шрифтом выше. Волшебная сантехника, выполненная нашим контейнером Java EE 6 Web Profile между всеми этими классами:
|
1
2
3
|
@PersistenceContext EntityManager em;@EJB HelloDao helloDao;@WebFilter('/index.jsp') |
Напишите одну конфигурацию JPA persistence.xml (заполните здесь xml)
|
01
02
03
04
05
06
07
08
09
10
11
12
|
<?xml version="1.0" encoding="UTF-8"?><persistence version="2.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_2_0.xsd"> <persistence-unit name="adventscloud-persist" transaction-type="JTA"> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> <jta-data-source>jdbc/DefaultDB</jta-data-source> <class>net.aequologica.adventscloud.Hello</class> <properties> <property name="eclipselink.ddl-generation" value="create-or-extend-tables" /> </properties> </persistence-unit></persistence> |
Напишите один файл web.xml, чтобы инициировать вход в систему при доступе пользователя к index.jsp и сообщить веб-приложению о наличии управляемой контейнером базы данных (заполните xml здесь ):
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
<?xml version="1.0" encoding="UTF-8"?><web-app xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> <login-config> <auth-method>FORM</auth-method> </login-config> <security-constraint> <web-resource-collection> <web-resource-name>Protected Area</web-resource-name> <url-pattern>/index.jsp</url-pattern> </web-resource-collection> <auth-constraint> <role-name>Everyone</role-name> </auth-constraint> </security-constraint> <security-role> <description>All SAP NetWeaver Cloud users</description> <role-name>Everyone</role-name> </security-role> <resource-ref> <res-ref-name>jdbc/DefaultDB</res-ref-name> <res-type>javax.sql.DataSource</res-type> </resource-ref></web-app> |
Опять же, NB. Выделено жирным шрифтом дальнейшая волшебная сантехника:
|
1
2
3
|
<jta-data-source>jdbc/DefaultDB</jta-data-source><class>net.aequologica.adventscloud.Hello</class><res-ref-name>jdbc/DefaultDB</res-ref-name> |
Наконец, напишите одну страницу java-сервера index.jsp, которая отображает все «hellos» (полная страница здесь ):
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %><%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt_rt" %><!DOCTYPE html><html> <head> <title>adventscloud</title> </head> <body> <table> <tbody> <c:forEach var="hello" items="${requestScope.helloDao.all}" varStatus="status"> <tr> <td><fmt:formatDate type="both" value="${hello.when}" /></td> <td>${hello.counter}</td> <td>hello<c:if test = "${hello.counter > 1}">(s)</c:if> from</td> <td>${hello.username}</td> </tr> </c:forEach> </tbody> </table> </body></html> |
Мы почти закончили … две последние вещи: 1. ад classpath и 2. генерация метамодели JPA 2.0 с javac -процессором.
1. Classpath ад.
Чтобы скомпилировать все это, вам нужно как-то иметь следующие jar-файлы на classpath:
группа | артефакт | версия javax.persistence: постоянство-API :> = 1,0 javax.ejb: ejb-api :> = 3.0 javax.servlet: javax.servlet-api :> = 3.0 javax.servlet: jstl :> = 1.2
Конечно, самый простой способ — объявить эти зависимости в проекте maven, подобном моему , но если вы не любите maven, я потратил время на гиперссылку на jar-файлы выше на maven central, чтобы сэкономить время на погоне за jar-файлами.
2. Генерация метамодели JPA 2.0 с помощью javac -процессора.
Наконец, сборка должна быть способна генерировать классы метамодели JPA 2.0 . Здесь я выбираю генератор eclipselink, поскольку в конечном итоге eclipselink является реализацией JPA, используемой SAP NetWeaver Cloud. Я считаю, что любой JPA 2.0-совместимый генератор должен делать эту работу также. Здесь также помогает maven со следующим фрагментом xml в разделе <build> <plugins> файла pom.xml:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
<plugin> <groupId>org.bsc.maven</groupId> <artifactId>maven-processor-plugin</artifactId> <version>2.1.0</version> <executions> <execution> <id>process</id> <goals> <goal>process</goal> </goals> <phase>generate-sources</phase> <configuration> <processors> <processor>org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProcessor</processor> </processors> </configuration> </execution> </executions></plugin> |
Maven- averse может обратиться к документации eclipselink о генерации метамодели JPA 2.0 для альтернативных способов генерации классов метамодели JPA 2.0.
На данный момент у нас есть файл adventscloud.war, который должен дословно выполняться в любом контейнере, совместимом с Java EE 6 Web Profile .
Среди них — SAP NetWeaver Cloud. Вы можете взглянуть на приложение, запущенное в моей бесплатной пробной версии SAP NetWeaver Cloud . Это немного богаче, чем код, показанный в этом сообщении в блоге, с искрой щебетать наворотов и свистки. Следуйте GitHub ленты в приложении, если вас интересуют искры.
Если вы хотите получить пробный экземпляр SAP NetWeaver Cloud в течение всей жизни, выполните начальные шаги, описанные здесь .
Ссылка: веб-профиль Java EE 6. На облаке. Легко. от нашего партнера по JCG Кристофа Тибо из блога Java Advent Calendar .

