fixed bug 32308: error on update if an observer loaded current object in memory
authorAsier Lostalé <asier.lostale@openbravo.com>
Tue, 23 Feb 2016 16:37:30 +0100
changeset 28632 64dcdb9cf68b
parent 28631 ea854655f9aa
child 28633 216fb4e6048c
fixed bug 32308: error on update if an observer loaded current object in memory

In case an entity observer loaded current object in memory (ie. observing orderLine)
doing orderLine.getSalesOrder().getOrderLineList() there were two different instances
in memory representing the same DB row. This caused problems when trying to evict it.
Causing an exception to be thrown when updating from UI in this case.

As solution eviction is no longer performed, object is forced to be fetched from DB by
executing a Criteria.
modules/org.openbravo.service.json/src/org/openbravo/service/json/DefaultJsonDataService.java
src/org/openbravo/base/structure/BaseOBObject.java
--- a/modules/org.openbravo.service.json/src/org/openbravo/service/json/DefaultJsonDataService.java	Tue Feb 23 16:38:23 2016 +0100
+++ b/modules/org.openbravo.service.json/src/org/openbravo/service/json/DefaultJsonDataService.java	Tue Feb 23 16:37:30 2016 +0100
@@ -769,17 +769,19 @@
           }
         }
 
-        // refresh the objects from the db as they can have changed
-        // put the refreshed objects into a new array as we are going to retrieve them using
-        // OBDal.getInstance().get as performs better than OBDal.getInstance().getSession().refresh
-        // See issue https://issues.openbravo.com/view.php?id=30308
+        // Objects might have been modified in DB through triggers, let's force them to be fetched
+        // DB again, to do so session is cleared (any possible modification is already persisted by
+        // previous flush).
+        // Using OBDal.refresh does not perform well, see issue
+        // https://issues.openbravo.com/view.php?id=30308
+        OBDal.getInstance().getSession().clear();
+
         final List<BaseOBObject> refreshedBobs = new ArrayList<BaseOBObject>();
         for (BaseOBObject bob : bobs) {
-          // Remove the bob instance from the session cache with evict
-          OBDal.getInstance().getSession().evict(bob);
-          // With get() we retrieve the object from db as we have cleared it from cache with evict()
+          // forcing fetch from DB
           BaseOBObject refreshedBob = OBDal.getInstance().get(bob.getEntityName(),
               DalUtil.getId(bob));
+
           // if object has computed columns refresh from the database too
           if (refreshedBob.getEntity().hasComputedColumns()) {
             OBDal.getInstance().getSession()
@@ -788,7 +790,7 @@
           refreshedBobs.add(refreshedBob);
         }
 
-        // almost successfull, now create the response
+        // almost successful, now create the response
         // needs to be done before the close of the session
         final DataToJsonConverter toJsonConverter = OBProvider.getInstance().get(
             DataToJsonConverter.class);
--- a/src/org/openbravo/base/structure/BaseOBObject.java	Tue Feb 23 16:38:23 2016 +0100
+++ b/src/org/openbravo/base/structure/BaseOBObject.java	Tue Feb 23 16:37:30 2016 +0100
@@ -11,7 +11,7 @@
  * under the License. 
  * The Original Code is Openbravo ERP. 
  * The Initial Developer of the Original Code is Openbravo SLU 
- * All portions are Copyright (C) 2008-2011 Openbravo SLU 
+ * All portions are Copyright (C) 2008-2016 Openbravo SLU 
  * All Rights Reserved. 
  * Contributor(s):  ______________________________________.
  ************************************************************************
@@ -50,6 +50,8 @@
 
 public abstract class BaseOBObject implements BaseOBObjectDef, Identifiable, DynamicEnabled,
     OBNotSingleton, Serializable {
+  public static final String ID = "id";
+
   private static final org.apache.log4j.Logger log = org.apache.log4j.Logger
       .getLogger(BaseOBObject.class);
 
@@ -182,11 +184,11 @@
   }
 
   public Object getId() {
-    return get("id");
+    return get(ID);
   }
 
   public void setId(Object id) {
-    set("id", id);
+    set(ID, id);
   }
 
   public abstract String getEntityName();