5
votes

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
    }
}
2
can you give a code example of how you do it?Aksel Willgert
don't think i will do any change , but try @ManagedProperty(value = "#{parentBean}") ,Daniel
The expressions are equivalent, but I tried. No change.Spomf
I don't have any injections and get the same problem with Tomcat7.0.53 / Mojarra 2.2.6. My app scope eager bean is constructed 3 times. Non eager ones are constructed only once.Panu Haaramo

2 Answers

1
votes

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.

0
votes

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.