9 Replies Latest reply on Jan 25, 2008 4:18 PM by waynebaylor

    problems with optimistic locking/persistence data in EJB3 ac

    wiggy

      Got a problem thats doing my head in if anyone can explain whats going on. Spent too much time trying to figure this and getting nowhere. Any HELP greatfully received.

      I have a simple ejb3 stateless EAR application. it consists of an ejb jar for my entity classes, and an enterprise object access wrapper (EJB equiv of generic DAO pattern for old hibernate - tried this based on EJB3 in action book).

      the app is simple - it has a node entity and link entity, and you link nodes to links backwards and forwards (at java level its a bit like a doubly linked list.

      I have set transitive persistence for persist and merge actions

      essentially i have an external test app that creates some nodes and links them. I use the nodeEAO to persist the 3 nodes and two links in the DB (mysql). This works okay, and the entities are persisted.

      client app code outside the conatiner ...
       ctx = getInitialContext();
      
       aNode = new Node();
       bNode = new Node ();
       cNode = new Node ();
       uNode = new Node (); // empty
       zNode = new Node (); // empty
      
      
       aNode.setNodeName("William");
       bNode.setNodeName("10 South Close");
       cNode.setNodeName("G01 B32");
      
       try
       {
       UserTransaction ut = (UserTransaction)ctx.lookup("UserTransaction");
       ut.begin();
       Link aLink = aNode.addLinkTo(bNode);
       aNode.addLinkTo(cNode);
       //update uNode to persisted value
       uNode = nodeEAO.save(aNode);
      
       ut.commit();
       } catch (Exception e)
       {e.printStackTrace();
       System.exit(0);}
      
      ...
      
      then later i call the following
      
       if (nodeEAO.removeLink(uNode, zNode))
       {
      
       System.out.println ("deleted link : \n");
       }
      
      


      The code in the EJB in the container for this looks like

      EJB nodeEAO code ...
      
      
      @Stateless
      public class NodeEAOBean extends EAOBean<Node, Long> implements NodeEAO, NodeEAOLocal, NodeEAORemote
      {
       @Resource
       private SessionContext sc;
      
       static final long serialVersionUID =1;
      ...
      
       @TransactionAttribute (TransactionAttributeType.REQUIRED)
       public boolean removeLink (Node fromNode, Node remoteNode)
       {
      
       List<Link> qres;
       Logger log = Logger.getLogger("NodeEAOBean");
       log.setLevel(org.apache.log4j.Level.DEBUG);
      
       if (fromNode == null || remoteNode == null)
       {
       log.error("was passed a null reference");
       return false;
       }
      
       fromNode = em.merge(fromNode);
       remoteNode = em.merge(remoteNode);
       Query q = em.createNamedQuery("findLinksBetweenNodes");
       q.setParameter("toNode", remoteNode);
       q.setParameter("fromNode", fromNode);
      
       log.debug("to node details " + remoteNode.getNodeName() + "\n");
      
       qres = (List<Link>)q.getResultList();
       if (qres != null && qres.size () == 1)
       {
       Link link = qres.get(0);
       remoteNode.deleteLinkFrom(link);
       fromNode.deleteLinkTo(link);
       em.remove(link);
       return true;
       }
       else
       {return false;}
      
       }
      


      when i get to the removeLink call in the client this works and the database is updated and one of my links is deleted.

      Next I query for remaining links seen from the first node this calls

      
      ...
       List<Node> nodeList2 = nodeEAO.getConnectedToNodes(uNode);
       if (nodeList2 != null)
       {
       for (Node n : nodeList )
       {
       System.out.println ("got connected node : " + n.getNodeName() + "/n");
       }
       }
      
      


      on the the ejb server this runs a query to get the result .

      
       @TransactionAttribute (TransactionAttributeType.REQUIRED)
       public List<Node> getConnectedToNodes (Node fromNode)
       {
       Logger log = Logger.getLogger("NodeEAOBean");
       log.setLevel(org.apache.log4j.Level.DEBUG);
      
       if (fromNode == null )
       {
       log.error("was passed a null reference");
       return null;
       }
      
       fromNode = em.merge(fromNode);
       Query q = em.createNamedQuery("getLinkedNodes");
       q.setParameter("fromNode", fromNode);
      
       return (List<Node>)q.getResultList();
      
       }
      


      however when i run this i get the foillowing error




      Exception in thread "main" javax.ejb.EJBException: javax.persistence.OptimisticLockException at org.jboss.ejb3.tx.Ejb3TxPolicy.handleExceptionInOurTx(Ejb3TxPolicy.java:63)
      at org.jboss.aspects.tx.TxPolicy.invokeInOurTx(TxPolicy.java:83)
      at org.jboss.aspects.tx.TxInterceptor$Required.invoke(TxInterceptor.java:191)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.aspects.tx.TxPropagationInterceptor.invoke(TxPropagationInterceptor.java:95)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.ejb3.stateless.StatelessInstanceInterceptor.invoke(StatelessInstanceInterceptor.java:62)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.aspects.security.AuthenticationInterceptor.invoke(AuthenticationInterceptor.java:77)
      at org.jboss.ejb3.security.Ejb3AuthenticationInterceptor.invoke(Ejb3AuthenticationInterceptor.java:110)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.ejb3.ENCPropagationInterceptor.invoke(ENCPropagationInterceptor.java:46)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.ejb3.asynchronous.AsynchronousInterceptor.invoke(AsynchronousInterceptor.java:106)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.ejb3.stateless.StatelessContainer.dynamicInvoke(StatelessContainer.java:304)
      at org.jboss.aop.Dispatcher.invoke(Dispatcher.java:106)
      at org.jboss.aspects.remoting.AOPRemotingInvocationHandler.invoke(AOPRemotingInvocationHandler.java:82)
      at org.jboss.remoting.ServerInvoker.invoke(ServerInvoker.java:769)
      at org.jboss.remoting.transport.socket.ServerThread.processInvocation(ServerThread.java:573)
      at org.jboss.remoting.transport.socket.ServerThread.dorun(ServerThread.java:373)
      at org.jboss.remoting.transport.socket.ServerThread.run(ServerThread.java:166)
      Caused by: javax.persistence.OptimisticLockException
      at org.hibernate.ejb.AbstractEntityManagerImpl.wrapStaleStateException(AbstractEntityManagerImpl.java:642)
      at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:599)
      at org.hibernate.ejb.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:236)
      at org.jboss.ejb3.entity.TransactionScopedEntityManager.merge(TransactionScopedEntityManager.java:188)
      at org.softwood.neilsapp.eao.NodeEAOBean.getConnectedToNodes(NodeEAOBean.java:135)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
      at java.lang.reflect.Method.invoke(Unknown Source)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:112)
      at org.jboss.ejb3.interceptor.InvocationContextImpl.proceed(InvocationContextImpl.java:166)
      at org.jboss.ejb3.interceptor.EJB3InterceptorsInterceptor.invoke(EJB3InterceptorsInterceptor.java:63)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.ejb3.entity.TransactionScopedEntityManagerInterceptor.invoke(TransactionScopedEntityManagerInterceptor.java:54)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.ejb3.AllowedOperationsInterceptor.invoke(AllowedOperationsInterceptor.java:47)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.aspects.tx.TxPolicy.invokeInOurTx(TxPolicy.java:79)
      at org.jboss.aspects.tx.TxInterceptor$Required.invoke(TxInterceptor.java:191)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.aspects.tx.TxPropagationInterceptor.invoke(TxPropagationInterceptor.java:95)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.ejb3.stateless.StatelessInstanceInterceptor.invoke(StatelessInstanceInterceptor.java:62)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.aspects.security.AuthenticationInterceptor.invoke(AuthenticationInterceptor.java:77)
      at org.jboss.ejb3.security.Ejb3AuthenticationInterceptor.invoke(Ejb3AuthenticationInterceptor.java:110)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.ejb3.ENCPropagationInterceptor.invoke(ENCPropagationInterceptor.java:46)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.ejb3.asynchronous.AsynchronousInterceptor.invoke(AsynchronousInterceptor.java:106)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.ejb3.stateless.StatelessContainer.dynamicInvoke(StatelessContainer.java:304)
      at org.jboss.aop.Dispatcher.invoke(Dispatcher.java:106)
      at org.jboss.aspects.remoting.AOPRemotingInvocationHandler.invoke(AOPRemotingInvocationHandler.java:82)
      at org.jboss.remoting.ServerInvoker.invoke(ServerInvoker.java:769)
      at org.jboss.remoting.transport.socket.ServerThread.processInvocation(ServerThread.java:573)
      at org.jboss.remoting.transport.socket.ServerThread.dorun(ServerThread.java:373)
      at org.jboss.remoting.transport.socket.ServerThread.run(ServerThread.java:166)
      at org.jboss.remoting.MicroRemoteClientInvoker.invoke(MicroRemoteClientInvoker.java:163)
      at org.jboss.remoting.Client.invoke(Client.java:1634)
      at org.jboss.remoting.Client.invoke(Client.java:548)
      at org.jboss.aspects.remoting.InvokeRemoteInterceptor.invoke(InvokeRemoteInterceptor.java:62)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.aspects.tx.ClientTxPropagationInterceptor.invoke(ClientTxPropagationInterceptor.java:67)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.aspects.security.SecurityClientInterceptor.invoke(SecurityClientInterceptor.java:53)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.ejb3.remoting.IsLocalInterceptor.invoke(IsLocalInterceptor.java:74)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.ejb3.stateless.StatelessRemoteProxy.invoke(StatelessRemoteProxy.java:107)
      at $Proxy0.getConnectedToNodes(Unknown Source)
      at org.EAOtest.main(EAOtest.java:121)
      at org.jboss.aspects.remoting.InvokeRemoteInterceptor.invoke(InvokeRemoteInterceptor.java:74)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.aspects.tx.ClientTxPropagationInterceptor.invoke(ClientTxPropagationInterceptor.java:67)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.aspects.security.SecurityClientInterceptor.invoke(SecurityClientInterceptor.java:53)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.ejb3.remoting.IsLocalInterceptor.invoke(IsLocalInterceptor.java:74)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.ejb3.stateless.StatelessRemoteProxy.invoke(StatelessRemoteProxy.java:107)
      at $Proxy0.getConnectedToNodes(Unknown Source)
      at org.EAOtest.main(EAOtest.java:121)
      Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [org.softwood.neilsapp.model.node.Node#1] at org.hibernate.event.def.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:261)
      at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:120)
      at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:53)
      at org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:677)
      at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:661)
      at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:665)
      at org.hibernate.ejb.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:227)
      at org.jboss.ejb3.entity.TransactionScopedEntityManager.merge(TransactionScopedEntityManager.java:188)
      at org.softwood.neilsapp.eao.NodeEAOBean.getConnectedToNodes(NodeEAOBean.java:135)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
      at java.lang.reflect.Method.invoke(Unknown Source)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:112)
      at org.jboss.ejb3.interceptor.InvocationContextImpl.proceed(InvocationContextImpl.java:166)
      at org.jboss.ejb3.interceptor.EJB3InterceptorsInterceptor.invoke(EJB3InterceptorsInterceptor.java:63)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.ejb3.entity.TransactionScopedEntityManagerInterceptor.invoke(TransactionScopedEntityManagerInterceptor.java:54)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.ejb3.AllowedOperationsInterceptor.invoke(AllowedOperationsInterceptor.java:47)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.aspects.tx.TxPolicy.invokeInOurTx(TxPolicy.java:79)
      at org.jboss.aspects.tx.TxInterceptor$Required.invoke(TxInterceptor.java:191)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.aspects.tx.TxPropagationInterceptor.invoke(TxPropagationInterceptor.java:95)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.ejb3.stateless.StatelessInstanceInterceptor.invoke(StatelessInstanceInterceptor.java:62)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.aspects.security.AuthenticationInterceptor.invoke(AuthenticationInterceptor.java:77)
      at org.jboss.ejb3.security.Ejb3AuthenticationInterceptor.invoke(Ejb3AuthenticationInterceptor.java:110)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.ejb3.ENCPropagationInterceptor.invoke(ENCPropagationInterceptor.java:46)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.ejb3.asynchronous.AsynchronousInterceptor.invoke(AsynchronousInterceptor.java:106)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.ejb3.stateless.StatelessContainer.dynamicInvoke(StatelessContainer.java:304)
      at org.jboss.aop.Dispatcher.invoke(Dispatcher.java:106)
      at org.jboss.aspects.remoting.AOPRemotingInvocationHandler.invoke(AOPRemotingInvocationHandler.java:82)
      at org.jboss.remoting.ServerInvoker.invoke(ServerInvoker.java:769)
      at org.jboss.remoting.transport.socket.ServerThread.processInvocation(ServerThread.java:573)
      at org.jboss.remoting.transport.socket.ServerThread.dorun(ServerThread.java:373)
      at org.jboss.remoting.transport.socket.ServerThread.run(ServerThread.java:166)




      WHat is wrong here - each method in the bean is defined as tranasctional - so when the delete action is run doesnt the persistence context flushed?.

      If so when i run the next query method - which passes the original node as base of the search and merge that inside a new transaction do I get this optimistic error.

      if i try to debug this from eclipse i get another error from the server which says a transaction isnt active ! bizarre as its got the required annotation for the method

      HELP please anyone who can understand whats wrong.



      Exception in thread "main" java.lang.IllegalStateException: [com.arjuna.ats.internal.jta.transaction.arjunacore.inactive] [com.arjuna.ats.internal.jta.transaction.arjunacore.inactive] The transaction is not active! at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.commitAndDisassociate(TransactionImple.java:1379)
      at com.arjuna.ats.internal.jta.transaction.arjunacore.BaseTransaction.commit(BaseTransaction.java:135)
      at com.arjuna.ats.jbossatx.BaseTransactionManagerDelegate.commit(BaseTransactionManagerDelegate.java:87)
      at org.jboss.aspects.tx.TxPolicy.endTransaction(TxPolicy.java:175)
      at org.jboss.aspects.tx.TxPolicy.invokeInOurTx(TxPolicy.java:87)
      at org.jboss.aspects.tx.TxInterceptor$Required.invoke(TxInterceptor.java:191)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.aspects.tx.TxPropagationInterceptor.invoke(TxPropagationInterceptor.java:95)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.ejb3.stateless.StatelessInstanceInterceptor.invoke(StatelessInstanceInterceptor.java:62)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.aspects.security.AuthenticationInterceptor.invoke(AuthenticationInterceptor.java:77)
      at org.jboss.ejb3.security.Ejb3AuthenticationInterceptor.invoke(Ejb3AuthenticationInterceptor.java:110)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.ejb3.ENCPropagationInterceptor.invoke(ENCPropagationInterceptor.java:46)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.ejb3.asynchronous.AsynchronousInterceptor.invoke(AsynchronousInterceptor.java:106)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.ejb3.stateless.StatelessContainer.dynamicInvoke(StatelessContainer.java:304)
      at org.jboss.aop.Dispatcher.invoke(Dispatcher.java:106)
      at org.jboss.aspects.remoting.AOPRemotingInvocationHandler.invoke(AOPRemotingInvocationHandler.java:82)
      at org.jboss.remoting.ServerInvoker.invoke(ServerInvoker.java:769)
      at org.jboss.remoting.transport.socket.ServerThread.processInvocation(ServerThread.java:573)
      at org.jboss.remoting.transport.socket.ServerThread.dorun(ServerThread.java:373)
      at org.jboss.remoting.transport.socket.ServerThread.run(ServerThread.java:166)
      at org.jboss.remoting.MicroRemoteClientInvoker.invoke(MicroRemoteClientInvoker.java:163)
      at org.jboss.remoting.Client.invoke(Client.java:1634)
      at org.jboss.remoting.Client.invoke(Client.java:548)
      at org.jboss.aspects.remoting.InvokeRemoteInterceptor.invoke(InvokeRemoteInterceptor.java:62)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.aspects.tx.ClientTxPropagationInterceptor.invoke(ClientTxPropagationInterceptor.java:67)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.aspects.security.SecurityClientInterceptor.invoke(SecurityClientInterceptor.java:53)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.ejb3.remoting.IsLocalInterceptor.invoke(IsLocalInterceptor.java:74)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.ejb3.stateless.StatelessRemoteProxy.invoke(StatelessRemoteProxy.java:107)
      at $Proxy0.removeLink(Unknown Source)
      at org.EAOtest.main(EAOtest.java:115)
      at org.jboss.aspects.remoting.InvokeRemoteInterceptor.invoke(InvokeRemoteInterceptor.java:74)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.aspects.tx.ClientTxPropagationInterceptor.invoke(ClientTxPropagationInterceptor.java:67)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.aspects.security.SecurityClientInterceptor.invoke(SecurityClientInterceptor.java:53)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.ejb3.remoting.IsLocalInterceptor.invoke(IsLocalInterceptor.java:74)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.ejb3.stateless.StatelessRemoteProxy.invoke(StatelessRemoteProxy.java:107)
      at $Proxy0.removeLink(Unknown Source)
      at org.EAOtest.main(EAOtest.java:115)





      the code for the query is defined with the entity.

      @Entity
      @Inheritance(strategy=InheritanceType.SINGLE_TABLE)
      @DiscriminatorColumn
      (name="nodeType",
       discriminatorType=DiscriminatorType.STRING)
      @DiscriminatorValue ("generic node")
      
      @NamedQueries ({
       @NamedQuery(
       name = "findLinksBetweenNodes",
       query = "SELECT l FROM Link l " +
       "WHERE (l.fromNode = :fromNode " +
       "AND l.toNode = :toNode)"
       ),
       @NamedQuery(
       name = "getLinkedNodes",
       query = "SELECT l.toNode FROM Link l " +
       "WHERE (l.fromNode = :fromNode) "
       )
       })
      public class Node implements Serializable
      {
       static final long serialVersionUID = 1;
      
       @Id @GeneratedValue
       @Column(name="nodeID")
       private Long nodeID;
      
       @Version
       private long version;
      
       //enable transitive persistence from owning node to links
       @OneToMany (mappedBy="fromNode", cascade={CascadeType.PERSIST, CascadeType.MERGE })
       @org.hibernate.annotations.Cascade(org.hibernate.annotations.CascadeType.SAVE_UPDATE)
       protected Set<Link> fromLinks;
      
       @OneToMany (mappedBy="toNode", cascade={CascadeType.PERSIST, CascadeType.MERGE })
       @org.hibernate.annotations.Cascade(org.hibernate.annotations.CascadeType.SAVE_UPDATE)
       protected Set<Link> toLinks;
      
       // not required and errors on load @Temporal (TemporalType.TIMESTAMP)
       private Timestamp lastUpdated;
      
       @Column(length=255, nullable=false) @NotNull
       private String nodeName;
      
       @Column(length=255)
       private String aliasName;
      
       //calculated: how important is this node
       private int weight;
      
       //as set by a user: how important is this node
       private int importance;
      
       public Long getID () {return nodeID;}
      
       public Node ()
       {
       //initialise the links
       toLinks = new HashSet<Link>();
       fromLinks = new HashSet<Link>();
      
       DateFormat fmt = DateFormat.getDateTimeInstance();
       nodeName = "generic node: " + fmt.format(new Date());
       }
      
       public Node (String name)
       {
       if (name != null)
       this.nodeName = name;
       else nodeName = "null";
       }
      
       public long getVersion() {return version;}
       public String getNodeName () {return nodeName;}
       public void setNodeName (String name) {this.nodeName = name;}
      
       public String getAliasName () {return aliasName;}
       public void setAliasName (String name) {this.aliasName = name;}
      
       public int getImportance () {return importance;}
       public void setImportance (int imp) {this.importance = imp;}
       public void incrementImportance () {this.importance++;}
       public void decrementImportance () {this.importance--;}
      
       public void calculateWeight ()
       {/*TODO*/};
      
       protected void setLastUpdated()
       {
       Date now = new Date();
       lastUpdated = new Timestamp (now.getTime());
       }
      
       @TransactionAttribute (TransactionAttributeType.REQUIRED)
       public Link addLinkTo (Node remoteNode)
       {
       Link aLink = new Link ();
       aLink.setName("link from " + this.getNodeName() + " to " + remoteNode.getNodeName());
       //set the link relationships
       aLink.setToNode(remoteNode);
       aLink.setFromNode(this);
       //set the node relationships to the joining link
       this.setLinkTo(aLink);
       remoteNode.setLinkFrom(aLink);
      
       //return the new link
       return aLink;
       }
      
       public Set<Link> getLinkTo ()
       {
       return toLinks;
       }
      
       public void setLinkTo (Link link)
       {
       toLinks.add(link);
       }
      
       public void deleteLinkTo (Link link)
       {
       toLinks.remove(link);
       }
      
       public Set<Link> getLinkFrom ()
       {
       return fromLinks;
       }
      
       public void setLinkFrom (Link link)
       {
       fromLinks.add(link);
       }
      
       public void deleteLinkFrom (Link link)
       {
       fromLinks.remove(link);
       }
      }
      




        • 1. Re: problems with optimistic locking/persistence data in EJB
          waynebaylor

          my guess is that the problem lies with the @Version field. you may be inadvertently incrementing the entity's version, so when you try to merge hibernate thinks the object is out of date.

          • 2. Re: problems with optimistic locking/persistence data in EJB
            wiggy

            I'm thinking the same way - but dont know how to fix it!

            the delete action updates the version number from the previous transaction.

            ----------
            ---- | ----- |
            | | ---> | | | |
            ----- | ------ |
            ----------

            client AS server and EJB server code

            ... container based delete action that updates the DB and increments the version i'ds on the DB . Server code ...
            
            @TransactionAttribute (TransactionAttributeType.REQUIRED)
             public boolean removeLink (Node fromNode, Node remoteNode)
             {
            
             List<Link> qres;
             Logger log = Logger.getLogger("NodeEAOBean");
             log.setLevel(org.apache.log4j.Level.DEBUG);
            
             if (fromNode == null || remoteNode == null)
             {
             log.error("was passed a null reference");
             return false;
             }
            
             fromNode = em.merge(fromNode);
             remoteNode = em.merge(remoteNode);
             Query q = em.createNamedQuery("findLinksBetweenNodes");
             q.setParameter("toNode", remoteNode);
             q.setParameter("fromNode", fromNode);
            
             log.debug("to node details " + remoteNode.getNodeName() + "\n");
            
             qres = (List<Link>)q.getResultList();
             if (qres != null && qres.size () == 1)
             {
             Link link = qres.get(0);
             remoteNode.deleteLinkFrom(link);
             fromNode.deleteLinkTo(link);
             em.remove(link);
             //fix?
             em.flush();
             return true;
             }
             else
             {return false;}
            
             }
            


            however despite the merge actions and the end of the transaction completing ( i even put the flush in and it made no difference). These changes dont get synced back to the application client (outside the container).

            so how are you supposed to get the client back in sync ? I tried a resync operation from the client like this

            ... client code - calls the remove link then tries to resynch with server
            after the the above code has ompleted...
            
             //local if (removeLink(uNode, zNode))
             if (nodeEAO.removeLink(uNode, zNode))
             {
            
             System.out.println ("deleted link : \n");
             }
            
             //update to latest version number
             yNode = nodeEAO.refresh(uNode);
            


            and this errors with the same optimistic lock exception

            on the EJB server side the refresh is implemented as

            ... generic EAO class code ...
            
             public T refresh (T entity)
             {
             entity = em.merge(entity);
             em.refresh (entity);
             return entity;
             }
            


            I thought this was going to be enough to resync the client local copy to the extant version on the DB. but the error still occurs.

            How is this supposed to work ???

            do i have to do a complete new findByID call and get a new reference from the client ? seems a bit weird - surely there is a way to update a disconnected client copy with the changes on the EJB server?

            should version managment be avoided (doesnt seem right). If not just how the heck is this supposed to work.


            thanks in advance if you can help






            • 3. Re: problems with optimistic locking/persistence data in EJB
              waynebaylor

              entities referenced by an application client (i.e. client outside of the container) are not managed. the exception you're getting is probably the container saying that the client wants to save data that is out of date.

              • 4. Re: problems with optimistic locking/persistence data in EJB
                wiggy

                wayne

                thats not all complete problem -

                as the remote debugger reported problems with the transaction failure when remote debugging into the server, i rewrote the removeLinks method in the local application client using an application scoped EM.

                that way i could run the debugger in local mode.

                 public static boolean removeLink (Node fromNode, Node remoteNode)
                 {
                 EntityManager em;
                 EntityManagerFactory emf ;
                 List<Link> res;
                 boolean result = false;
                
                 emf = Persistence.createEntityManagerFactory("embedDS");
                
                 em = emf.createEntityManager();
                
                 try
                 {
                 EntityTransaction t = em.getTransaction();
                
                 t.begin();
                 fromNode = em.merge(fromNode);
                 remoteNode = em.merge(remoteNode);
                 Query q = em.createNamedQuery("findLinksBetweenNodes");
                 q.setParameter("toNode", remoteNode);
                 q.setParameter("fromNode", fromNode);
                
                 res = (List<Link>)q.getResultList();
                 if (res != null && res.size () == 1)
                 {
                 Link link = res.get(0);
                 remoteNode.deleteLinkFrom(link);
                 fromNode.deleteLinkTo(link);
                 em.remove(link);
                 result = true;
                 }
                 else
                 {result = false;}
                
                 t.commit();
                 return result;
                 }
                 finally
                 {
                 em.close();
                 emf.close();
                 }
                
                 }
                



                this essentally throws the same optimistic lock error - so its something to do with the transaction that this lives in updates the version for the attached elements. when this completes the next step in the main application path


                
                 //local if (removeLink(uNode, zNode))
                 if (nodeEAO.removeLink(uNode, zNode))
                 {
                
                 System.out.println ("deleted link : \n");
                 }
                
                 //update to latest version number
                 yNode = nodeEAO.refresh(uNode);
                


                the code errors with optimistic lock when i try and do an em.merge within the nodeEAO.refresh routine.

                what this kind of implies i think is that i have to issue another "find" operation to reread a fresh copy of the entity back to avoid this rather than being able to "merge" the starting uNode back into the persistence context.

                Is this the only/correct way to proceed - or am i not understanding properly and theres a easy 'correct' fix that would allow me to avoid the exception (I havnt tried to take the version annonation of yet - and see if it handles it without the optimistic lock force enabled.



                • 5. Aarg - more guideance required
                  wiggy

                  okay so heres the latest

                  1. if a enable the @Version tag on the entity model - it gives me the optimistic lock error - even on the local resynch operation.

                  2. if disable the optimistic lock - the error disppears - however the database behavior is not as expected.

                  hers the local client code - the NodeEAO ejb runs the server. The rest as is in the client.

                  
                  public class EAOtest {
                  
                   /**
                   * @param args
                   */
                   public static void main(String[] args) throws Exception
                   {
                   InitialContext ctx;
                   DataSource ds;
                   Connection conn;
                   MessageEAO myMess;
                   NodeEAO nodeEAO;
                   LinkEAO linkEAO;
                  
                   Node aNode, bNode, cNode, uNode, zNode, yNode;
                  
                  
                   ctx = getInitialContext();
                   nodeEAO = (NodeEAO) ctx.lookup ("NeilsAppEar/NodeEAOBean/remote");
                   linkEAO = (LinkEAO) ctx.lookup ("NeilsAppEar/LinkEAOBean/remote");
                  
                   aNode = new Node();
                   bNode = new Node ();
                   cNode = new Node ();
                   uNode = new Node (); // empty
                   zNode = new Node (); // empty
                   yNode = new Node();
                  
                  
                   aNode.setNodeName("William");
                   bNode.setNodeName("10 South Close");
                   cNode.setNodeName("G01 B32");
                  
                   try
                   {
                   UserTransaction ut = (UserTransaction)ctx.lookup("UserTransaction");
                   ut.begin();
                   //now works!
                   Link aLink = aNode.addLinkTo(bNode);
                   aNode.addLinkTo(cNode);
                   //update uNode to persisted value
                   uNode = nodeEAO.save(aNode);
                  
                   ut.commit();
                   } catch (Exception e)
                   {e.printStackTrace();
                   System.exit(0);}
                  
                   System.out.println ("done/n");
                  
                  
                   Long pk = Long.valueOf(3);
                   zNode = nodeEAO.findById(pk);
                  
                  
                   //local if (removeLink(uNode, zNode))
                   if (nodeEAO.removeLink(uNode, zNode)) {
                  
                   System.out.println ("deleted link : \n");
                   }
                  
                   yNode = resynch (uNode);
                   //update to latest version number
                   yNode = nodeEAO.refresh(uNode);
                   List<Node> nodeList2 = nodeEAO.getConnectedToNodes(uNode);
                   if (nodeList2 != null)
                   {
                   for (Node n : nodeList2 )
                   {
                   System.out.println ("got connected node : " + n.getNodeName() + "/n");
                   }
                   }
                   else
                   System.out.println ("got empty connection : /n");
                  
                   }
                  
                   public static boolean removeLink (Node fromNode, Node remoteNode)
                   {
                   EntityManager em;
                   EntityManagerFactory emf ;
                   List<Link> res;
                   boolean result = false;
                  
                   emf = Persistence.createEntityManagerFactory("embedDS");
                  
                   em = emf.createEntityManager();
                  
                   try
                   {
                   EntityTransaction t = em.getTransaction();
                  
                   t.begin();
                   fromNode = em.merge(fromNode);
                   remoteNode = em.merge(remoteNode);
                   Query q = em.createNamedQuery("findLinksBetweenNodes");
                   q.setParameter("toNode", remoteNode);
                   q.setParameter("fromNode", fromNode);
                  
                   res = (List<Link>)q.getResultList();
                   if (res != null && res.size () == 1)
                   {
                   Link link = res.get(0);
                   remoteNode.deleteLinkFrom(link);
                   fromNode.deleteLinkTo(link);
                   em.remove(link);
                   result = true;
                   }
                   else
                   {result = false;}
                  
                   t.commit();
                   return result;
                   }
                   finally
                   {
                   em.close();
                   emf.close();
                   }
                  
                   }
                  
                   public static Node resynch (Node fromNode)
                   {
                   EntityManager em;
                   EntityManagerFactory emf ;
                   List<Link> res;
                   boolean result = false;
                  
                   emf = Persistence.createEntityManagerFactory("embedDS");
                  
                   em = emf.createEntityManager();
                  
                   try
                   {
                   EntityTransaction t = em.getTransaction();
                  
                   t.begin();
                   fromNode = em.merge(fromNode);
                   em.refresh(fromNode);
                  
                   t.commit();
                   return fromNode;
                   }
                   finally
                   {
                   em.close();
                   emf.close();
                   }
                  
                   }
                  
                   public static InitialContext getInitialContext() throws Exception
                   {
                   Hashtable<String,String> props = getInitialContextProperties();
                   return new InitialContext(props);
                   }
                  
                   private static Hashtable<String,String> getInitialContextProperties()
                   {
                   Hashtable<String,String> props = new Hashtable<String,String>();
                   // fails corrected version below : props.put("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
                   props.put("java.naming.factory.initial", "org.jboss.naming.NamingContextFactory");
                   props.put("java.naming.provider.url", "jnp://localhost:1099");
                   props.put("java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces");
                   return props;
                   }
                  }
                  


                  so what happens

                  1) first i create an A Node, and two remote nodes, b and c.
                  I connect the a end to the b and c ends - this creates the link entities that joins the start and end node.

                  in the entity model i have transitive persistence set for PERSIST and MERGE, therefore the nodeEAO.save (aNode) - persists the whole network - this goes across from app client to ejb server.
                  hold the returned object into uNode.

                  This works okay and the DB has three nodes and 2 link records.

                  2) I then read zNode by a nodeEAO.find method (again to ejb server). This returns the 3rd node - however its been lazy loaded it appears and the Set attributes (toLinks and fromLinks) are null - and therefore cant be walked from the client.

                  heres the query from the server side.

                  23:03:29,639 INFO [STDOUT] Hibernate: select node0_.nodeID as nodeID73_0_, node0_.version as version73_0_, node0_.lastUpdated as lastUpda4_73_0_, node0_.nodeName as nodeName73_0_, node0_.aliasName as aliasName73_0_, node0_.weight as weight73_0_, node0_.importance as importance73_0_, node0_.firstName as firstName73_0_, node0_.middleName as middleName73_0_, node0_.lastName as lastName73_0_, node0_.nickName as nickName73_0_, node0_.dateOfBirth as dateOfB13_73_0_, node0_.dateOfDeath as dateOfD14_73_0_, node0_.sex as sex73_0_, node0_.nodeType as nodeType73_0_ from Node node0_ where node0_.nodeID=?


                  I think this is as the book says - if i want the Set attributes i have to force a non lazy load. Still okay i think.

                  3) i call the nodeEAO.removeLink (on the server). This seems to work okay - and the DB now has 3 nodes and 1 link left.

                  heres the sql coming out of the server this action to update A and C nodes and delete the link from A-C nodes in the DB.

                  23:05:36,121 INFO [STDOUT] Hibernate: select node0_.nodeID as nodeID73_2_, node0_.version as version73_2_, node0_.lastUpdated as lastUpda4_73_2_, node0_.nodeName as nodeName73_2_, node0_.aliasName as aliasName73_2_, node0_.weight as weight73_2_, node0_.importance as importance73_2_, node0_.firstName as firstName73_2_, node0_.middleName as middleName73_2_, node0_.lastName as lastName73_2_, node0_.nickName as nickName73_2_, node0_.dateOfBirth as dateOfB13_73_2_, node0_.dateOfDeath as dateOfD14_73_2_, node0_.sex as sex73_2_, node0_.nodeType as nodeType73_2_, fromlinks1_.fromNode_nodeID as fromNode5_4_, fromlinks1_.linkID as linkID4_, fromlinks1_.linkID as linkID70_0_, fromlinks1_.version as version70_0_, fromlinks1_.toNode_nodeID as toNode6_70_0_, fromlinks1_.fromNode_nodeID as fromNode5_70_0_, fromlinks1_.name as name70_0_, fromlinks1_.description as descript4_70_0_, node2_.nodeID as nodeID73_1_, node2_.version as version73_1_, node2_.lastUpdated as lastUpda4_73_1_, node2_.nodeName as nodeName73_1_, node2_.aliasName as aliasName73_1_, node2_.weight as weight73_1_, node2_.importance as importance73_1_, node2_.firstName as firstName73_1_, node2_.middleName as middleName73_1_, node2_.lastName as lastName73_1_, node2_.nickName as nickName73_1_, node2_.dateOfBirth as dateOfB13_73_1_, node2_.dateOfDeath as dateOfD14_73_1_, node2_.sex as sex73_1_, node2_.nodeType as nodeType73_1_ from Node node0_ left outer join Link fromlinks1_ on node0_.nodeID=fromlinks1_.fromNode_nodeID left outer join Node node2_ on fromlinks1_.toNode_nodeID=node2_.nodeID where node0_.nodeID=?
                  23:05:36,131 INFO [STDOUT] Hibernate: select fromlinks0_.fromNode_nodeID as fromNode5_2_, fromlinks0_.linkID as linkID2_, fromlinks0_.linkID as linkID70_1_, fromlinks0_.version as version70_1_, fromlinks0_.toNode_nodeID as toNode6_70_1_, fromlinks0_.fromNode_nodeID as fromNode5_70_1_, fromlinks0_.name as name70_1_, fromlinks0_.description as descript4_70_1_, node1_.nodeID as nodeID73_0_, node1_.version as version73_0_, node1_.lastUpdated as lastUpda4_73_0_, node1_.nodeName as nodeName73_0_, node1_.aliasName as aliasName73_0_, node1_.weight as weight73_0_, node1_.importance as importance73_0_, node1_.firstName as firstName73_0_, node1_.middleName as middleName73_0_, node1_.lastName as lastName73_0_, node1_.nickName as nickName73_0_, node1_.dateOfBirth as dateOfB13_73_0_, node1_.dateOfDeath as dateOfD14_73_0_, node1_.sex as sex73_0_, node1_.nodeType as nodeType73_0_ from Link fromlinks0_ left outer join Node node1_ on fromlinks0_.toNode_nodeID=node1_.nodeID where fromlinks0_.fromNode_nodeID=?
                  23:05:36,131 INFO [STDOUT] Hibernate: select fromlinks0_.fromNode_nodeID as fromNode5_2_, fromlinks0_.linkID as linkID2_, fromlinks0_.linkID as linkID70_1_, fromlinks0_.version as version70_1_, fromlinks0_.toNode_nodeID as toNode6_70_1_, fromlinks0_.fromNode_nodeID as fromNode5_70_1_, fromlinks0_.name as name70_1_, fromlinks0_.description as descript4_70_1_, node1_.nodeID as nodeID73_0_, node1_.version as version73_0_, node1_.lastUpdated as lastUpda4_73_0_, node1_.nodeName as nodeName73_0_, node1_.aliasName as aliasName73_0_, node1_.weight as weight73_0_, node1_.importance as importance73_0_, node1_.firstName as firstName73_0_, node1_.middleName as middleName73_0_, node1_.lastName as lastName73_0_, node1_.nickName as nickName73_0_, node1_.dateOfBirth as dateOfB13_73_0_, node1_.dateOfDeath as dateOfD14_73_0_, node1_.sex as sex73_0_, node1_.nodeType as nodeType73_0_ from Link fromlinks0_ left outer join Node node1_ on fromlinks0_.toNode_nodeID=node1_.nodeID where fromlinks0_.fromNode_nodeID=?
                  23:05:36,131 INFO [STDOUT] Hibernate: select tolinks0_.toNode_nodeID as toNode6_2_, tolinks0_.linkID as linkID2_, tolinks0_.linkID as linkID70_1_, tolinks0_.version as version70_1_, tolinks0_.toNode_nodeID as toNode6_70_1_, tolinks0_.fromNode_nodeID as fromNode5_70_1_, tolinks0_.name as name70_1_, tolinks0_.description as descript4_70_1_, node1_.nodeID as nodeID73_0_, node1_.version as version73_0_, node1_.lastUpdated as lastUpda4_73_0_, node1_.nodeName as nodeName73_0_, node1_.aliasName as aliasName73_0_, node1_.weight as weight73_0_, node1_.importance as importance73_0_, node1_.firstName as firstName73_0_, node1_.middleName as middleName73_0_, node1_.lastName as lastName73_0_, node1_.nickName as nickName73_0_, node1_.dateOfBirth as dateOfB13_73_0_, node1_.dateOfDeath as dateOfD14_73_0_, node1_.sex as sex73_0_, node1_.nodeType as nodeType73_0_ from Link tolinks0_ left outer join Node node1_ on tolinks0_.fromNode_nodeID=node1_.nodeID where tolinks0_.toNode_nodeID=?
                  23:05:36,141 INFO [STDOUT] Hibernate: select link0_.linkID as linkID70_, link0_.version as version70_, link0_.toNode_nodeID as toNode6_70_, link0_.fromNode_nodeID as fromNode5_70_, link0_.name as name70_, link0_.description as descript4_70_ from Link link0_ where link0_.fromNode_nodeID=? and link0_.toNode_nodeID=?
                  23:05:36,151 INFO [STDOUT] Hibernate: delete from Link where linkID=?


                  however the entity updates are not returned as objects via serialisation to the client (think this probably the first problem here as uNode still shows two links to original bNode and cNode. Therefore now out of date relative to DB.

                  4. I then call the local resync method - thinking to reset the uNode back to the DB

                  however the initial merge action - actually calls a new create - so i get two links back and three nodes still.

                  Hibernate: select node0_.nodeID as nodeID0_2_, node0_.version as version0_2_, node0_.lastUpdated as lastUpda4_0_2_, node0_.nodeName as nodeName0_2_, node0_.aliasName as aliasName0_2_, node0_.weight as weight0_2_, node0_.importance as importance0_2_, fromlinks1_.fromNode_nodeID as fromNode6_4_, fromlinks1_.linkID as linkID4_, fromlinks1_.linkID as linkID1_0_, fromlinks1_.version as version1_0_, fromlinks1_.toNode_nodeID as toNode5_1_0_, fromlinks1_.fromNode_nodeID as fromNode6_1_0_, fromlinks1_.name as name1_0_, fromlinks1_.description as descript4_1_0_, node2_.nodeID as nodeID0_1_, node2_.version as version0_1_, node2_.lastUpdated as lastUpda4_0_1_, node2_.nodeName as nodeName0_1_, node2_.aliasName as aliasName0_1_, node2_.weight as weight0_1_, node2_.importance as importance0_1_ from Node node0_ left outer join Link fromlinks1_ on node0_.nodeID=fromlinks1_.fromNode_nodeID left outer join Node node2_ on fromlinks1_.toNode_nodeID=node2_.nodeID where node0_.nodeID=?
                  Hibernate: select link0_.linkID as linkID1_2_, link0_.version as version1_2_, link0_.toNode_nodeID as toNode5_1_2_, link0_.fromNode_nodeID as fromNode6_1_2_, link0_.name as name1_2_, link0_.description as descript4_1_2_, node1_.nodeID as nodeID0_0_, node1_.version as version0_0_, node1_.lastUpdated as lastUpda4_0_0_, node1_.nodeName as nodeName0_0_, node1_.aliasName as aliasName0_0_, node1_.weight as weight0_0_, node1_.importance as importance0_0_, fromlinks2_.fromNode_nodeID as fromNode6_4_, fromlinks2_.linkID as linkID4_, fromlinks2_.linkID as linkID1_1_, fromlinks2_.version as version1_1_, fromlinks2_.toNode_nodeID as toNode5_1_1_, fromlinks2_.fromNode_nodeID as fromNode6_1_1_, fromlinks2_.name as name1_1_, fromlinks2_.description as descript4_1_1_ from Link link0_ left outer join Node node1_ on link0_.toNode_nodeID=node1_.nodeID left outer join Link fromlinks2_ on node1_.nodeID=fromlinks2_.fromNode_nodeID where link0_.linkID=?
                  Hibernate: select node0_.nodeID as nodeID0_2_, node0_.version as version0_2_, node0_.lastUpdated as lastUpda4_0_2_, node0_.nodeName as nodeName0_2_, node0_.aliasName as aliasName0_2_, node0_.weight as weight0_2_, node0_.importance as importance0_2_, fromlinks1_.fromNode_nodeID as fromNode6_4_, fromlinks1_.linkID as linkID4_, fromlinks1_.linkID as linkID1_0_, fromlinks1_.version as version1_0_, fromlinks1_.toNode_nodeID as toNode5_1_0_, fromlinks1_.fromNode_nodeID as fromNode6_1_0_, fromlinks1_.name as name1_0_, fromlinks1_.description as descript4_1_0_, node2_.nodeID as nodeID0_1_, node2_.version as version0_1_, node2_.lastUpdated as lastUpda4_0_1_, node2_.nodeName as nodeName0_1_, node2_.aliasName as aliasName0_1_, node2_.weight as weight0_1_, node2_.importance as importance0_1_ from Node node0_ left outer join Link fromlinks1_ on node0_.nodeID=fromlinks1_.fromNode_nodeID left outer join Node node2_ on fromlinks1_.toNode_nodeID=node2_.nodeID where node0_.nodeID=?
                  Hibernate: insert into Link (version, toNode_nodeID, fromNode_nodeID, name, description) values (?, ?, ?, ?, ?)
                  Hibernate: select fromlinks0_.fromNode_nodeID as fromNode6_2_, fromlinks0_.linkID as linkID2_, fromlinks0_.linkID as linkID1_1_, fromlinks0_.version as version1_1_, fromlinks0_.toNode_nodeID as toNode5_1_1_, fromlinks0_.fromNode_nodeID as fromNode6_1_1_, fromlinks0_.name as name1_1_, fromlinks0_.description as descript4_1_1_, node1_.nodeID as nodeID0_0_, node1_.version as version0_0_, node1_.lastUpdated as lastUpda4_0_0_, node1_.nodeName as nodeName0_0_, node1_.aliasName as aliasName0_0_, node1_.weight as weight0_0_, node1_.importance as importance0_0_ from Link fromlinks0_ left outer join Node node1_ on fromlinks0_.toNode_nodeID=node1_.nodeID where fromlinks0_.fromNode_nodeID=?
                  Hibernate: select tolinks0_.toNode_nodeID as toNode5_2_, tolinks0_.linkID as linkID2_, tolinks0_.linkID as linkID1_1_, tolinks0_.version as version1_1_, tolinks0_.toNode_nodeID as toNode5_1_1_, tolinks0_.fromNode_nodeID as fromNode6_1_1_, tolinks0_.name as name1_1_, tolinks0_.description as descript4_1_1_, node1_.nodeID as nodeID0_0_, node1_.version as version0_0_, node1_.lastUpdated as lastUpda4_0_0_, node1_.nodeName as nodeName0_0_, node1_.aliasName as aliasName0_0_, node1_.weight as weight0_0_, node1_.importance as importance0_0_ from Link tolinks0_ left outer join Node node1_ on tolinks0_.fromNode_nodeID=node1_.nodeID where tolinks0_.toNode_nodeID=?


                  the em.refresh call just causes the following query


                  Hibernate: select node0_.nodeID as nodeID0_0_, node0_.version as version0_0_, node0_.lastUpdated as lastUpda4_0_0_, node0_.nodeName as nodeName0_0_, node0_.aliasName as aliasName0_0_, node0_.weight as weight0_0_, node0_.importance as importance0_0_ from Node node0_ where node0_.nodeID=?


                  thus the 'refresh' has just reinserted the link i just deleted remotely vian the nodeEAO.removeLink previously called. Presumably because the uNode passed in to resynch was a pointer to the network originally peristed in step 1!

                  worse the yNode returned to main has no toLinks/fromLink Set attributes set at all - they come back null - i expected this to come back with a proxy set - though as its loaded lazily it would have errored with lazy initialisation fail. However - this would fail with null pointer.

                  Is this the expected behaviour for the code? doesnt feel right.



                  5 i then call the same function on my server (essentially a merge and refresh call) and get the following trace on the server



                  23:22:23,500 INFO [STDOUT] Hibernate: select node0_.nodeID as nodeID73_2_, node0_.version as version73_2_, node0_.lastUpdated as lastUpda4_73_2_, node0_.nodeName as nodeName73_2_, node0_.aliasName as aliasName73_2_, node0_.weight as weight73_2_, node0_.importance as importance73_2_, node0_.firstName as firstName73_2_, node0_.middleName as middleName73_2_, node0_.lastName as lastName73_2_, node0_.nickName as nickName73_2_, node0_.dateOfBirth as dateOfB13_73_2_, node0_.dateOfDeath as dateOfD14_73_2_, node0_.sex as sex73_2_, node0_.nodeType as nodeType73_2_, fromlinks1_.fromNode_nodeID as fromNode5_4_, fromlinks1_.linkID as linkID4_, fromlinks1_.linkID as linkID70_0_, fromlinks1_.version as version70_0_, fromlinks1_.toNode_nodeID as toNode6_70_0_, fromlinks1_.fromNode_nodeID as fromNode5_70_0_, fromlinks1_.name as name70_0_, fromlinks1_.description as descript4_70_0_, node2_.nodeID as nodeID73_1_, node2_.version as version73_1_, node2_.lastUpdated as lastUpda4_73_1_, node2_.nodeName as nodeName73_1_, node2_.aliasName as aliasName73_1_, node2_.weight as weight73_1_, node2_.importance as importance73_1_, node2_.firstName as firstName73_1_, node2_.middleName as middleName73_1_, node2_.lastName as lastName73_1_, node2_.nickName as nickName73_1_, node2_.dateOfBirth as dateOfB13_73_1_, node2_.dateOfDeath as dateOfD14_73_1_, node2_.sex as sex73_1_, node2_.nodeType as nodeType73_1_ from Node node0_ left outer join Link fromlinks1_ on node0_.nodeID=fromlinks1_.fromNode_nodeID left outer join Node node2_ on fromlinks1_.toNode_nodeID=node2_.nodeID where node0_.nodeID=?
                  23:22:23,530 INFO [STDOUT] Hibernate: select link0_.linkID as linkID70_2_, link0_.version as version70_2_, link0_.toNode_nodeID as toNode6_70_2_, link0_.fromNode_nodeID as fromNode5_70_2_, link0_.name as name70_2_, link0_.description as descript4_70_2_, node1_.nodeID as nodeID73_0_, node1_.version as version73_0_, node1_.lastUpdated as lastUpda4_73_0_, node1_.nodeName as nodeName73_0_, node1_.aliasName as aliasName73_0_, node1_.weight as weight73_0_, node1_.importance as importance73_0_, node1_.firstName as firstName73_0_, node1_.middleName as middleName73_0_, node1_.lastName as lastName73_0_, node1_.nickName as nickName73_0_, node1_.dateOfBirth as dateOfB13_73_0_, node1_.dateOfDeath as dateOfD14_73_0_, node1_.sex as sex73_0_, node1_.nodeType as nodeType73_0_, fromlinks2_.fromNode_nodeID as fromNode5_4_, fromlinks2_.linkID as linkID4_, fromlinks2_.linkID as linkID70_1_, fromlinks2_.version as version70_1_, fromlinks2_.toNode_nodeID as toNode6_70_1_, fromlinks2_.fromNode_nodeID as fromNode5_70_1_, fromlinks2_.name as name70_1_, fromlinks2_.description as descript4_70_1_ from Link link0_ left outer join Node node1_ on link0_.toNode_nodeID=node1_.nodeID left outer join Link fromlinks2_ on node1_.nodeID=fromlinks2_.fromNode_nodeID where link0_.linkID=?
                  23:22:23,530 INFO [STDOUT] Hibernate: select fromlinks0_.fromNode_nodeID as fromNode5_2_, fromlinks0_.linkID as linkID2_, fromlinks0_.linkID as linkID70_1_, fromlinks0_.version as version70_1_, fromlinks0_.toNode_nodeID as toNode6_70_1_, fromlinks0_.fromNode_nodeID as fromNode5_70_1_, fromlinks0_.name as name70_1_, fromlinks0_.description as descript4_70_1_, node1_.nodeID as nodeID73_0_, node1_.version as version73_0_, node1_.lastUpdated as lastUpda4_73_0_, node1_.nodeName as nodeName73_0_, node1_.aliasName as aliasName73_0_, node1_.weight as weight73_0_, node1_.importance as importance73_0_, node1_.firstName as firstName73_0_, node1_.middleName as middleName73_0_, node1_.lastName as lastName73_0_, node1_.nickName as nickName73_0_, node1_.dateOfBirth as dateOfB13_73_0_, node1_.dateOfDeath as dateOfD14_73_0_, node1_.sex as sex73_0_, node1_.nodeType as nodeType73_0_ from Link fromlinks0_ left outer join Node node1_ on fromlinks0_.toNode_nodeID=node1_.nodeID where fromlinks0_.fromNode_nodeID=?
                  23:22:23,530 INFO [STDOUT] Hibernate: insert into Link (version, toNode_nodeID, fromNode_nodeID, name, description) values (?, ?, ?, ?, ?)
                  23:22:23,540 INFO [STDOUT] Hibernate: select fromlinks0_.fromNode_nodeID as fromNode5_2_, fromlinks0_.linkID as linkID2_, fromlinks0_.linkID as linkID70_1_, fromlinks0_.version as version70_1_, fromlinks0_.toNode_nodeID as toNode6_70_1_, fromlinks0_.fromNode_nodeID as fromNode5_70_1_, fromlinks0_.name as name70_1_, fromlinks0_.description as descript4_70_1_, node1_.nodeID as nodeID73_0_, node1_.version as version73_0_, node1_.lastUpdated as lastUpda4_73_0_, node1_.nodeName as nodeName73_0_, node1_.aliasName as aliasName73_0_, node1_.weight as weight73_0_, node1_.importance as importance73_0_, node1_.firstName as firstName73_0_, node1_.middleName as middleName73_0_, node1_.lastName as lastName73_0_, node1_.nickName as nickName73_0_, node1_.dateOfBirth as dateOfB13_73_0_, node1_.dateOfDeath as dateOfD14_73_0_, node1_.sex as sex73_0_, node1_.nodeType as nodeType73_0_ from Link fromlinks0_ left outer join Node node1_ on fromlinks0_.toNode_nodeID=node1_.nodeID where fromlinks0_.fromNode_nodeID=?
                  23:22:23,540 INFO [STDOUT] Hibernate: select tolinks0_.toNode_nodeID as toNode6_2_, tolinks0_.linkID as linkID2_, tolinks0_.linkID as linkID70_1_, tolinks0_.version as version70_1_, tolinks0_.toNode_nodeID as toNode6_70_1_, tolinks0_.fromNode_nodeID as fromNode5_70_1_, tolinks0_.name as name70_1_, tolinks0_.description as descript4_70_1_, node1_.nodeID as nodeID73_0_, node1_.version as version73_0_, node1_.lastUpdated as lastUpda4_73_0_, node1_.nodeName as nodeName73_0_, node1_.aliasName as aliasName73_0_, node1_.weight as weight73_0_, node1_.importance as importance73_0_, node1_.firstName as firstName73_0_, node1_.middleName as middleName73_0_, node1_.lastName as lastName73_0_, node1_.nickName as nickName73_0_, node1_.dateOfBirth as dateOfB13_73_0_, node1_.dateOfDeath as dateOfD14_73_0_, node1_.sex as sex73_0_, node1_.nodeType as nodeType73_0_ from Link tolinks0_ left outer join Node node1_ on tolinks0_.fromNode_nodeID=node1_.nodeID where tolinks0_.toNode_nodeID=?
                  23:22:23,540 INFO [STDOUT] Hibernate: select node0_.nodeID as nodeID73_0_, node0_.version as version73_0_, node0_.lastUpdated as lastUpda4_73_0_, node0_.nodeName as nodeName73_0_, node0_.aliasName as aliasName73_0_, node0_.weight as weight73_0_, node0_.importance as importance73_0_, node0_.firstName as firstName73_0_, node0_.middleName as middleName73_0_, node0_.lastName as lastName73_0_, node0_.nickName as nickName73_0_, node0_.dateOfBirth as dateOfB13_73_0_, node0_.dateOfDeath as dateOfD14_73_0_, node0_.sex as sex73_0_, node0_.nodeType as nodeType73_0_ from Node node0_ where node0_.nodeID=?
                  23:22:23,800 WARN [LoadContexts] fail-safe cleanup (collections) : org.hibernate.engine.loading.CollectionLoadContext@137695c<rs=com.mysql.jdbc.ResultSet@3d0d64>


                  this action inserts yet one more link into the links table - i now have three links and 3 nodes - the last two links appear to be the same i.e they both link node A to node C.

                  7. Lastly i call a query on the server to reuturn the number of nodes connected to my uNode (still pointing to original graph returned from the first persist action.

                  This query - forces a new Link to be created - god knows how. I know have 4 links the last three of which are the same and link A to C!

                  heres the trace.



                  23:29:06,099 INFO [STDOUT] Hibernate: select node0_.nodeID as nodeID73_2_, node0_.version as version73_2_, node0_.lastUpdated as lastUpda4_73_2_, node0_.nodeName as nodeName73_2_, node0_.aliasName as aliasName73_2_, node0_.weight as weight73_2_, node0_.importance as importance73_2_, node0_.firstName as firstName73_2_, node0_.middleName as middleName73_2_, node0_.lastName as lastName73_2_, node0_.nickName as nickName73_2_, node0_.dateOfBirth as dateOfB13_73_2_, node0_.dateOfDeath as dateOfD14_73_2_, node0_.sex as sex73_2_, node0_.nodeType as nodeType73_2_, fromlinks1_.fromNode_nodeID as fromNode5_4_, fromlinks1_.linkID as linkID4_, fromlinks1_.linkID as linkID70_0_, fromlinks1_.version as version70_0_, fromlinks1_.toNode_nodeID as toNode6_70_0_, fromlinks1_.fromNode_nodeID as fromNode5_70_0_, fromlinks1_.name as name70_0_, fromlinks1_.description as descript4_70_0_, node2_.nodeID as nodeID73_1_, node2_.version as version73_1_, node2_.lastUpdated as lastUpda4_73_1_, node2_.nodeName as nodeName73_1_, node2_.aliasName as aliasName73_1_, node2_.weight as weight73_1_, node2_.importance as importance73_1_, node2_.firstName as firstName73_1_, node2_.middleName as middleName73_1_, node2_.lastName as lastName73_1_, node2_.nickName as nickName73_1_, node2_.dateOfBirth as dateOfB13_73_1_, node2_.dateOfDeath as dateOfD14_73_1_, node2_.sex as sex73_1_, node2_.nodeType as nodeType73_1_ from Node node0_ left outer join Link fromlinks1_ on node0_.nodeID=fromlinks1_.fromNode_nodeID left outer join Node node2_ on fromlinks1_.toNode_nodeID=node2_.nodeID where node0_.nodeID=?
                  23:29:06,129 INFO [STDOUT] Hibernate: select link0_.linkID as linkID70_2_, link0_.version as version70_2_, link0_.toNode_nodeID as toNode6_70_2_, link0_.fromNode_nodeID as fromNode5_70_2_, link0_.name as name70_2_, link0_.description as descript4_70_2_, node1_.nodeID as nodeID73_0_, node1_.version as version73_0_, node1_.lastUpdated as lastUpda4_73_0_, node1_.nodeName as nodeName73_0_, node1_.aliasName as aliasName73_0_, node1_.weight as weight73_0_, node1_.importance as importance73_0_, node1_.firstName as firstName73_0_, node1_.middleName as middleName73_0_, node1_.lastName as lastName73_0_, node1_.nickName as nickName73_0_, node1_.dateOfBirth as dateOfB13_73_0_, node1_.dateOfDeath as dateOfD14_73_0_, node1_.sex as sex73_0_, node1_.nodeType as nodeType73_0_, fromlinks2_.fromNode_nodeID as fromNode5_4_, fromlinks2_.linkID as linkID4_, fromlinks2_.linkID as linkID70_1_, fromlinks2_.version as version70_1_, fromlinks2_.toNode_nodeID as toNode6_70_1_, fromlinks2_.fromNode_nodeID as fromNode5_70_1_, fromlinks2_.name as name70_1_, fromlinks2_.description as descript4_70_1_ from Link link0_ left outer join Node node1_ on link0_.toNode_nodeID=node1_.nodeID left outer join Link fromlinks2_ on node1_.nodeID=fromlinks2_.fromNode_nodeID where link0_.linkID=?
                  23:29:06,129 INFO [STDOUT] Hibernate: select fromlinks0_.fromNode_nodeID as fromNode5_2_, fromlinks0_.linkID as linkID2_, fromlinks0_.linkID as linkID70_1_, fromlinks0_.version as version70_1_, fromlinks0_.toNode_nodeID as toNode6_70_1_, fromlinks0_.fromNode_nodeID as fromNode5_70_1_, fromlinks0_.name as name70_1_, fromlinks0_.description as descript4_70_1_, node1_.nodeID as nodeID73_0_, node1_.version as version73_0_, node1_.lastUpdated as lastUpda4_73_0_, node1_.nodeName as nodeName73_0_, node1_.aliasName as aliasName73_0_, node1_.weight as weight73_0_, node1_.importance as importance73_0_, node1_.firstName as firstName73_0_, node1_.middleName as middleName73_0_, node1_.lastName as lastName73_0_, node1_.nickName as nickName73_0_, node1_.dateOfBirth as dateOfB13_73_0_, node1_.dateOfDeath as dateOfD14_73_0_, node1_.sex as sex73_0_, node1_.nodeType as nodeType73_0_ from Link fromlinks0_ left outer join Node node1_ on fromlinks0_.toNode_nodeID=node1_.nodeID where fromlinks0_.fromNode_nodeID=?
                  23:29:06,139 INFO [STDOUT] Hibernate: insert into Link (version, toNode_nodeID, fromNode_nodeID, name, description) values (?, ?, ?, ?, ?)
                  23:29:06,139 INFO [STDOUT] Hibernate: select fromlinks0_.fromNode_nodeID as fromNode5_2_, fromlinks0_.linkID as linkID2_, fromlinks0_.linkID as linkID70_1_, fromlinks0_.version as version70_1_, fromlinks0_.toNode_nodeID as toNode6_70_1_, fromlinks0_.fromNode_nodeID as fromNode5_70_1_, fromlinks0_.name as name70_1_, fromlinks0_.description as descript4_70_1_, node1_.nodeID as nodeID73_0_, node1_.version as version73_0_, node1_.lastUpdated as lastUpda4_73_0_, node1_.nodeName as nodeName73_0_, node1_.aliasName as aliasName73_0_, node1_.weight as weight73_0_, node1_.importance as importance73_0_, node1_.firstName as firstName73_0_, node1_.middleName as middleName73_0_, node1_.lastName as lastName73_0_, node1_.nickName as nickName73_0_, node1_.dateOfBirth as dateOfB13_73_0_, node1_.dateOfDeath as dateOfD14_73_0_, node1_.sex as sex73_0_, node1_.nodeType as nodeType73_0_ from Link fromlinks0_ left outer join Node node1_ on fromlinks0_.toNode_nodeID=node1_.nodeID where fromlinks0_.fromNode_nodeID=?
                  23:29:06,139 INFO [STDOUT] Hibernate: select tolinks0_.toNode_nodeID as toNode6_2_, tolinks0_.linkID as linkID2_, tolinks0_.linkID as linkID70_1_, tolinks0_.version as version70_1_, tolinks0_.toNode_nodeID as toNode6_70_1_, tolinks0_.fromNode_nodeID as fromNode5_70_1_, tolinks0_.name as name70_1_, tolinks0_.description as descript4_70_1_, node1_.nodeID as nodeID73_0_, node1_.version as version73_0_, node1_.lastUpdated as lastUpda4_73_0_, node1_.nodeName as nodeName73_0_, node1_.aliasName as aliasName73_0_, node1_.weight as weight73_0_, node1_.importance as importance73_0_, node1_.firstName as firstName73_0_, node1_.middleName as middleName73_0_, node1_.lastName as lastName73_0_, node1_.nickName as nickName73_0_, node1_.dateOfBirth as dateOfB13_73_0_, node1_.dateOfDeath as dateOfD14_73_0_, node1_.sex as sex73_0_, node1_.nodeType as nodeType73_0_ from Link tolinks0_ left outer join Node node1_ on tolinks0_.fromNode_nodeID=node1_.nodeID where tolinks0_.toNode_nodeID=?
                  23:29:06,149 INFO [STDOUT] Hibernate: select node0_.nodeID as nodeID73_0_, node0_.version as version73_0_, node0_.lastUpdated as lastUpda4_73_0_, node0_.nodeName as nodeName73_0_, node0_.aliasName as aliasName73_0_, node0_.weight as weight73_0_, node0_.importance as importance73_0_, node0_.firstName as firstName73_0_, node0_.middleName as middleName73_0_, node0_.lastName as lastName73_0_, node0_.nickName as nickName73_0_, node0_.dateOfBirth as dateOfB13_73_0_, node0_.dateOfDeath as dateOfD14_73_0_, node0_.sex as sex73_0_, node0_.nodeType as nodeType73_0_ from Node node0_ where node0_.nodeID=?
                  23:29:06,149 INFO [STDOUT] Hibernate: select node1_.nodeID as nodeID73_, node1_.version as version73_, node1_.lastUpdated as lastUpda4_73_, node1_.nodeName as nodeName73_, node1_.aliasName as aliasName73_, node1_.weight as weight73_, node1_.importance as importance73_, node1_.firstName as firstName73_, node1_.middleName as middleName73_, node1_.lastName as lastName73_, node1_.nickName as nickName73_, node1_.dateOfBirth as dateOfB13_73_, node1_.dateOfDeath as dateOfD14_73_, node1_.sex as sex73_, node1_.nodeType as nodeType73_ from Link link0_ inner join Node node1_ on link0_.toNode_nodeID=node1_.nodeID where link0_.fromNode_nodeID=?
                  23:29:06,189 WARN [LoadContexts] fail-safe cleanup (collections) : org.hibernate.engine.loading.CollectionLoadContext@acca00<rs=com.mysql.jdbc.ResultSet@5babce>


                  heres the server based method that calls the query

                   @TransactionAttribute (TransactionAttributeType.REQUIRED)
                   public List<Node> getConnectedToNodes (Node fromNode)
                   {
                   Logger log = Logger.getLogger("NodeEAOBean");
                   log.setLevel(org.apache.log4j.Level.DEBUG);
                  
                   if (fromNode == null )
                   {
                   log.error("was passed a null reference");
                   return null;
                   }
                  
                   fromNode = this.refresh(fromNode);
                   Query q = em.createNamedQuery("getLinkedNodes");
                   q.setParameter("fromNode", fromNode);
                  
                   return (List<Node>)q.getResultList();
                  
                   }
                  


                  the this.refresh - calls a merge and fresh on the EM - presumably this somehow triggered the new insert.

                  So there you have it - I am somewhat confused and lost here.

                  - turning on versioning gets the optimistic lock exception as the version seen from the server is not aligned and passed back to the client.

                  if i turn versioing off - it doesnt error just does weird things and creates two many links in the db when i try to resyn locally (or remotely).

                  Can you help me unravel what I am doing wrong in my thinking and get myself back on track!

                  I'd swear so far that the overhead in getting my head round this has cost me more than the hack out a bit of sql you'd have written in olden days ..

                  Aaarg.




                  • 6. Re: problems with optimistic locking/persistence data in EJB
                    waynebaylor

                    for the client side: what you see is the correct behavior.

                    in your removeLink method, when you execute

                    fromNode = em.merge(fromNode);
                    remoteNode = em.merge(remoteNode);

                    you're losing the references to the client's entities uNode and zNode. so when you call resynch(uNode) you're merging the old state over the changes that were just made.

                    for the server side: it's hard to tell what code is being executed, but the behavior will be different since the entities are managed.

                    • 7. Re: problems with optimistic locking/persistence data in EJB
                      wiggy

                      Wayne,

                      thanks for the comment - been off line getting an arthroscopy so just picked up your reply .

                      I think I still have a copy of problems here that i cant make sense of.

                      I can see that the client has serialised the uNode/Znode and passed this to the server which has run the NodeEAO.Remove method - and therefore whilst the local references held at the server are updated - there is no return and therefore the client still references a local proxy thats now out of step with the server.

                      however what i then do is try to resynchronise my local copy uNode against the database. I do this on the client side - just cos its easier to work with the debugger and watch it.

                      client side ...
                      
                       //call server side delete action in EJB
                       // this successfuly deletes the link in the DB
                       // but doesnt update the local uNode
                       if (nodeEAO.removeLink(uNode, zNode))
                       {
                      
                       System.out.println ("deleted link : \n");
                       }
                      
                       //try a local resynch to get in step
                       yNode = resynch (uNode);
                      



                      This has behaves as follows. The now stale uNode is passed into this routine. I create a local Entity Manager (dont go to the server this time) and try and merge the uNode to a persistence context.

                      The merge action queues an update to the database as the stale uNode has two link references (whereas the database now has one because of the previous remove action).

                      I then call the em.refresh action - hoping to resync the uNode with the DB - however the previous queued updated kicks in first and it the DB is left with new links added (i have transitive persist/merge set on the uNode.myLinks collection)

                      what i expected to have happen was that the instance would be overwritten by the refresh - but the queued merge kicks in first.

                      
                       public static Node resynch (Node fromNode)
                       {
                       EntityManager em;
                       EntityManagerFactory emf ;
                       List<Link> res;
                       boolean result = false;
                      
                       emf = Persistence.createEntityManagerFactory("embedDS");
                      
                       em = emf.createEntityManager();
                      
                       try
                       {
                       EntityTransaction t = em.getTransaction();
                      
                       t.begin();
                       //queues an update from stale uNode
                       Node mergedNode = em.merge(fromNode);
                      
                       //refresh reads back queued model
                       em.refresh(mergedNode);
                      
                       t.commit();
                       return mergedNode;
                       }
                       finally
                       {
                       em.close();
                       emf.close();
                       }
                      
                       }
                      
                      
                      


                      This code actually puts the link back in the DB that i'd just deleteted on the server.

                      so i dont understand how refresh is supposed to work - I thought it was supposed to update the instance you merge with the current DB state - (effectively an undo action). In reality my stale data gets recommitted and I cant refresh the node as expected.

                      How am I supposed to resync a current client copy after the call on the server. Do i have to just just a em.find /query to get latest.

                      I dont understand what the books tell me vs what I see when i watch the code go through in the debugger and watch the db



                      • 8. Re: problems with optimistic locking/persistence data in EJB
                        wiggy

                        okay - still dont get this at all !

                        i've just watched the code through the debugger again - heres what i see on the hibernate sql console

                        heres the client code again

                        
                         if (nodeEAO.removeLink(uNode, zNode))
                         {
                        
                         System.out.println ("deleted link : \n");
                         }
                        
                         //now just calls a local em.find to get db copy
                         yNode = resynch (uNode);
                        
                         //then call server side refresh (merge - then refresh
                         yNode = nodeEAO.refresh(uNode);
                        
                         List<Node> nodeList2 = nodeEAO.getConnectedToNodes(uNode); if (nodeList2 != null)
                         {
                         for (Node n : nodeList2 )
                         {
                         System.out.println ("got connected node : " + n.getNodeName() + "/n");
                         }
                         }
                         else
                         System.out.println ("got empty connection : /n");
                        
                         }
                        
                        


                        when i call the server side refresh action - it does a row insert !??



                        11:48:53,452 INFO [STDOUT] Hibernate: select node0_.nodeID as nodeID17_2_, node0_.version as version17_2_, node0_.lastUpdated as lastUpda4_17_2_, node0_.nodeName as nodeName17_2_, node0_.aliasName as aliasName17_2_, node0_.description as descript7_17_2_, node0_.weight as weight17_2_, node0_.importance as importance17_2_, node0_.firstName as firstName17_2_, node0_.middleName as middleName17_2_, node0_.lastName as lastName17_2_, node0_.nickName as nickName17_2_, node0_.dateOfBirth as dateOfB14_17_2_, node0_.dateOfDeath as dateOfD15_17_2_, node0_.sex as sex17_2_, node0_.nodeType as nodeType17_2_, mylinksto1_.fromNode_nodeID as fromNode7_4_, mylinksto1_.linkID as linkID4_, mylinksto1_.linkID as linkID14_0_, mylinksto1_.version as version14_0_, mylinksto1_.toNode_nodeID as toNode6_14_0_, mylinksto1_.fromNode_nodeID as fromNode7_14_0_, mylinksto1_.name as name14_0_, mylinksto1_.description as descript4_14_0_, mylinksto1_.lastUpdated as lastUpda5_14_0_, node2_.nodeID as nodeID17_1_, node2_.version as version17_1_, node2_.lastUpdated as lastUpda4_17_1_, node2_.nodeName as nodeName17_1_, node2_.aliasName as aliasName17_1_, node2_.description as descript7_17_1_, node2_.weight as weight17_1_, node2_.importance as importance17_1_, node2_.firstName as firstName17_1_, node2_.middleName as middleName17_1_, node2_.lastName as lastName17_1_, node2_.nickName as nickName17_1_, node2_.dateOfBirth as dateOfB14_17_1_, node2_.dateOfDeath as dateOfD15_17_1_, node2_.sex as sex17_1_, node2_.nodeType as nodeType17_1_ from Node node0_ left outer join Link mylinksto1_ on node0_.nodeID=mylinksto1_.fromNode_nodeID left outer join Node node2_ on mylinksto1_.toNode_nodeID=node2_.nodeID where node0_.nodeID=?
                        11:48:53,492 INFO [STDOUT] Hibernate: select linksfromo0_.toNode_nodeID as toNode6_2_, linksfromo0_.linkID as linkID2_, linksfromo0_.linkID as linkID14_1_, linksfromo0_.version as version14_1_, linksfromo0_.toNode_nodeID as toNode6_14_1_, linksfromo0_.fromNode_nodeID as fromNode7_14_1_, linksfromo0_.name as name14_1_, linksfromo0_.description as descript4_14_1_, linksfromo0_.lastUpdated as lastUpda5_14_1_, node1_.nodeID as nodeID17_0_, node1_.version as version17_0_, node1_.lastUpdated as lastUpda4_17_0_, node1_.nodeName as nodeName17_0_, node1_.aliasName as aliasName17_0_, node1_.description as descript7_17_0_, node1_.weight as weight17_0_, node1_.importance as importance17_0_, node1_.firstName as firstName17_0_, node1_.middleName as middleName17_0_, node1_.lastName as lastName17_0_, node1_.nickName as nickName17_0_, node1_.dateOfBirth as dateOfB14_17_0_, node1_.dateOfDeath as dateOfD15_17_0_, node1_.sex as sex17_0_, node1_.nodeType as nodeType17_0_ from Link linksfromo0_ left outer join Node node1_ on linksfromo0_.fromNode_nodeID=node1_.nodeID where linksfromo0_.toNode_nodeID=?
                        11:48:53,502 INFO [STDOUT] Hibernate: select link0_.linkID as linkID14_2_, link0_.version as version14_2_, link0_.toNode_nodeID as toNode6_14_2_, link0_.fromNode_nodeID as fromNode7_14_2_, link0_.name as name14_2_, link0_.description as descript4_14_2_, link0_.lastUpdated as lastUpda5_14_2_, node1_.nodeID as nodeID17_0_, node1_.version as version17_0_, node1_.lastUpdated as lastUpda4_17_0_, node1_.nodeName as nodeName17_0_, node1_.aliasName as aliasName17_0_, node1_.description as descript7_17_0_, node1_.weight as weight17_0_, node1_.importance as importance17_0_, node1_.firstName as firstName17_0_, node1_.middleName as middleName17_0_, node1_.lastName as lastName17_0_, node1_.nickName as nickName17_0_, node1_.dateOfBirth as dateOfB14_17_0_, node1_.dateOfDeath as dateOfD15_17_0_, node1_.sex as sex17_0_, node1_.nodeType as nodeType17_0_, mylinksto2_.fromNode_nodeID as fromNode7_4_, mylinksto2_.linkID as linkID4_, mylinksto2_.linkID as linkID14_1_, mylinksto2_.version as version14_1_, mylinksto2_.toNode_nodeID as toNode6_14_1_, mylinksto2_.fromNode_nodeID as fromNode7_14_1_, mylinksto2_.name as name14_1_, mylinksto2_.description as descript4_14_1_, mylinksto2_.lastUpdated as lastUpda5_14_1_ from Link link0_ left outer join Node node1_ on link0_.toNode_nodeID=node1_.nodeID left outer join Link mylinksto2_ on node1_.nodeID=mylinksto2_.fromNode_nodeID where link0_.linkID=?
                        11:48:53,512 INFO [STDOUT] Hibernate: select node0_.nodeID as nodeID17_2_, node0_.version as version17_2_, node0_.lastUpdated as lastUpda4_17_2_, node0_.nodeName as nodeName17_2_, node0_.aliasName as aliasName17_2_, node0_.description as descript7_17_2_, node0_.weight as weight17_2_, node0_.importance as importance17_2_, node0_.firstName as firstName17_2_, node0_.middleName as middleName17_2_, node0_.lastName as lastName17_2_, node0_.nickName as nickName17_2_, node0_.dateOfBirth as dateOfB14_17_2_, node0_.dateOfDeath as dateOfD15_17_2_, node0_.sex as sex17_2_, node0_.nodeType as nodeType17_2_, mylinksto1_.fromNode_nodeID as fromNode7_4_, mylinksto1_.linkID as linkID4_, mylinksto1_.linkID as linkID14_0_, mylinksto1_.version as version14_0_, mylinksto1_.toNode_nodeID as toNode6_14_0_, mylinksto1_.fromNode_nodeID as fromNode7_14_0_, mylinksto1_.name as name14_0_, mylinksto1_.description as descript4_14_0_, mylinksto1_.lastUpdated as lastUpda5_14_0_, node2_.nodeID as nodeID17_1_, node2_.version as version17_1_, node2_.lastUpdated as lastUpda4_17_1_, node2_.nodeName as nodeName17_1_, node2_.aliasName as aliasName17_1_, node2_.description as descript7_17_1_, node2_.weight as weight17_1_, node2_.importance as importance17_1_, node2_.firstName as firstName17_1_, node2_.middleName as middleName17_1_, node2_.lastName as lastName17_1_, node2_.nickName as nickName17_1_, node2_.dateOfBirth as dateOfB14_17_1_, node2_.dateOfDeath as dateOfD15_17_1_, node2_.sex as sex17_1_, node2_.nodeType as nodeType17_1_ from Node node0_ left outer join Link mylinksto1_ on node0_.nodeID=mylinksto1_.fromNode_nodeID left outer join Node node2_ on mylinksto1_.toNode_nodeID=node2_.nodeID where node0_.nodeID=?
                        11:48:53,512 INFO [STDOUT] Hibernate: select linksfromo0_.toNode_nodeID as toNode6_2_, linksfromo0_.linkID as linkID2_, linksfromo0_.linkID as linkID14_1_, linksfromo0_.version as version14_1_, linksfromo0_.toNode_nodeID as toNode6_14_1_, linksfromo0_.fromNode_nodeID as fromNode7_14_1_, linksfromo0_.name as name14_1_, linksfromo0_.description as descript4_14_1_, linksfromo0_.lastUpdated as lastUpda5_14_1_, node1_.nodeID as nodeID17_0_, node1_.version as version17_0_, node1_.lastUpdated as lastUpda4_17_0_, node1_.nodeName as nodeName17_0_, node1_.aliasName as aliasName17_0_, node1_.description as descript7_17_0_, node1_.weight as weight17_0_, node1_.importance as importance17_0_, node1_.firstName as firstName17_0_, node1_.middleName as middleName17_0_, node1_.lastName as lastName17_0_, node1_.nickName as nickName17_0_, node1_.dateOfBirth as dateOfB14_17_0_, node1_.dateOfDeath as dateOfD15_17_0_, node1_.sex as sex17_0_, node1_.nodeType as nodeType17_0_ from Link linksfromo0_ left outer join Node node1_ on linksfromo0_.fromNode_nodeID=node1_.nodeID where linksfromo0_.toNode_nodeID=?
                        11:48:53,522 INFO [STDOUT] Hibernate: insert into Link (version, toNode_nodeID, fromNode_nodeID, name, description, lastUpdated) values (?, ?, ?, ?, ?, ?)
                        11:48:53,522 INFO [STDOUT] Hibernate: select node0_.nodeID as nodeID17_2_, node0_.version as version17_2_, node0_.lastUpdated as lastUpda4_17_2_, node0_.nodeName as nodeName17_2_, node0_.aliasName as aliasName17_2_, node0_.description as descript7_17_2_, node0_.weight as weight17_2_, node0_.importance as importance17_2_, node0_.firstName as firstName17_2_, node0_.middleName as middleName17_2_, node0_.lastName as lastName17_2_, node0_.nickName as nickName17_2_, node0_.dateOfBirth as dateOfB14_17_2_, node0_.dateOfDeath as dateOfD15_17_2_, node0_.sex as sex17_2_, node0_.nodeType as nodeType17_2_, mylinksto1_.fromNode_nodeID as fromNode7_4_, mylinksto1_.linkID as linkID4_, mylinksto1_.linkID as linkID14_0_, mylinksto1_.version as version14_0_, mylinksto1_.toNode_nodeID as toNode6_14_0_, mylinksto1_.fromNode_nodeID as fromNode7_14_0_, mylinksto1_.name as name14_0_, mylinksto1_.description as descript4_14_0_, mylinksto1_.lastUpdated as lastUpda5_14_0_, node2_.nodeID as nodeID17_1_, node2_.version as version17_1_, node2_.lastUpdated as lastUpda4_17_1_, node2_.nodeName as nodeName17_1_, node2_.aliasName as aliasName17_1_, node2_.description as descript7_17_1_, node2_.weight as weight17_1_, node2_.importance as importance17_1_, node2_.firstName as firstName17_1_, node2_.middleName as middleName17_1_, node2_.lastName as lastName17_1_, node2_.nickName as nickName17_1_, node2_.dateOfBirth as dateOfB14_17_1_, node2_.dateOfDeath as dateOfD15_17_1_, node2_.sex as sex17_1_, node2_.nodeType as nodeType17_1_ from Node node0_ left outer join Link mylinksto1_ on node0_.nodeID=mylinksto1_.fromNode_nodeID left outer join Node node2_ on mylinksto1_.toNode_nodeID=node2_.nodeID where node0_.nodeID=?
                        11:48:53,532 INFO [STDOUT] Hibernate: select link0_.linkID as linkID14_2_, link0_.version as version14_2_, link0_.toNode_nodeID as toNode6_14_2_, link0_.fromNode_nodeID as fromNode7_14_2_, link0_.name as name14_2_, link0_.description as descript4_14_2_, link0_.lastUpdated as lastUpda5_14_2_, node1_.nodeID as nodeID17_0_, node1_.version as version17_0_, node1_.lastUpdated as lastUpda4_17_0_, node1_.nodeName as nodeName17_0_, node1_.aliasName as aliasName17_0_, node1_.description as descript7_17_0_, node1_.weight as weight17_0_, node1_.importance as importance17_0_, node1_.firstName as firstName17_0_, node1_.middleName as middleName17_0_, node1_.lastName as lastName17_0_, node1_.nickName as nickName17_0_, node1_.dateOfBirth as dateOfB14_17_0_, node1_.dateOfDeath as dateOfD15_17_0_, node1_.sex as sex17_0_, node1_.nodeType as nodeType17_0_, mylinksto2_.fromNode_nodeID as fromNode7_4_, mylinksto2_.linkID as linkID4_, mylinksto2_.linkID as linkID14_1_, mylinksto2_.version as version14_1_, mylinksto2_.toNode_nodeID as toNode6_14_1_, mylinksto2_.fromNode_nodeID as fromNode7_14_1_, mylinksto2_.name as name14_1_, mylinksto2_.description as descript4_14_1_, mylinksto2_.lastUpdated as lastUpda5_14_1_ from Link link0_ left outer join Node node1_ on link0_.toNode_nodeID=node1_.nodeID left outer join Link mylinksto2_ on node1_.nodeID=mylinksto2_.fromNode_nodeID where link0_.linkID=?
                        11:48:53,542 INFO [STDOUT] Hibernate: select node0_.nodeID as nodeID17_2_, node0_.version as version17_2_, node0_.lastUpdated as lastUpda4_17_2_, node0_.nodeName as nodeName17_2_, node0_.aliasName as aliasName17_2_, node0_.description as descript7_17_2_, node0_.weight as weight17_2_, node0_.importance as importance17_2_, node0_.firstName as firstName17_2_, node0_.middleName as middleName17_2_, node0_.lastName as lastName17_2_, node0_.nickName as nickName17_2_, node0_.dateOfBirth as dateOfB14_17_2_, node0_.dateOfDeath as dateOfD15_17_2_, node0_.sex as sex17_2_, node0_.nodeType as nodeType17_2_, mylinksto1_.fromNode_nodeID as fromNode7_4_, mylinksto1_.linkID as linkID4_, mylinksto1_.linkID as linkID14_0_, mylinksto1_.version as version14_0_, mylinksto1_.toNode_nodeID as toNode6_14_0_, mylinksto1_.fromNode_nodeID as fromNode7_14_0_, mylinksto1_.name as name14_0_, mylinksto1_.description as descript4_14_0_, mylinksto1_.lastUpdated as lastUpda5_14_0_, node2_.nodeID as nodeID17_1_, node2_.version as version17_1_, node2_.lastUpdated as lastUpda4_17_1_, node2_.nodeName as nodeName17_1_, node2_.aliasName as aliasName17_1_, node2_.description as descript7_17_1_, node2_.weight as weight17_1_, node2_.importance as importance17_1_, node2_.firstName as firstName17_1_, node2_.middleName as middleName17_1_, node2_.lastName as lastName17_1_, node2_.nickName as nickName17_1_, node2_.dateOfBirth as dateOfB14_17_1_, node2_.dateOfDeath as dateOfD15_17_1_, node2_.sex as sex17_1_, node2_.nodeType as nodeType17_1_ from Node node0_ left outer join Link mylinksto1_ on node0_.nodeID=mylinksto1_.fromNode_nodeID left outer join Node node2_ on mylinksto1_.toNode_nodeID=node2_.nodeID where node0_.nodeID=?
                        11:48:53,623 INFO [STDOUT] Hibernate: select link0_.linkID as linkID14_2_, link0_.version as version14_2_, link0_.toNode_nodeID as toNode6_14_2_, link0_.fromNode_nodeID as fromNode7_14_2_, link0_.name as name14_2_, link0_.description as descript4_14_2_, link0_.lastUpdated as lastUpda5_14_2_, node1_.nodeID as nodeID17_0_, node1_.version as version17_0_, node1_.lastUpdated as lastUpda4_17_0_, node1_.nodeName as nodeName17_0_, node1_.aliasName as aliasName17_0_, node1_.description as descript7_17_0_, node1_.weight as weight17_0_, node1_.importance as importance17_0_, node1_.firstName as firstName17_0_, node1_.middleName as middleName17_0_, node1_.lastName as lastName17_0_, node1_.nickName as nickName17_0_, node1_.dateOfBirth as dateOfB14_17_0_, node1_.dateOfDeath as dateOfD15_17_0_, node1_.sex as sex17_0_, node1_.nodeType as nodeType17_0_, mylinksto2_.fromNode_nodeID as fromNode7_4_, mylinksto2_.linkID as linkID4_, mylinksto2_.linkID as linkID14_1_, mylinksto2_.version as version14_1_, mylinksto2_.toNode_nodeID as toNode6_14_1_, mylinksto2_.fromNode_nodeID as fromNode7_14_1_, mylinksto2_.name as name14_1_, mylinksto2_.description as descript4_14_1_, mylinksto2_.lastUpdated as lastUpda5_14_1_ from Link link0_ left outer join Node node1_ on link0_.toNode_nodeID=node1_.nodeID left outer join Link mylinksto2_ on node1_.nodeID=mylinksto2_.fromNode_nodeID where link0_.linkID=?
                        11:48:53,633 INFO [STDOUT] Hibernate: select node0_.nodeID as nodeID17_2_, node0_.version as version17_2_, node0_.lastUpdated as lastUpda4_17_2_, node0_.nodeName as nodeName17_2_, node0_.aliasName as aliasName17_2_, node0_.description as descript7_17_2_, node0_.weight as weight17_2_, node0_.importance as importance17_2_, node0_.firstName as firstName17_2_, node0_.middleName as middleName17_2_, node0_.lastName as lastName17_2_, node0_.nickName as nickName17_2_, node0_.dateOfBirth as dateOfB14_17_2_, node0_.dateOfDeath as dateOfD15_17_2_, node0_.sex as sex17_2_, node0_.nodeType as nodeType17_2_, mylinksto1_.fromNode_nodeID as fromNode7_4_, mylinksto1_.linkID as linkID4_, mylinksto1_.linkID as linkID14_0_, mylinksto1_.version as version14_0_, mylinksto1_.toNode_nodeID as toNode6_14_0_, mylinksto1_.fromNode_nodeID as fromNode7_14_0_, mylinksto1_.name as name14_0_, mylinksto1_.description as descript4_14_0_, mylinksto1_.lastUpdated as lastUpda5_14_0_, node2_.nodeID as nodeID17_1_, node2_.version as version17_1_, node2_.lastUpdated as lastUpda4_17_1_, node2_.nodeName as nodeName17_1_, node2_.aliasName as aliasName17_1_, node2_.description as descript7_17_1_, node2_.weight as weight17_1_, node2_.importance as importance17_1_, node2_.firstName as firstName17_1_, node2_.middleName as middleName17_1_, node2_.lastName as lastName17_1_, node2_.nickName as nickName17_1_, node2_.dateOfBirth as dateOfB14_17_1_, node2_.dateOfDeath as dateOfD15_17_1_, node2_.sex as sex17_1_, node2_.nodeType as nodeType17_1_ from Node node0_ left outer join Link mylinksto1_ on node0_.nodeID=mylinksto1_.fromNode_nodeID left outer join Node node2_ on mylinksto1_.toNode_nodeID=node2_.nodeID where node0_.nodeID=?
                        11:48:53,693 WARN [LoadContexts] fail-safe cleanup (collections) : org.hibernate.engine.loading.CollectionLoadContext@103b97<rs=com.mysql.jdbc.ResultSet@c5b819>
                        11:48:53,693 WARN [LoadContexts] fail-safe cleanup (collections) : org.hibernate.engine.loading.CollectionLoadContext@1b8378f<rs=com.mysql.jdbc.ResultSet@1165e21>
                        11:48:53,693 WARN [LoadContexts] fail-safe cleanup (collections) : org.hibernate.engine.loading.CollectionLoadContext@147cab0<rs=com.mysql.jdbc.ResultSet@38e9e9>



                        i then run a query action to get connected nodes to this uNode and the query action causes another DB insert at the server!!!???



                        11:57:23,756 INFO [STDOUT] Hibernate: select node0_.nodeID as nodeID17_2_, node0_.version as version17_2_, node0_.lastUpdated as lastUpda4_17_2_, node0_.nodeName as nodeName17_2_, node0_.aliasName as aliasName17_2_, node0_.description as descript7_17_2_, node0_.weight as weight17_2_, node0_.importance as importance17_2_, node0_.firstName as firstName17_2_, node0_.middleName as middleName17_2_, node0_.lastName as lastName17_2_, node0_.nickName as nickName17_2_, node0_.dateOfBirth as dateOfB14_17_2_, node0_.dateOfDeath as dateOfD15_17_2_, node0_.sex as sex17_2_, node0_.nodeType as nodeType17_2_, mylinksto1_.fromNode_nodeID as fromNode7_4_, mylinksto1_.linkID as linkID4_, mylinksto1_.linkID as linkID14_0_, mylinksto1_.version as version14_0_, mylinksto1_.toNode_nodeID as toNode6_14_0_, mylinksto1_.fromNode_nodeID as fromNode7_14_0_, mylinksto1_.name as name14_0_, mylinksto1_.description as descript4_14_0_, mylinksto1_.lastUpdated as lastUpda5_14_0_, node2_.nodeID as nodeID17_1_, node2_.version as version17_1_, node2_.lastUpdated as lastUpda4_17_1_, node2_.nodeName as nodeName17_1_, node2_.aliasName as aliasName17_1_, node2_.description as descript7_17_1_, node2_.weight as weight17_1_, node2_.importance as importance17_1_, node2_.firstName as firstName17_1_, node2_.middleName as middleName17_1_, node2_.lastName as lastName17_1_, node2_.nickName as nickName17_1_, node2_.dateOfBirth as dateOfB14_17_1_, node2_.dateOfDeath as dateOfD15_17_1_, node2_.sex as sex17_1_, node2_.nodeType as nodeType17_1_ from Node node0_ left outer join Link mylinksto1_ on node0_.nodeID=mylinksto1_.fromNode_nodeID left outer join Node node2_ on mylinksto1_.toNode_nodeID=node2_.nodeID where node0_.nodeID=?
                        11:57:23,776 INFO [STDOUT] Hibernate: select linksfromo0_.toNode_nodeID as toNode6_2_, linksfromo0_.linkID as linkID2_, linksfromo0_.linkID as linkID14_1_, linksfromo0_.version as version14_1_, linksfromo0_.toNode_nodeID as toNode6_14_1_, linksfromo0_.fromNode_nodeID as fromNode7_14_1_, linksfromo0_.name as name14_1_, linksfromo0_.description as descript4_14_1_, linksfromo0_.lastUpdated as lastUpda5_14_1_, node1_.nodeID as nodeID17_0_, node1_.version as version17_0_, node1_.lastUpdated as lastUpda4_17_0_, node1_.nodeName as nodeName17_0_, node1_.aliasName as aliasName17_0_, node1_.description as descript7_17_0_, node1_.weight as weight17_0_, node1_.importance as importance17_0_, node1_.firstName as firstName17_0_, node1_.middleName as middleName17_0_, node1_.lastName as lastName17_0_, node1_.nickName as nickName17_0_, node1_.dateOfBirth as dateOfB14_17_0_, node1_.dateOfDeath as dateOfD15_17_0_, node1_.sex as sex17_0_, node1_.nodeType as nodeType17_0_ from Link linksfromo0_ left outer join Node node1_ on linksfromo0_.fromNode_nodeID=node1_.nodeID where linksfromo0_.toNode_nodeID=?
                        11:57:23,806 INFO [STDOUT] Hibernate: select link0_.linkID as linkID14_2_, link0_.version as version14_2_, link0_.toNode_nodeID as toNode6_14_2_, link0_.fromNode_nodeID as fromNode7_14_2_, link0_.name as name14_2_, link0_.description as descript4_14_2_, link0_.lastUpdated as lastUpda5_14_2_, node1_.nodeID as nodeID17_0_, node1_.version as version17_0_, node1_.lastUpdated as lastUpda4_17_0_, node1_.nodeName as nodeName17_0_, node1_.aliasName as aliasName17_0_, node1_.description as descript7_17_0_, node1_.weight as weight17_0_, node1_.importance as importance17_0_, node1_.firstName as firstName17_0_, node1_.middleName as middleName17_0_, node1_.lastName as lastName17_0_, node1_.nickName as nickName17_0_, node1_.dateOfBirth as dateOfB14_17_0_, node1_.dateOfDeath as dateOfD15_17_0_, node1_.sex as sex17_0_, node1_.nodeType as nodeType17_0_, mylinksto2_.fromNode_nodeID as fromNode7_4_, mylinksto2_.linkID as linkID4_, mylinksto2_.linkID as linkID14_1_, mylinksto2_.version as version14_1_, mylinksto2_.toNode_nodeID as toNode6_14_1_, mylinksto2_.fromNode_nodeID as fromNode7_14_1_, mylinksto2_.name as name14_1_, mylinksto2_.description as descript4_14_1_, mylinksto2_.lastUpdated as lastUpda5_14_1_ from Link link0_ left outer join Node node1_ on link0_.toNode_nodeID=node1_.nodeID left outer join Link mylinksto2_ on node1_.nodeID=mylinksto2_.fromNode_nodeID where link0_.linkID=?
                        11:57:23,826 INFO [STDOUT] Hibernate: select linksfromo0_.toNode_nodeID as toNode6_2_, linksfromo0_.linkID as linkID2_, linksfromo0_.linkID as linkID14_1_, linksfromo0_.version as version14_1_, linksfromo0_.toNode_nodeID as toNode6_14_1_, linksfromo0_.fromNode_nodeID as fromNode7_14_1_, linksfromo0_.name as name14_1_, linksfromo0_.description as descript4_14_1_, linksfromo0_.lastUpdated as lastUpda5_14_1_, node1_.nodeID as nodeID17_0_, node1_.version as version17_0_, node1_.lastUpdated as lastUpda4_17_0_, node1_.nodeName as nodeName17_0_, node1_.aliasName as aliasName17_0_, node1_.description as descript7_17_0_, node1_.weight as weight17_0_, node1_.importance as importance17_0_, node1_.firstName as firstName17_0_, node1_.middleName as middleName17_0_, node1_.lastName as lastName17_0_, node1_.nickName as nickName17_0_, node1_.dateOfBirth as dateOfB14_17_0_, node1_.dateOfDeath as dateOfD15_17_0_, node1_.sex as sex17_0_, node1_.nodeType as nodeType17_0_ from Link linksfromo0_ left outer join Node node1_ on linksfromo0_.fromNode_nodeID=node1_.nodeID where linksfromo0_.toNode_nodeID=?
                        11:57:23,846 INFO [STDOUT] Hibernate: insert into Link (version, toNode_nodeID, fromNode_nodeID, name, description, lastUpdated) values (?, ?, ?, ?, ?, ?)
                        11:57:23,856 INFO [STDOUT] Hibernate: update Node set version=?, lastUpdated=?, nodeName=?, aliasName=?, description=?, weight=?, importance=? where nodeID=?
                        11:57:23,856 INFO [STDOUT] Hibernate: update Node set version=?, lastUpdated=?, nodeName=?, aliasName=?, description=?, weight=?, importance=? where nodeID=?
                        11:57:23,866 INFO [STDOUT] Hibernate: select node1_.nodeID as nodeID17_, node1_.version as version17_, node1_.lastUpdated as lastUpda4_17_, node1_.nodeName as nodeName17_, node1_.aliasName as aliasName17_, node1_.description as descript7_17_, node1_.weight as weight17_, node1_.importance as importance17_, node1_.firstName as firstName17_, node1_.middleName as middleName17_, node1_.lastName as lastName17_, node1_.nickName as nickName17_, node1_.dateOfBirth as dateOfB14_17_, node1_.dateOfDeath as dateOfD15_17_, node1_.sex as sex17_, node1_.nodeType as nodeType17_ from Link link0_ inner join Node node1_ on link0_.toNode_nodeID=node1_.nodeID where link0_.fromNode_nodeID=?
                        11:57:24,097 WARN [LoadContexts] fail-safe cleanup (collections) : org.hibernate.engine.loading.CollectionLoadContext@1b9bbf6<rs=com.mysql.jdbc.ResultSet@18dbef1>


                        so somehow starting from having a uNode with two links - i delete one at the server EJB end - then by doing a find (issues a select only), and a refresh and a query i get three links in the database when I only expected 1.

                        What is happening here - I cant see why it keeps inserting rows

                        Weird


                        • 9. Re: problems with optimistic locking/persistence data in EJB
                          waynebaylor

                          try this:

                           t.begin();
                           //queues an update from stale uNode
                           //Node mergedNode = em.merge(fromNode);
                          
                           //refresh reads back queued model
                           em.refresh(fromNode);
                          
                           t.commit();
                          


                          i commented out the call to merge (i think this is the call that's undoing your changes) and changed the argument to refresh (now it's fromNode instead of mergedNode).