JSF Backing Bean constructor called multiple times
Asked Answered
A

4

5

I'm trying out JSF 2.0 (after using ICEfaces 1.8 for the past few months) and I'm trying to figure out why in JSF 2.0 my backing bean constructor gets called multiple times.

The bean is supposed to be instantiated once upon creation, but the "Bean Initialized" text shows up whenever I click the commandButton, indicating a new Bean object being instansiated.

The facelet page:

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

    <h:body>
        <div id="content">
            <h:form id="form">
                <h:commandButton value="Toggle" action="#{bean.toggleShowMe}"/>
            </h:form>


            <h:panelGrid rendered="#{bean.showMe}">
                <h:outputText value="Show me!"/>
            </h:panelGrid>
        </div>
    </h:body>
</html>

The backing bean:

@ManagedBean
@RequestScoped
public class Bean {
    private boolean showMe = false;

    public boolean isShowMe() {
        return showMe;
    }

    public void setShowMe(boolean showMe) {
        this.showMe = showMe;
    }

    public void toggleShowMe(){
        System.out.println(showMe);
        if(showMe==true){
            showMe=false;
        }else{
            showMe=true;
        }
    }
    /** Creates a new instance of Bean */
    public Bean() {
        System.out.println("Bean Initialized");
    }

}

Thats all it is. Just a simple test. The same behaviour shows itself if I use ICEfaces 2.0 and in place of the panelGrid I use:

<ice:panelPopup visible="#{bean.showMe}">

I'd appreciate any help here. I'm at a loss to explain it.

Update: In response to Aba Dov, I @SessionScoped the bean, figuring it wouldn't be calling the constructor upon each request and ran into the same behavior. What am I missing?

Abrupt answered 28/1, 2011 at 8:50 Comment(2)
If the component IS session scoped, it will not be created more than once per session - since this beahviour is widely used, the bug is probably in your code, not JSF; are you using @SessionScoped from the right package? (there are two in EE6).Healion
fdreger-I'm using javax.faces.bean.SessionScoped. Should I be using javax.enterprise.context.SessionScoped?Abrupt
J
6

You have declared the bean to be placed in the request scope and you're firing a new HTTP request everytime by the command button. Truly the bean will be created on every request.

If you want that the bean lives as long as the view itself (like as IceFaces is doing under the covers for all that ajax stuff), then you need to declare the bean view scoped (this is new in JSF 2.0).

@ManagedBean
@ViewScoped
public class Bean implements Serializable {}
Jdavie answered 28/1, 2011 at 12:39 Comment(5)
Thanks for the explanation! It works. Any suggestions for a good place to bone up on whats new JSF 2.0? The specifications are pretty heavy reading.Abrupt
Also watch out for code involving <c:forEach ...> and a list coming from a bean. This will call the constructor multiple times even when ViewScopedGotthard
@Chris: see also #2842901Jdavie
@Jdavie I should have read that post more in detail, found this the hard way. I do have problems with nested ui:repeat (#3708990). I really want to see JSF 2.2 come out to solve such issues.Gotthard
@Chris: state management of <ui:repeat> is severely broken in Mojarra. Use MyFaces or a 3rd party component library offering it in UIData flavor (e.g. <t:dataList>).Jdavie
H
2

In my case the problem was I imported "javax.faces.bean.ViewScoped" instead of importing "javax.faces.view.ViewScoped".

Hope it could help someone.

Hypozeuxis answered 1/10, 2018 at 8:47 Comment(1)
As mentioned in #5542313Tapley
P
0

The bean is called every time there is a request from the page.

when you click the <h:commandButton> the form is submitted and a request is sent to the server

in order to prevent it you can use <t:saveState> or <a4j:keepAlive> tags for your been.

for example <a4j:keepAlive beanName="YourBean" />

those tags stores the bean instance in the component tree .

also make sure that your class implements Serializable. so it can be serialized

Hope this helps

Proparoxytone answered 28/1, 2011 at 10:56 Comment(1)
In JSF 2 the viewscope does the work of keepAlive or saveStateGotthard
L
0

The bean should be in the ViewScoped.

Lyman answered 29/1, 2011 at 7:15 Comment(1)
What if you do not have the need to preserve the data for so long.. viewScoped works but not for free, it consumes memory on your server, why do you need to keep unneccesary data for so long ? Since the data is already requested by the bean will be already with the view what's the point of keeping the data in view scope, & why does JSF need to fire creation of all managed beans in the view when the commmandButton is pressed, why not just the actionListener bean is instantiated ?Ambrosial

© 2022 - 2024 — McMap. All rights reserved.