YJH16120
YJH16120

Reputation: 545

Class org.apache.derby.jdbc.ClientDriver not found despite derbyclient.jar being in CLASSPATH

I'm running this via Visual Studio Code and have the Language Support for Java (TM) by RedHat extension. The quickstart code I am using is found here. I modified it slightly to become this:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.ResultSetMetaData;


public class Restaurants
{
    private static String dbURL = "jdbc:derby://localhost:1527/myDB;create=true;user=me;password=mine";
    private static String tableName = "restaurants";
    // jdbc Connection
    private static Connection conn = null;
    private static Statement stmt = null;

    public static void main(String[] args)
    {
        createConnection();
        insertRestaurants(5, "LaVals", "Berkeley");
        selectRestaurants();
        shutdown();
    }
    
    private static void createConnection()
    {
        try
        {
            Class.forName("org.apache.derby.jdbc.ClientDriver"); //.newInstance();
            //Get a connection
            conn = DriverManager.getConnection(dbURL); 
        }
        catch (Exception except)
        {
            except.printStackTrace();
        }
    }
    
    private static void insertRestaurants(int id, String restName, String cityName)
    {
        try
        {
            stmt = conn.createStatement();
            stmt.execute("insert into " + tableName + " values (" +
                    id + ",'" + restName + "','" + cityName +"')");
            stmt.close();
        }
        catch (SQLException sqlExcept)
        {
            sqlExcept.printStackTrace();
        }
    }
    
    private static void selectRestaurants()
    {
        try
        {
            stmt = conn.createStatement();
            ResultSet results = stmt.executeQuery("select * from " + tableName);
            ResultSetMetaData rsmd = results.getMetaData();
            int numberCols = rsmd.getColumnCount();
            for (int i=1; i<=numberCols; i++)
            {
                //print Column Names
                System.out.print(rsmd.getColumnLabel(i)+"\t\t");  
            }

            System.out.println("\n-------------------------------------------------");

            while(results.next())
            {
                int id = results.getInt(1);
                String restName = results.getString(2);
                String cityName = results.getString(3);
                System.out.println(id + "\t\t" + restName + "\t\t" + cityName);
            }
            results.close();
            stmt.close();
        }
        catch (SQLException sqlExcept)
        {
            sqlExcept.printStackTrace();
        }
    }
    
    private static void shutdown()
    {
        try
        {
            if (stmt != null)
            {
                stmt.close();
            }
            if (conn != null)
            {
                DriverManager.getConnection(dbURL + ";shutdown=true");
                conn.close();
            }           
        }
        catch (SQLException sqlExcept)
        {
            
        }

    }
}

The main difference is Class.forName("org.apache.derby.jdbc.ClientDriver").newInstance(); -> Class.forName("org.apache.derby.jdbc.ClientDriver"); //.newInstance();.

When I run it with the play button, I get this output:

star@platinum:~/Documents/Projects/Distributed Computing/DerbyTest/DerbyTest$  /usr/bin/env /usr/lib/jvm/java-21-openjdk-amd64/bin/java -XX:+ShowCodeDetailsInExceptionMessages -cp /home/star/Documents/Projects/Distributed\ Computing/DerbyTest/DerbyTest/bin Restaurants 
java.lang.ClassNotFoundException: org.apache.derby.jdbc.ClientDriver
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
        at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526)
        at java.base/java.lang.Class.forName0(Native Method)
        at java.base/java.lang.Class.forName(Class.java:421)
        at java.base/java.lang.Class.forName(Class.java:412)
        at Restaurants.createConnection(Restaurants.java:29)
        at Restaurants.main(Restaurants.java:19)
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "java.sql.Connection.createStatement()" because "Restaurants.conn" is null
        at Restaurants.insertRestaurants(Restaurants.java:43)
        at Restaurants.main(Restaurants.java:20)

From my research there are three possible issues

  1. Malformed dbURL
  2. derbyclient.jar is not in CLASSPATH
  3. derby.jar is not in CLASSPATH

I assume dbURL is not malformed because it is directly copied and pasted from the apahce website. As for 2 and 3 this is my CLASSPATH:

/home/star/.local/bin/derby/lib/derbynet.jar:/home/star/.local/bin/derby/lib/derbyshared.jar:/home/star/.local/bin/derby/lib/derbyLocale_zh_CN.jar:/home/star/.local/bin/derby/lib/derbyLocale_pl.jar:/home/star/.local/bin/derby/lib/derbyLocale_pt_BR.jar:/home/star/.local/bin/derby/lib/derbyLocale_ja_JP.jar:/home/star/.local/bin/derby/lib/derbyoptionaltools.jar:/home/star/.local/bin/derby/lib/derbyrun.jar:/home/star/.local/bin/derby/lib/derbyLocale_de_DE.jar:/home/star/.local/bin/derby/lib/derbyLocale_ru.jar:/home/star/.local/bin/derby/lib/derbyLocale_es.jar:/home/star/.local/bin/derby/lib/derby.jar:/home/star/.local/bin/derby/lib/derbyLocale_it.jar:/home/star/.local/bin/derby/lib/derbyLocale_ko_KR.jar:/home/star/.local/bin/derby/lib/derbyLocale_fr.jar:/home/star/.local/bin/derby/lib/derbyclient.jar:/home/star/.local/bin/derby/lib/derbytools.jar:/home/star/.local/bin/derby/lib/derbyLocale_zh_TW.jar:/home/star/.local/bin/derby/lib/derbyLocale_cs.jar:/home/star/.local/bin/derby/lib/derbyLocale_hu.jar

Both jar files are in the classpath. I'm not sure if it is significant but the CLASSPATH variable is set inside /etc/environment. So, I am unsure of the issue I am facing. I have ran through the Apache's quickstart by creating, inserting, and selecting using ij, so i can confirm that ij works properly as does sysinfo, etc. So, I am quite certain there is no issue with derby but rather configuration, but I am unsure of what solutions are avaiable to me, thanks.

Upvotes: 1

Views: 64

Answers (1)

John Williams
John Williams

Reputation: 5430

The class org.apache.derby.jdbc.ClientDriver is in derbytools.jar, not in derby.jar or derbyclient.jar.

I see that derbytools.jar is in the CLASSPATH environment variable. However, because 'the play button' is invoking java with the -cp flag set, it is ignoring the CLASSPATH environment variable. Also, derbytools.jar might not be at /home/star/.local/bin/derby/lib/derbytools.jar

star@platinum:~/Documents/Projects/Distributed Computing/DerbyTest/DerbyTest$  /usr/bin/env /usr/lib/jvm/java-21-openjdk-amd64/bin/java -XX:+ShowCodeDetailsInExceptionMessages -cp /home/star/Documents/Projects/Distributed\ Computing/DerbyTest/DerbyTest/bin Restaurants 

A command line as follows should fix:

/usr/lib/jvm/java-21-openjdk-amd64/bin/java -XX:+ShowCodeDetailsInExceptionMessages -cp /home/star/.local/bin/derby/lib/derbynet.jar:/home/star/.local/bin/derby/lib/derbyshared.jar:/home/star/.local/bin/derby/lib/derbyLocale_zh_CN.jar:/home/star/.local/bin/derby/lib/derbyLocale_pl.jar:/home/star/.local/bin/derby/lib/derbyLocale_pt_BR.jar:/home/star/.local/bin/derby/lib/derbyLocale_ja_JP.jar:/home/star/.local/bin/derby/lib/derbyoptionaltools.jar:/home/star/.local/bin/derby/lib/derbyrun.jar:/home/star/.local/bin/derby/lib/derbyLocale_de_DE.jar:/home/star/.local/bin/derby/lib/derbyLocale_ru.jar:/home/star/.local/bin/derby/lib/derbyLocale_es.jar:/home/star/.local/bin/derby/lib/derby.jar:/home/star/.local/bin/derby/lib/derbyLocale_it.jar:/home/star/.local/bin/derby/lib/derbyLocale_ko_KR.jar:/home/star/.local/bin/derby/lib/derbyLocale_fr.jar:/home/star/.local/bin/derby/lib/derbyclient.jar:/home/star/.local/bin/derby/lib/derbytools.jar:/home/star/.local/bin/derby/lib/derbyLocale_zh_TW.jar:/home/star/.local/bin/derby/lib/derbyLocale_cs.jar:/home/star/.local/bin/derby/lib/derbyLocale_hu.jar:/home/star/Documents/Projects/Distributed\ Computing/DerbyTest/DerbyTest/bin Restaurants

It's easier (and more usual) to use the -jar option rather than -cp. That way your CLASSPATH env var will be used. Your build does need to create a jar for the project, eg DerbyTest.jar

/usr/lib/jvm/java-21-openjdk-amd64/bin/java -XX:+ShowCodeDetailsInExceptionMessages -jar /home/star/Documents/Projects/Distributed\ Computing/DerbyTest/DerbyTest.jar Restaurants

assuming the jar is at /home/star/Documents/Projects/Distributed Computing/DerbyTest/DerbyTest.jar

Upvotes: 1

Related Questions