yuqi1129 commented on code in PR #6432:
URL: https://github.com/apache/gravitino/pull/6432#discussion_r1969121631


##########
integration-test-common/src/test/java/org/apache/gravitino/integration/test/container/MySQLContainer.java:
##########
@@ -119,6 +119,14 @@ public void createDatabase(TestDatabaseName 
testDatabaseName) {
         StringUtils.substring(
             getJdbcUrl(testDatabaseName), 0, 
getJdbcUrl(testDatabaseName).lastIndexOf("/"));
 
+    // Fix https://github.com/apache/gravitino/issues/6392, MYSQL JDBC driver 
may not load
+    // automatically.
+    try {
+      Class.forName("com.mysql.jdbc.Driver");

Review Comment:
   @FANNG1 @jerryshao 
   
   The root cause is as follows:
   
   When `SparkIcebergCatalogRestBackendIT33` executes Spark SQL, it will enable 
the IsolatedClientLoader (used for isolating Hive dependencies; the parent 
classloader of this classloader is the root classloader) to execute part of the 
code. This causes the static code block(loadInitialDrivers) of 
`java.sql.DriverManager` to be triggered by the `IsolatedClientLoader`, thereby 
resulting in the driver's classloader in the `DriverInfo` registered with 
`DriverManager` being `IsolatedClientLoader`.
   
   `SparkIcebergCatalogRestBackendIT33` and `SparkJdbcMysqlCatalogIT33` run in 
the same JVM. Since the static code block of a class loaded by the root 
classloader can only be initialized once, executing `SparkJdbcMysqlCatalogIT33` 
afterward will cause an error due to the incorrect driver classloader.
   
   ```
     @CallerSensitive
       public static Driver getDriver(String url)
           throws SQLException {
   
           println("DriverManager.getDriver(\"" + url + "\")");
   
           Class<?> callerClass = Reflection.getCallerClass();
   
           // Walk through the loaded registeredDrivers attempting to locate 
someone
           // who understands the given URL.
           for (DriverInfo aDriver : registeredDrivers) {
               // If the caller does not have permission to load the driver then
               // skip it.
   
           // aDriver loaded by IsolatedClientLoader will fail here
               if(isDriverAllowed(aDriver.driver, callerClass)) {
                   try {
                       if(aDriver.driver.acceptsURL(url)) {
                           // Success!
                           println("getDriver returning " + 
aDriver.driver.getClass().getName());
                       return (aDriver.driver);
                       }
   
                   } catch(SQLException sqe) {
                       // Drop through and try the next driver.
                   }
               } else {
                   println("    skipping: " + 
aDriver.driver.getClass().getName());
               }
   
           }
   
           println("getDriver: no suitable driver");
           throw new SQLException("No suitable driver", "08001");
       }
   
   
       private static boolean isDriverAllowed(Driver driver, ClassLoader 
classLoader) {
           boolean result = false;
           if(driver != null) {
               Class<?> aClass = null;
               try {
                   aClass =  Class.forName(driver.getClass().getName(), true, 
classLoader);
               } catch (Exception ex) {
                   result = false;
               }
           
               **// The class loader of aClass is `AppClassLoader` and that of 
the driver.getClass() is IsolatedClientLoader, that is why the driver does 
exist, but can't fetch it successfully. **
                result = ( aClass == driver.getClass() ) ? true : false;
           }
   
           return result;
       }
   ```
   
   The order of these unit tests matters. If SparkJdbcMysqlCatalogIT33 is 
executed first each time, there will be no problem. Therefore, this issue is 
not consistently reproducible.
   
   Solutions:
   - Re-register using Class.forName("") with the App Classloader.
   - Ensure that SparkJdbcMysqlCatalogIT33 is always executed first in the 
module
   - Run the first test in a separate JVM. This can be achieved by.
   ```
   test {
       forkCount = 1  
       maxParallelForks = 1  
   }
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscr...@gravitino.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to