1

@ManagedBean is deprecated so I used recommended CDI replacement @Named with its javax.faces.view.ViewScoped annotation (not the JSF javax.faces.bean.ViewScoped one).

PROBLEM

Bean behaves as @ApplicationScoped that is @PostConstruct is being invoked on app deploy and then never gets invoked again i.e. I do not see @PostConstruct invocation on page visit/refresh.

If I switch back to JSF annotations i.e. @ManagedBean + javax.faces.bean.ViewScoped bean works as expected.

I have also tried @Named + org.omnifaces.cdi.ViewScoped as listed in How to replace @ManagedBean / @ViewScope by CDI in JSF 2.0/2.1 but the result was same as with javax.faces.view.ViewScoped (OmniFaces 2.6.2).

LONG STORY SHORT

This is a JSF + Spring integration problem (4.3.1.RELEASE).


DETAILS

Application is running on Wildfly 11.0.0.

  • specTitle: JSR-000344: JavaServer(TM) Faces 2.2 API
  • specVersion: 2.2
  • specVendor: Oracle
  • implTitle: JavaServer(TM) Faces 2.2 API
  • 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; }
}

View (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

After Kukeltje's suggestion I have looked at bean's creation call-stack. Somehow Spring manages bean creations. This is a stack-trace if I throw an exception from the TestBean constructor.

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

I checked configs and found registering of custom Spring @Scope("view") implementation (something similar to this but without callbacks handling) which is used in project beans (@Controller + @Scope("view") - probably bad design). I think this has nothing to do with given problem, but for completness, this is how applicationContext.xhtml looks like:

<?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>

This is probably root of the problem:

@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...
}

It seems, that Spring's CDI clashes with application's CDI. Have you any suggestion what should I do?

matoni
  • 2,171
  • 17
  • 33
  • 1
    Did you add `@ViewScoped` to your bean? I have a bean with `@Named` and `@ViewScoped` and it works as expected. – K.Nicholas May 15 '19 at 16:37
  • @K.Nicholas I've tested it again - same result. – matoni May 15 '19 at 16:49
  • I tried it and I'm not seeing any problems. The method `onPostConstruct()` is called on every GET request. – K.Nicholas May 15 '19 at 18:03
  • If you set a breakpoint in the constructor and run in debug mode, where does the call originate? – Kukeltje May 15 '19 at 18:25
  • Oh and should the metadata be around the `preRenderComponent` event? Never used that construct – Kukeltje May 15 '19 at 18:26
  • @Kukeltje Thanks for your suggestion, It helped me to identify cause of the problem, even though I do not know how to cope with it. – matoni May 15 '19 at 19:41
  • 1
    Step 1: remove the omnifaces tag and add the spring tag (or drop using spring all together ;-)) And 2: I have no clue, support stops for me here since I never used nor will never use Spring (pure java-ee here), sorry. But effectively, this is not a JSF problem either, since all scopes and annotations are for CDI and not JSF. And afaik, Spring does not do/know CDI, it knows the JSR-299 annotations (@Named), but does not know the JSF(CDI) Scopes iirc. so the JSF viewscope is unknown and it might fall back to a default or something... – Kukeltje May 15 '19 at 20:53
  • Even if this is for spring Boot, it might help you : https://stackoverflow.com/questions/46187725/spring-boot-jsf-integration – Xtreme Biker May 15 '19 at 21:17
  • @XtremeBiker Thanks, I will check. – matoni May 15 '19 at 21:19

0 Answers0