1

(Please view edit down below)

As a continuation of the code from this SO question, I am now trying to save the modified values of a <h:dataTable> using the persistance of the entity class.

I have a dataTable as follows:

<h:form>
    <h:dataTable id="userTable" value="#{admin.customerList}" 
                 var="c" 
                 binding="#{admin.customerTable}"<!-- Not sure if this is necessary -->
                 styleClass="gnomeTable"
                 headerClass="gnomeTableHeader"
                 rowClasses="gnomeTableOddRow,gnomeTableEvenRow"
                 bgcolor="#F1F1F1" border="10"  cellspacing="2"
                 rules="all" >           

        <f:facet name="header">
            <h:outputText value="All registered customers" />
        </f:facet> 

        <h:column>
            <f:facet name="header">
                <h:outputText value="User ID" />
            </f:facet> 
            <h:outputText value="#{c.id}"></h:outputText>
        </h:column>

        <h:column>
            <f:facet name="header">
                <h:outputText value="Username"/>
            </f:facet> 
            <h:outputText value="#{c.username}" rendered="#{not c.editable}"></h:outputText>
            <h:inputText value="#{c.username}" rendered="#{c.editable}"></h:inputText>
        </h:column>

        <h:column>
            <f:facet name="header">
                <h:outputText value="Email"/>
            </f:facet>
            <h:outputText value="#{c.email}" rendered="#{not c.editable}"></h:outputText>
            <h:inputText  value="#{c.email}" rendered="#{c.editable}"></h:inputText>
        </h:column>

        <h:column>
            <f:facet name="header">
                <h:outputText value="Banned?"/>
            </f:facet>
            <h:selectBooleanCheckbox value="#{c.banned}" rendered="#{not c.editable}" disabled="true"></h:selectBooleanCheckbox>
            <h:selectBooleanCheckbox value="#{c.banned}" rendered="#{c.editable}" disabled="false"></h:selectBooleanCheckbox>
        </h:column>

        <h:column>
            <f:facet name="header">
                <h:outputText value="Admin?"/>
            </f:facet>
            <h:selectBooleanCheckbox value="#{c.admin}" rendered="#{not c.editable}" disabled="true"></h:selectBooleanCheckbox>
            <h:selectBooleanCheckbox value="#{c.admin}" rendered="#{c.editable}" disabled="false"></h:selectBooleanCheckbox>
        </h:column>

        <h:column>
            <f:facet name="header">
                <h:outputText value="Edit"/>
            </f:facet>
            <h:commandLink value="Edit" action="#{admin.editAction(c)}" rendered="#{not c.editable}" />
            <h:commandButton value="Save" action="#{admin.saveAction(c)}" rendered="#{c.editable}" />
        </h:column>
    </h:dataTable>
</h:form>

The table is populated successfully, and when I click the edit button in the last column, I am able to modify the values of the columns. If I then click the Save button of the last column, #{admin.saveAction(c)}, is called with the parameter c, which is the customer that I believe I have just modified.

The method is called, though no changes are being made.

saveAction(Customer c) looks like this:

public String saveAction() {
    for (Customer customer : customerList) {
        System.out.println("Trying to update customer with ID: " + customer.getId());
        customerFacade.updateCustomer(customer);
    }
    return null;
}

and updateCustomer(Customer c) looks like this:

public void updateCustomer(Customer c) {
    em.merge(c);
}

Either I have not understood how the variable c corresponds to a Customer object in the list of customers customerList, or I have not successfully bound it to it's property. Simply put, no changes are made to the Customer object when I modify any of the fields.

Is there a way to bind the properties of each Customer object c in customerList, so that the values are being updated when the fields in the datatable connected to the current object is being changed?

Must I use a listener that monitors if a field is being modified, and then calls the setter of the objects property?


Edit: Summarize of the changes to the code that I've made. The main issue seems to be the fact that the customer object (entity class) doesn't get modified when I modify the field values in the datatable.

The saveAction method now look as follows

public String saveAction() {
    for (Customer customer : customerList) {
        System.out.println("Trying to update customer with ID: " + customer.getId());
        customerFacade.updateCustomer(customer);
    }
    return null;
}

The bean class:

@ManagedBean(name = "admin")
@ViewScoped
public class AdminBean implements Serializable {

    @EJB
    CustomerFacade customerFacade;

    private List<Customer> customerList = new ArrayList<>();

    @PostConstruct
    public void init() {
        customerList = customerFacade.findAll();
    }

...

So, the main question is now only why my values aren't being updated?

Community
  • 1
  • 1
Daniel B
  • 8,770
  • 5
  • 43
  • 76
  • With regards to the `binding` attribute. This attribute creates a binding between the [data table instance](http://docs.oracle.com/javaee/7/api/javax/faces/component/html/HtmlDataTable.html) and the backing beans. You might do this if you wanted to provision or interact with the object in code. This is rarely necessary and you should avoid adding a `binding` attribute by default. It is unlikely to have anything to do with your data persistence problem. – McDowell Jan 04 '14 at 17:11
  • What scope is `#{admin.customerList}`? – McDowell Jan 04 '14 at 17:15
  • Thank you for making that a bit clearer! It felt wrong when I did that, my hesitance to whether it was necessary or not. The scope of the bean is @ViewScoped. – Daniel B Jan 04 '14 at 17:17
  • If the action is not being fired, then it is likely that an earlier phase of the of the lifecycle fails. Add a `` to the page to see if it prints anything. – McDowell Jan 04 '14 at 17:19

0 Answers0