Menu

#3133 database connection: java.sql.SQLException: No suitable driver found for jdbc

Next Release
not-fixable
nobody
None
normal
minor
HaveNotTried
none
2022-03-15
2022-03-04
peter
No

I write a test to try to make freeplane work with mysql, but it failed.

code:

import groovy.sql.Sql

def url = "jdbc:mysql://localhost:3306/mindmap"
def user = "root"
def password = "root"
def driver = "com.mysql.jdbc.Driver"

def sql = Sql.newInstance(url, user, password, driver)

sql.execute """
  CREATE TABLE Author (
    id          INTEGER,
    firstName   VARCHAR(64),
    lastName    VARCHAR(64)
  );
"""

sql.close()

exception:

STDOUT: Mar 05, 2022 12:18:32 AM org.freeplane.core.util.LogUtils warn
WARNING: ExecuteScriptAction failed:
java.sql.SQLException: No suitable driver found for jdbc:mysql://localhost:3306/mindmap
    at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:702)
    at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:228)
    at groovy.sql.Sql.newInstance(Sql.java:396)
    at groovy.sql.Sql.newInstance(Sql.java:437)
    at groovy.sql.Sql$newInstance.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:166)
    at common.run(common.groovy:22)
    at org.freeplane.plugin.script.GroovyScript.execute(GroovyScript.java:112)
    at org.freeplane.plugin.script.ScriptRunner.execute(ScriptRunner.java:56)
    at org.freeplane.plugin.script.ExecuteScriptAction.actionPerformed(ExecuteScriptAction.java:112)
    at java.desktop/javax.swing.SwingUtilities.notifyAction(SwingUtilities.java:1810)
    at org.freeplane.core.ui.ActionAcceleratorManager.processKeyBinding(ActionAcceleratorManager.java:440)
    at org.freeplane.main.mindmapmode.MModeControllerFactory$2.processKeyBinding(MModeControllerFactory.java:288)
    at org.freeplane.view.swing.ui.UserInputListenerFactory$2.processKeyBinding(UserInputListenerFactory.java:172)
    at org.freeplane.core.ui.components.FreeplaneMenuBar.processKeyBinding(FreeplaneMenuBar.java:116)
    at org.freeplane.main.application.MenuKeyProcessor.processKeyBinding(MenuKeyProcessor.java:26)
    at org.freeplane.main.application.ConnectedToMenuView.processKeyBinding(ConnectedToMenuView.java:41)
    at java.desktop/javax.swing.JComponent.processKeyBindings(JComponent.java:2962)
    at java.desktop/javax.swing.JComponent.processKeyEvent(JComponent.java:2862)
    at java.desktop/java.awt.Component.processEvent(Component.java:6412)
    at java.desktop/java.awt.Container.processEvent(Container.java:2263)
    at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:5011)
    at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2321)
    at java.desktop/java.awt.Component.dispatchEvent(Component.java:4843)
    at java.desktop/java.awt.KeyboardFocusManager.redispatchEvent(KeyboardFocusManager.java:1950)
    at java.desktop/java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(DefaultKeyboardFocusManager.java:870)
    at java.desktop/java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(DefaultKeyboardFocusManager.java:1139)
    at java.desktop/java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(DefaultKeyboardFocusManager.java:1009)
    at java.desktop/java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:835)
    at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:4892)
    at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2321)
    at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2772)
    at java.desktop/java.awt.Component.dispatchEvent(Component.java:4843)
    at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:772)
    at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:721)
    at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:715)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:95)
    at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:745)
    at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:743)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
    at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:742)
    at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)

Discussion

  • peter

    peter - 2022-03-04

    but it worked in idea's Groovy Console. I want to know where goes wrong.

     
  • macmarrum

    macmarrum - 2022-03-04

    Just a though: is the mysql jdbc driver on your classpath when you try to run it from within Freeplane?

     
    • peter

      peter - 2022-03-05

      sure, I put it in class path, did it work for you?

      • jar: mysql-connector-java-5.1.37-bin.jar
      • mysql version: 5.5
       

      Last edit: peter 2022-03-05
  • Dimitry Polivaev

    Where have you put the jar file?
    Have you tried to put it into <freeplane-user-config>/1.9.x/lib ?

     
    • peter

      peter - 2022-03-15

      sorry, late for replying. like macmarrum mentioned, datasource is a solution, and I will also test your suggestion sometime. thanks for replying.
      I just have a nice idea and was about to put a request, and found that I was forbidden to create new ticket, I don't know what's wrong with it, did I make a mistake or something?
      if yes, I am sorry and please let me know, I will avoid making to this.
      Thanks.

       
      • Dimitry Polivaev

        Could you please open the new ticket at https://github.com/freeplane/freeplane/issues ?

         
        • peter

          peter - 2022-03-15

          no problem, sorry for missing the announcement.

           
  • macmarrum

    macmarrum - 2022-03-13

    I have tried with sqlite-jdbc-3.36.0.3.jar, puting the driver in <freeplane-user-config>/1.9.x/lib. There seems to be a more generic issue around JDBC

     

    Last edit: macmarrum 2022-03-13
  • Dimitry Polivaev

    The problem comes with a combination of dynamic features by Groovy and Class Loaders.
    I can not fix it but I can suggest a workaround:

    =import java.sql.*
    
    @groovy.transform.CompileStatic
    class DriverManagerWrapper {
        def registerDriver(){
            Driver driver = new org.sqlite.JDBC()
            DriverManager.registerDriver(driver)
            return DriverManager.drivers.collect{it.class.name}.join('\n') ?: 'no drivers registered'
        }
    }
    
    new DriverManagerWrapper().registerDriver()
    
     
  • Dimitry Polivaev

    • status: new --> not-fixable
     
  • Dimitry Polivaev

    Try to wrap calls to Sql.newInstance(url, user, password, driver)and DriverManager.getConnection in a similar way

     
  • macmarrum

    macmarrum - 2022-03-13

    Thanks, Dimitry.

    I was unsuccessful wrapping Sql.newInstance this way.
    I suppose DriverManager.getConnection could be used instead. But apart from it being a bit cumbersome as compared to groovy.sql.Sql, with @CompileStatic the code seems to loose the ability to interact with the map/nodes.

    What I did instead was to add sqlite-jdbc-3.36.0.3.jar to classpath for Java, by copying the jar to <freeplane-install-dir> and modifying freeplanelauncher.jar#META-INF/MANIFEST.MF:

    Class-Path: framework.jar sqlite-jdbc-3.36.0.3.jar
    

    This has registered the driver correctly with the DriverManager and groovy.sql.Sql worked as expected. But I ran into access denied. To allow the sqlite driver to work (for the in-memory database case), I had to extend <freeplane-install-dir>/freeplane.policy, adding:

    grant {
        permission java.io.FilePermission "/tmp/*", "read,write,delete";
        permission java.lang.RuntimePermission "loadLibrary.*";
    };
    
     

    Last edit: macmarrum 2022-03-13
  • Dimitry Polivaev

    I have checked only the DriverManager.
    I would wrap into the helper class only the call to getConnection keeping the rest unchanged.

     
  • macmarrum

    macmarrum - 2022-03-14

    Success 📯 😄 🙌

    Whereas SQL.newInstance fails, creating a new Sql by providing a DataSource succeeds.

    Here's a working example for MariaDB -- I put mariadb-java-client-3.0.3.jar in <freeplane-user-config>/1.9.x/lib

    =
    import org.mariadb.jdbc.MariaDbDataSource
    import groovy.sql.Sql
    
    def ds = new MariaDbDataSource('jdbc:mariadb://localhost/test')
    ds.user = 'my_user'
    ds.password = 'my_password_for_the_user'
    def db = new Sql(ds)
    db.execute('create table x (a int)')
    db.execute('insert into x values (1)')
    db.execute('insert into x values (2)')
    db.eachRow('select * from x') { node.createChild(it) }
    db.execute('drop table x')
    db.close()
    "run ${new Date()}"