Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using request-scoped bean function as action for a temporary rendered button in JSF

Tags:

java

jsf

I have the following basic (and maybe stupid) understanding problem in JSF:

There is one JSF page "testPage.xhtml" :

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html">

<f:view>
<h:body>
<h:form>
    <h:commandLink id="B1" value="B1" action="#{testBean.ctrl}"/>

    <h:commandLink id="B2" value="B2" action="#{testBean.ctrl}"
            rendered="#{testBean.renderB2}"/>
</h:form>
</h:body>
</f:view>
</html>

And one backing bean "TestBean.java" :

package test;

import java.io.Serializable;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;

@ManagedBean(name="testBean")
@RequestScoped
public class TestBean implements Serializable {

    public static final long serialVersionUID = 1L;

    private boolean renderB2 = false;

    public String ctrl() {
            setRenderB2(true);

            System.out.println("ctrl() is called.");

            return null;
    }

    public boolean getRenderB2() {
            return renderB2;
    }

    public void setRenderB2(boolean renderB2) {
            this.renderB2 = renderB2;
    }
}

So both links have TestBean.ctrl() as action.

First only B1 is rendered. Clicking B1 causes execution of TestBean.ctrl() and B2 is rendered too.

However, clicking B2 then does not execute TestBean.ctrl().

And this is my question: Why is the action method not executed when clicking B2?

Probably it is because B2 is not rendered again.But why does that prevent the execution of the action method (called by the previously rendered B2 link)?

like image 957
hubba Avatar asked Aug 10 '11 14:08

hubba


1 Answers

That's because the rendered attribute is re-evaluated again during apply request values phase of the form submit. If an UIInput or UICommand component is not rendered at that point, then JSF won't apply the request values for the component. I.e. the UIInput component's model value will not be updated and the UICommand component's action will not be invoked.

Because your bean is request scoped, it's been trashed by end of the response which displays the form and a brand new one is been created by start of the request of the form submit.

You have to preserve any request scoped properties responsible for the rendered attribute. The easiest way is to place the bean in the view scope by marking it @ViewScoped and ensuring that you return null or void from action methods which should postback to the same view.

like image 51
BalusC Avatar answered Oct 14 '22 09:10

BalusC