views:

34

answers:

1

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:)

A: 

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.

BalusC
Okay now I get that I update my lastName to new lastName, but the value isn't updated in the model. The lastName is still Lindhardt.
AnAmuser
Ah yes, I see. Sorry, I don't see any other problems in the information provided as far. There may be more into your original code. Why did you think that the parameter is the cause of the problems? Are you suggesting that it works when you remove `rendered="#{param.change}"` and the `<input name="change">`?
BalusC
I don't know yet. Just did something similar on all the pages without a parameter and there is no problem. Here i can see that this.lastName is set to new lastName in phase 4 and then in phase 5 it is back to Lindhardt. :(
AnAmuser
There must have been more into the action method than you have shown in the question.
BalusC
No there isn't. It just refuses to set the new value of lastName. And there is no errors.
AnAmuser
I copypasted your code, emptied the `changeName()` method, updated the `setLastName()`, opened it by `test.jsf?change=name`, altered the fields, submitted it and it prints the expected values: get old name, set new name, get new name. Sorry, there must be more into your code/environment. I'd say, run the IDE debugger and let it track the `lastName` field so that you can see who/what is accessing/modifying it.
BalusC
It looks like the constructor is called in every phase so that the value is set to the old value in every phase. Should it be doing that.
AnAmuser
No, it shouldn't be doing that. Did you debugging the constructor calls?
BalusC
I set a field breakpoint on lastName and then i landed in my constructor from phase 3 and on wards. I just tried deleting the two line this.lastName=user.getLastName(); but Lindhardt is still my lastName.
AnAmuser
Weird. May be related to `@Named` and CDI. Try replacing it by the normal JSF `@ManagedBean`.
BalusC
Hurray:) That's it.Don't know why i suddenly had that @named.
AnAmuser
You're welcome. Looking back, I should have mentioned that I didn't use it as well while testing your snippet, but I really didn't expect it to be the cause. Might be a misconfiguration in CDI stuff.
BalusC