Added new persistence event framework
authorMartin Taal <martin.taal@openbravo.com>
Mon, 24 Jan 2011 14:26:52 +0100
changeset 10095 94073d2a81f3
parent 10094 4d859c79a1ae
child 10096 7a0d3db89d15
Added new persistence event framework
modules/org.openbravo.client.kernel/src-db/database/sourcedata/AD_MODEL_OBJECT.xml
modules/org.openbravo.client.kernel/src/org/openbravo/client/kernel/KernelContextListener.java
modules/org.openbravo.client.kernel/src/org/openbravo/client/kernel/KernelInitializer.java
modules/org.openbravo.client.kernel/src/org/openbravo/client/kernel/event/EntityDeleteEvent.java
modules/org.openbravo.client.kernel/src/org/openbravo/client/kernel/event/EntityNewEvent.java
modules/org.openbravo.client.kernel/src/org/openbravo/client/kernel/event/EntityPersistenceEvent.java
modules/org.openbravo.client.kernel/src/org/openbravo/client/kernel/event/EntityPersistenceEventObserver.java
modules/org.openbravo.client.kernel/src/org/openbravo/client/kernel/event/EntityUpdateEvent.java
modules/org.openbravo.client.kernel/src/org/openbravo/client/kernel/event/PersistenceEventOBInterceptor.java
--- a/modules/org.openbravo.client.kernel/src-db/database/sourcedata/AD_MODEL_OBJECT.xml	Mon Jan 24 14:18:25 2011 +0100
+++ b/modules/org.openbravo.client.kernel/src-db/database/sourcedata/AD_MODEL_OBJECT.xml	Mon Jan 24 14:26:52 2011 +0100
@@ -13,4 +13,18 @@
 <!--A761FF99519C45D1A4BEE9FA30B40AAC-->  <NAME><![CDATA[Client Kernel Servlet]]></NAME>
 <!--A761FF99519C45D1A4BEE9FA30B40AAC--></AD_MODEL_OBJECT>
 
+<!--FF8081812DB7706D012DB777A1AD0010--><AD_MODEL_OBJECT>
+<!--FF8081812DB7706D012DB777A1AD0010-->  <AD_MODEL_OBJECT_ID><![CDATA[FF8081812DB7706D012DB777A1AD0010]]></AD_MODEL_OBJECT_ID>
+<!--FF8081812DB7706D012DB777A1AD0010-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
+<!--FF8081812DB7706D012DB777A1AD0010-->  <AD_ORG_ID><![CDATA[0]]></AD_ORG_ID>
+<!--FF8081812DB7706D012DB777A1AD0010-->  <ISACTIVE><![CDATA[Y]]></ISACTIVE>
+<!--FF8081812DB7706D012DB777A1AD0010-->  <ACTION><![CDATA[M]]></ACTION>
+<!--FF8081812DB7706D012DB777A1AD0010-->  <CLASSNAME><![CDATA[org.openbravo.client.kernel.KernelContextListener]]></CLASSNAME>
+<!--FF8081812DB7706D012DB777A1AD0010-->  <ISDEFAULT><![CDATA[N]]></ISDEFAULT>
+<!--FF8081812DB7706D012DB777A1AD0010-->  <AD_MODULE_ID><![CDATA[4B828F4D03264080AA1D2057B13F613C]]></AD_MODULE_ID>
+<!--FF8081812DB7706D012DB777A1AD0010-->  <OBJECT_TYPE><![CDATA[L]]></OBJECT_TYPE>
+<!--FF8081812DB7706D012DB777A1AD0010-->  <SEQNO><![CDATA[30]]></SEQNO>
+<!--FF8081812DB7706D012DB777A1AD0010-->  <NAME><![CDATA[org.openbravo.client.kernel.KernelContextListener]]></NAME>
+<!--FF8081812DB7706D012DB777A1AD0010--></AD_MODEL_OBJECT>
+
 </data>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.client.kernel/src/org/openbravo/client/kernel/KernelContextListener.java	Mon Jan 24 14:26:52 2011 +0100
@@ -0,0 +1,42 @@
+/*
+ *************************************************************************
+ * 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) 2011 Openbravo SLU 
+ * All Rights Reserved. 
+ * Contributor(s):  ______________________________________.
+ ************************************************************************
+ */
+
+package org.openbravo.client.kernel;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+
+import org.openbravo.base.weld.WeldUtils;
+
+/**
+ * Initializes the kernel layer in a servlet environment.
+ * 
+ * @see KernelInitializer
+ * 
+ * @author mtaal
+ */
+public class KernelContextListener implements ServletContextListener {
+
+  public void contextInitialized(ServletContextEvent event) {
+    WeldUtils.getInstanceFromStaticBeanManager(KernelInitializer.class).initialize();
+  }
+
+  public void contextDestroyed(ServletContextEvent event) {
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.client.kernel/src/org/openbravo/client/kernel/KernelInitializer.java	Mon Jan 24 14:26:52 2011 +0100
@@ -0,0 +1,53 @@
+/*
+ *************************************************************************
+ * 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) 2011 Openbravo SLU 
+ * All Rights Reserved. 
+ * Contributor(s):  ______________________________________.
+ ************************************************************************
+ */
+
+package org.openbravo.client.kernel;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+
+import org.openbravo.base.session.SessionFactoryController;
+import org.openbravo.client.kernel.event.PersistenceEventOBInterceptor;
+import org.openbravo.dal.core.OBInterceptor;
+
+/**
+ * Class responsible for initializing the kernel layer. Can be used in a servlet as well as a
+ * non-servlet environment.
+ * 
+ * @author mtaal
+ */
+@ApplicationScoped
+public class KernelInitializer {
+
+  @Inject
+  private PersistenceEventOBInterceptor persistenceEventOBInterceptor;
+
+  public void initialize() {
+    setInterceptor();
+  }
+
+  public synchronized void setInterceptor() {
+    final OBInterceptor interceptor = (OBInterceptor) SessionFactoryController.getInstance()
+        .getConfiguration().getInterceptor();
+    if (interceptor.getInterceptorListener() == null) {
+      interceptor.setInterceptorListener(persistenceEventOBInterceptor);
+    }
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.client.kernel/src/org/openbravo/client/kernel/event/EntityDeleteEvent.java	Mon Jan 24 14:26:52 2011 +0100
@@ -0,0 +1,37 @@
+/*
+ *************************************************************************
+ * 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) 2011 Openbravo SLU 
+ * All Rights Reserved. 
+ * Contributor(s):  ______________________________________.
+ ************************************************************************
+ */
+package org.openbravo.client.kernel.event;
+
+import javax.enterprise.context.ApplicationScoped;
+
+/**
+ * The event object send out when an entity gets deleted.
+ * 
+ * To receive this event, create a class with a method which has this signature:
+ * 
+ * public void onEvent(@Observes EntityDeleteEvent event) {
+ * 
+ * Note, the method name is unimportant, the @Observes EntityDeleteEvent specifies that this method
+ * will be called before persisting a new instance.
+ * 
+ * @author mtaal
+ */
+@ApplicationScoped
+public class EntityDeleteEvent extends EntityPersistenceEvent {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.client.kernel/src/org/openbravo/client/kernel/event/EntityNewEvent.java	Mon Jan 24 14:26:52 2011 +0100
@@ -0,0 +1,36 @@
+/*
+ *************************************************************************
+ * 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) 2011 Openbravo SLU 
+ * All Rights Reserved. 
+ * Contributor(s):  ______________________________________.
+ ************************************************************************
+ */
+package org.openbravo.client.kernel.event;
+
+
+/**
+ * The event object send out when an entity gets saved for the first time.
+ * 
+ * To receive this event, create a class with a method which has this signature:
+ * 
+ * public void onSave(@Observes EntityNewEvent event) {
+ * 
+ * Note, the method name is unimportant, the @Observes EntityNewEvent specifies that this method
+ * will be called before persisting a new instance.
+ * 
+ * @author mtaal
+ */
+public class EntityNewEvent extends EntityPersistenceEvent {
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.client.kernel/src/org/openbravo/client/kernel/event/EntityPersistenceEvent.java	Mon Jan 24 14:26:52 2011 +0100
@@ -0,0 +1,156 @@
+/*
+ *************************************************************************
+ * 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) 2011 Openbravo SLU 
+ * All Rights Reserved. 
+ * Contributor(s):  ______________________________________.
+ ************************************************************************
+ */
+package org.openbravo.client.kernel.event;
+
+import org.hibernate.type.Type;
+import org.openbravo.base.model.Property;
+import org.openbravo.base.structure.BaseOBObject;
+
+/**
+ * The base event object send out to reflect a persistence event on an entity (save, update, delete,
+ * etc.).
+ * 
+ * Note: it is possible to directly access/retrieve the object which is being deleted or persisted.
+ * To update the object's state one should NOT call setters directly on that object. Instead use the
+ * {@link #setCurrentState(Property, Object)} method.
+ * 
+ * @author mtaal
+ */
+public class EntityPersistenceEvent {
+  private BaseOBObject targetInstance;
+
+  private String id;
+  private Object[] currentState;
+  private String[] propertyNames;
+  private Type[] types;
+  private boolean stateUpdated = false;
+
+  /**
+   * Get the current value (which will be persisted) for a certain property.
+   */
+  public Object getCurrentState(Property property) {
+    int index = 0;
+    for (String propName : propertyNames) {
+      if (propName.equals(property.getName())) {
+        return currentState[index];
+      }
+      index++;
+    }
+    throw new IllegalArgumentException("Property " + property + " not found for entity "
+        + getTargetInstance());
+  }
+
+  /**
+   * The current values of the properties of the entity, these values are persisted. Use the
+   * {@link EntityPersistenceEvent#getPropertyNames()} to see which properties are located where in
+   * this array.
+   * 
+   * @see #getPropertyNames()
+   */
+  public Object[] getCurrentState() {
+    return currentState;
+  }
+
+  void setCurrentState(Object[] currentState) {
+    this.currentState = currentState;
+  }
+
+  /**
+   * The names of the properties of the entity which are persisted. The array corresponds to the
+   * types and state arrays.
+   * 
+   * @see #getTypes()
+   * @see #getCurrentState()
+   */
+  public String[] getPropertyNames() {
+    return propertyNames;
+  }
+
+  void setPropertyNames(String[] propertyNames) {
+    this.propertyNames = propertyNames;
+  }
+
+  /**
+   * @return the target instance of the event, note that depending on the event it it not correct to
+   *         directly update the instance, use the api's offered by the specific subclass of the
+   *         EntityPersistenceEvent class.
+   */
+  public BaseOBObject getTargetInstance() {
+    return targetInstance;
+  }
+
+  void setTargetInstance(BaseOBObject targetInstance) {
+    this.targetInstance = targetInstance;
+  }
+
+  /**
+   * Change the value/state of a property. The change will also be passed on to the entity and to
+   * the database (in case of update and save events).
+   * 
+   * @param property
+   *          the property to change
+   * @param value
+   *          its new value
+   */
+  public void setCurrentState(Property property, Object value) {
+    int index = 0;
+    for (String propName : propertyNames) {
+      if (propName.equals(property.getName())) {
+        currentState[index] = value;
+        stateUpdated = true;
+        return;
+      }
+      index++;
+    }
+    throw new IllegalArgumentException("Property " + property + " not found for entity "
+        + getTargetInstance());
+  }
+
+  /**
+   * @return true if the state of the entity was updated/changed, false otherwise.
+   */
+  public boolean isStateUpdated() {
+    return stateUpdated;
+  }
+
+  /**
+   * The id of the entity being persisted, can be null for new entities.
+   */
+  public String getId() {
+    return id;
+  }
+
+  void setId(String id) {
+    this.id = id;
+  }
+
+  /**
+   * The type definition of the properties of the entity to be persisted.
+   * 
+   * @see #getPropertyNames()
+   */
+  public Type[] getTypes() {
+    return types;
+  }
+
+  void setTypes(Type[] types) {
+    this.types = types;
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.client.kernel/src/org/openbravo/client/kernel/event/EntityPersistenceEventObserver.java	Mon Jan 24 14:26:52 2011 +0100
@@ -0,0 +1,56 @@
+/*
+ *************************************************************************
+ * 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) 2011 Openbravo SLU 
+ * All Rights Reserved. 
+ * Contributor(s):  ______________________________________.
+ ************************************************************************
+ */
+package org.openbravo.client.kernel.event;
+
+import org.openbravo.base.model.Entity;
+
+/**
+ * A base listener which can be extended to perform specific actions when persisting entities.
+ * 
+ * @author mtaal
+ */
+public abstract class EntityPersistenceEventObserver {
+
+  /**
+   * Must be implemented by subclass to signal which {@link Entity} types are observed.
+   * 
+   * @return the array of entity instances to observe.
+   * @see #isValidEvent(EntityPersistenceEvent)
+   */
+  protected abstract Entity[] getObservedEntities();
+
+  /**
+   * Convenience method which can be used by subclass to check if a certain event is indeed targeted
+   * for this observer.
+   * 
+   * @param event
+   *          the persistence event which is being handled by this observer.
+   * @return true if the event applies to one of the observed entities.
+   * @see #getObservedEntities()
+   */
+  protected boolean isValidEvent(EntityPersistenceEvent event) {
+    final Entity targetEntity = event.getTargetInstance().getEntity();
+    for (Entity entity : getObservedEntities()) {
+      if (entity == targetEntity) {
+        return true;
+      }
+    }
+    return false;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.client.kernel/src/org/openbravo/client/kernel/event/EntityUpdateEvent.java	Mon Jan 24 14:26:52 2011 +0100
@@ -0,0 +1,69 @@
+/*
+ *************************************************************************
+ * 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) 2011 Openbravo SLU 
+ * All Rights Reserved. 
+ * Contributor(s):  ______________________________________.
+ ************************************************************************
+ */
+package org.openbravo.client.kernel.event;
+
+import org.openbravo.base.model.Property;
+
+/**
+ * The event object send out when an entity gets updated.
+ * 
+ * To receive this event, create a class with a method which has this signature:
+ * 
+ * public void onEvent(@Observes EntityUpdateEvent event) {
+ * 
+ * Note, the method name is unimportant, the @Observes EntityUpdateEvent specifies that this method
+ * will be called before persisting a new instance.
+ * 
+ * @author mtaal
+ */
+public class EntityUpdateEvent extends EntityPersistenceEvent {
+  private Object[] previousState;
+
+  /**
+   * Returns the state of a property which was there when reading from the database.
+   * 
+   * @param property
+   *          the property to get the old state
+   * @return the old/previous state/value of the property
+   */
+  public Object getPreviousState(Property property) {
+    int index = 0;
+    for (String propName : getPropertyNames()) {
+      if (propName.equals(property.getName())) {
+        return previousState[index];
+      }
+      index++;
+    }
+    throw new IllegalArgumentException("Property " + property + " not found for entity "
+        + getTargetInstance());
+  }
+
+  /**
+   * Get the complete array of previous states. To see what value corresponds to what property use
+   * the {@link #getPropertyNames()} array.
+   */
+  public Object[] getPreviousState() {
+    return previousState;
+  }
+
+  void setPreviousState(Object[] previousState) {
+    this.previousState = previousState;
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.client.kernel/src/org/openbravo/client/kernel/event/PersistenceEventOBInterceptor.java	Mon Jan 24 14:26:52 2011 +0100
@@ -0,0 +1,108 @@
+/*
+ *************************************************************************
+ * 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) 2011 Openbravo SLU 
+ * All Rights Reserved. 
+ * Contributor(s):  ______________________________________.
+ ************************************************************************
+ */
+package org.openbravo.client.kernel.event;
+
+import java.io.Serializable;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.event.Event;
+import javax.inject.Inject;
+
+import org.hibernate.EmptyInterceptor;
+import org.hibernate.type.Type;
+import org.openbravo.base.structure.BaseOBObject;
+import org.openbravo.base.structure.Traceable;
+
+/**
+ * The interceptor which listens to persistence events and passes them on to observers.
+ * 
+ * @author mtaal
+ */
+@ApplicationScoped
+public class PersistenceEventOBInterceptor extends EmptyInterceptor {
+
+  private static final long serialVersionUID = 1L;
+
+  @Inject
+  private Event<EntityNewEvent> entityNewEventProducer;
+
+  @Inject
+  private Event<EntityUpdateEvent> entityUpdateEventProducer;
+
+  @Inject
+  private Event<EntityDeleteEvent> entityDeleteEventProducer;
+
+  public void onDelete(Object entity, Serializable id, Object[] state, String[] propertyNames,
+      Type[] types) {
+    final EntityDeleteEvent entityEvent = new EntityDeleteEvent();
+    entityEvent.setTargetInstance((BaseOBObject) entity);
+    entityEvent.setPropertyNames(propertyNames);
+    entityEvent.setCurrentState(state);
+    entityEvent.setTypes(types);
+    entityEvent.setId((String) id);
+    entityDeleteEventProducer.fire(entityEvent);
+  }
+
+  @Override
+  public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState,
+      Object[] previousState, String[] propertyNames, Type[] types) {
+    if (isNew(entity)) {
+      return sendNewEvent(entity, id, currentState, propertyNames, types);
+    } else {
+      return sendUpdateEvent(entity, id, currentState, previousState, propertyNames, types);
+    }
+  }
+
+  @Override
+  public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames,
+      Type[] types) {
+    return sendNewEvent(entity, id, state, propertyNames, types);
+  }
+
+  private boolean sendNewEvent(Object entity, Serializable id, Object[] state,
+      String[] propertyNames, Type[] types) {
+    final EntityNewEvent entityEvent = new EntityNewEvent();
+    entityEvent.setTargetInstance((BaseOBObject) entity);
+    entityEvent.setPropertyNames(propertyNames);
+    entityEvent.setCurrentState(state);
+    entityEvent.setTypes(types);
+    entityEvent.setId((String) id);
+    entityNewEventProducer.fire(entityEvent);
+    return entityEvent.isStateUpdated();
+  }
+
+  private boolean sendUpdateEvent(Object entity, Serializable id, Object[] currentState,
+      Object[] previousState, String[] propertyNames, Type[] types) {
+    final EntityUpdateEvent entityEvent = new EntityUpdateEvent();
+    entityEvent.setTargetInstance((BaseOBObject) entity);
+    entityEvent.setPropertyNames(propertyNames);
+    entityEvent.setCurrentState(currentState);
+    entityEvent.setPreviousState(previousState);
+    entityEvent.setTypes(types);
+    entityEvent.setId((String) id);
+    entityUpdateEventProducer.fire(entityEvent);
+    return entityEvent.isStateUpdated();
+  }
+
+  private boolean isNew(Object entity) {
+    final Traceable t = (Traceable) entity;
+    return t.getCreatedBy() == null;
+  }
+
+}