简体   繁体   中英

Eager ApplicationScoped managed beans constructed multiple times

I have a bunch of eager ApplicationScoped managed beans. Some of them are injected into others by the ManagedProperty annotation, forming a tree of dependencies. Each depending bean manipulates its parent after construction.

However, it seems like a new instance is created for each injection, thus making previous manipulations undone. To my understanding, an ApplicationScoped bean should only be created once. Have I misunderstood or why is this happening? Is it because they are eager?

Here is an example:

ParentBean.java

package example;

import javax.annotation.PostConstruct;
import javax.faces.bean.ApplicationScoped;
import javax.faces.bean.ManagedBean;

@ManagedBean(eager = true)
@ApplicationScoped
public class ParentBean
{
    static int initCount = 0;

    // ...

    @PostConstruct
    public void init()
    {
        ++initCount; // Will end up being between 1 and 3. Expected always 1.

        // ...
    }
}

Child1Bean.java

package example;

import javax.annotation.PostConstruct;
import javax.faces.bean.ApplicationScoped;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;

@ManagedBean(eager = true)
@ApplicationScoped
public class Child1Bean
{
    @ManagedProperty("#{parentBean}") ParentBean parentBean;

    public ParentBean getParentBean()
    {
        return parentBean;
    }

    public void setParentBean(ParentBean parentBean)
    {
        this.parentBean = parentBean;
    }

    @PostConstruct
    public void init()
    {
        // manipulate parentBean
    }
}

Child2Bean.java

package example;

import javax.annotation.PostConstruct;
import javax.faces.bean.ApplicationScoped;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;

@ManagedBean(eager = true)
@ApplicationScoped
public class Child2Bean
{
    @ManagedProperty("#{parentBean}") ParentBean parentBean;

    public ParentBean getParentBean()
    {
        return parentBean;
    }

    public void setParentBean(ParentBean parentBean)
    {
        this.parentBean = parentBean;
    }

    @PostConstruct
    public void init()
    {
        // manipulate parentBean
    }
}

I have hopefully resolved this problem on Tomcat 8 + Mojarra 2.2.0. In my case I just removed listener declaration from web.xml

<listener>
    <listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>

Constructor seems to be called once afterwards.

About listener entry, there is a part of BalusC answer of this question.

In any case, the explicit registration of Mojarra's ConfigureListener in web.xml is actually only necessary to workaround old buggy servers such as GlassFish v3 and Jetty who failed to find the listener in Mojarra's TLD file. When deployed to a decent server, the whole entry is unnecessary.

I have same problems with Mojarra 2.0.x. I guess that problem is connected with multithreaded JSF initilization. Try disabling it by com.sun.faces.enableMultiThreadedStartup parameter.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM