Improved the starting time of tomcat by avoiding the recreation of the session on DomainType classes
authorAntonio Moreno <antonio.moreno@openbravo.com>
Wed, 19 Jan 2011 17:31:57 +0100
changeset 9945 7fc34fd92373
parent 9944 c31665acce93
child 9946 abd8d6d9e950
Improved the starting time of tomcat by avoiding the recreation of the session on DomainType classes
modules/org.openbravo.userinterface.selector/src/org/openbravo/userinterface/selector/model/domaintype/SelectorDomainType.java
src/org/openbravo/base/model/ModelProvider.java
src/org/openbravo/base/model/domaintype/BaseDomainType.java
--- a/modules/org.openbravo.userinterface.selector/src/org/openbravo/userinterface/selector/model/domaintype/SelectorDomainType.java	Wed Jan 19 17:17:47 2011 +0100
+++ b/modules/org.openbravo.userinterface.selector/src/org/openbravo/userinterface/selector/model/domaintype/SelectorDomainType.java	Wed Jan 19 17:31:57 2011 +0100
@@ -18,6 +18,7 @@
  */
 package org.openbravo.userinterface.selector.model.domaintype;
 
+import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.log4j.Logger;
@@ -26,7 +27,7 @@
 import org.hibernate.criterion.Expression;
 import org.hibernate.criterion.Order;
 import org.openbravo.base.model.Column;
-import org.openbravo.base.model.ModelSessionFactoryController;
+import org.openbravo.base.model.ModelProvider;
 import org.openbravo.base.model.Table;
 import org.openbravo.base.model.domaintype.BaseForeignKeyDomainType;
 
@@ -41,69 +42,53 @@
   private Column column;
   private String tableName;
 
+  public static List<Class<?>> getClasses() {
+    List<Class<?>> listOfClasses = new ArrayList<Class<?>>();
+    listOfClasses.add(SelectorDefinition.class);
+    listOfClasses.add(DatasourceDefinition.class);
+    return listOfClasses;
+  }
+
   // Note: implementation should clean-up and close database connections or hibernate sessions. If
   // this is not done then the update.database task may hang when disabling foreign keys.
   public void initialize() {
 
-    final ModelSessionFactoryController sessionFactoryController = new ModelSessionFactoryController();
-    sessionFactoryController.addAdditionalClasses(SelectorDefinition.class);
-    sessionFactoryController.addAdditionalClasses(DatasourceDefinition.class);
+    Session session = ModelProvider.getInstance().getSession();
 
-    Session session = null;
-    try {
-      session = sessionFactoryController.getSessionFactory().openSession();
-      session.beginTransaction();
-
-      final Criteria criteria = session.createCriteria(SelectorDefinition.class);
-      criteria.add(Expression.eq("referenceId", getReference().getId()));
-      final List<?> list = criteria.list();
-      if (list.isEmpty()) {
-        // a base reference
-        if (getReference().getParentReference() == null) {
-          return;
+    final Criteria criteria = session.createCriteria(SelectorDefinition.class);
+    criteria.add(Expression.eq("referenceId", getReference().getId()));
+    final List<?> list = criteria.list();
+    if (list.isEmpty()) {
+      // a base reference
+      if (getReference().getParentReference() == null) {
+        return;
+      }
+      log.error("No selector definition found for reference " + getReference());
+      return;
+    } else if (list.size() > 1) {
+      log.warn("Reference " + getReference()
+          + " has more than one selector definition, only one is really used");
+    }
+    final SelectorDefinition selectorDefinition = (SelectorDefinition) list.get(0);
+    Table table = selectorDefinition.getTable();
+    if (table == null && selectorDefinition.getDatasourceDefinition() != null) {
+      table = selectorDefinition.getDatasourceDefinition().getTable();
+    }
+    if (table == null) {
+      throw new IllegalStateException("The selector " + selectorDefinition.getIdentifier()
+          + " is used in a foreign key reference but no table has been set");
+    }
+    tableName = table.getTableName();
+    if (selectorDefinition.getColumn() == null) {
+      final List<Column> columns = readColumns(session, table);
+      for (Column col : columns) {
+        if (col.isKey()) {
+          column = col;
+          break;
         }
-        log.error("No selector definition found for reference " + getReference());
-        return;
-      } else if (list.size() > 1) {
-        log.warn("Reference " + getReference()
-            + " has more than one selector definition, only one is really used");
       }
-      final SelectorDefinition selectorDefinition = (SelectorDefinition) list.get(0);
-      Table table = selectorDefinition.getTable();
-      if (table == null && selectorDefinition.getDatasourceDefinition() != null) {
-        table = selectorDefinition.getDatasourceDefinition().getTable();
-      }
-      if (table == null) {
-        throw new IllegalStateException("The selector " + selectorDefinition.getIdentifier()
-            + " is used in a foreign key reference but no table has been set");
-      }
-      tableName = table.getTableName();
-      if (selectorDefinition.getColumn() == null) {
-        final List<Column> columns = readColumns(session, table);
-        for (Column col : columns) {
-          if (col.isKey()) {
-            column = col;
-            break;
-          }
-        }
-      } else {
-        column = selectorDefinition.getColumn();
-      }
-    } finally {
-      try {
-        session.getTransaction().commit();
-      } catch (Throwable t) {
-        // ignored on purpose
-        log.error(t.getMessage(), t);
-      }
-      try {
-        session.close();
-      } catch (Throwable t) {
-        // ignored on purpose
-        log.error(t.getMessage(), t);
-      }
-      // always force a close of the session factory
-      sessionFactoryController.getSessionFactory().close();
+    } else {
+      column = selectorDefinition.getColumn();
     }
   }
 
--- a/src/org/openbravo/base/model/ModelProvider.java	Wed Jan 19 17:17:47 2011 +0100
+++ b/src/org/openbravo/base/model/ModelProvider.java	Wed Jan 19 17:31:57 2011 +0100
@@ -19,6 +19,9 @@
 
 package org.openbravo.base.model;
 
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
@@ -43,6 +46,7 @@
 import org.openbravo.base.session.UniqueConstraintColumn;
 import org.openbravo.base.util.Check;
 import org.openbravo.base.util.CheckException;
+import org.openbravo.database.ConnectionProviderImpl;
 
 /**
  * Builds the Runtime model base on the data model (application dictionary: table, column,
@@ -75,6 +79,7 @@
   // a list because for small numbers a list is faster than a hashmap
   private List<Entity> entitiesWithTreeType = null;
   private List<Module> modules;
+  private Session session;
 
   /**
    * Returns the singleton instance providing the ModelProvider functionality.
@@ -134,14 +139,14 @@
 
   private void initialize() {
     log.info("Building runtime model");
-
     // Caching model (tables, table-references, search-references,
     // list-references)
     // Changed to use the SessionHandler directly because the dal
     // layer uses the ModelProvider, so otherwise there will be a
     // cyclic relation.
-    final SessionFactoryController sessionFactoryController = new ModelSessionFactoryController();
-    final Session session = sessionFactoryController.getSessionFactory().openSession();
+    final ModelSessionFactoryController sessionFactoryController = new ModelSessionFactoryController();
+    initializeReferenceClasses(sessionFactoryController);
+    session = sessionFactoryController.getSessionFactory().openSession();
     final Transaction tx = session.beginTransaction();
     try {
       log.debug("Read model from db");
@@ -155,7 +160,6 @@
         reference.getDomainType().initialize();
         referencesById.put(reference.getId(), reference);
       }
-
       // read the columns in one query and assign them to the table
       final List<Column> cols = readColumns(session);
       assignColumnsToTable(cols);
@@ -279,6 +283,48 @@
   }
 
   /**
+   * This method uses a normal JDBC connection to retrieve the classes of the references. These
+   * classes will be instantiated and if they implement the correct interface, they will be added to
+   * the SessionFactoryController
+   */
+  private void initializeReferenceClasses(ModelSessionFactoryController sessionFactoryController) {
+    ConnectionProviderImpl con = null;
+    Connection connection = null;
+    try {
+      con = new ConnectionProviderImpl(OBPropertiesProvider.getInstance().getOpenbravoProperties()
+          .getProperty("source.path")
+          + "/config/Openbravo.properties");
+      connection = con.getConnection();
+      PreparedStatement ps = connection
+          .prepareStatement("select distinct model_impl from ad_reference where model_impl is not null");
+      ResultSet rs = ps.executeQuery();
+      Class<?> baseDomainType = Class.forName("org.openbravo.base.model.domaintype.BaseDomainType");
+      while (rs.next()) {
+        String classname = rs.getString(1);
+        Class<?> myClass = Class.forName(classname);
+        if (baseDomainType.isAssignableFrom(myClass)) {
+          Object classInstance = myClass.newInstance();
+          List<Class<?>> listOfClasses = (List<Class<?>>) myClass.getMethod("getClasses",
+              new Class[0]).invoke(classInstance, new Object[0]);
+          for (Class<?> aClass : listOfClasses) {
+            sessionFactoryController.addAdditionalClasses(aClass);
+          }
+        }
+      }
+    } catch (Exception e) {
+      throw new OBException("Failed to load reference classes", e);
+    } finally {
+      try {
+        connection.close();
+        con.destroy();
+      } catch (Exception e) {
+        // do nothing
+      }
+    }
+
+  }
+
+  /**
    * Returns the tables in the database, is usefull for debugging purposes.
    * 
    * @return list of tables in the database
@@ -921,4 +967,12 @@
     }
     return null;
   }
+
+  /**
+   * This method can be used to get the session of the ModelProvider. This method is intended to be
+   * used by DomainType classes during initialization phase, to do queries in the database
+   */
+  public Session getSession() {
+    return session;
+  }
 }
--- a/src/org/openbravo/base/model/domaintype/BaseDomainType.java	Wed Jan 19 17:17:47 2011 +0100
+++ b/src/org/openbravo/base/model/domaintype/BaseDomainType.java	Wed Jan 19 17:31:57 2011 +0100
@@ -19,6 +19,9 @@
 
 package org.openbravo.base.model.domaintype;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import org.openbravo.base.model.BaseOBObjectDef;
 import org.openbravo.base.model.ModelProvider;
 import org.openbravo.base.model.Property;
@@ -67,4 +70,8 @@
     checkIsValidValue(property, obObject.get(property.getName()));
   }
 
+  public static List<Class<?>> getClasses() {
+    return new ArrayList<Class<?>>();
+  }
+
 }