Issue Details (XML | Word | Printable)

Key: JDBC-325
Type: Bug Bug
Status: Closed Closed
Resolution: Fixed
Priority: Major Major
Assignee: Mark Rotteveel
Reporter: Mark Rotteveel
Votes: 0
Watchers: 0
Operations

If you were logged in you would be able to see more operations.
Jaybird JCA/JDBC Driver

Hibernate reverse engineering in Netbeans gives NullPointerException

Created: 20/Sep/13 02:02 PM   Updated: 08/Dec/13 09:47 PM
Component/s: JDBC driver
Affects Version/s: Jaybird 2.1.6, Jaybird 2.2, Jaybird 2.2.1, Jaybird 2.2.2, Jaybird 2.2.3
Fix Version/s: Jaybird 2.2.4, Jaybird 3.0

Time Tracking:
Not Specified

Environment: Netbeans 7.3, Java 1.7.0_40


 Description  « Hide
Performing a Hibernate reverse engineering in Netbeans leads to a NullPointerException in the wizard.

See:
http://stackoverflow.com/questions/14500429/nullpointerexception-in-netbeans-hibernate-mapping-files-and-pojos-wizard-from-f
http://stackoverflow.com/questions/18904451/how-to-configure-jaybird-with-hibernate

Looking at the Hibernate (3.2) and Netbeans code involved, the problem seems to be in the way that Netbeans creates the connection in org.netbeans.modules.hibernate.util.CustomJDBCConnectionProvider and this somehow leads to a null connection being returned from Firebird. This might be a classloading issue.

The specific code (which matches with the logging in Netbeans) in CustomJDBCConnectionProvider (based on 7.3.1 source) is:

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Class clazz = classLoader.loadClass(driverClassName);

java.sql.Driver driver = (java.sql.Driver) clazz.newInstance();

logger.info("Loaded JDBC driver ");
// Establish the connection
java.util.Properties info = new java.util.Properties();
info.setProperty("user", username);
info.setProperty("password", password);
connection = driver.connect(driverURL, info);
logger.info("Got connection.. returning");

Looking at org.firebirdsql.jdbc.FBDriver this can only return null if GDSFactory.getTypeForProtocol(url); does not return a GDSType, which should only happen if the URL is not a Firebird url.

 All   Comments   Work Log   Change History   Version Control   Subversion Commits      Sort Order: Ascending order - Click to sort in descending order
Mark Rotteveel added a comment - 20/Sep/13 02:41 PM
Added logging to debug this in Netbeans and the problem is indeed that somehow the driver fails to locate the GDSType for the url, the logging I added shows:

INFO [org.netbeans.modules.hibernate.util.HibernateUtil]: Found pre-existing database connection.
INFO [org.netbeans.modules.hibernate.util.HibernateUtil]: Database Connection not established, connecting..
INFO [org.firebirdsql.jdbc.AbstractDriver]: Load event of driver
INFO [org.firebirdsql.jdbc.AbstractDriver]: Loading url jdbc:firebirdsql://localhost/D:/data/db/testdatabase.fdb?columnLabelForName=true
INFO [org.firebirdsql.gds.impl.GDSFactory]: Attempting to load class org.firebirdsql.gds.impl.wire.WireGDSFactoryPlugin
INFO [org.firebirdsql.gds.impl.GDSFactory]: Attempting to load class org.firebirdsql.gds.impl.jni.NativeGDSFactoryPlugin
INFO [org.firebirdsql.gds.impl.GDSFactory]: Attempting to load class org.firebirdsql.gds.impl.jni.LocalGDSFactoryPlugin
INFO [org.firebirdsql.gds.impl.GDSFactory]: Attempting to load class org.firebirdsql.gds.impl.jni.EmbeddedGDSFactoryPlugin
INFO [org.firebirdsql.gds.impl.GDSFactory]: Attempting to load class org.firebirdsql.gds.impl.oo.OOGDSFactoryPlugin
INFO [org.hibernate.connection.ConnectionProviderFactory]: Initializing connection provider: org.netbeans.modules.hibernate.util.CustomJDBCConnectionProvider
INFO [org.firebirdsql.jdbc.AbstractDriver]: Load event of driver
INFO [org.netbeans.modules.hibernate.util.CustomJDBCConnectionProvider]: Loaded JDBC driver
INFO [org.firebirdsql.jdbc.AbstractDriver]: Loading url jdbc:firebirdsql://localhost/D:/data/db/testdatabase.fdb?columnLabelForName=true
INFO [org.firebirdsql.jdbc.AbstractDriver]: No GDSType for url jdbc:firebirdsql://localhost/D:/data/db/testdatabase.fdb?columnLabelForName=true
INFO [org.netbeans.modules.hibernate.util.CustomJDBCConnectionProvider]: Got connection.. returning

It looks like first the HibernateUtil class (succesfully) loads the driver including the types, and then the CustomJDBCConnectionProvider loads another driver and this Driver somehow can't find the GDSFactoryPlugin types.

Mark Rotteveel added a comment - 20/Sep/13 02:52 PM
Added further logging that shows that 1) HibernateUtil succesfully connects, and 2) CustomJDBCConnectionProvider fails to connect because the jdbcUrlToPluginMap is empty.

INFO [org.netbeans.modules.hibernate.util.HibernateUtil]: Found pre-existing database connection.
INFO [org.netbeans.modules.hibernate.util.HibernateUtil]: Database Connection not established, connecting..
INFO [org.firebirdsql.jdbc.AbstractDriver]: Load event of driver
INFO [org.firebirdsql.jdbc.AbstractDriver]: Loading url jdbc:firebirdsql://localhost/D:/data/db/testdatabase.fdb?columnLabelForName=true
INFO [org.firebirdsql.gds.impl.GDSFactory]: Attempting to load class org.firebirdsql.gds.impl.wire.WireGDSFactoryPlugin
INFO [org.firebirdsql.gds.impl.GDSFactory]: Attempting to load class org.firebirdsql.gds.impl.jni.NativeGDSFactoryPlugin
INFO [org.firebirdsql.gds.impl.GDSFactory]: Attempting to load class org.firebirdsql.gds.impl.jni.LocalGDSFactoryPlugin
INFO [org.firebirdsql.gds.impl.GDSFactory]: Attempting to load class org.firebirdsql.gds.impl.jni.EmbeddedGDSFactoryPlugin
INFO [org.firebirdsql.gds.impl.GDSFactory]: Attempting to load class org.firebirdsql.gds.impl.oo.OOGDSFactoryPlugin
INFO [org.firebirdsql.gds.impl.GDSFactory]: Finding type for url jdbc:firebirdsql://localhost/D:/data/db/testdatabase.fdb?columnLabelForName=true
INFO [org.firebirdsql.gds.impl.GDSFactory]: Entry count in jdbcUrlToPluginMap: 7
INFO [org.firebirdsql.gds.impl.GDSFactory]: Attempting to match protocol jdbc:firebirdsql:oo: and plugin GDS implementation for OpenOffice.
INFO [org.firebirdsql.gds.impl.GDSFactory]: Attempting to match protocol jdbc:firebirdsql:native: and plugin JNI-based GDS implementation.
INFO [org.firebirdsql.gds.impl.GDSFactory]: Attempting to match protocol jdbc:firebirdsql:local: and plugin JNI-based GDS implementation using IPC communication.
INFO [org.firebirdsql.gds.impl.GDSFactory]: Attempting to match protocol jdbc:firebirdsql:java: and plugin Pure Java GDS implementation.
INFO [org.firebirdsql.gds.impl.GDSFactory]: Attempting to match protocol jdbc:firebirdsql:embedded: and plugin GDS implementation for embedded server.
INFO [org.firebirdsql.gds.impl.GDSFactory]: Attempting to match protocol jdbc:firebirdsql: and plugin Pure Java GDS implementation.
INFO [org.firebirdsql.gds.impl.GDSFactory]: Matched protocol jdbc:firebirdsql: of plugin Pure Java GDS implementation. to url jdbc:firebirdsql://localhost/D:/data/db/testdatabase.fdb?columnLabelForName=true
INFO [org.firebirdsql.jdbc.AbstractDriver]: Returned connection org.firebirdsql.jdbc.FBConnection@10ddee69
INFO [org.hibernate.connection.ConnectionProviderFactory]: Initializing connection provider: org.netbeans.modules.hibernate.util.CustomJDBCConnectionProvider
INFO [org.firebirdsql.jdbc.AbstractDriver]: Load event of driver
INFO [org.netbeans.modules.hibernate.util.CustomJDBCConnectionProvider]: Loaded JDBC driver
INFO [org.firebirdsql.jdbc.AbstractDriver]: Loading url jdbc:firebirdsql://localhost/D:/data/db/testdatabase.fdb?columnLabelForName=true
INFO [org.firebirdsql.gds.impl.GDSFactory]: Finding type for url jdbc:firebirdsql://localhost/D:/data/db/testdatabase.fdb?columnLabelForName=true
INFO [org.firebirdsql.gds.impl.GDSFactory]: Entry count in jdbcUrlToPluginMap: 0
INFO [org.firebirdsql.gds.impl.GDSFactory]: No protocol match found for url jdbc:firebirdsql://localhost/D:/data/db/testdatabase.fdb?columnLabelForName=true
INFO [org.firebirdsql.jdbc.AbstractDriver]: No GDSType for url jdbc:firebirdsql://localhost/D:/data/db/testdatabase.fdb?columnLabelForName=true

Mark Rotteveel added a comment - 20/Sep/13 03:11 PM
A closer look at org.netbeans.modules.hibernate.util.CustomClassLoader shows that the issue is with the custom classloader that netbeans uses for Hibernate:

@Override
    public Enumeration<URL> findResources(String name) throws IOException {
        if (name.startsWith("META-INF/services")) { //NOI18N
            return Collections.enumeration(Collections.<URL>emptyList());
        } else {
            return super.findResources(name);
        }
    }

This prevents Jaybird from loading the GDSFactoryPlugin implementations.

Mark Rotteveel added a comment - 20/Sep/13 03:48 PM - edited
This problem will also impact the new wire protocol (or more specifically: encodings and ProtocolDefinitions) in Jaybird 2.3, as those are also loaded from META-INF/services

Mark Rotteveel added a comment - 21/Sep/13 07:27 AM
Committed for 2.2.4: As a workaround, the GDSFactory will now load a hardcoded list of classes if none were loaded through the META-INF/services file(s).

I will further investigate this for 2.3.

Mark Rotteveel added a comment - 21/Sep/13 08:08 AM
Released a 2.2.4 snapshot that includes this fix to sourceforge: http://sourceforge.net/projects/firebird/files/firebird-jca-jdbc-driver/2.2.4-SNAPSHOT/

Mark Rotteveel added a comment - 02/Nov/13 12:46 PM