5 Replies Latest reply on May 29, 2007 3:53 AM by Damian Harvey

    OneToMany List refresh after insert

    Damian Harvey Master

      Hi,

      I have a page where a header/detail set of data is entered. There is a relationship between the entities handled like so:

      @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "parentObject")
      public List<childObject> getChildObjects() {
       return this.childObjects;
      }
      
      When I insert header & detail data the action returns to the same page that the insert was done. This page also has a dataTable showing header data. One of these fields is based on the List above and is used to show the first child Objects start date.
      
      The problem is that this List is not updated until the user navigates away and back. Is there anyway to force this List to update at the time that the records are created?
      
      I have tried setting the FetchType to EAGER but this had no effect.
      
      Thanks,
      
      Damian.
      


        • 1. Re: OneToMany List refresh after insert
          Damian Harvey Master

          sorry about the crappy layout of the post above.

          • 2. Re: OneToMany List refresh after insert
            Pete Muir Master

            Show your JSF and your backing beans

            • 3. Re: OneToMany List refresh after insert
              Damian Harvey Master

              I've recreated this with a simple example using Seam Gen. If you have a PERSON entity and a CITY entity. Then you wish to show a list of CITYs with a column holding a ui:repeat (or similar) displaying all associated PERSONs. The cause of the problem is that this is an "all-in-one" type page where the form to add the record is on the same page as the table to display. I suspect that something is needed to force the refresh.

              The page:

              <!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
               "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
              
              <ui:composition xmlns="http://www.w3.org/1999/xhtml"
               xmlns:s="http://jboss.com/products/seam/taglib"
               xmlns:ui="http://java.sun.com/jsf/facelets"
               xmlns:f="http://java.sun.com/jsf/core"
               xmlns:h="http://java.sun.com/jsf/html"
               xmlns:a="https://ajax4jsf.dev.java.net/ajax"
               xmlns:rich="http://richfaces.ajax4jsf.org/rich"
               template="layout/template.xhtml">
              <ui:define name="body">
               <h:messages globalOnly="true" styleClass="message" id="globalMessages"/>
               <h:form id="person" styleClass="edit">
               <rich:panel>
               <f:facet name="header">Create Person</f:facet>
               <s:decorate id="firstnameDecoration" template="layout/edit.xhtml">
               <ui:define name="label">Firstname</ui:define>
               <h:inputText id="firstname" value="#{personHome.instance.firstname}"/>
               </s:decorate>
               <s:decorate id="surnameDecoration" template="layout/edit.xhtml">
               <ui:define name="label">Surname</ui:define>
               <h:inputText id="surname" value="#{personHome.instance.surname}"/>
               </s:decorate>
               <s:decorate id="cityDecoration" template="layout/edit.xhtml">
               <ui:define name="label">City</ui:define>
               <h:selectOneMenu id="city" value="#{personHome.instance.city}" style="width:250px;">
               <s:selectItems value="#{cityList.resultList}" var="city"
               noSelectionLabel="Please Select..." label="#{city.cityname}"/>
               <s:convertEntity />
               </h:selectOneMenu>
               </s:decorate>
               <div style="clear:both">
               <span class="required">*</span>
               required fields
               </div>
               </rich:panel>
               <div class="actionButtons">
               <h:commandButton id="save" value="Save"
               action="#{personHome.persist}" rendered="#{!personHome.managed}"/>
               </div>
               </h:form>
               <rich:dataTable var="city" value="#{cityList.resultList}"
               rowClasses="rvgRowOne,rvgRowTwo" id="cityTable">
               <h:column>
               <f:facet name="header">City</f:facet>
               #{city.cityname}
               </h:column>
               <h:column>
               <f:facet name="header">people</f:facet>
               <ui:repeat var="person" value="#{city.persons}">
               <h:outputText value="#{person.firstname} #{person.surname}"/>
               <br/>
               </ui:repeat>
               </h:column>
               </rich:dataTable>
              </ui:define>
              </ui:composition>
              

              The page has no pages.xml entries or associated page.xml file. The persist action returns to the current page. I would have thought that as the dataTable is re-rendered, that the List of Persons would be refreshed; however it isn't.

              And I have changed the PersonHome object from what Seam generated to remove the PersonHome from the conversation so that the same page can be reused:
              package com.seamtest;
              
              import org.jboss.seam.annotations.In;
              import org.jboss.seam.annotations.Name;
              import org.jboss.seam.annotations.Transactional;
              import org.jboss.seam.contexts.Contexts;
              import org.jboss.seam.framework.EntityHome;
              
              @Name("personHome")
              public class PersonHome extends EntityHome<Person> {
              
               public void setPersonPersonid(Long id) {
               setId(id);
               }
              
               public Long getPersonPersonid() {
               return (Long) getId();
               }
              
               @Override
               protected Person createInstance() {
               Person person = new Person();
               return person;
               }
              
               public Person getDefinedInstance() {
               return isIdDefined() ? getInstance() : null;
               }
              
               @Override
               @Transactional
               public String persist() {
               String status = super.persist();
               Contexts.removeFromAllContexts("personHome");
               return status;
               }
              
              }
              


              The Person entity is unchanged from Seam-Gen. It contains only firstname, surname and City. I have changed the City entity to store a java.util.List of Persons rather than a set:
              package com.seamtest;
              // Generated Apr 16, 2007 6:03:07 PM by Hibernate Tools 3.2.0.b9
              
              import java.util.ArrayList;
              import java.util.List;
              
              import javax.persistence.CascadeType;
              import javax.persistence.Column;
              import javax.persistence.Entity;
              import javax.persistence.FetchType;
              import javax.persistence.Id;
              import javax.persistence.JoinColumn;
              import javax.persistence.ManyToOne;
              import javax.persistence.OneToMany;
              import javax.persistence.Table;
              
              import org.hibernate.validator.NotNull;
              
              /**
               * City generated by hbm2java
               */
              @Entity
              @Table(name = "CITY", catalog = "SEAMTEST")
              public class City implements java.io.Serializable {
              
               private long cityid;
               private String cityname;
              // private Set<Person> persons = new HashSet<Person>(0);
               private List<Person> persons = new ArrayList<Person>(0);
              
               public City() {
               }
              
               public City(long cityid) {
               this.cityid = cityid;
               }
               public City(long cityid, String cityname,
               List<Person> persons) {
               this.cityid = cityid;
               this.cityname = cityname;
               this.persons = persons;
               }
              
               @Id
               @Column(name = "CITYID", unique = true, nullable = false)
               @NotNull
               public long getCityid() {
               return this.cityid;
               }
              
               public void setCityid(long cityid) {
               this.cityid = cityid;
               }
              
               @Column(name = "CITYNAME")
               public String getCityname() {
               return this.cityname;
               }
              
               public void setCityname(String cityname) {
               this.cityname = cityname;
               }
               @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "city")
               public List<Person> getPersons() {
               return this.persons;
               }
              
               public void setPersons(List<Person> persons) {
               this.persons = persons;
               }
              
              }
              
              

              Happy to email a stripped down project if it would help.

              Thanks,

              Damian.

              • 4. Re: OneToMany List refresh after insert
                Glenn Marcus Newbie

                I am having a similar refresh issue. The database is being updated correctly, but the context variables managed by SEAM are not reflecting the updates. When I navigate away from the page and come back, the context variables are refreshed from the database and the page renders correctly.

                Were you able to find a solution?

                • 5. Re: OneToMany List refresh after insert
                  Damian Harvey Master

                  Yes. I'm working my way through the Hibernate book so I'm not 100% that this is the correct way - but it works.

                  You need to explicitly add the PERSON to the Collection of PERSONs in the CITY when doing the persist. I'm not in front of my normal laptop but the code looks something like this:

                  @Override
                  @Transactional
                  public String persist() {
                  String status = super.persist();
                  
                  getInstance().getCity().getPersons().add(getInstance());
                  
                  Contexts.removeFromAllContexts("personHome");
                  return status;
                  }