CDI
С версии JSF 2.3.0 стандартная аннотация
@ManagedBean
признана устаревшей. Т.е. чтобы обратиться к своему Java-коду из формы нам потребуется добавить в проект CDI (Context and Dependency Injection) — Weld.В файл
pom.xml
добавляем: <dependencies>
...
<dependency>
<groupId>org.jboss.weld.servlet</groupId>
<artifactId>weld-servlet</artifactId>
<version>2.4.3.Final</version>
</dependency>
</dependencies>
Создадим файл
/src/main/webapp/WEB-INF/beans.xml
:<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
bean-discovery-mode="all">
</beans>
Там прям особая специфика в регистрации listener'а?
ОК! В файл
/src/main/webapp/WEB-INF/web.xml
добавляем:<web-app ...
<listener>
<listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
</listener>
...
</web-app>
Запускаем:
mvn jetty:run
Читаем
Создадим файл
/src/main/webapp/WEB-INF/jetty-env.xml
:<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN"
"http://www.eclipse.org/jetty/configure.dtd">
<Configure id="webAppCtx" class="org.eclipse.jetty.webapp.WebAppContext">
<Call name="prependServerClass">
<Arg>-org.eclipse.jetty.server.handler.ContextHandler</Arg>
</Call>
<Call name="prependServerClass">
<Arg>-org.eclipse.jetty.servlet.FilterHolder</Arg>
</Call>
<Call name="prependServerClass">
<Arg>-org.eclipse.jetty.servlet.ServletContextHandler</Arg>
</Call>
<Call name="prependServerClass">
<Arg>-org.eclipse.jetty.servlet.ServletHolder</Arg>
</Call>
<New id="BeanManager" class="org.eclipse.jetty.plus.jndi.Resource">
<Arg>
<Ref id="webAppCtx"/>
</Arg>
<Arg>BeanManager</Arg>
<Arg>
<New class="javax.naming.Reference">
<Arg>javax.enterprise.inject.spi.BeanManager</Arg>
<Arg>org.jboss.weld.resources.ManagerObjectFactory</Arg>
<Arg/>
</New>
</Arg>
</New>
</Configure>
В файл
/src/main/webapp/WEB-INF/web.xml
добавляем:<web-app ...
<resource-env-ref>
<resource-env-ref-name>BeanManager</resource-env-ref-name>
<resource-env-ref-type>javax.enterprise.inject.spi.BeanManager</resource-env-ref-type>
</resource-env-ref>
...
</web-app>
Теперь вместо
@ManagedBean
будет работать @Named
. Учитывая что CDI штука хорошая, а с версии JSF 2.3.0 — критичная, стоит понимать что CDI в JSF используется по своему прямому назначению и к JSF непосредственно отношения не имеет.Больше к CDI мы возвращаться не будем!
Классы FormData и FormCtrl
Теперь давайте напишем немного кода. Нам потребуется 2 класса — в 1-ом мы будем передавать данные, во 2-ом будет функция обработки этих данных.
Класс-данных
/src/main/java/ru/habr/FormData.java
:package ru.habr;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
@Named
@RequestScoped
public class FormData {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
Класс-обработчик
/src/main/java/ru/habr/FormCtrl.java
:package ru.habr;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.inject.Named;
@Named
@RequestScoped
public class FormCtrl {
@Inject
FormData formData;
public String doAction() {
// Очень полезные действия с данными...
System.out.println(formData.getUsername());
System.out.println(formData.getPassword());
return null;
}
}
Если с
FormData
все понятно, то на FormCtrl
стоит взглянуть пристальней:- Благодаря
@Inject
, данные формы будут доступны в классе-обработчике в полеformData
. - Рекомендую придерживаться тезиса «метод-обработчик должен возвращать строку» хоть это и не обязательно. Строка в дальнейшем используется в навигации, но об этом позже.
Форма
Тут все просто! В файл
/src/main/webapp/index.xhtml
добавляем:<h:body>
...
<h:form id="habrForm">
<h:inputText value="#{formData.username}"/><br/>
<h:inputSecret value="#{formData.password}"/><br/>
<h:commandButton action="#{formCtrl.doAction}" value="Send">
</h:commandButton>
</h:form>
</h:body>
Запускаем:
mvn jetty:run
Проверяем:
http://127.0.0.1:8080/
AJAX
На дворе 2017 год, а формы все еще без AJAX?! В файл
/src/main/webapp/index.xhtml
внесем пару правок:<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
...
<h:body>
...
<h:inputText value="#{formData.username}"/><br/>
<h:inputSecret value="#{formData.password}"/><br/>
<h:commandButton action="#{formCtrl.doAction}" value="Send">
<f:ajax execute="@form" render="@form"/>
</h:commandButton>
</h:body>
</html>
Что изменилось:
- Добавилось определение библиотеки тегов
xmlns:f="http://xmlns.jcp.org/jsf/core"
. Без этого можно реализовать AJAX, но обрабатывать придется ручками, что долго и неблагодарно. - Внутри
h:commandButton
появился<f:ajax execute="@form" render="@form"/>
. Вexecute
— указываем что необходимо отправить на сервер (всю форму/все поля формы), вrender
— что необходимо обновить с сервера после выполнения AJAX.
Про
f:ajax
можно писать отдельный. Сейчас достаточно знать только что с его помощью можно отправить/обновить не только текущую форму на странице, а любой элемент страницы.Послесловие
Проект все еще очень скромен в своих возможностях, но я буду продолжать!
Комментарии (6)
Apx
04.06.2017 16:52Подождём немного до того как автору понадобятся конверсейшн и вью скоуп бины. Тогда возможно придёт осознание того что пора перестать тревожить древнее зло и взять что-то свеженькое и интересное.
MaximusWork
05.06.2017 07:02Извините пожалуйста. Но может быть вы мне подскажете на что стоит смотреть из свежего из интересного? Spring? Или что-то другое. Просто начал интересоваться этой темой. Но выбрать из сегодняшнего множества — очень сложно. Спасибо заранее.
Apx
05.06.2017 15:32Да можно махнуть в последний спринг со своими интеграциями с клаудом и распределением. Ui уже давно на js и тоже можно организовать server rendering если тяготеет к нему душа. Если же в вашей задаче ещё есть и рендер в зависимости от ролей пользователя то можно ещё и тут хорошо так поломать голову если список ролей в js, на ваш взгляд, это плохая идея
jbubsk
04.06.2017 19:19Хочется верить, что это какие-то садисты с включенным паяльником заставили человека написать про JSF.
Koobeton