JSF @ViewScoped ведет себя как @ApplicationScoped - PullRequest
0 голосов
/ 15 мая 2019

@ManagedBean является устаревшим , поэтому я использовал рекомендованную замену CDI @Named с ее javax.faces.view.ViewScoped аннотацией (не JSF javax.faces.bean.ViewScoped) .

ПРОБЛЕМА

Бин ведет себя как @ApplicationScoped, то есть @PostConstruct вызывается , вызывается при развертывании приложения , а затем никогда не вызывается снова т.е. я не вижу @PostConstruct вызов при посещении страницы / обновить.

Если я вернусь к аннотациям JSF, т.е. @ManagedBean + javax.faces.bean.ViewScoped bean работает как положено .

Я также пытался @Named + org.omnifaces.cdi.ViewScoped, как указано в Как заменить @ManagedBean / @ViewScope на CDI в JSF 2.0 / 2.1 , но результат был таким же, как с javax.faces.view.ViewScoped (OmniFaces 2.6.2).

КОРОТКО ДОЛГОЙ ИСТОРИИ

Это проблема интеграции JSF + Spring (4.3.1.RELEASE).


Подробнее 1049 *

Приложение работает на Wildfly 11.0.0 .

  • specTitle : JSR-000344: API JavaServer (TM) Faces 2.2
  • specVersion : 2,2
  • specVendor : Oracle
  • implTitle : API JavaServer (TM) Faces 2.2
  • implVersion : 2.2.13 implVendor: JBoss by Red Hat

Bean

import javax.annotation.PostConstruct;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
import java.io.Serializable;

@Named
@ViewScoped
public class TestBean implements Serializable {

    private String text;

    @PostConstruct
    private void onPostConstruct() { /* ... */ }
    public void init() { /* ... */ }
    public void onCommandButton() { /* ... */ }

    public String getText() { return text; }
    public void setText(String text) { this.text = text; }
    public String getOutput() { return text; }
}

Просмотр (PrimeFaces 6.0.18)

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:p="http://primefaces.org/ui">

    <h:head>
    </h:head>

    <h:body>
        <f:event type="preRenderComponent" listener="#{testBean.init}"/>

        <h:form id="form">
            <p:inputText id="text" value="#{testBean.text}"/>
            <h:outputText id="output" value="#{testBean.output}" />
            <p:commandButton value="SUBMIT" 
                    action="#{testBean.onCommandButton}" 
                    update="output"/>
        </h:form>
    </h:body>
</html>

EDIT

После Kukeltje я рассмотрел стек вызовов создания бина. Каким-то образом Spring управляет созданием бобов . Это трассировка стека, если я сгенерирую исключение из конструктора TestBean.

Constructor threw exception; nested exception is java.lang.RuntimeException: TestBean
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1105)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1050)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:775)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:861)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:541)
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:444)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:326)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:107)
    at io.undertow.servlet.core.ApplicationListeners.contextInitialized(ApplicationListeners.java:187)
    at io.undertow.servlet.core.DeploymentManagerImpl$1.call(DeploymentManagerImpl.java:205)
    at io.undertow.servlet.core.DeploymentManagerImpl$1.call(DeploymentManagerImpl.java:174)
    at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:42)
    at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
    at org.wildfly.extension.undertow.security.SecurityContextThreadSetupAction.lambda$create$0(SecurityContextThreadSetupAction.java:105)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1508)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1508)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1508)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1508)
    at io.undertow.servlet.core.DeploymentManagerImpl.deploy(DeploymentManagerImpl.java:239)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentService.startContext(UndertowDeploymentService.java:99)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentService$1.run(UndertowDeploymentService.java:81)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266)
    at java.util.concurrent.FutureTask.run(FutureTask.java)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
    at org.jboss.threads.JBossThread.run(JBossThread.java:320)

    Constructor threw exception; nested exception is java.lang.RuntimeException: TestBean
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:159)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:89)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1098)
    ... 33 more

Я проверил конфиги и нашел регистрацию пользовательской реализации Spring @Scope("view") (что-то похожее на this , но без обработки обратных вызовов), которая используется в bean-компонентах проекта (@Controller + @Scope("view") - вероятно, плохой дизайн ). Я думаю, что это не имеет никакого отношения к данной проблеме, но для полноты, вот как выглядит applicationContext.xhtml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:task="http://www.springframework.org/schema/task"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd">

    <context:annotation-config/>

    <context:property-placeholder location="classpath*:application.properties" ignore-unresolvable="true"/>
    <context:property-placeholder location="classpath*:versionInfo.properties"/>

    <task:annotation-driven executor="myExecutor" scheduler="myScheduler"/>
    <task:executor id="myExecutor" pool-size="5"/>
    <task:scheduler id="myScheduler" pool-size="10"/>

    <bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
        <property name="scopes">
            <map>
                <entry key="view">
                    <bean class="path.to.custom.ViewScope"/>
                </entry>
            </map>
        </property>
    </bean>
</beans>

Вероятно, это корень проблемы:

@Configuration
@ComponentScan(basePackages = "path.to.beans.base.package")
@ImportResource({"/WEB-INF/hibernate-config.xml", "/WEB-INF/applicationContext.xml"})
@PropertySource(value={"classpath:application.properties"}, ignoreResourceNotFound = true)
@Import( SecurityConfig.class )
public class WebConfig {
    // nothing more...
}

Кажется, что Spring CDI конфликтует с CDI приложения. Есть ли у вас предложения, что мне делать?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...