title: JSF setter called multiple time overwriting values
body: <p>Hi I am using PrimeFaces to create a data table which has 1 column within it and each row of that datatable holds a accordian. 
  i want to update a specific row within the data table with the values from some input boxes associated with each row. </p>
  
  <p>When I submit the form per row 
  firstly the set property action listener is never called and 
  secondly the setters for the fields I am updating are called multiple times. In fact they are called
  once for every row in the data table. </p>
  
  <p>The problem being that when debugging I can see that no matter which ever row I am editing the setters are called for all the rows in the datatable. So unless i am editing the last row the values I am setting always get overwritten.  Any one know whey this is happening as i thought it would only have called the setter once per row edit.</p>
  
  <p>UPDATE: Worst case i can get around the setters being called by putting a null check in. however I do not know which row I am working with since the set property action listener is not called</p>
  
  <p>JSF page</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:p="http://primefaces.org/ui"
      xmlns:ui="http://java.sun.com/jsf/facelets"&gt;
        &lt;h:form id="userDetailsForm" style="padding:5px"&gt; 
          &lt;p:growl id="messages" showDetail="true" autoUpdate="true" life="2000"/&gt;
          &lt;p:spacer height="15"&gt;&lt;/p:spacer&gt;
  
      &lt;div class="row"&gt;     
        &lt;div class="col-lg-4"&gt;
          &lt;div class="input-group"&gt;
            &lt;p:inputText type="text" styleClass="form-control" value="#{emailArticleBean.searchText}" /&gt;
            &lt;span class="input-group-btn" style="margin:3px;"&gt;
              &lt;p:commandButton actionListener="#{emailArticleBean.search}" value="Go!" update=":userDetailsForm:emailArticleTable" /&gt;
            &lt;/span&gt;
          &lt;/div&gt;&lt;!-- /input-group --&gt;
        &lt;/div&gt;&lt;!-- /.col-lg-6 --&gt;
      &lt;/div&gt;&lt;!-- /.row --&gt;
  
      &lt;p:spacer height="15"&gt;&lt;/p:spacer&gt;
  
      &lt;div class="row"&gt;
          &lt;div class="col-lg-1"&gt;
  
          &lt;/div&gt;
          &lt;div class="col-lg-11"&gt;
          &lt;p:dataTable var="email" value="#{emailArticleBean.emailArticles}" scrollRows="20"  
                      scrollable="true" liveScroll="true" scrollHeight="750" id="emailArticleTable" 
                      &gt;
              &lt;p:column&gt;
                  &lt;p:accordionPanel multiple="true" activeIndex="-1" id="panel#{email.id}"&gt;  
  
                      &lt;p:tab title="#{email.headline}" titleStyleClass="email-header"&gt;  
                             &lt;div style="clear:both;margin-bottom:10px;"&gt;
                             &lt;h6 style="font-weight:bold;"&gt;Summary&lt;/h6&gt;
                              &lt;h:outputText  
                                  value="#{email.summary}" /&gt;     
                              &lt;/div&gt;  
                              &lt;div style="clear:both;margin-bottom:10px;"&gt;
                              &lt;h6 style="font-weight:bold;"&gt;Implication&lt;/h6&gt;
                              &lt;h:outputText  
                                  value="#{email.implication}" /&gt;     
                              &lt;/div&gt;           
                              &lt;div style="float:left;clear:both"&gt;
                                  &lt;p:commandButton  value="View Existing Actions" 
                                      oncomplete="PF('dlg2').show();" update=":userDetailsForm:emailActionDialog"&gt;
                                       &lt;f:setPropertyActionListener value="#{email}" target="#{emailArticleBean.selectedEmail}" /&gt;  
                                  &lt;/p:commandButton&gt;                  
                               &lt;/div&gt; 
                               &lt;br/&gt;
                               &lt;br/&gt;
                               &lt;div style="margin-top:10px;"&gt;        
                                  &lt;h:inputTextarea id="accordian1" value="#{emailArticleBean.emailAction}" cols="90" rows="3" /&gt;                          
                              &lt;/div&gt;
                              &lt;h6 style="font-weight:bold;"&gt;Due Date&lt;/h6&gt;  
                              &lt;p:calendar value="#{emailArticleBean.actionDueDate}" id="popupCal" pattern="dd MMM, yyyy"/&gt; 
                              &lt;p:commandButton actionListener="#{emailArticleBean.updateAction}" value="Add Action" 
                                   style="margin-left:5px;"&gt;
                                  &lt;f:setPropertyActionListener value="#{email}" target="#{emailArticleBean.selectedEmail}" /&gt;
                              &lt;/p:commandButton&gt; 
  
                      &lt;/p:tab&gt;
                  &lt;/p:accordionPanel&gt;
              &lt;/p:column&gt;
          &lt;/p:dataTable&gt;
          &lt;/div&gt;
  
      &lt;/div&gt; 
  
      &lt;p:dialog id="emailActionDialog" header="Email Actions" widgetVar="dlg2" modal="true" height="100"&gt;  
          &lt;h3&gt;Email Actions&lt;/h3&gt;  
          &lt;p:dataList value="#{emailArticleBean.selectedEmail.actions}" var="action" itemType="disc"&gt;  
              #{action.action} --- #{action.username}  
          &lt;/p:dataList&gt;  
      &lt;/p:dialog&gt; 
  
  
  
      &lt;/h:form&gt;   
  
  
  
  &lt;/html&gt;
  </code></pre>
  
  <p>My backing bean</p>
  
  <pre><code>@ManagedBean
  @Configurable
  @ViewScoped
  public class EmailArticleBean implements Serializable {
  
      /**
       * 
       */
      private static final long serialVersionUID = 1L;
  
      @Autowired
      EmailArticleService emailArticleService;
  
      private List&lt;EmailArticle&gt; emailArticles;
      private String searchText;
      private String emailAction;
      private EmailArticle selectedEmail;
      private Date actionDueDate;
  
      /**
       * Using the search term entered will
       * query the database and return a list of articles 
       * that match that parameter
       * @param ae
       */
      public void search(ActionEvent ae) {
          emailArticles = emailArticleService.findEmailArticles(searchText);
      }   
  
      /**
       * add the inputted action to the list of existing actions
       * @param ae
       */
      public void updateAction(ActionEvent ae) {
          selectedEmail.getActions().add(new EmailActions(emailAction, "testUser", actionDueDate));
          selectedEmail.merge();
          emailAction = "";
          actionDueDate = null;
      }
  
      public List&lt;EmailArticle&gt; getEmailArticles() {
          return emailArticles;
      }
  
      public void setEmailArticles(List&lt;EmailArticle&gt; emailArticles) {
          this.emailArticles = emailArticles;
      }
  
      public String getSearchText() {
          return searchText;
      }
  
      public void setSearchText(String searchText) {
          this.searchText = searchText;
      }
  
      public String getEmailAction() {
          return emailAction;
      }
  
      public void setEmailAction(String emailAction) {
          //putting this check in because it the jsf lifecycle
          //seems to be calling the setter once for every row overwriting the new value set by the user
          if(StringUtils.isEmpty(this.emailAction)) {
              this.emailAction = emailAction;
          }       
      }   
  
      public EmailArticle getSelectedEmail() {
          return selectedEmail;
      }
  
      public void setSelectedEmail(EmailArticle selectedEmail) {
          if(selectedEmail == null) {
              this.selectedEmail = selectedEmail;
          }       
      }
  
      public Date getActionDueDate() {
          return actionDueDate;
      }
  
      public void setActionDueDate(Date actionDueDate) {
          if(this.actionDueDate == null) {
              this.actionDueDate = actionDueDate;
          }       
      }
  
  
  }
  </code></pre>