0

I've got this page, I have two forms on. The second form is loaded (rendered) by ajax. The problem is, that when button of the next form is pressed, the page just reloads itself, not actually calling the method specified in 'action'.

XHTML

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
                template="./../WEB-INF/employeeTemplate.xhtml"
                xmlns:h="http://java.sun.com/jsf/html"
                xmlns:f="http://java.sun.com/jsf/core"
                xmlns="http://www.w3.org/1999/xhtml">

    <ui:define name="content">
        finding user ...
        <h:form id="mainForm">
            <h:inputText id="userId" value="#{eFindUser.userId}" />
            <h:commandButton value="Render!" action="#{eFindUser.findUser}" >
                <f:ajax event="action" execute="userId" render="@all" />
            </h:commandButton>
        </h:form>        

        <h:panelGroup id="result">
            <h:panelGroup layout="block" rendered="#{eFindUser.notFound}" style="color:red">
                User not found
            </h:panelGroup>

            <h:form>
                <h:panelGroup layout="block" rendered="#{eFindUser.responseRendered}" >

                    <h:inputHidden value="#{eFindUser.user}" />
                    <table>
                        <tr>
                            <td>Name</td> <td>#{eFindUser.user.name}</td>
                        </tr>
                        <tr>
                            <td>Balance:</td> <td>#{eFindUser.user.account.balance}</td>
                        </tr>

                        <tr>
                            <td><h:commandButton value="update balance" action="#{eFindUser.process()}" /></td>
                        </tr>
                    </table>


                </h:panelGroup>
            </h:form>                        
        </h:panelGroup>



    </ui:define>

</ui:composition>

Backing bean

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package backingbeans;

import entities.User;
import java.io.Serializable;
import java.util.Random;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.inject.Inject;
import javax.validation.constraints.NotNull;
import stateless.EmployeeFacade;

/**
 *
 * @author Martin
 */
    @ManagedBean(name="eFindUser")
    @ViewScoped
    public class EFindUserManagedBean implements Serializable{
        private static final long serialVersionUID = -7106162864352727534L;
        private boolean responseRendered = false;
        private boolean notFound = false;
        @NotNull
        private Long userId;
        private User user;

        @Inject
        private EUpdateBalanceManagedBean updateBalance;

        @Inject
        private EmployeeFacade employeeFacade;

        /**
         * Creates a new instance of EFindUserManagedBean
         */

        public EFindUserManagedBean() {
        }

        public void findUser() {
            if(new Random().nextDouble() < 0.3) {
                notFound = true;
                responseRendered = false;
            } else {
                notFound = false;
                responseRendered = true;
                user = employeeFacade.getUserById(3L);
            }

        }
        public boolean isResponseRendered() {
            return responseRendered;
        }

        public void setResponseRendered(boolean responseRendered) {
            this.responseRendered = responseRendered;
        }

    public boolean isNotFound() {
        return notFound;
    }

    public void setNotFound(boolean notFound) {
        this.notFound = notFound;
    }

    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        System.out.println("blah");
        this.userId = userId;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        System.out.println("setting user");
        this.user = user;
    }


    public String process() {
        updateBalance.setUser(user);
        System.out.println("process");
        return "/employee/updateBalance.xhtml?faces-redirect=true";
    }

    }

When I click the first 'Render!'-labeled button, it works like charm. Second form is loaded and ready to work. When I click the next 'update balance'-labeled button, the page just reloads which it shouldn't, of course. It should redirect to "/employee/updateBalance". Or it should at least call the process method.

Thanks a lot

EDIT: @BalusC is right, the answer is in previous question

Martin P
  • 39
  • 1
  • 2
  • 7

2 Answers2

0

The culprit can be found in <h:inputHidden> tag of the second form:

<h:form>
    <h:panelGroup layout="block" rendered="#{eFindUser.responseRendered}" >
        <h:inputHidden value="#{eFindUser.user}" />
    </h:panelGroup>
</h:form>

Most probably its bound value, eFindUser.user is of type User and when you submit that form JSF doesn't know how to assign a string representation of user with a User object.

Hence, there is a conversion error, in which case action method is not called, according to JSF lifecycle. Additionally, you would have known that if you had <h:messages> in your view.

What can be done is the following:

  1. Assign converter to your input like <h:inputHidden value="#{eFindUser.user}" converter="userConverter"/> with a @FacesConverter implemented. More details can be found here.
  2. Bind <h:inputHidden> to a String, so that no converter would be needed: <h:inputHidden value="#{eFindUser.user.userNickname}"> or to an Integer in a similar way.
Community
  • 1
  • 1
skuntsel
  • 11,624
  • 11
  • 44
  • 67
0

modify <h:commandButton value="update balance" action="#{eFindUser.process()}" /> to <h:commandButton value="update balance" action="#{eFindUser.process}" /> el expression can't contain “()”

lee tan
  • 133
  • 2
  • 9