6 Replies Latest reply on Oct 29, 2007 10:10 AM by jfrankman

    Question - Can't save outjected DataModelSelection until 2nd

      I had a problem where I selected an item outjected from a SFSB's datamodel to an edit page and when I tried to save it my changes would not be saved on the first attempt. No errors occurred, but the changes I entered on my edit page would not get saved to the DB. Debugging the application showed that the object injected from the edit page did not contain the changes made on the form. However, after the first attempt everything worked fine.

      I solved the problem and was able to eliminate this behavior by setting the dataModel to null (transmittals=null;) in the editClientTransmittal method. I don't understand why this problem happened in the first place and why modifying the editClientTransmittals method solved the problem. I would appreciate it if anyone could look at this example and help me understand:

      I had the following SFSB using the Datamodel:

      @Stateful
      @Name("officeTransmittalAction")
      @Scope(ScopeType.SESSION)
      public class OfficeTransmittalsActionImpl implements OfficeTransmittalsAction {
      
      
       @In(create=true) private ClientTransmittalService clientTransmittalService;
      
       @DataModelSelection("transmittals")
       @In(required=false) @Out(required=false)
       private ClientTransmittalVO clientTransmittal;
      
       @DataModel
       List<ClientTransmittalVO> transmittals;
      
       @Factory("transmittals")
       public void findTransmittals()
       {
       transmittals=clientTransmittalService.findTransmittalsByOfficeAndDate(worker.getOffice(), transdate);
       }
      
       @Begin(join=true)
       public String editClientTransmittal()
       {
       return "";
       }
      
       @Begin(join=true)
       public void saveClientTransmittal()
       {
       clientTransmittalService.saveClientTransmittal(clientTransmittal);
       transmittals=null; //refresh data model
       }

      ...

      My List Page (transMaster.xhtml) is:
      <rich:dataTable id="transmittals" value="#{transmittals}" var="clientTransmittal" >
       <h:column>
       <f:facet name="header">
       <h:outputText value="Transmittal ID">
       </h:outputText>
       </f:facet>
       <h:outputText value="#{clientTransmittal.id}" />
       </h:column>
       <h:column>
       <f:facet name="header">
       <h:outputText value="Last Name" />
       </f:facet>
       <h:outputText value="#{clientTransmittal.clientlastname}" />
       </h:column>
       <h:column>
       <f:facet name="header">
       <h:outputText value="First Name" />
       </f:facet>
       <h:outputText value="#{clientTransmittal.clientfirstname}" />
       </h:column>
       <h:column>
       <f:facet name="header">
       <h:outputText value="Receipt Number" />
       </f:facet>
       <h:outputText value="#{clientTransmittal.receiptnumber}" />
       <rich:spacer />
       </h:column>
       <h:column>
       <f:facet name="header">
       <h:outputText value="Action" />
       </f:facet>
      
       <s:link value="Edit" action="#{officeTransmittalAction.editClientTransmittal}">
       </s:link>
       </h:column>
       </rich:dataTable>
      


      My Edit page (officeTransmittalEdit.xhtml) was as follows:
       <ui:define name="body">
      
       <h:messages globalOnly="true" styleClass="message" id="globalMessages" />
      
       <h:form id="countytrans" styleClass="edit">
       <s:validateAll>
       <rich:panel>
       <f:facet name="header">Edit Transmittal</f:facet>
       <s:decorate id="idDecoration" template="layout/edit.xhtml">
       <ui:define name="label">id</ui:define>
       <h:inputText id="id" required="true" readonly="true"
       value="#{clientTransmittal.id}">
       <a:support event="onblur" reRender="idDecoration" />
       </h:inputText>
       </s:decorate>
      
       <s:decorate id="clientfirstnameDecoration"
       template="layout/edit.xhtml">
       <ui:define name="label">Client First Name</ui:define>
       <h:inputText id="clientfirstname" size="50" maxlength="50"
       value="#{clientTransmittal.clientfirstname}">
       <a:support event="onblur" reRender="clientfirstnameDecoration" />
       </h:inputText>
       </s:decorate>
      
       <s:decorate id="clientlastnameDecoration"
       template="layout/edit.xhtml">
       <ui:define name="label">Client Last Name</ui:define>
       <h:inputText id="clientlastname" size="50" maxlength="50"
       value="#{clientTransmittal.clientlastname}">
       <a:support event="onblur" reRender="clientlastnameDecoration" />
       </h:inputText>
       </s:decorate>
      
       </rich:panel>
      
       <div class="actionButtons1">
       <h:commandButton
       action="#{officeTransmittalAction.saveClientTransmittal}"
       id="saveTransButton2" value="Save TransmittalMaster">
       </h:commandButton>
       </div>
       </s:validateAll>
       </h:form>
       </ui:define>


      My navigation rules:
      <navigation from-action="#{officeTransmittalAction.editClientTransmittal}">
       <redirect view-id="/officeTransmittalEdit.xhtml"/>
       </navigation>
       <navigation
       from-action="#{officeTransmittalAction.saveClientTransmittal}">
       <redirect view-id="/transMaster.xhtml" />
       </navigation>


      I experience a problem where my "clientTransmittal" object would not save on the first try. I would open the list page, choose to edit the transmittal, make a change, and click the save button. One the first try, the injected clientTransmittal would not contain any of the changes made on the form. The second time I brought up the edit page the injected clientTransmittal would contain the changes made on the form. I sensed that the datamodel was not getting updated, but I did not understand why. As an experiment I changed the edit method from:

      @Begin(join=true)
       public String editClientTransmittal()
       {
       return "";
       }


      To:

      @Begin(join=true)
       public String editClientTransmittal()
       {
       transmittals=null; //refresh data model
       return "";
       }


      When I did this I no longer experienced the problem. Why would setting the dataModel object to null fix this problem?

        • 1. Re: Question - Can't save outjected DataModelSelection until
          dhinojosa

          Wow, that looks interesting....
          What does the class ClientTransmittalVO have annotation wise?

          • 2. Re: Question - Can't save outjected DataModelSelection until

            Here is the ClientTransmittalVO class:

            @Entity
            
            @NamedQueries
            ( {
             @NamedQuery(name = "findClientTransmittalByOfficeId",
             query = "select clientTransmittal from ClientTransmittalVO clientTransmittal " +
             "join fetch clientTransmittal.office office " +
             "where (office.id = :officeid and clientTransmittal.transdate=:filterDate) ")
            
            
            })
            @Table(name = "FBCLIENTTRANS")
            @Name("clientTransmittal")
            public class ClientTransmittalVO {
            
             private int id;
             private Date transdate;
             private String countycode;
             private Integer agentno;
             private String clientfirstname;
             private String clientlastname;
             private String receiptnumber;
             private Integer clientid;
             private ClientVO client;
             private FBOffice office;
            
             private Set<ClientTransmittalLineItemVO> clientTransmittalLineItemVOs = new HashSet<ClientTransmittalLineItemVO>(
             0);
            
             public ClientTransmittalVO() {
             }
            
             public ClientTransmittalVO(int id, String countycode) {
             this.id = id;
             this.countycode = countycode;
             }
             public ClientTransmittalVO(int id, Date transdate, String countycode,
             Integer agentno, String clientfirstname, String clientlastname,
             String receiptnumber, Integer clientid,
             Set<ClientTransmittalLineItemVO> clientTransmittalLineItemVOs) {
             this.id = id;
             this.transdate = transdate;
             this.countycode = countycode;
             this.agentno = agentno;
             this.clientfirstname = clientfirstname;
             this.clientlastname = clientlastname;
             this.receiptnumber = receiptnumber;
             this.clientid = clientid;
             this.clientTransmittalLineItemVOs = clientTransmittalLineItemVOs;
             }
            
             @Id
             @Column(name = "ID", unique = true, nullable = false)
             @NotNull @GeneratedValue
             public int getId() {
             return this.id;
             }
            
             @Temporal(TemporalType.DATE)
             @Basic @Column(name = "TRANSDATE")
             @NotNull
             public Date getTransdate() {
             return this.transdate;
             }
            
             @Column(name = "COUNTYCODE", nullable = false, length = 5)
             @NotNull
             @Length(max = 5)
             public String getCountycode() {
             return this.countycode;
             }
            
             @Column(name = "AGENTNO")
             public Integer getAgentno() {
             return this.agentno;
             }
            
             @Column(name = "CLIENTFIRSTNAME", length = 50)
             @Length(max = 50)
             public String getClientfirstname() {
             return this.clientfirstname;
             }
            
             @Column(name = "CLIENTLASTNAME", length = 50)
             @Length(max = 50)
             public String getClientlastname() {
             return this.clientlastname;
             }
            
             @Column(name = "RECEIPTNUMBER", length = 10)
             @Length(max = 10)
             public String getReceiptnumber() {
             return this.receiptnumber;
             }
            
             @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "clientTransmittal")
             @OrderBy(value="lineitemid")
             @Cascade(value = org.hibernate.annotations.CascadeType.DELETE_ORPHAN) //hibernate annotation, not jpa
             public Set<ClientTransmittalLineItemVO> getClientTransmittalLineItems() {
             return this.clientTransmittalLineItemVOs;
             }
            
             @ManyToOne(cascade = {CascadeType.MERGE})
             @JoinColumn(name = "CLIENTID", nullable = false)
             @NotNull
             public ClientVO getClient() {
             return client;
             }
            
             @ManyToOne(fetch=FetchType.EAGER)
             @JoinColumn(name="OFFICEID")
             public FBOffice getOffice() {
             return office;
             }
            
             public void setId(int id) {
             this.id = id;
             }
            
             public void setTransdate(Date transdate) {
             this.transdate = transdate;
             }
            
            
            
             public void setCountycode(String countycode) {
             this.countycode = countycode;
             }
            
            
             public void setAgentno(Integer agentno) {
             this.agentno = agentno;
             }
            
            
             public void setClientfirstname(String clientfirstname) {
             this.clientfirstname = clientfirstname;
             }
            
             public void setClientlastname(String clientlastname) {
             this.clientlastname = clientlastname;
             }
            
             public void setReceiptnumber(String receiptnumber) {
             this.receiptnumber = receiptnumber;
             }
            
            
             public void setClientTransmittalLineItems(
             Set<ClientTransmittalLineItemVO> clientTransmittalLineItemVOs) {
             this.clientTransmittalLineItemVOs = clientTransmittalLineItemVOs;
             }
            
             @Transient
             public List<ClientTransmittalLineItemVO> getLineItemsList()
             {
             List<ClientTransmittalLineItemVO> list = new ArrayList<ClientTransmittalLineItemVO>(getClientTransmittalLineItems());
             return list;
            
             }
            
             public void setClient(ClientVO client) {
             this.client = client;
             }
            
             @Transient
             public void addLineItem(ClientTransmittalLineItemVO lineItem)
             {
             clientTransmittalLineItemVOs.add(lineItem);
             lineItem.setClientTransmittal(this);
             }
            
             @Transient
             public void removeLineItem(ClientTransmittalLineItemVO lineItem)
             {
             //clientTransmittalLineItemVOs.add(lineItem);
             clientTransmittalLineItemVOs.remove(lineItem);
             //lineItem.setClientTransmittal(this);
             }
            
             public void setOffice(FBOffice office) {
             this.office = office;
             }
            
             @Override
             public int hashCode() {
             final int PRIME = 31;
             int result = 1;
             result = PRIME * result + id;
             return result;
             }
            
             @Override
             public boolean equals(Object obj) {
             if (this == obj)
             return true;
             if (obj == null)
             return false;
             if (getClass() != obj.getClass())
             return false;
             final ClientTransmittalVO other = (ClientTransmittalVO) obj;
             if (id != other.id)
             return false;
             return true;
             }
            }


            • 3. Re: Question - Can't save outjected DataModelSelection until
              dhinojosa

              Hmm, I'm baffled. So you can select the VO from the table, edit the VO record, but when you come back to the table the results aren't correct? Is that right?

              • 4. Re: Question - Can't save outjected DataModelSelection until

                Yes, that is the end result. But the root cause of the incorrect table results is that when the saveClientTransmittal() action is called, the VO object that gets injected as the @DataModelSelection does not contain the changes made on the form so no updates are performed. Its as if the user had not made any changes on the form. But the second time and on all subsequent tries the injection of the VO is fine.

                • 5. Re: Question - Can't save outjected DataModelSelection until
                  pmuir

                  Remember @DataModelSelection injects a value. So, when you hit save, you get a value injected both by @In and by @DataModelSelection which is injecting the last data model selection made which as you are in a conversation is the one from your list page. And Seam injects data model selections after @In injections.

                  Putting @In and @DataModelSelection on the same variable isn't really sensible, try splitting them out to separate variables.

                  • 6. Re: Question - Can't save outjected DataModelSelection until

                    That makes sense. I will do as you suggest. Thanks for your help.