details:   https://code.openbravo.com/erp/devel/pi/rev/d8c618c02470
changeset: 34832:d8c618c02470
user:      Asier Lostalé <asier.lostale <at> openbravo.com>
date:      Fri Sep 28 08:03:08 2018 +0200
summary:   fixed issue 39362: can't create tickets if one failed due to pool 
without conns

  After a ticket failed to be imported due to the pool is out of connections, no
  new tickets can be created from that terminal until all import entries are set
  again in Initial status.

  Now in this case instead of setting the import entry as Error preventing new
  tickets from the same terminal to be processed, it's kept in Initial status,
  in this way it will be tried to be processed in next cycle, not exposing the
  problem to users.

details:   https://code.openbravo.com/erp/devel/pi/rev/ba9ef09516cf
changeset: 34833:ba9ef09516cf
user:      Asier Lostalé <asier.lostale <at> openbravo.com>
date:      Tue Oct 02 09:43:11 2018 +0200
summary:   related to issue 39362: added test cases covering no DB conns 
detection

diffstat:

 
modules/org.openbravo.apachejdbcconnectionpool/src/org/openbravo/apachejdbcconnectionpool/JdbcExternalConnectionPool.java
 |  12 +-
 src-core/src/org/openbravo/database/ExternalConnectionPool.java                
                                           |  29 +++
 src-test/src/org/openbravo/test/AllAntTaskTests.java                           
                                           |   2 +
 src-test/src/org/openbravo/test/db/pool/PoolHasNoConnectionsDetection.java     
                                           |  73 ++++++++++
 src/org/openbravo/service/importprocess/ImportEntryProcessor.java              
                                           |  18 +-
 5 files changed, 128 insertions(+), 6 deletions(-)

diffs (228 lines):

diff -r 6ce7922086d7 -r ba9ef09516cf 
modules/org.openbravo.apachejdbcconnectionpool/src/org/openbravo/apachejdbcconnectionpool/JdbcExternalConnectionPool.java
--- 
a/modules/org.openbravo.apachejdbcconnectionpool/src/org/openbravo/apachejdbcconnectionpool/JdbcExternalConnectionPool.java
 Wed Oct 03 17:18:12 2018 +0200
+++ 
b/modules/org.openbravo.apachejdbcconnectionpool/src/org/openbravo/apachejdbcconnectionpool/JdbcExternalConnectionPool.java
 Tue Oct 02 09:43:11 2018 +0200
@@ -19,6 +19,7 @@
 package org.openbravo.apachejdbcconnectionpool;
 
 import java.sql.Connection;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -30,6 +31,7 @@
 
 import org.apache.commons.lang.StringUtils;
 import org.apache.tomcat.jdbc.pool.DataSource;
+import org.apache.tomcat.jdbc.pool.PoolExhaustedException;
 import org.apache.tomcat.jdbc.pool.PoolProperties;
 import org.openbravo.base.exception.OBException;
 import org.openbravo.base.session.OBPropertiesProvider;
@@ -47,12 +49,14 @@
  * connection from a pool, close the different pools and other actions.
  */
 public class JdbcExternalConnectionPool extends ExternalConnectionPool {
-
   final static private Logger log = 
LoggerFactory.getLogger(JdbcExternalConnectionPool.class);
 
   private Map<String, DataSource> availableDataSources = null;
   private DataSource defaultDataSource = null;
 
+  private static final List<Class<? extends Exception>> EXHAUSTED_EXCEPTION = 
Arrays
+      .asList(PoolExhaustedException.class);
+
   /**
    * This method loads all the interceptors of Apache JDBC Connection Pool 
injected with weld.
    */
@@ -349,4 +353,10 @@
     }
     super.closePool();
   }
+
+  @Override
+  protected List<Class<? extends Exception>> getExhaustedExceptions() {
+    return EXHAUSTED_EXCEPTION;
+  }
+
 }
diff -r 6ce7922086d7 -r ba9ef09516cf 
src-core/src/org/openbravo/database/ExternalConnectionPool.java
--- a/src-core/src/org/openbravo/database/ExternalConnectionPool.java   Wed Oct 
03 17:18:12 2018 +0200
+++ b/src-core/src/org/openbravo/database/ExternalConnectionPool.java   Tue Oct 
02 09:43:11 2018 +0200
@@ -18,6 +18,8 @@
 package org.openbravo.database;
 
 import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.Collections;
 import java.util.List;
 
 import org.apache.log4j.Logger;
@@ -34,6 +36,9 @@
 
   private static ExternalConnectionPool instance;
 
+  private static final String PG_TOO_MANY_CONNECTIONS = "53300";
+  private static final String ORA_CONNECTION_REFUSED = "66000";
+
   /**
    * 
    * @param externalConnectionPoolClassName
@@ -93,4 +98,28 @@
     return getConnection();
   }
 
+  /** {@code Exception}s thrown when trying to create a new connection and 
pool is exhausted. */
+  protected List<Class<? extends Exception>> getExhaustedExceptions() {
+    return Collections.emptyList();
+  }
+
+  /** Checks if {@code Throwable} was caused by pool not having more 
connections. */
+  public boolean hasNoConnections(Throwable t) {
+    if (t == null) {
+      return false;
+    }
+
+    boolean isOutOfPhysicalConns;
+    if (t instanceof SQLException) {
+      String state = ((SQLException) t).getSQLState();
+      isOutOfPhysicalConns = PG_TOO_MANY_CONNECTIONS.equals(state)
+          || ORA_CONNECTION_REFUSED.equals(state);
+    } else {
+      isOutOfPhysicalConns = false;
+    }
+
+    return isOutOfPhysicalConns
+        || getExhaustedExceptions().stream().anyMatch(e -> 
e.isAssignableFrom(t.getClass()))
+        || hasNoConnections(t.getCause());
+  }
 }
diff -r 6ce7922086d7 -r ba9ef09516cf 
src-test/src/org/openbravo/test/AllAntTaskTests.java
--- a/src-test/src/org/openbravo/test/AllAntTaskTests.java      Wed Oct 03 
17:18:12 2018 +0200
+++ b/src-test/src/org/openbravo/test/AllAntTaskTests.java      Tue Oct 02 
09:43:11 2018 +0200
@@ -68,6 +68,7 @@
 import org.openbravo.test.db.model.functions.ADOrgTreeTest;
 import org.openbravo.test.db.model.functions.Ad_isorgincludedTest;
 import org.openbravo.test.db.model.functions.SqlCallableStatement;
+import org.openbravo.test.db.pool.PoolHasNoConnectionsDetection;
 import org.openbravo.test.expression.EvaluationTest;
 import org.openbravo.test.expression.OBBindingsTest;
 import 
org.openbravo.test.generalsetup.enterprise.organization.ADOrgPersistInfoTestSuite;
@@ -274,6 +275,7 @@
 
     // db
     SqlCallableStatement.class, //
+    PoolHasNoConnectionsDetection.class, //
 
     // grid configuration
     ViewGenerationWithDifferentConfigLevelTest.class, //
diff -r 6ce7922086d7 -r ba9ef09516cf 
src-test/src/org/openbravo/test/db/pool/PoolHasNoConnectionsDetection.java
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ 
b/src-test/src/org/openbravo/test/db/pool/PoolHasNoConnectionsDetection.java    
    Tue Oct 02 09:43:11 2018 +0200
@@ -0,0 +1,73 @@
+/*
+ *************************************************************************
+ * 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) 2018 Openbravo SLU 
+ * All Rights Reserved. 
+ ************************************************************************
+ */
+
+package org.openbravo.test.db.pool;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import java.sql.SQLException;
+
+import org.apache.tomcat.jdbc.pool.PoolExhaustedException;
+import org.junit.Test;
+import org.openbravo.apachejdbcconnectionpool.JdbcExternalConnectionPool;
+import org.openbravo.base.exception.OBException;
+
+/** Test cases covering checking of Exceptions thrown when DB pool gets out of 
connections */
+public class PoolHasNoConnectionsDetection {
+  private JdbcExternalConnectionPool pool = new JdbcExternalConnectionPool();
+
+  @Test
+  public void tomcatPoolExhaustedShouldBeDetected() {
+    assertThat("PoolExhaustedException should be detected as no connections 
exception",
+        pool.hasNoConnections(new PoolExhaustedException()), is(true));
+  }
+
+  @Test
+  public void tomcatPoolNestedExhaustedShouldBeDetected() {
+    Exception nestedException = new OBException(new PoolExhaustedException());
+    assertThat("Nested PoolExhaustedException should be detected as no 
connections exception",
+        pool.hasNoConnections(nestedException), is(true));
+
+    Exception nested2LevelException = new Exception(nestedException);
+    assertThat(
+        "Nested 2 levels PoolExhaustedException should be detected as no 
connections exception",
+        pool.hasNoConnections(nested2LevelException), is(true));
+  }
+
+  @Test
+  public void pgOutOfConnectionsShouldBeDetected() {
+    SQLException se = new SQLException("PG cannot create DB connection", 
"53300");
+    assertThat("Cannot create DB connections should be detected as no 
connections exception",
+        pool.hasNoConnections(se), is(true));
+  }
+
+  @Test
+  public void oraOutOfConnectionsShouldBeDetected() {
+    SQLException se = new SQLException("ORA cannot create DB connection", 
"66000");
+    assertThat("Cannot create DB connections should be detected as no 
connections exception",
+        pool.hasNoConnections(se), is(true));
+  }
+
+  @Test
+  public void otherExceptionsShoulNotBeDetected() {
+    assertThat("Other Exception detected as no connections",
+        pool.hasNoConnections(new SQLException()), is(false));
+  }
+
+}
diff -r 6ce7922086d7 -r ba9ef09516cf 
src/org/openbravo/service/importprocess/ImportEntryProcessor.java
--- a/src/org/openbravo/service/importprocess/ImportEntryProcessor.java Wed Oct 
03 17:18:12 2018 +0200
+++ b/src/org/openbravo/service/importprocess/ImportEntryProcessor.java Tue Oct 
02 09:43:11 2018 +0200
@@ -38,6 +38,7 @@
 import org.openbravo.dal.core.SessionHandler;
 import org.openbravo.dal.core.TriggerHandler;
 import org.openbravo.dal.service.OBDal;
+import org.openbravo.database.ExternalConnectionPool;
 import org.openbravo.database.SessionInfo;
 import org.openbravo.model.common.enterprise.Organization;
 
@@ -421,11 +422,18 @@
           } catch (Exception ignored) {
           }
 
-          // store the error
-          try {
-            
importEntryManager.setImportEntryErrorIndependent(queuedImportEntry.importEntryId,
 t);
-          } catch (Throwable ignore) {
-            ImportProcessUtils.logError(logger, ignore);
+          ExternalConnectionPool pool = ExternalConnectionPool.getInstance();
+          if (pool != null && pool.hasNoConnections(t)) {
+            // If the exception was caused by not having connections in pool, 
import entry will be
+            // kept in Initial status to be processed in next cycle if there 
are connections. We
+            // also break the loop to stop trying to process any other pending 
entry in this cycle.
+            break;
+          } else {
+            try {
+              
importEntryManager.setImportEntryErrorIndependent(queuedImportEntry.importEntryId,
 t);
+            } catch (Throwable ignore) {
+              ImportProcessUtils.logError(logger, ignore);
+            }
           }
         } finally {
           cleanUpThreadForNextCycle();


_______________________________________________
Openbravo-commits mailing list
Openbravo-commits@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openbravo-commits

Reply via email to