0

what I have is jsf page that shows users in a table, one of the columns is commandbutton, that hides that table and shows another table with all articles that that user has.Here things are OK. The articles table again has column with commandbuttons that has to hide that table and show the article content, but it shows the user table. In my bean I have 3 properties

    private Boolean usersViewActive;
    private Boolean articlesViewActive;
    private Boolean articleContentViweActive;

and methods that activate one of them and deactivate the others

    public void activateUsersView() {
        this.usersViewActive = true;
        this.articlesViewActive = false;
        this.articleContentViweActive=false;
    }

    public void activateArticleView() {
        this.usersViewActive = false;
        this.articlesViewActive = true;
        this.articleContentViweActive = false;
    }

    public void activateArticleContentView() {
        this.articleContentViweActive = true;
        this.usersViewActive = false;
        this.articlesViewActive = false;
    }

My bean

@ManagedBean
@RequestScoped
public class DataBean {
    private List<UserAcc> users;
    private List<Article> articles;
    private List<ArticleComment> articleComments;

    private Article currentArticle;

    private Boolean usersViewActive;
    private Boolean articlesViewActive;
    private Boolean articleContentViweActive;

    public DataBean() {
        DataBaseUtil dbu = new DataBaseUtil();
        users = dbu.loadUsers();
        this.usersViewActive = true;
    }

    public void activateUsersView() {
        this.usersViewActive = true;
        this.articlesViewActive = false;
        this.articleContentViweActive=false;
    }

    public void activateArticleView() {
        this.usersViewActive = false;
        this.articlesViewActive = true;
        this.articleContentViweActive = false;
    }

    public void activateArticleContentView() {
        this.articleContentViweActive = true;
        this.usersViewActive = false;
        this.articlesViewActive = false;
    }

    public void loadArticles(ActionEvent e) {
        DataBaseUtil dbu = new DataBaseUtil();
        int userId = (Integer) e.getComponent().getAttributes().get("userId");
        articles = dbu.loadUserArticles(userId);
    }

    public void loadComments(ActionEvent e) {
        DataBaseUtil dbu = new DataBaseUtil();
        int articleId = (Integer) e.getComponent().getAttributes()
                .get("articleId");
        articleComments = dbu.loadArticleComments(articleId);
    }

    public void loadCurrentArticle(ActionEvent e) {
        DataBaseUtil dbu = new DataBaseUtil();
        int articleId = (Integer) e.getComponent().getAttributes()
                .get("articleId");
        this.currentArticle = dbu.loadArticleById(articleId);
    }

  Getters and Setters...
}

My Page:

<h:body>
    <h:panelGroup rendered="#{loginBean.authorised}">
        User: <h:outputText value="#{loginBean.name}"></h:outputText>
        <a href="new_article.jsf">Add article</a>
    </h:panelGroup>
    <h:panelGroup rendered="#{not loginBean.authorised}">
        <h:outputText>You are not authorised to be here!</h:outputText>
        <a href="index.jsf">Login or Registrate</a>
    </h:panelGroup>

    <h:form>
        <h:panelGroup rendered="#{loginBean.authorised}">

            <!--                    All users -->
            <h:panelGroup rendered="#{dataBean.usersViewActive}">
                <rich:dataTable value="#{dataBean.users}" var="user" rows="10">
                    <f:facet name="header">Users</f:facet>
                    <rich:column>
                        <f:facet name="header">User Id</f:facet>
                        <h:outputText value="#{user.id}"></h:outputText>
                    </rich:column>
                    <rich:column>
                        <f:facet name="header">User Name</f:facet>
                        <h:outputText value="#{user.name}"></h:outputText>
                    </rich:column>
                    <rich:column>
                        <h:commandButton value="Show articles"
                            action="#{dataBean.activateArticleView}"
                            actionListener="#{dataBean.loadArticles}">
                            <f:attribute name="userId" value="#{user.id}"></f:attribute>
                        </h:commandButton>
                    </rich:column>
                    <f:facet name="footer">
                        <rich:dataScroller></rich:dataScroller>
                    </f:facet>
                </rich:dataTable>
            </h:panelGroup>

            <!--                    All articles -->
            <h:panelGroup rendered="#{dataBean.articlesViewActive}">
                <h:commandButton value="Back to users"
                    action="#{dataBean.activateUsersView}"></h:commandButton> 
                <rich:dataTable value="#{dataBean.articles}" var="article" rows="10">
                    <f:facet name="header">Articles</f:facet>
                    <rich:column>
                        <f:facet name="header">Article Id</f:facet>
                        <h:outputText value="#{article.id}"></h:outputText>
                    </rich:column>
                    <rich:column>
                        <f:facet name="header">Article Title</f:facet>
                        <h:outputText value="#{article.title}"></h:outputText>
                    </rich:column>
                    <rich:column>
                    <!-- Here is the problem  -->
                    <!-- This button renders all users instead article content -->
                        <h:commandButton value="Show article content and comments" 
                        action="#{dataBean.activateArticleContentView}"
                        actionListener="#{dataBean.loadCurrentArticle}">
                            <f:attribute name="articleId" value="#{article.id}"></f:attribute>
                        </h:commandButton>
                    </rich:column>
                    <f:facet name="footer">
                        <rich:dataScroller></rich:dataScroller>
                    </f:facet>
                </rich:dataTable>
            </h:panelGroup>

                <!-- Article content -->
            <h:panelGroup rendered="#{dataBean.articleContentViweActive}">
                <h:outputText value="#{dataBean.currentArticle.title}"></h:outputText>
                <h:outputText value="#{dataBean.currentArticle.text}"></h:outputText>
            </h:panelGroup>
        </h:panelGroup>
    </h:form>

</h:body>
Evgeni Dimitrov
  • 21,976
  • 33
  • 120
  • 145

1 Answers1

3

Your bean is request scoped and you aren't maintaining/preserving the value behind rendered attribute for the subsequent request. All those values defaults to false when a fresh new request scoped bean is constructed upon form submit. The commandbutton's action won't be invoked when the rendered attribute evaluates false during the form submit. JSF will namely test it once again before processing the form submit.

Put the bean in the view scope.

@ManagedBean
@ViewScoped
public class DataBean implements Serializable {
    // ...
}

This way the bean lives as long as you're interacting with the same view by returning void or null in action methods.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • When change it to ViewScoped I get this "No saved view state could be found for the view identifier: /content.jsf" when click on click commandbutton in the Users table – Evgeni Dimitrov May 04 '11 at 13:21
  • What a vague error. Google leans me that it is coming from MyFaces. I don't use it (I use Mojarra only) and I *guess* that you need to let the bean implement serializable. This is by the way also mandated by Mojarra, but it emits a more clear warning message for that *before* the bean is fully constructed. – BalusC May 04 '11 at 13:31
  • 1
    @JustinKSU: question concerns JSF2, so the answer definitely assumes JSF2. If you're *still* on JSF1, look for alternate ways like http://stackoverflow.com/questions/5897262/jsf-1-2-how-to-keep-managed-bean-with-request-scope/5897322#5897322 or ask a new question if you stucks. – BalusC Sep 06 '12 at 19:09
  • I didn't see JSF2 in the question. Thanks for the link to the other page. I just gave up and switched to Session scope, but the t:saveState will do exactly what I need. Thanks for the help. – JustinKSU Sep 06 '12 at 21:22
  • @Justin: `@ManagedBean`, ``, etc are JSF2 specific. – BalusC Sep 06 '12 at 23:41