Search code examples
jdbchivewebsphere

Define hive-jdbc JNDI data source on WebSphere


I am trying to setup a JNDI Data Source on WebSphere 8.5.5.11, using hive-jdbc.jar. When using the console in WebSphere, and using the form to create a new JDBC provider, there is a field for the implementation class name. WebSphere requires that the class implements javax.sql.XADataSource or javax.sql.ConnectionPoolDataSource. However, the hive-jdbc driver implements non of those, it implements only java.sql.DataSource. For this reason, it doesn't work, WebSphere reports an error when trying to save the form.

enter image description here

Any idea what can I do about this?


Solution

  • You can write a trivial implementation of javax.sql.ConnectionPoolDataSource that delegates to the javax.sql.DataSource implementation. Here is an example,

    package example.datasource;
    
    import java.sql.*;
    import javax.sql.*;
    
    public class HiveConnectionPoolDataSource extends org.apache.hive.jdbc.HiveDataSource implements ConnectionPoolDataSource {
        public PooledConnection getPooledConnection() throws SQLException {
            return new HivePooledConnection(null, null);
        }
    
        public PooledConnection getPooledConnection(String user, String password) throws SQLException {
            return new HivePooledConnection(user, password);
        }
    
        public boolean isWrapperFor(Class<?> iface) throws SQLException {
            return ConnectionPoolDataSource.class.equals(iface) || super.isWrapperFor(iface);
        }
    
        public <T> T unwrap(Class<T> iface) throws SQLException {
            return ConnectionPoolDataSource.class.equals(iface) ? (T) this : super.unwrap(iface);
        }
    
        class HivePooledConnection implements PooledConnection {
            private Connection con;
            private final String user;
            private final String password;
    
            HivePooledConnection(String user, String password) {
                this.user = user;
                this.password = password;
            }
    
            public void addConnectionEventListener(ConnectionEventListener listener) {}
    
            public void addStatementEventListener(StatementEventListener listener) {}
    
            public void close() throws SQLException {
                if (con != null) {
                    con.close();
                    con = null;
                }
            }
    
            public Connection getConnection() throws SQLException {
                if (con == null || con.isClosed()) {
                    con = user == null
                            ? HiveConnectionPoolDataSource.this.getConnection()
                            : HiveConnectionPoolDataSource.this.getConnection(user, password);
                    return con;
                } else
                    throw new IllegalStateException();
            }
    
            public void removeConnectionEventListener(ConnectionEventListener listener) {}
    
            public void removeStatementEventListener(StatementEventListener listener) {}
        }
    }
    

    Package your compiled class in a JAR alongside the JDBC driver JAR(s), and configure your custom JDBC provider in WebSphere Application Server to point at this JAR as though it were a part of the JDBC driver. Specify the implementation class name as example.datasource.HiveConnectionPoolDataSource or whatever package/name you chose for your own implementation. You should then be able to use the JDBC driver.

    Also adding a link to the WebSphere Application Server request for enhancements page if anyone wants to request that support for javax.sql.DataSource be added.