简体   繁体   中英

Why are JSF ManagedBean methods executed more than once while they are intended to be executed only once?

While working with JSF in order to develop web applications using NetBeans, I many a times noticed that in some circumstances, the getter methods (and probably setters too) in JSF ManagedBeand are executed more than once while they are intended to be executed only once. In such a scenario, it is sometimes extremely crucial to enforce some critical conditions (if etc.) for some operations (especially some calculations) to prevent them from being overwhelmed. I had been keeping on trying to know the actual reason behind it but I could not.

Here, I'm demonstrating a very simple application in which a getter method namely

public Collection<entity.Country> getCountries(){};

calls a remote EJB and retrieves all countries from a relevant table in MySql database and displays on JSF page. A screen shot of the web page is simply looks as below.

There is no need to pay much and special attention to the screen shot, JSF page code and it's corresponding ManagedBean.

来自MySql数据库的所有国家。

Here is the JSF page code

<?xml version='1.0' encoding='UTF-8' ?>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core">

<h:head>
    <title>Countries</title>
</h:head>

<h:body>
    <h:form>
        <center><br/><br/><br/>

        <h:dataTable id="dataTable" styleClass="table" frame="box" value="#
             {country.countries}" var="row" bgcolor="lightyellow" border="7" 
             cellpadding="7" cellspacing="7" rules="all" width="50%" dir="ltr">

            <f:facet id="header" name="header">
                <h:outputText value="~:Country:~" styleClass="tableHeader"/>
            </f:facet>

            <h:column>
                <f:facet name="header">Country ID</f:facet>
                <h:outputText id="countryID" value="#{row.countryID}"/>
            </h:column>

            <h:column>
                <f:facet name="header">Country Name :</f:facet>
                <h:outputText id="countryName" value="#{row.countryName}"/>
            </h:column>

    </h:dataTable>
        </center>
    </h:form>
</h:body>
</html>

and the corresponding simple JSF ManagedBean code goes here.

package country;

import commonBean.CommomBeanRemote;
import java.util.Collection;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean; 
import javax.faces.bean.RequestScoped;

@ManagedBean
@RequestScoped

public class Country
{
    @EJB
    private CommomBeanRemote obj=null;
    private Collection<entity.Country>countries=null;

    public Country() {}

    public Collection<entity.Country> getCountries()
    {
        countries=obj.getAllCountries(); //Calls a remote EJB to retrieve the data.
        System.out.println("The Country() method called.");//Here this displays 8 times unnecessarily
        return countries;
    }

    public void setCountries(Collection<entity.Country> countries)
    {
        this.countries = countries;
    }

}

The dataTable in which the actual data are being displayed is bound to the countries property value="#{country.countries}" of the ManagedBean and it's corresponding getter and setter are as follows.

public Collection<entity.Country> getCountries()
{
    countries=obj.getAllCountries();
    System.out.println("The Country() method called.");
    return countries;
}

public void setCountries(Collection<entity.Country> countries)
{
    this.countries = countries;
}

The method countries=obj.getAllCountries(); retrieves data from remote EJB . I felt that posting the actual implementation of this method (Which in EJB) here is quite unnecessary. All of these is just to show what I'm trying to.

Now, my actual question is that public Collection<entity.Country> getCountries(){} is being executed unnecessarily 8 times while it is bound to execute only once which is extremely critical in some very specific situations.

I have tried this so many times while increasing and decreasing the number of rows being displayed still this method is always executed 8 times, why...???

Long story short: Why JSF calls getters multiple times

In this particular case, you should be using a @PostConstruct method instead to preload/initialize stuff retrieved from an injected business service, not a getter method.

@ManagedBean
@RequestScoped
public class Country {

    @EJB
    private CommomBeanRemote commonBeanRemote;
    private Collection<entity.Country> countries;

    @PostConstruct
    public void init() {
        countries = commonBeanRemote.getAllCountries();
    }

    public Collection<entity.Country> getCountries() {
        return countries;
    }

    // Setter is completely unnecessary here.
}

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