3 Replies Latest reply on Jan 29, 2009 5:11 PM by wolfgangknauf

    Eager fetching missing an element when retrieved remotely no

    bigdaddy

      I am not sure if this forum is where this problem should be posted, but here it goes.

      Using:

      Java: 1.5.0_15; Java HotSpot(TM) Client VM 1.5.0_15-b04
      JBoss AS: 4.2.2.GA

      I am trying to implement eager fetching with a parent-to-child (many-to-many) and child-to-grandchild (many-to-many) relationship setup. After all entities are created and I retrieve the grandchildren with EAGER fetching, I am able to iterate through the list of grandchildren and view the grandchildren with it's related children and the children's related parents BEFORE leaving the JBoss server to return the results to a remote client. AFTER leaving the server and the remote client receives the results I iterate through the same grandchildren and see that the parent does not contain the same children as was present before the data left the server. If you run the files I have provided you will notice output from the server log console does not match output from the remote client. It is as if the returned information is being cut off. The child sizes for parentId=402881821a263a42011a26a349aa00ab are different (JBossAS = 2 and remote client = 1) in this sample output. The output from the server side is what is expected.

      Sample output

      JBossAS console:


      ...

      15:10:15,296 INFO [ParentChildGrandchildWorkerBean]
      -------------------------------------------------------------------------
      15:10:15,296 INFO [ParentChildGrandchildWorkerBean] Parent[test.ejb3.ParentTbl[
      parentId=402881821a263a42011a26a3498b00aa]] has child size = 3 -- [test.ejb3.Chi
      ldTbl[childId=402881821a263a42011a26a349d900ac], test.ejb3.ChildTbl[childId=4028
      81821a263a42011a26a34a2700ae], test.ejb3.ChildTbl[childId=402881821a263a42011a26
      a34a0800ad]]
      15:10:15,296 INFO [ParentChildGrandchildWorkerBean] Parent[test.ejb3.ParentTbl[
      parentId=402881821a263a42011a26a349aa00ab]] has child size = 2 -- [test.ejb3.Chi
      ldTbl[childId=402881821a263a42011a26a349d900ac], test.ejb3.ChildTbl[childId=4028
      81821a263a42011a26a34a2700ae]]
      15:10:15,296 INFO [ParentChildGrandchildWorkerBean]
      DONE=========================================================================DON
      E


      Remote client:


      ...

      -------------------------------------------------------------------------
      Parent[test.ejb3.ParentTbl[parentId=402881821a263a42011a26a349aa00ab]] has child size = 1 -- [test.ejb3.ChildTbl[childId=402881821a263a42011a26a349d900ac]]
      Parent[test.ejb3.ParentTbl[parentId=402881821a263a42011a26a3498b00aa]] has child size = 3 -- [test.ejb3.ChildTbl[childId=402881821a263a42011a26a34a0800ad], test.ejb3.ChildTbl[childId=402881821a263a42011a26a34a2700ae], test.ejb3.ChildTbl[childId=402881821a263a42011a26a349d900ac]]

      DONE=========================================================================DONE


      I do not know if there is something wrong with Java, JBoss remoting, EJB3, etc. Hopefully, someone will be able to point out something I may have overlooked or something that I may have misunderstood.

      Here are the files:

      persistence.xml
      <?xml version="1.0" encoding="UTF-8"?>
      <persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
       <persistence-unit name="test-parent-child-grandchildPU" transaction-type="JTA">
       <provider>org.hibernate.ejb.HibernatePersistence</provider>
       <jta-data-source>java:/testerejb3db</jta-data-source>
       <properties>
       <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
       </properties>
       </persistence-unit>
      </persistence>
      


      ParentChildGrandchildWorkerBean.java
      package test.ejb3.workers;
      
      import java.util.Date;
      import java.util.Iterator;
      import java.util.List;
      import java.util.Vector;
      import javax.ejb.Stateless;
      import javax.persistence.EntityManager;
      import javax.persistence.PersistenceContext;
      import javax.persistence.Query;
      import org.apache.log4j.Logger;
      import test.ejb3.entity.ChildTbl;
      import test.ejb3.entity.GrandchildTbl;
      import test.ejb3.entity.ParentTbl;
      import test.ejb3.localinterfaces.ParentChildGrandchildWorkerLocal;
      import test.ejb3.remoteinterfaces.ParentChildGrandchildWorkerRemote;
      
      @Stateless
      public class ParentChildGrandchildWorkerBean implements ParentChildGrandchildWorkerLocal, ParentChildGrandchildWorkerRemote {
       private static final long serialVersionUID = 1L;
       private static Logger logger = Logger.getLogger(ParentChildGrandchildWorkerBean.class);
      
       @PersistenceContext
       private EntityManager entityManager;
      
      
       public ParentTbl addParent(ParentTbl parentTbl) {
       return entityManager.merge(parentTbl);
       }
      
       public ParentTbl findParent(String parentId) {
       return entityManager.find(ParentTbl.class, parentId);
       }
      
       public Vector<ParentTbl> findUnassignedParents() {
       Vector<ParentTbl> resultList;
       Query query;
      
       query = entityManager.createNamedQuery("ParentTbl.findUnassigned");
       resultList = new Vector<ParentTbl>(query.getResultList());
      
       return resultList;
       }
      
       public ChildTbl addChild(ChildTbl childTbl) {
       return entityManager.merge(childTbl);
       }
      
       public ChildTbl findChild(String childId) {
       return entityManager.find(ChildTbl.class, childId);
       }
      
       public Vector<ChildTbl> findUnassignedChildren() {
       Vector<ChildTbl> resultList;
       Query query;
      
       query = entityManager.createNamedQuery("ChildTbl.findUnassigned");
       resultList = new Vector<ChildTbl>(query.getResultList());
      
       return resultList;
       }
      
       public GrandchildTbl addGrandchild(GrandchildTbl grandchildTbl) {
       return entityManager.merge(grandchildTbl);
       }
      
       public GrandchildTbl findGrandchild(String grandchildId) {
       return entityManager.find(GrandchildTbl.class, grandchildId);
       }
      
       public GrandchildTbl findGrandchild(Date startDate, Date endDate) {
       Vector<GrandchildTbl> gtList;
       GrandchildTbl result = null;
      
       gtList = findGrandchild(startDate, endDate, true);
       if (! gtList.isEmpty()) {
       result = gtList.get(0);
       }
      
       return result;
       }
      
       public Vector<GrandchildTbl> findGrandchildren(Date startDate, Date endDate) {
       return findGrandchild(startDate, endDate, false);
       }
      
       public void removeAll() {
       List<ParentTbl> parentTbls;
       List<ChildTbl> childTbls;
       List<GrandchildTbl> grandchildTbls;
       Query query;
      
       query = entityManager.createNamedQuery("ParentTbl.findAll");
       parentTbls = query.getResultList();
       for (Iterator<ParentTbl> i = parentTbls.iterator(); i.hasNext();) {
       entityManager.remove(i.next());
       i.remove();
       }
      
       query = entityManager.createNamedQuery("ChildTbl.findAll");
       childTbls = query.getResultList();
       for (Iterator<ChildTbl> i = childTbls.iterator(); i.hasNext();) {
       entityManager.remove(i.next());
       i.remove();
       }
      
       query = entityManager.createNamedQuery("GrandchildTbl.findAll");
       grandchildTbls = query.getResultList();
       for (Iterator<GrandchildTbl> i = grandchildTbls.iterator(); i.hasNext();) {
       entityManager.remove(i.next());
       i.remove();
       }
       }
      
       private Vector<GrandchildTbl> findGrandchild(Date startDate, Date endDate, boolean useExactDate) {
       Vector<GrandchildTbl> resultList;
       Query query;
      
       entityManager.flush();
       query = useExactDate ? entityManager.createNamedQuery("GrandchildTbl.findByExactDate") :
       entityManager.createNamedQuery("GrandchildTbl.findByDates");
       query.setParameter("startDate", startDate);
       query.setParameter("endDate", endDate);
       resultList = new Vector<GrandchildTbl>(query.getResultList());
      
       for (GrandchildTbl gt : resultList) {
       logger.info("\n#########################################################################");
       for (ChildTbl ct : gt.getChildTblCollection()) {
       logger.info("\n=========================================================================");
       logger.info("Child[" + ct + "] has grand child size = " + ct.getGrandChildTblCollection().size());
       logger.info("Child[" + ct + "] has parent size = " + ct.getParentTblCollection().size());
       logger.info("\n-------------------------------------------------------------------------");
       for (ParentTbl pt : ct.getParentTblCollection()) {
       logger.info("Parent[" + pt + "] has child size = " + pt.getChildTblCollection().size() + " -- " + pt.getChildTblCollection());
       }
       }
       }
       logger.info("\nDONE=========================================================================DONE\n");
      
       return resultList;
       }
      
       public Vector<GrandchildTbl> findUnassignedGrandchildren() {
       Vector<GrandchildTbl> resultList;
       Query query;
      
       query = entityManager.createNamedQuery("GrandchildTbl.findUnassigned");
       resultList = new Vector<GrandchildTbl>(query.getResultList());
      
       return resultList;
       }
      
       public void addChildToParent(ParentTbl parentTbl, ChildTbl childTbl) {
       ParentTbl pt;
       ChildTbl ct;
      
       pt = findParent(parentTbl.getParentId());
       ct = findChild(childTbl.getChildId());
      
       pt.getChildTblCollection().add(ct);
       ct.getParentTblCollection().add(pt);
       }
      
       public void addGrandchildToChild(ChildTbl childTbl, GrandchildTbl grandchildTbl) {
       ChildTbl ct;
       GrandchildTbl gt;
      
       ct = findChild(childTbl.getChildId());
       gt = findGrandchild(grandchildTbl.getGrandchildId());
      
       ct.getGrandChildTblCollection().add(gt);
       gt.getChildTblCollection().add(ct);
       }
      }
      


      ParentChildGrandchildWorker.java
      package test.ejb3.commoninterfaces;
      
      import java.util.Date;
      import java.util.Vector;
      import test.ejb3.entity.ChildTbl;
      import test.ejb3.entity.GrandchildTbl;
      import test.ejb3.entity.ParentTbl;
      
      public interface ParentChildGrandchildWorker {
      
       public void removeAll();
       public ParentTbl addParent(ParentTbl parentTbl);
       public ParentTbl findParent(String parentId);
       public Vector<ParentTbl> findUnassignedParents();
      
       public ChildTbl addChild(ChildTbl childTbl);
       public ChildTbl findChild(String childId);
      
       public GrandchildTbl addGrandchild(GrandchildTbl grandchildTbl);
       public GrandchildTbl findGrandchild(String grandchildId);
       public Vector<ChildTbl> findUnassignedChildren();
      
       /**
       * Get all grandchildren between provided dates.
       *
       * @param startDate
       * @param endDate
       */
       public Vector<GrandchildTbl> findGrandchildren(Date startDate, Date endDate);
       public GrandchildTbl findGrandchild(Date startDate, Date endDate);
       public Vector<GrandchildTbl> findUnassignedGrandchildren();
      
       public void addChildToParent(ParentTbl parentTbl, ChildTbl childTbl);
       public void addGrandchildToChild(ChildTbl childTbl, GrandchildTbl grandchildTbl);
      }
      


      ParentChildGrandchildWorkerRemote.java
      package test.ejb3.remoteinterfaces;
      
      import javax.ejb.Remote;
      import test.ejb3.commoninterfaces.ParentChildGrandchildWorker;
      
      @Remote
      public interface ParentChildGrandchildWorkerRemote extends ParentChildGrandchildWorker {
      
      }
      


      ParentChildGrandchildWorkerLocal.java
      package test.ejb3.localinterfaces;
      
      import javax.ejb.Local;
      import test.ejb3.commoninterfaces.ParentChildGrandchildWorker;
      
      @Local
      public interface ParentChildGrandchildWorkerLocal extends ParentChildGrandchildWorker {
      
      }
      


      GrandchildTbl.java
      package test.ejb3.entity;
      
      import java.io.Serializable;
      import java.util.Date;
      import java.util.Set;
      import javax.persistence.CascadeType;
      import javax.persistence.Column;
      import javax.persistence.Entity;
      import javax.persistence.FetchType;
      import javax.persistence.GeneratedValue;
      import javax.persistence.Id;
      import javax.persistence.JoinColumn;
      import javax.persistence.JoinTable;
      import javax.persistence.ManyToMany;
      import javax.persistence.NamedQueries;
      import javax.persistence.NamedQuery;
      import javax.persistence.Table;
      import javax.persistence.Temporal;
      import javax.persistence.TemporalType;
      
      @Entity
      @Table(name = "grandchildtbl")
      @NamedQueries({@NamedQuery(name = "GrandchildTbl.findAll", query = "SELECT g FROM GrandchildTbl g"),
       @NamedQuery(name = "GrandchildTbl.findByExactDate", query = "SELECT g FROM GrandchildTbl g WHERE g.startDate = :startDate AND " +
       "g.endDate = :endDate"),
       @NamedQuery(name = "GrandchildTbl.findByDates", query = "SELECT g FROM GrandchildTbl g WHERE g.startDate >= :startDate AND " +
       "g.endDate <= :endDate"),
       @NamedQuery(name = "GrandchildTbl.findUnassigned", query = "SELECT DISTINCT g FROM GrandchildTbl g WHERE g.childTblCollection IS EMPTY")})
      public class GrandchildTbl implements Serializable {
       private static final long serialVersionUID = 1L;
      
       @Id
       @GeneratedValue(generator = "system-uuid")
       @Column(name = "grandchild_id", nullable = false)
       private String grandchildId;
       @Column(name = "notes")
       private String notes;
       @Column(name = "start_date", nullable = false)
       @Temporal(TemporalType.TIMESTAMP)
       private Date startDate;
       @Column(name = "end_date", nullable = false)
       @Temporal(TemporalType.TIMESTAMP)
       private Date endDate;
       @JoinTable(name = "childgrandchild",
       joinColumns = {@JoinColumn(name = "grandchild_id", referencedColumnName = "grandchild_id")},
       inverseJoinColumns = {@JoinColumn(name = "child_id", referencedColumnName = "child_id")})
       @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
       private Set<ChildTbl> childTblCollection;
      
       public GrandchildTbl() {
       }
      
       public GrandchildTbl(String grandchildId) {
       this.grandchildId = grandchildId;
       }
      
       public String getGrandchildId() {
       return grandchildId;
       }
      
       public void setGrandchildId(String grandchildId) {
       this.grandchildId = grandchildId;
       }
      
       public String getNotes() {
       return notes;
       }
      
       public void setNotes(String notes) {
       this.notes = notes;
       }
      
       public Date getStartDate() {
       return startDate;
       }
      
       public void setStartDate(Date startDate) {
       this.startDate = startDate;
       }
      
       public Date getEndDate() {
       return endDate;
       }
      
       public void setEndDate(Date endDate) {
       this.endDate = endDate;
       }
      
       public Set<ChildTbl> getChildTblCollection() {
       return childTblCollection;
       }
      
       public void setChildTblCollection(Set<ChildTbl> childTblCollection) {
       this.childTblCollection = childTblCollection;
       }
      
       @Override
       public int hashCode() {
       int hash = 0;
       hash += (grandchildId != null ? grandchildId.hashCode() : 0);
       return hash;
       }
      
       @Override
       public boolean equals(Object object) {
       // TODO: Warning - this method won't work in the case the id fields are not set
       if (!(object instanceof GrandchildTbl)) {
       return false;
       }
       GrandchildTbl other = (GrandchildTbl) object;
       if ((this.grandchildId == null && other.grandchildId != null) || (this.grandchildId != null && !this.grandchildId.equals(other.grandchildId))) {
       return false;
       }
       return true;
       }
      
       @Override
       public String toString() {
       return "test.ejb3.GrandchildTbl[grandchildId=" + grandchildId + "]";
       }
      
      }
      


      ChildTbl.java
      package test.ejb3.entity;
      
      import java.io.Serializable;
      import java.util.Set;
      import javax.persistence.CascadeType;
      import javax.persistence.Column;
      import javax.persistence.Entity;
      import javax.persistence.FetchType;
      import javax.persistence.GeneratedValue;
      import javax.persistence.Id;
      import javax.persistence.JoinColumn;
      import javax.persistence.JoinTable;
      import javax.persistence.ManyToMany;
      import javax.persistence.NamedQueries;
      import javax.persistence.NamedQuery;
      import javax.persistence.Table;
      
      @Entity
      @Table(name = "childtbl")
      @NamedQueries({@NamedQuery(name = "ChildTbl.findAll", query = "SELECT c FROM ChildTbl c"),
       @NamedQuery(name = "ChildTbl.findUnassigned", query = "SELECT DISTINCT c FROM ChildTbl c " +
       "WHERE c.grandchildTblCollection IS EMPTY AND " +
       "c.parentTblCollection IS EMPTY")})
      public class ChildTbl implements Serializable {
       private static final long serialVersionUID = 1L;
      
       @Id
       @GeneratedValue(generator = "system-uuid")
       @Column(name = "child_id", nullable = false)
       private String childId;
       @Column(name = "notes")
       private String notes;
       @JoinTable(name = "parentchild",
       joinColumns = {@JoinColumn(name = "child_id", referencedColumnName = "child_id")},
       inverseJoinColumns = {@JoinColumn(name = "parent_id", referencedColumnName = "parent_id")})
       @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
       private Set<ParentTbl> parentTblCollection;
       @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "childTblCollection")
       private Set<GrandchildTbl> grandchildTblCollection;
      
       public ChildTbl() {
       }
      
       public ChildTbl(String childId) {
       this.childId = childId;
       }
      
       public String getChildId() {
       return childId;
       }
      
       public void setChildId(String childId) {
       this.childId = childId;
       }
      
       public String getNotes() {
       return notes;
       }
      
       public void setNotes(String notes) {
       this.notes = notes;
       }
      
       public Set<ParentTbl> getParentTblCollection() {
       return parentTblCollection;
       }
      
       public void setParentTblCollection(Set<ParentTbl> parentTblCollection) {
       this.parentTblCollection = parentTblCollection;
       }
      
       public Set<GrandchildTbl> getGrandChildTblCollection() {
       return grandchildTblCollection;
       }
      
       public void setGrandChildTblCollection(Set<GrandchildTbl> grandchildTblCollection) {
       this.grandchildTblCollection = grandchildTblCollection;
       }
      
       @Override
       public int hashCode() {
       int hash = 0;
       hash += (childId != null ? childId.hashCode() : 0);
       return hash;
       }
      
       @Override
       public boolean equals(Object object) {
       // TODO: Warning - this method won't work in the case the id fields are not set
       if (!(object instanceof ChildTbl)) {
       return false;
       }
       ChildTbl other = (ChildTbl) object;
       if ((this.childId == null && other.childId != null) || (this.childId != null && !this.childId.equals(other.childId))) {
       return false;
       }
       return true;
       }
      
       @Override
       public String toString() {
       return "test.ejb3.ChildTbl[childId=" + childId + "]";
       }
      
      }
      


      ParentTbl.java
      package test.ejb3.entity;
      
      import java.io.Serializable;
      import java.util.Set;
      import javax.persistence.CascadeType;
      import javax.persistence.Column;
      import javax.persistence.Entity;
      import javax.persistence.FetchType;
      import javax.persistence.GeneratedValue;
      import javax.persistence.Id;
      import javax.persistence.ManyToMany;
      import javax.persistence.NamedQueries;
      import javax.persistence.NamedQuery;
      import javax.persistence.Table;
      
      @Entity
      @Table(name = "parenttbl")
      @NamedQueries({@NamedQuery(name = "ParentTbl.findAll", query = "SELECT p FROM ParentTbl p"),
       @NamedQuery(name = "ParentTbl.findUnassigned", query = "SELECT DISTINCT p FROM ParentTbl p WHERE p.childTblCollection IS EMPTY")})
      public class ParentTbl implements Serializable {
       private static final long serialVersionUID = 1L;
      
       @Id
       @GeneratedValue(generator = "system-uuid")
       @Column(name = "parent_id", nullable = false)
       private String parentId;
       @Column(name = "notes")
       private String notes;
       @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "parentTblCollection")
       private Set<ChildTbl> childTblCollection;
      
       public ParentTbl() {
       }
      
       public ParentTbl(String parentId) {
       this.parentId = parentId;
       }
      
       public String getParentId() {
       return parentId;
       }
      
       public void setParentId(String parentId) {
       this.parentId = parentId;
       }
      
       public String getNotes() {
       return notes;
       }
      
       public void setNotes(String notes) {
       this.notes = notes;
       }
      
       public Set<ChildTbl> getChildTblCollection() {
       return childTblCollection;
       }
      
       public void setChildTblCollection(Set<ChildTbl> childTblCollection) {
       this.childTblCollection = childTblCollection;
       }
      
       @Override
       public int hashCode() {
       int hash = 0;
       hash += (parentId != null ? parentId.hashCode() : 0);
       return hash;
       }
      
       @Override
       public boolean equals(Object object) {
       // TODO: Warning - this method won't work in the case the id fields are not set
       if (!(object instanceof ParentTbl)) {
       return false;
       }
       ParentTbl other = (ParentTbl) object;
       if ((this.parentId == null && other.parentId != null) || (this.parentId != null && !this.parentId.equals(other.parentId))) {
       return false;
       }
       return true;
       }
      
       @Override
       public String toString() {
       return "test.ejb3.ParentTbl[parentId=" + parentId + "]";
       }
      
      }
      


      package-info.java
      @GenericGenerator(name="system-uuid", strategy="uuid")
      package test.ejb3.entity;
      
      import org.hibernate.annotations.GenericGenerator;
      


      TestParentChildGrandchild.java <---- remote client
      package testclientejb3;
      
      import java.util.Calendar;
      import java.util.Date;
      import java.util.GregorianCalendar;
      import java.util.Vector;
      import java.util.logging.Level;
      import java.util.logging.Logger;
      import javax.naming.Context;
      import javax.naming.InitialContext;
      import javax.naming.NamingException;
      import javax.rmi.PortableRemoteObject;
      import test.ejb3.entity.ChildTbl;
      import test.ejb3.entity.GrandchildTbl;
      import test.ejb3.entity.ParentTbl;
      import test.ejb3.remoteinterfaces.ParentChildGrandchildWorkerRemote;
      
      public class TestParentChildGrandchild {
      
       private enum ContextScheme {
       JNP, HTTP;
       }
      
       private java.util.Hashtable <java.lang.String, java.lang.String> environment;
      
       private void initEnvironment(ContextScheme contextScheme, String providerHost, String providerPort) {
       String url = contextScheme.toString().toLowerCase() + "://" + providerHost + ":" + providerPort;
       String initialContextFactory = "org.jnp.interfaces.NamingContextFactory";
      
       if (contextScheme.equals(ContextScheme.HTTP)) {
       url = url + "/invoker/JNDIFactory";
       initialContextFactory = "org.jboss.naming.HttpNamingContextFactory";
       }
      
       environment = new java.util.Hashtable<java.lang.String, java.lang.String>();
       environment.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, initialContextFactory);
       environment.put(javax.naming.Context.PROVIDER_URL, url);
       environment.put(javax.naming.Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");
       }
      
       public ParentTbl getParent(int parentNumber) {
       ParentTbl parentTbl;
      
       parentTbl = new ParentTbl();
       parentTbl.setNotes("Hello world - parent " + parentNumber + ".");
      
       return parentTbl;
       }
      
       public ChildTbl getChild(int childNumber) {
       ChildTbl childTbl;
      
       childTbl = new ChildTbl();
       childTbl.setNotes("Hello world - child " + childNumber + ".");
      
       return childTbl;
       }
      
       public GrandchildTbl getGrandchildTbl(int grandchildNumber) {
       GrandchildTbl grandchildTbl;
       Date date = new Date();
      
       grandchildTbl = new GrandchildTbl();
       grandchildTbl.setNotes("Hello world - grand child " + grandchildNumber + ".");
       grandchildTbl.setStartDate(date);
       grandchildTbl.setEndDate(date);
      
       return grandchildTbl;
       }
      
       public void test() {
       Context initialContext;
       Vector<ParentTbl> parentVector;
       Vector<ChildTbl> childVector;
       Vector<GrandchildTbl> grandchildVector;
       GregorianCalendar gregorianCalendar;
       ParentTbl firstParentTbl;
       ParentTbl lastParentTbl;
       ChildTbl childTbl;
       GrandchildTbl grandchildTbl;
       int numOfParents = 2;
       int numOfChildren = 3;
       int numOfGrandchildren = 8;
      
       try {
       initEnvironment(ContextScheme.JNP, "localhost", "1099");
       initialContext = new InitialContext(environment);
       Object ref = initialContext.lookup("ParentChildGrandchildWorkerBean/remote");
       ParentChildGrandchildWorkerRemote parentChildGrandchildWorkerRemote = (ParentChildGrandchildWorkerRemote) PortableRemoteObject.narrow(ref, ParentChildGrandchildWorkerRemote.class);
      
       parentChildGrandchildWorkerRemote.removeAll();
      
       // Create parents, children, and grandchildren
       for (int i = 0; i < numOfParents; i++) {
       parentChildGrandchildWorkerRemote.addParent(getParent(i));
       }
       for (int i = 0; i < numOfChildren; i++) {
       parentChildGrandchildWorkerRemote.addChild(getChild(i));
       }
       for (int i = 0; i < numOfGrandchildren; i++) {
       parentChildGrandchildWorkerRemote.addGrandchild(getGrandchildTbl(i));
       }
      
       parentVector = parentChildGrandchildWorkerRemote.findUnassignedParents();
       childVector = parentChildGrandchildWorkerRemote.findUnassignedChildren();
       grandchildVector = parentChildGrandchildWorkerRemote.findUnassignedGrandchildren();
      
       firstParentTbl = parentVector.get(0);
       lastParentTbl = parentVector.get(numOfParents - 1);
      
       // Add 1st grandchild to 1st child
       // Add 1st child to 1st and last parent
       childTbl = childVector.get(0);
       grandchildTbl = grandchildVector.get(0);
       parentChildGrandchildWorkerRemote.addGrandchildToChild(childTbl, grandchildTbl);
       parentChildGrandchildWorkerRemote.addChildToParent(firstParentTbl, childTbl);
       parentChildGrandchildWorkerRemote.addChildToParent(lastParentTbl, childTbl);
      
       // Add middle grandchildren to middle child
       // Add middle child to 1st parent
       childTbl = childVector.get(1);
       for (int i = 1; i < numOfGrandchildren - 1; i++) {
       grandchildTbl = grandchildVector.get(i);
       parentChildGrandchildWorkerRemote.addGrandchildToChild(childTbl, grandchildTbl);
       }
       parentChildGrandchildWorkerRemote.addChildToParent(firstParentTbl, childTbl);
      
       // Add last grandchild to last child
       // Add last child to 1st and last parent
       childTbl = childVector.get(numOfChildren - 1);
       grandchildTbl = grandchildVector.get(numOfGrandchildren - 1);
       parentChildGrandchildWorkerRemote.addGrandchildToChild(childTbl, grandchildTbl);
       parentChildGrandchildWorkerRemote.addChildToParent(firstParentTbl, childTbl);
       parentChildGrandchildWorkerRemote.addChildToParent(lastParentTbl, childTbl);
      
       gregorianCalendar = new GregorianCalendar();
       gregorianCalendar.clear();
       gregorianCalendar.set(Calendar.YEAR, 1600);
      
       System.out.println("searching from " + gregorianCalendar.getTime());
      
       // Get all grandchildren with eager fetching
       grandchildVector = parentChildGrandchildWorkerRemote.findGrandchildren(gregorianCalendar.getTime(), new Date());
      
       System.out.println("grandchildVector = " + grandchildVector);
       for (GrandchildTbl gt : grandchildVector) {
       System.out.println("\n#########################################################################");
       for (ChildTbl ct : gt.getChildTblCollection()) {
       System.out.println("\n=========================================================================");
       System.out.println("Child[" + ct + "] has grand child size = " + ct.getGrandChildTblCollection().size());
       System.out.println("Child[" + ct + "] has parent size = " + ct.getParentTblCollection().size());
       System.out.println("\n-------------------------------------------------------------------------");
       for (ParentTbl pt : ct.getParentTblCollection()) {
       System.out.println("Parent[" + pt + "] has child size = " + pt.getChildTblCollection().size() + " -- " + pt.getChildTblCollection());
       }
       }
       }
       System.out.println("\nDONE=========================================================================DONE\n");
      
       } catch (NamingException ex) {
       Logger.getLogger(TestParentChildGrandchild.class.getName()).log(Level.SEVERE, null, ex);
       }
       }
      
       /**
       * @param args the command line arguments
       */
       public static void main(String[] args) {
       TestParentChildGrandchild test = new TestParentChildGrandchild();
       test.test();
       }
      }
      


        • 1. Re: Eager fetching missing an element when retrieved remotel
          bigdaddy

          Will someone from JBoss look at this? Unless I have made a misstep this is a significant problem. I have only seen this with eager fetching. Maybe this is a problem with the entity manager or maybe it's a problem with the data marshaller. I am not sure what it is, but something is cutting off the returned results to the remote client.

          • 2. Re: Eager fetching missing an element when retrieved remotel
            bigdaddy

            Wow, I almost forgot about this.

            I still do not know what the problem is with this implementation of @ManyToMany. Actually, I do not believe anything is wrong with the code as written. I am fairly certain there is a problem with Hibernate, the entity manager, data marshaller, or something else. I would welcome someone to point out a mistake that I may have made.

            Anyhow, for those interested there is a workaround. Create the relational entities (i.e. ParentChildTbl and ChildGrandchildTbl) yourself and apply @ManyToOne, @OneToMany annotations with Sets-- not Collections-- for the foreign attributes on the ChildTbl and eager fetching will work as expected. If you must use Collections, I read somewhere that setting the hibernate annotation @Fetch(FetchMode.SUBSELECT) on bags (Collections) may work or you may use a List with an @IndexColumn.

            For example:

            Under ChildTbl.java
            (Similarly, update ParentTbl.java and GrandchildTbl.java. They would have @OneToMany relationships with ParentChildTbl.java and ChildGrandchildTbl.java, respectively)

            ...
             @Id
             @GeneratedValue(generator = "system-uuid")
             @Column(name = "child_id", nullable = false)
             private String childId;
            
             @Column(name = "notes")
             private String notes;
            
             @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "childTbl")
             private Set<ParentChildTbl> parentChildTblSet
            
             @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "childTbl")
             private Set<ChildGrandchildTbl> grandchildTblSet;
            ...
            


            Create ChildGrandchildTbl.java (Similarly create ParentChildTbl.java)
            ...
             @EmbeddedId
             protected ChildGrandchildPK childGrandchildPK;
            
             @JoinColumn(name = "child_id", insertable = false, nullable = false, updatable = false)
             @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
             private ChildTbl childTbl;
            
             @JoinColumn(name = "grandchild_id", insertable = false, nullable = false, updatable = false)
             @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
             private GrandchildTbl grandchildTbl;
            ...
            



            • 3. Re: Eager fetching missing an element when retrieved remotel
              wolfgangknauf

              Hi,

              I would not recommend usage of FetchType.EAGER in a many-to-many relationship, because on loading one parent, it might happen that half of the database is loaded, if fetching cascades from parent to childs to other parents to other childs and so on ;-).
              Better use LAZY and provide some methods in the session bean to fetch the parents of the children of a parent.

              Best regards

              Wolfgang