details:   https://code.openbravo.com/erp/devel/pi/rev/ea854655f9aa
changeset: 28631:ea854655f9aa
user:      Asier Lostalé <asier.lostale <at> openbravo.com>
date:      Tue Feb 23 16:38:23 2016 +0100
summary:   related to bug 32308: added test cases covering observers with ds 
update

details:   https://code.openbravo.com/erp/devel/pi/rev/64dcdb9cf68b
changeset: 28632:64dcdb9cf68b
user:      Asier Lostalé <asier.lostale <at> openbravo.com>
date:      Tue Feb 23 16:37:30 2016 +0100
summary:   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.

diffstat:

 
modules/org.openbravo.client.application/src-test/org/openbravo/client/application/test/event/DatasourceEventObserver.java
 |  191 ++++++++++
 
modules/org.openbravo.client.application/src-test/org/openbravo/client/application/test/event/OrderLineTestObserver.java
   |   83 ++++
 
modules/org.openbravo.service.json/src/org/openbravo/service/json/DefaultJsonDataService.java
                              |   18 +-
 src-test/src/org/openbravo/test/AllAntTaskTests.java                           
                                            |    4 +-
 src/org/openbravo/base/structure/BaseOBObject.java                             
                                            |    8 +-
 5 files changed, 292 insertions(+), 12 deletions(-)

diffs (truncated from 384 to 300 lines):

diff -r 0f887315d105 -r 64dcdb9cf68b 
modules/org.openbravo.client.application/src-test/org/openbravo/client/application/test/event/DatasourceEventObserver.java
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ 
b/modules/org.openbravo.client.application/src-test/org/openbravo/client/application/test/event/DatasourceEventObserver.java
        Tue Feb 23 16:37:30 2016 +0100
@@ -0,0 +1,191 @@
+/*
+ *************************************************************************
+ * The contents of this file are subject to the Openbravo  Public  License
+ * Version  1.1  (the  "License"),  being   the  Mozilla   Public  License
+ * Version 1.1  with a permitted attribution clause; you may not  use this
+ * file except in compliance with the License. You  may  obtain  a copy of
+ * the License at http://www.openbravo.com/legal/license.html 
+ * Software distributed under the License  is  distributed  on  an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific  language  governing  rights  and  limitations
+ * under the License.
+ * The Original Code is Openbravo ERP.
+ * The Initial Developer of the Original Code is Openbravo SLU
+ * All portions are Copyright (C) 2016 Openbravo SLU
+ * All Rights Reserved.
+ * Contributor(s):  ______________________________________.
+ ************************************************************************
+ */
+
+package org.openbravo.client.application.test.event;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+import java.util.HashMap;
+
+import javax.inject.Inject;
+
+import org.codehaus.jettison.json.JSONException;
+import org.codehaus.jettison.json.JSONObject;
+import org.hibernate.criterion.Restrictions;
+import org.junit.AfterClass;
+import org.junit.Test;
+import org.openbravo.base.structure.BaseOBObject;
+import org.openbravo.base.weld.test.WeldBaseTest;
+import org.openbravo.client.application.Note;
+import org.openbravo.dal.core.OBContext;
+import org.openbravo.dal.service.OBCriteria;
+import org.openbravo.dal.service.OBDal;
+import org.openbravo.model.ad.datamodel.Table;
+import org.openbravo.model.common.order.Order;
+import org.openbravo.model.common.order.OrderLine;
+import org.openbravo.service.datasource.DataSourceService;
+import org.openbravo.service.datasource.DataSourceServiceProvider;
+import org.openbravo.service.json.JsonConstants;
+
+/**
+ * Test cases covering updates through standard datasource that include a 
persistence observer.
+ * 
+ * Observer is implemented in {@link OrderLineTestObserver}.
+ * 
+ * @author alostale
+ *
+ */
+public class DatasourceEventObserver extends WeldBaseTest {
+
+  @Inject
+  private DataSourceServiceProvider dataSourceServiceProvider;
+
+  enum ObserverExecutionType {
+    OFF, UPDATE_DESCRIPTION, CREATE_NOTE, COUNT_LINES, UPDATE_PARENT
+  };
+
+  static ObserverExecutionType observerExecutionType = 
ObserverExecutionType.OFF;
+
+  /** Updating order line without observer */
+  @Test
+  public void standardUpdateRequestWithoutObserver() throws JSONException {
+    observerExecutionType = ObserverExecutionType.OFF;
+
+    OrderLine ol = pickARandomOrderLine();
+
+    String randomDescription = Long.toString(System.currentTimeMillis());
+    JSONObject updatedOrder = datasourceUpdate(ol, randomDescription);
+
+    assertDescription(ol, updatedOrder, randomDescription);
+  }
+
+  /** The observer updates line description to a fixed value */
+  @Test
+  public void observerCanModifyPropertyValues() throws JSONException {
+    observerExecutionType = ObserverExecutionType.UPDATE_DESCRIPTION;
+
+    OrderLine ol = pickARandomOrderLine();
+
+    String randomDescription = Long.toString(System.currentTimeMillis());
+    JSONObject updatedOrder = datasourceUpdate(ol, randomDescription);
+
+    assertDescription(ol, updatedOrder, 
OrderLineTestObserver.FORCED_DESCRIPTION);
+  }
+
+  /** The observer creates a new note on order line */
+  @Test
+  public void observerCanAddNewObjects() throws JSONException {
+    observerExecutionType = ObserverExecutionType.CREATE_NOTE;
+
+    OrderLine ol = pickARandomOrderLine();
+    int notesBeforeUpdate = countNotes(ol);
+
+    String randomDescription = Long.toString(System.currentTimeMillis());
+    JSONObject updatedOrder = datasourceUpdate(ol, randomDescription);
+
+    int notesAfterUpdate = countNotes(ol);
+
+    assertThat("number of notes", notesAfterUpdate, is(notesBeforeUpdate + 1));
+    assertDescription(ol, updatedOrder, randomDescription);
+  }
+
+  /** Observer does ol.getSalesOrder().getOrderLineList(). Covers issue #32308 
*/
+  @Test
+  public void observerCanInstantiateObservedObject() throws JSONException {
+    observerExecutionType = ObserverExecutionType.COUNT_LINES;
+
+    OrderLine ol = pickARandomOrderLine();
+    int numberOfLines = ol.getSalesOrder().getOrderLineList().size();
+
+    String randomDescription = Long.toString(System.currentTimeMillis());
+    JSONObject updatedOrder = datasourceUpdate(ol, randomDescription);
+
+    assertDescription(ol, updatedOrder, 
OrderLineTestObserver.FORCED_DESCRIPTION + numberOfLines);
+  }
+
+  /** Observer updates order line's header */
+  @Test
+  public void observerCanUpdateParentObject() throws JSONException {
+    observerExecutionType = ObserverExecutionType.UPDATE_PARENT;
+
+    OrderLine ol = pickARandomOrderLine();
+
+    String randomDescription = Long.toString(System.currentTimeMillis());
+    datasourceUpdate(ol, randomDescription);
+
+    Order order = ol.getSalesOrder();
+
+    assertThat(order.getEntityName() + " - " + order.getId() + " actual 
description",
+        (String) order.get(OrderLine.PROPERTY_DESCRIPTION),
+        is(OrderLineTestObserver.FORCED_DESCRIPTION));
+  }
+
+  private OrderLine pickARandomOrderLine() {
+    return (OrderLine) 
OBDal.getInstance().createCriteria(OrderLine.class).setMaxResults(1)
+        .uniqueResult();
+  }
+
+  private JSONObject datasourceUpdate(OrderLine ol, String randomDescription) 
throws JSONException {
+    final DataSourceService dataSource = dataSourceServiceProvider
+        .getDataSource(OrderLine.ENTITY_NAME);
+
+    JSONObject data = new JSONObject();
+    data.put(JsonConstants.ID, ol.getId());
+    data.put(OrderLine.PROPERTY_DESCRIPTION, randomDescription);
+
+    JSONObject content = new JSONObject();
+    content.put(JsonConstants.DATA, data);
+
+    String resp = dataSource.update(new HashMap<String, String>(), 
content.toString());
+    return new JSONObject(resp).getJSONObject(JsonConstants.RESPONSE_RESPONSE)
+        .getJSONArray(JsonConstants.DATA).getJSONObject(0);
+  }
+
+  private void assertDescription(BaseOBObject obj, JSONObject updatedOrder,
+      String expectedDescription) throws JSONException {
+    OBDal.getInstance().commitAndClose();
+
+    BaseOBObject refreshedBob = (BaseOBObject) OBDal.getInstance()
+        
.createCriteria(obj.getEntityName()).add(Restrictions.eq(BaseOBObject.ID, 
obj.getId()))
+        .uniqueResult();
+    assertThat(obj.getEntityName() + " - " + obj.getId() + " response 
description",
+        updatedOrder.getString("description"), is(expectedDescription));
+    assertThat(obj.getEntityName() + " - " + obj.getId() + " actual 
description",
+        (String) refreshedBob.get(OrderLine.PROPERTY_DESCRIPTION), 
is(expectedDescription));
+  }
+
+  private int countNotes(BaseOBObject obj) {
+    OBContext.setAdminMode(true);
+    try {
+      OBCriteria<Note> q = OBDal.getInstance().createCriteria(Note.class);
+      q.add(Restrictions.eq(Note.PROPERTY_RECORD, obj.getId()));
+      q.add(Restrictions.eq(Note.PROPERTY_TABLE,
+          OBDal.getInstance().getProxy(Table.class, 
obj.getEntity().getTableId())));
+      return q.count();
+    } finally {
+      OBContext.restorePreviousMode();
+    }
+  }
+
+  @AfterClass
+  public static void reset() {
+    observerExecutionType = ObserverExecutionType.OFF;
+  }
+}
diff -r 0f887315d105 -r 64dcdb9cf68b 
modules/org.openbravo.client.application/src-test/org/openbravo/client/application/test/event/OrderLineTestObserver.java
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ 
b/modules/org.openbravo.client.application/src-test/org/openbravo/client/application/test/event/OrderLineTestObserver.java
  Tue Feb 23 16:37:30 2016 +0100
@@ -0,0 +1,83 @@
+/*
+ *************************************************************************
+ * The contents of this file are subject to the Openbravo  Public  License
+ * Version  1.1  (the  "License"),  being   the  Mozilla   Public  License
+ * Version 1.1  with a permitted attribution clause; you may not  use this
+ * file except in compliance with the License. You  may  obtain  a copy of
+ * the License at http://www.openbravo.com/legal/license.html 
+ * Software distributed under the License  is  distributed  on  an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific  language  governing  rights  and  limitations
+ * under the License.
+ * The Original Code is Openbravo ERP.
+ * The Initial Developer of the Original Code is Openbravo SLU
+ * All portions are Copyright (C) 2016 Openbravo SLU
+ * All Rights Reserved.
+ * Contributor(s):  ______________________________________.
+ ************************************************************************
+ */
+package org.openbravo.client.application.test.event;
+
+import javax.enterprise.event.Observes;
+
+import org.openbravo.base.model.Entity;
+import org.openbravo.base.model.ModelProvider;
+import org.openbravo.base.provider.OBProvider;
+import org.openbravo.client.application.Note;
+import org.openbravo.client.kernel.event.EntityPersistenceEventObserver;
+import org.openbravo.client.kernel.event.EntityUpdateEvent;
+import org.openbravo.dal.service.OBDal;
+import org.openbravo.model.ad.datamodel.Table;
+import org.openbravo.model.common.order.Order;
+import org.openbravo.model.common.order.OrderLine;
+
+/**
+ * Test persistence observer used by {@link DatasourceEventObserver} to ensure 
observer is correctly
+ * invoked and works fine together with datasource update invocations.
+ * 
+ * @author alostale
+ *
+ */
+public class OrderLineTestObserver extends EntityPersistenceEventObserver {
+  static final String FORCED_DESCRIPTION = "test description";
+  private static Entity[] entities = { 
ModelProvider.getInstance().getEntity(OrderLine.ENTITY_NAME) };
+
+  public void onUpdate(@Observes EntityUpdateEvent event) {
+    if (!isValidEvent(event)) {
+      return;
+    }
+
+    switch (DatasourceEventObserver.observerExecutionType) {
+    case OFF:
+      return;
+    case UPDATE_DESCRIPTION:
+      
event.setCurrentState(entities[0].getProperty(OrderLine.PROPERTY_DESCRIPTION),
+          FORCED_DESCRIPTION);
+      break;
+    case CREATE_NOTE:
+      final OrderLine orderLine = (OrderLine) event.getTargetInstance();
+      Note newNote = OBProvider.getInstance().get(Note.class);
+      newNote.setTable(OBDal.getInstance()
+          .getProxy(Table.class, orderLine.getEntity().getTableId()));
+      newNote.setRecord(orderLine.getId());
+      newNote.setNote("test");
+      OBDal.getInstance().save(newNote);
+      break;
+    case COUNT_LINES:
+      int numOfLines = ((OrderLine) 
event.getTargetInstance()).getSalesOrder().getOrderLineList()
+          .size();
+      
event.setCurrentState(entities[0].getProperty(OrderLine.PROPERTY_DESCRIPTION),
+          FORCED_DESCRIPTION + numOfLines);
+      break;
+    case UPDATE_PARENT:
+      Order order = ((OrderLine) event.getTargetInstance()).getSalesOrder();
+      order.setDescription(FORCED_DESCRIPTION);
+      break;
+    }
+  }
+
+  @Override
+  protected Entity[] getObservedEntities() {
+    return entities;
+  }
+}
diff -r 0f887315d105 -r 64dcdb9cf68b 
modules/org.openbravo.service.json/src/org/openbravo/service/json/DefaultJsonDataService.java
--- 
a/modules/org.openbravo.service.json/src/org/openbravo/service/json/DefaultJsonDataService.java
     Fri Feb 19 13:54:47 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();
+

------------------------------------------------------------------------------
Site24x7 APM Insight: Get Deep Visibility into Application Performance
APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
Monitor end-to-end web transactions and take corrective actions now
Troubleshoot faster and improve end-user experience. Signup Now!
http://pubads.g.doubleclick.net/gampad/clk?id=272487151&iu=/4140
_______________________________________________
Openbravo-commits mailing list
Openbravo-commits@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openbravo-commits

Reply via email to