Search code examples
javajsflifecycle

Jsf updates model value with old value


I am having some problems updating to the right value. On the page which you can see part of down under, there is a parameter 'change'. I think that this parameter is causing jsf to update the backing bean with the old value and thus do nothing.

<h:panelGroup id="panel0">
            <h:form id="changeForm">
                <h:messages/>
                <!--This retains the parameter "change"-->
                <input type="hidden" name="change" value="#{param.change}"/>
                <!--CHANGE NAME-->
                <h:panelGrid id="panel1" rendered="#{param.change == 'name'}" columns="2">
                    First Name:
                    <h:inputText id="firstName" value="#{changeInfoBean.firstName}"/>
                    Last Name:
                    <h:inputText id="lastName" value="#{changeInfoBean.lastName}"/>
                     <f:facet name="footer">
                        <h:panelGroup style="display:block; text-align:center">
                            <h:commandButton value="Submit Name" action="#{changeInfoBean.changeName}"/>
                        </h:panelGroup>
                    </f:facet>
                </h:panelGrid>
          </h:form>
    </h:panelGroup>

I have also tried having the two inputText fields set to immediate="true" but this will not work either.

My backing bean:

@Named(value="changeInfoBean")
@SessionScoped
public class ChangeInfoBean {

    private String email;
    private String firstName;
    private String lastName;

    /** Creates a new instance of ChangeInfoBean */
    public ChangeInfoBean() {
            FacesContext context = FacesContext.getCurrentInstance();
            // Gets the user which is currently logged in
            LoginBean bean = (LoginBean) context.getExternalContext().getSessionMap().get("loginBean");
            BasicUser user = bean.getUser();
            this.email = user.getEmail();
            this.firstName = user.getFirstName();
            this.lastName = user.getLastName();

    }

    public void changeName() {
        Session session = null;
        try {
            session = HibernateUtil.getSessionFactory().openSession();
            Transaction tx = session.beginTransaction();
            String hql = "update BasicUser set firstName = :newFirstName, lastName = :newLastName "
                    + "where email = :email";
            Query query = session.createQuery(hql);
            query.setString("newFirstName", this.firstName);
            query.setString("newLastName", this.lastName);
            query.setString("email", this.email);
            int rowCount = query.executeUpdate();
            tx.commit();
            System.out.println("Rows affected: " + rowCount);
            }
            catch(Exception e) {
                e.printStackTrace();
            }
            finally {
                session.close();
            }
    }
    public String getLastName() {
        System.out.print("I am getting my lastName: " + this.lastName);
        return lastName;
    }

    public void setLastName(String lastName) {
        System.out.print("I am updating my lastName to: " + this.lastName);
        this.lastName = lastName;
    }
}

When I try to change my lastName from Lindhardt to something new I get this

INFO: START PHASE RESTORE_VIEW 1
INFO: END PHASE RESTORE_VIEW 1
INFO: START PHASE APPLY_REQUEST_VALUES 2
INFO: END PHASE APPLY_REQUEST_VALUES 2
INFO: START PHASE PROCESS_VALIDATIONS 3
INFO: I am getting my lastName: Lindhardt
INFO: END PHASE PROCESS_VALIDATIONS 3
INFO: START PHASE UPDATE_MODEL_VALUES 4
INFO: I am updating my lastName to: Lindhardt
INFO: END PHASE UPDATE_MODEL_VALUES 4
INFO: START PHASE INVOKE_APPLICATION 5
INFO: Hibernate: update coffeedrinkers.basic_user set First_Name=?, Last_Name=? where Email=?
INFO: Rows affected: 1
INFO: END PHASE INVOKE_APPLICATION 5
INFO: START PHASE RENDER_RESPONSE 6
INFO: I am getting my lastName: Lindhardt
INFO: END PHASE RENDER_RESPONSE 6

So the backing bean never recieves the new lastName but just updates the model with the old lastName. Isn't that weird:)


Solution

  • With this you're referencing the current instance's variable, not the local (passed-in) variable. You're printing the current instance's variable before it has been set with the passed-in variable, while your interest is rather the passed-in one.

    public void setLastName(String lastName) {
        System.out.print("I am updating my lastName to: " + this.lastName);
        this.lastName = lastName;
    }
    

    Change it to

    public void setLastName(String lastName) {
        System.out.print("I am updating my lastName to: " + lastName);
        this.lastName = lastName;
    }
    

    or

    public void setLastName(String lastName) {
        this.lastName = lastName;
        System.out.print("I am updating my lastName to: " + this.lastName);
    }
    

    and it'll print the right one.


    Update: as per the comments, the above only fixes the problem partly. After all, still the wrong value is been persisted/redisplayed. This seems to be related to the CDI's @Named annotation. It caused the bean to be seemingly resonctructed on every phase of the JSF lifecycle. Replacing it by JSF standard @ManagedBean annotation did fix the issue.