JSF @ViewScoped - @Postconstruct вызывается несколько раз
Метод postConstruct @Named bean, управляемый CDI, вызывается несколько раз для каждого просмотра при обновлении страницы в браузере. Однако @PreDestroy никогда не вызывается.
Метод @Postconstruct, вызываемый несколько раз в управляемом CDI bean-компоненте @Viewscoped, - это старая проблема со многими предложениями, как решить эту проблему. Многие из них можно найти здесь, на переполнении стека. Я перепробовал их все, но ни один из них не помог.
Я даже создал простой проект с одним бином, чтобы помочь каждому воспроизвести проблему. Его можно найти на GitHub.
я пробовал
- Проверена версия реализации JSF Mojarra 2.2.12
- Проверенная версия WELD (2.3.2)
- Проверенные аннотации (обе аннотации из пакета CDI)
- Развертывание на разных серверах приложений (Wildfly 9, WildFly 10, Payara 4.1.1.161_1) - ничего не получалось.
- Проверил страницу XHTML и привязки. Не работал.
- javax.faces.PARTIAL_STATE_SAVING - опять не сработало.
- Нет исключений ViewExpired
- В пути к классам нет других банок (включенных в WAR). Существует только предоставленная зависимость JEE-7. Сама WAR имеет только 2,6 кБ.
- Используются симпатичные лица или любые другие рамки (см. Предыдущий пункт).
Компонент CDI-Managed выглядит следующим образом:
package com.viewscopetest;
import javax.annotation.PostConstruct;
import javax.inject.Named;
import javax.faces.view.ViewScoped;
import java.io.Serializable;
@Named
@ViewScoped
public class TestViewBean implements Serializable {
private String hello;
public String getHello() {
return hello;
}
public void setHello(String hello) {
this.hello = hello;
}
@PostConstruct
private void postConstruct() {
hello = "Hello";
System.out.println("Again");
}
}
Вид выглядит так:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<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:form id="test">
<h:outputLabel value="#{testViewBean.hello}"/>
</h:form>
</html>
Есть почти пустые лица-config.xml
<?xml version='1.0' encoding='UTF-8'?>
<faces-config version="2.2" 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/web-facesconfig_2_2.xsd">
</faces-config>
И очень простой web.xml
<web-app
version="3.1"
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/web-app_3_1.xsd">
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.xhtml</welcome-file>
</welcome-file-list>
</web-app>
Наконец, очень простая конфигурация 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>
Все эти файлы конфигурации хранятся в папке WEB-INF (beans.xml, face-config.xml, web.xml).
Больше ничего в действительности нет в папке. Вот некоторые сведения об окружающей среде (взяты из журнала WildFly 9).
[2016-05-07 12:29:46,379] Artifact Gradle : com.test : viewscopetest-0.1.war: Artifact is being deployed, please wait...
12:29:46,532 INFO [org.jboss.as.server.deployment] (MSC service thread 1-7) WFLYSRV0027: Starting deployment of "viewscopetest-0.1.war" (runtime-name: "viewscopetest-0.1.war")
12:29:46,825 INFO [org.jboss.weld.deployer] (MSC service thread 1-5) WFLYWELD0003: Processing weld deployment viewscopetest-0.1.war
12:29:46,871 INFO [org.hibernate.validator.internal.util.Version] (MSC service thread 1-5) HV000001: Hibernate Validator 5.2.3.Final
12:29:47,003 INFO [org.jboss.weld.deployer] (MSC service thread 1-6) WFLYWELD0006: Starting Services for CDI deployment: viewscopetest-0.1.war
12:29:47,029 INFO [org.jboss.weld.Version] (MSC service thread 1-6) WELD-000900: 2.3.2 (Final)
12:29:47,078 INFO [org.jboss.weld.deployer] (MSC service thread 1-3) WFLYWELD0009: Starting weld service for deployment viewscopetest-0.1.war
12:29:47,766 INFO [javax.enterprise.resource.webcontainer.jsf.config] (ServerService Thread Pool -- 58) Initializing Mojarra 2.2.12-jbossorg-2 20150729-1131 for context '/viewscopetest-0.1'
12:29:48,085 INFO [org.wildfly.extension.undertow] (ServerService Thread Pool -- 58) WFLYUT0021: Registered web context: /viewscopetest-0.1
12:29:48,099 INFO [org.jboss.as.server] (management-handler-thread - 2) WFLYSRV0010: Deployed "viewscopetest-0.1.war" (runtime-name : "viewscopetest-0.1.war")
[2016-05-07 12:29:48,113] Artifact Gradle : com.test : viewscopetest-0.1.war: Artifact is deployed successfully
[2016-05-07 12:29:48,113] Artifact Gradle : com.test : viewscopetest-0.1.war: Deploy took 1 735 milliseconds
Проблема в том, что bean-компонент @VieScoped ведет себя как объект в области запроса. При обновлении страницы я ожидаю повторного использования компонента вместо его повторного создания и повторного вызова метода @PostConstruct.