5

I'm trying to work through creating a very simple class to send queries to an instance of Oracle XE 11g, essentially making a very simple SQL*Plus to get the basics of JDBC down.

The source code I'm currently working with is:

public class Example {
    static String username, password;
    static String dbDriver = "oracle.jdbc.driver.OracleDriver";
    static String dbConnection = "jdbc:oracle:thin:@//localhost:1521/xe";

    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        String line;
        Connection c = null;
        Statement stmt = null;
        int loginAttempts = 0;

        // Log in loop
        do {
            try {
                Class.forName(dbDriver);
                System.out.print("Enter username: ");
                line = input.nextLine();
                if (line.contains("/")) {
                    String[] login = line.split("/");
                    if (login.length != 2) {
                        System.out
                                .println("Unrecognized information, exiting...");
                        System.exit(0);
                    }

                    username = login[0].trim();
                    password = login[1].trim();
                } else {
                    username = line;
                    System.out.print("Enter password: ");
                    password = input.nextLine();
                }

                c = DriverManager.getConnection(dbConnection, username,
                        password);
                stmt = c.createStatement();
                loginAttempts = -1;
            } catch (ClassNotFoundException e) {
                System.err.println("Unable to connect to database, exiting...");
                System.exit(-1);
            } catch (SQLException e) {
                System.out.println("Username and/or password is incorrect");
                if (++loginAttempts == 1) {
                    System.out.println("Too many failed login attempts, exiting...");
                    System.exit(0);
                }
            }
        } while (loginAttempts != -1);

        // Input loop
        for (;;) {
            try {
                // Write out the prompt text and wait for input
                if(c == null) {
                    throw new IllegalStateException("Connection should not be null");
                }
                System.out.print(c.getSchema() + ":> ");
                String tmp = input.nextLine();

                // Check if the user entered "exit"
                if (tmp.toLowerCase().equals("exit")) {
                    System.out.println("Exiting...");
                    input.close();
                    System.exit(0);
                }

                String query;
                // TODO: For some reason, no semi-colon is allowed
                if (tmp.charAt(tmp.length() - 1) == ';')
                    query = tmp.split(";")[0];
                else
                    query = tmp;
                // System.out.println(query);
                ResultSet rset = stmt.executeQuery(query);
                ResultSetMetaData rmd = rset.getMetaData();
                int colCount = rmd.getColumnCount();

                // Column indices start with 1, print column names
                for (int i = 1; i <= colCount; i++) {
                    System.out.printf("%-20.20s   ", rmd.getColumnName(i));
                }
                System.out.println();

                while (rset.next()) {
                    for (int i = 0; i < colCount; i++) {
                        System.out.printf("%-20.20s | ", rset.getString(i + 1));
                    }
                    System.out.println();
                }
                System.out.println();
            } catch (SQLSyntaxErrorException e) {
                System.out.println("Encountered a syntax error:\n"
                        + e.getMessage());
            } catch (SQLException e) {
                System.err.println("An unexpected error occurred");
                e.printStackTrace();
                input.close();
                System.exit(-1);
            }
        }

    }
}

In the second try/catch block, in the for(;;) loop, I get the following output:

Enter username: hr/hr
Exception in thread "main" java.lang.AbstractMethodError: oracle.jdbc.driver.T4CConnection.getSchema()Ljava/lang/String;
at jdbctest.Example.main(Example.java:69)

I checked out the Oracle docs (java.lang.AbstractMethodError), and it says that this error can only be thrown if:

"the definition of some class has incompatibly changed since the currently executing method was last compiled."

I'm thinking that there's something I'm missing with line 27, but I'm not sure how to approach this problem and any guidance would be extremely helpful.

Nicolas Filotto
  • 43,537
  • 11
  • 94
  • 122
drognisep
  • 579
  • 1
  • 7
  • 16
  • 2
    Include the source code in your post. External links eventually go bad, making the post worthless for future readers. Future value is the whole point of SO. – Jim Garrison Jun 28 '16 at 18:32
  • 1
    And, please only add the relevant code - see [mcve]. Most likely you can eliminate a huge part of your code and still reproduce the issue. – Andreas Fester Jun 28 '16 at 18:34
  • btw, the error is not thrown in line 27, but in line 69 when calling the `getSchema()` method. Most likely you have some mismatch in JDBC versions - see http://stackoverflow.com/questions/1194990/why-do-i-get-java-lang-abstractmethoderror-when-trying-to-load-a-blob-in-the-db for a similar issue. Which Java version are you using, and which JDBC driver (version, downloaded from)? – Andreas Fester Jun 28 '16 at 18:38
  • 1
    I've checked your code with postgresql driver and it works OK, probably the driver you're using is not "complete" ;) – jaroslawj Jun 28 '16 at 18:40
  • @AndreasFester : The line that _was_ 27 was `Class.forName(dbDriver);`, and I'm not sure if there is something happening when the driver is created that is not consistent with what Java expects. I'm aware, due to the stack trace, where the exception is thrown. – drognisep Jun 28 '16 at 19:25

2 Answers2

13

I believe that your problem is due to the fact that you use a JDBC driver for a version of Java <= 6 and you use Java 7 or higher because the method Connection#getSchema() has been added in Java 7.

Use the latest version of your JDBC driver to avoid such issue or at least a JDBC driver compatible with your version of Java.

Nicolas Filotto
  • 43,537
  • 11
  • 94
  • 122
  • That makes sense, let me try an updated driver and I'll post back. – drognisep Jun 28 '16 at 19:26
  • 2
    That did it! I was using ojdbc6_g.jar, and downloading and referencing the newer [ojdbc7_g.jar](http://www.oracle.com/technetwork/database/features/jdbc/default-2280470.html) allowed me to use that method. Thanks for the help! – drognisep Jun 28 '16 at 19:41
0

This works on DB2 (and an old version of the driver)

Connection.getMetaData().getConnection().getSchema();
Sergio Gabari
  • 663
  • 6
  • 12