java bonecp connection-pool handling issue - java

I can't find anywhere is web
code example to how i enable the connection watch
because i get this message in log
153624 [com.google.common.base.internal.Finalizer] WARN
com.jolbox.bonecp.ConnectionPartition - BoneCP detected
an unclosed connection and will now attempt to close it
for you. You should be closing this connection in your
application - enable connectionWatch for additional debugging assistance.
this is my definition:
BoneCPConfig config = new BoneCPConfig();
Class.forName(loc.driver); // load the DB driver
config.setJdbcUrl(loc.url); // set the JDBC url
config.setUsername(loc.user); // set the username
config.setPassword(loc.password); // set the password
config.setMinConnectionsPerPartition(5);
config.setMaxConnectionsPerPartition(10);
config.setPartitionCount(5);
config.setAcquireIncrement(5);
//config.setCloseConnectionWatch(true);
connectionPool = new BoneCP(config);
i also used the:
config.setCloseConnectionWatch(true);
but it didn't give me additional debugging assistance.

I realize this is old and likely already resolved, but to get your debug information you also need to set the setCloseConnectionWatchTimeout or setCloseConnectionWatchTimeoutinMs.

Related

Postgresql JDBC connection error on Android

I am unable to connect a PostgreSQL db on Android. Using JDBC is for development purpose only and will change to proper web service.
I have implemented the PostgreSQL driver in build.gradle as "implementation 'org.postgresql:postgresql:42.2.18.jre7"
My PostgreSQL database server is listening to port: 5433
My computer IP in my network is 192.168.1.103
And the user name and password is set correct
The connection:
Connection con = null;
try
{
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
/* Register jdbc driver class. */
Class.forName("org.postgresql.Driver");
/* Create connection url. */
String postgresConnUrl = "jdbc:postgresql://192.168.1.103:5433/lmsdb";
Properties props = new Properties();
props.setProperty("user","postgres");
props.setProperty("password","xxxxxxx");
props.setProperty("ssl","false");
/* Get the Connection object. */
con = DriverManager.getConnection(postgresConnUrl, props);
}catch(Exception ex)
{
ex.printStackTrace();
}finally
{
return con ;
}
When I change the IP in "postgresConnUrl" to 127.0.0.1 which is set in pg_hba, I get the error
org.postgresql.util.PSQLException: Connection refused. Check that the
hostname and port are correct and that the postmaster is accepting
TCP/IP connections
And when I use my computer's IP address as shown in the connection code above, the connection con = DriverManager.getConnection(postgresConnUrl, props); is returning null. The log shows no exception or errors, but the con is null and I am unable to trace the problem. Any directions to the problem would be helpful.
DriverManager.getConnection(...) cannot return null. Unless there is a severe bug in the implementation, it always returns a non-null connection or throws a SQLException (or RuntimeException or Error as thrown by drivers).
The PostgreSQL driver is likely causing an Error to be thrown (e.g. a NoClassDefFoundError, because the PostgreSQL JDBC driver uses Java features or classes not present on Android). This is hidden by the fact that your finally block will unconditionally return con, and you only catch and log instances of Exception, but not Error. See also Adding return in finally hides the exception
Remove your catch and finally block and let any exception or other Throwable bubble up to the caller, instead of replacing an explicit exception or error with a hidden error (returning null), alternatively have the catch block wrap the exception in a custom exception and throw that custom exception.
I recommend you don't use JDBC on Android. Most recent JDBC drivers are using Java features or classes not present on Android, which can cause all kinds of issues. You mention you're doing this for development purposes, but I would suggest that creating or mocking your REST API and using that from the start will save you a lot of headaches and unnecessary development work.
I tried using older version of JDBC and I was able to connect. The newer version of JDBC does not seem to be compatible with Android and result in error as you posted. But, still I can see many people are using JDBC as it is easy although Rest API is better option but requires additional skills.

Hive JDBC connection problems

I am trying to connect to Hive2 server via JDBC with kerberos authentication. After numerous attempts to make it work, I can't get it to work with the Cloudera driver.
If someone can help me to solve the problem, I can greatly appreciate it.
I have this method:
private Connection establishConnection() {
final String driverPropertyClassName = "driver";
final String urlProperty = "url";
Properties hiveProperties = config.getMatchingProperties("hive.jdbc");
String driverClassName = (String) hiveProperties.remove(driverPropertyClassName);
String url = (String) hiveProperties.remove(urlProperty);
Configuration hadoopConfig = new Configuration();
hadoopConfig.set("hadoop.security.authentication", "Kerberos");
String p = config.getProperty("hadoop.core.site.path");
Path path = new Path(p);
hadoopConfig.addResource(path);
UserGroupInformation.setConfiguration(hadoopConfig);
Connection conn = null;
if (driverClassName != null) {
try {
UserGroupInformation.loginUserFromKeytab(config.getProperty("login.user"), config.getProperty("keytab.file"));
Driver driver = (Driver) Class.forName(driverClassName).newInstance();
DriverManager.registerDriver(driver);
conn = DriverManager.getConnection(url, hiveProperties);
} catch (Throwable e) {
LOG.error("Failed to establish Hive connection", e);
}
}
return conn;
}
URL for the server, that I am getting from the properties in the format described in Cloudera documentation
I am getting an exception:
2018-05-05 18:26:49 ERROR HiveReader:147 - Failed to establish Hive connection
java.sql.SQLException: [Cloudera][HiveJDBCDriver](500164) Error initialized or created transport for authentication: Peer indicated failure: Unsupported mechanism type PLAIN.
at com.cloudera.hiveserver2.hivecommon.api.HiveServer2ClientFactory.createTransport(Unknown Source)
at com.cloudera.hiveserver2.hivecommon.api.ZooKeeperEnabledExtendedHS2Factory.createClient(Unknown Source)
...
I thought, that it is missing AuthMech attribute and added AuthMech=1 to the URL. Now I am getting:
java.sql.SQLNonTransientConnectionException: [Cloudera][JDBC](10100) Connection Refused: [Cloudera][JDBC](11640) Required Connection Key(s): KrbHostFQDN, KrbServiceName; [Cloudera][JDBC](11480) Optional Connection Key(s): AsyncExecPollInterval, AutomaticColumnRename, CatalogSchemaSwitch, DecimalColumnScale, DefaultStringColumnLength, DelegationToken, DelegationUID, krbAuthType, KrbRealm, PreparedMetaLimitZero, RowsFetchedPerBlock, SocketTimeOut, ssl, StripCatalogName, transportMode, UseCustomTypeCoercionMap, UseNativeQuery, zk
at com.cloudera.hiveserver2.exceptions.ExceptionConverter.toSQLException(Unknown Source)
at com.cloudera.hiveserver2.jdbc.common.BaseConnectionFactory.checkResponseMap(Unknown Source)
...
But KrbHostFQDN is already specified in the principal property as required in the documentation.
Am I missing something or is this documentation wrong?
Below is the one of the similar kind of problem statement in Impala (just JDBC engine changes others are same) that is resolved by setting "KrbHostFQDN" related properties in JDBC connection string itself.
Try to use the URL below. Hopefully works for u.
String jdbcConnStr = "jdbc:impala://myserver.mycompany.corp:21050/default;SSL=1;AuthMech=1;KrbHostFQDN=myserver.mycompany.corp;KrbRealm=MYCOMPANY.CORP;KrbServiceName=impala"
I suppose that if you are not using SSL=1 but only Kerberos, you just drop that part from the connection string and don't worry about setting up SSL certificates in the java key store, which is yet another hassle.
However in order to get Kerberos to work properly we did the following:
Install MIT Kerberos 4.0.1, which is a kerberos ticket manager. (This is for Windows)
This ticket manager asks you for authentication every time you initiate a connection, creates a ticket and stores it in a kerberos_ticket.dat binary file, whose location can be configured somehow but I do not recall exactly how.
Finally, before launching your JAVA app you have to set an environment variable KRB5CCNAME=C:/path/to/kerberos_ticket.dat. In your java app, you can check that the variable was correctly set by doing System.out.println( "KRB5CCNAME = " + System.getenv( "KRB5CCNAME" ) ). If you are working with eclipse or other IDE you might even have to close the IDE,set up the environment variable and start the IDE again.
NOTE: this last bit is very important, I have observed that if this variable is not properly set up, the connection wont be established...
In Linux, instead MIT Kerberos 4.0.1, there is a program called kinit which does the same thing, although without a graphical interface, which is even more convenient for automation.
I wanted to put it in the comment but it was too long for the comment, therefore I am placing it here:
I tried your suggestion and got another exception:
java.sql.SQLException: [Cloudera]HiveJDBCDriver Error
creating login context using ticket cache: Unable to obtain Principal
Name for authentication .
May be my problem is, that I do not have environment variable KRB5CCNAME set.
I, honestly, never heard about it before.
What is supposed to be in that ticket file.
I do have, however, following line in my main method:
System.setProperty("java.security.krb5.conf", "path/to/krb5.conf");
Which is supposed to be used by
UserGroupInformation.loginUserFromKeytab(config.getProperty("login.user"), config.getProperty("keytab.file"));
to obtain the kerberos ticket.
To solve this issue update Java Cryptography Extension for the Java version that you use in your system.
Here's the link when you can download JCE for Java 1.7
Uncompress and overwrite those files in $JDK_HOME/jre/lib/security
Restart your computer.

How to enable connection pooling over LDAP SSL?

Okay, so I'm moving my application over from non-SSL to SSL connections to my LDAP server. When running the application in non-SSL, connection pooling is working fine. However when I switch to SSL connection pools no longer work.
While researching here I realized that I never set the "com.sun.jndi.ldap.connect.pool.protocol" property to "plain ssl" since defaultly it is set to plain. I thought this was the problem.
When I implemented the change to include "plain ssl", it did not fix the problem and connection pools were still not being used.
Is there some other setting that I am missing?
Relevant code:
Hashtable LDAPEnvironment = new Hashtable();
LDAPEnvironment.put(Context.SECURITY_AUTHENTICATION, SECURITY_AUTHENTICATION);
LDAPEnvironment.put(Context.SECURITY_PRINCIPAL, SECURITY_PRINCIPAL);
LDAPEnvironment.put(Context.SECURITY_CREDENTIALS, SECURITY_CREDENTIALS);
LDAPEnvironment.put(Context.INITIAL_CONTEXT_FACTORY, INITIAL_CONTEXT_FACTORY);
LDAPEnvironment.put(Context.PROVIDER_URL, PROVIDER_URL );
LDAPEnvironment.put(Context.SECURITY_AUTHENTICATION, "simple");
LDAPEnvironment.put("java.naming.ldap.version", versionOfLDAP );
if (ldapProtocol != null && ldapProtocol.equalsIgnoreCase("SSL")){
LDAPEnvironment.put(Context.SECURITY_PROTOCOL,"ssl");
LDAPEnvironment.put("com.sun.jndi.ldap.connect.pool.protocol","plain ssl");
}
LDAPEnvironment.put("com.sun.jndi.ldap.connect.pool", "true");
I have found the problem. The documentation specifically states that the those properties are system properties and not environment properties. I was setting these as environment properties. :-)
If you scroll down a little, at the link you provided (scroll to "How Connections are Pooled"), you'll see the explanation to how the pooling works.
When you request a pooled connection, you will get one only if ALL the specified properties are identical. And that's a long list of properties...
I your case this is:
connection controls
host name, port number as specified in the "java.naming.provider.url" property, referral, or URL supplied to the initial context
java.naming.security.protocol property
java.naming.ldap.version property
java.naming.security.principal property
java.naming.security.credentials property
If you always use the same constants when request a connection from the connection pool, I think you should get the same pooled connection. That is, if you set the com.sun.jndi.ldap.connect.pool.* properties properly - but I didn't see that in the code you provided.
If you did set the com.sun.jndi.ldap.connect.pool.* properties to sensible values, try setting com.sun.jndi.ldap.connect.pool.debug to fine. This will help you debug.
Another option is to use a framework, or a provider that supports connection pooling. Note that the pooling provided to you by Java is rather limited. I used Spring-Ldap in the past, and it has very good support.
Hope this helps.

Call to DataSource.getConnection not returning the expected connection

I have the following code:
Hashtable env1 = new Hashtable();
env1.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY,"com.ibm.websphere.naming.WsnInitialContextFactory");
log.info("Executed step 1");
env1.put(javax.naming.Context.PROVIDER_URL, "iiop://myhost.com:9301");
log.info("Executed step 2");
Context ctx = new InitialContext(env1);
DataSource ds = (DataSource)ctx.lookup("jdbc/mydatasource");
log.info("Excecuted lookup ="+ds);
conn = ds.getConnection();
I have the previous code in an standalone application that is connecting to WAS 6.1.0.3 in order to retrieve a connection from the datasource. The code is very straighforward, and I have seen the same code working in a different environment, but in this case when I call getConnection I get an exception. The datasource is WAS has the proper authentication alias set and when the connection is tested it works OK from the WAS side, but the previous code won't work.
If I change this line: conn = ds.getConnection();
to this: conn = ds.getConnection("username","password");
Then the code will work! But that's not what I want since the connections in the datasource should already have the credentials set. I was initially thinking this was a Sybase problem, but it's also happening with Oracle, so would rather say I have a problem with WAS.
If you are curious about the exceptions, for Sybase I get:
java.sql.SQLException: JZ004: User name property missing in DriverManager.getConnection(..., Properties).DSRA0010E: SQL State = JZ004, Error Code = 0
at com.sybase.jdbc2.jdbc.ErrorMessage.raiseError(ErrorMessage.java:569)
at com.sybase.jdbc2.tds.LoginToken.<init>(LoginToken.java:128)
at com.sybase.jdbc2.tds.Tds.doLogin(Tds.java:506)
at com.sybase.jdbc2.tds.Tds.login(Tds.java:449)
at com.sybase.jdbc2.jdbc.SybConnection.tryLogin(SybConnection.java:254)
at com.sybase.jdbc2.jdbc.SybConnection.regularConnect(SybConnection.java:230)
at com.sybase.jdbc2.jdbc.SybConnection.<init>(SybConnection.java:200)
at com.sybase.jdbc2.jdbc.SybPooledConnection.<init>(SybPooledConnection.java:72)
at com.sybase.jdbc2.jdbc.SybConnectionPoolDataSource.createConnection(SybConnectionPoolDataSource.java:138)
at com.sybase.jdbc2.jdbc.SybDriver.connect(SybDriver.java:485)
at com.sybase.jdbc2.jdbc.SybDriver.connect(SybDriver.java:517)
at com.sybase.jdbc2.jdbc.SybDataSource.getConnection(SybDataSource.java:227)
at com.sybase.jdbc2.jdbc.SybConnectionPoolDataSource.getPooledConnection(SybConnectionPoolDataSource.java:74)
at com.ibm.ws.rsadapter.spi.InternalGenericDataStoreHelper$1.run(InternalGenericDataStoreHelper.java:897)
at com.ibm.ws.security.util.AccessController.doPrivileged(AccessController.java:118)
at com.ibm.ws.rsadapter.spi.InternalGenericDataStoreHelper.getPooledConnection(InternalGenericDataStoreHelper.java:892)
at com.ibm.ws.rsadapter.spi.WSRdbDataSource.getPooledConnection(WSRdbDataSource.java:1181)
at com.ibm.ws.rsadapter.spi.WSManagedConnectionFactoryImpl.createManagedConnection(WSManagedConnectionFactoryImpl.java:1047)
at com.ibm.ws.rsadapter.spi.WSDefaultConnectionManagerImpl.allocateConnection(WSDefaultConnectionManagerImpl.java:81)
at com.ibm.ws.rsadapter.jdbc.WSJdbcDataSource.getConnection(WSJdbcDataSource.java:431)
at com.ibm.ws.rsadapter.jdbc.WSJdbcDataSource.getConnection(WSJdbcDataSource.java:400)
And for Oracle I get this one:
java.sql.SQLException: invalid arguments in callDSRA0010E: SQL State = null, Error Code = 17,433
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:146)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:208)
at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:236)
at oracle.jdbc.driver.PhysicalConnection.<init>(PhysicalConnection.java:420)
at oracle.jdbc.driver.T4CConnection.<init>(T4CConnection.java:165)
at oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.java:35)
at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:801)
at oracle.jdbc.pool.OracleDataSource.getPhysicalConnection(OracleDataSource.java:297)
at oracle.jdbc.pool.OracleDataSource.getConnection(OracleDataSource.java:221)
at oracle.jdbc.pool.OracleConnectionPoolDataSource.getPhysicalConnection(OracleConnectionPoolDataSource.java:157)
at oracle.jdbc.pool.OracleConnectionPoolDataSource.getPooledConnection(OracleConnectionPoolDataSource.java:94)
at oracle.jdbc.pool.OracleConnectionPoolDataSource.getPooledConnection(OracleConnectionPoolDataSource.java:75)
at com.ibm.ws.rsadapter.spi.InternalGenericDataStoreHelper$1.run(InternalGenericDataStoreHelper.java:897)
at com.ibm.ws.security.util.AccessController.doPrivileged(AccessController.java:118)
at com.ibm.ws.rsadapter.spi.InternalGenericDataStoreHelper.getPooledConnection(InternalGenericDataStoreHelper.java:892)
at com.ibm.ws.rsadapter.spi.WSRdbDataSource.getPooledConnection(WSRdbDataSource.java:1181)
at com.ibm.ws.rsadapter.spi.WSManagedConnectionFactoryImpl.createManagedConnection(WSManagedConnectionFactoryImpl.java:1047)
at com.ibm.ws.rsadapter.spi.WSDefaultConnectionManagerImpl.allocateConnection(WSDefaultConnectionManagerImpl.java:81)
at com.ibm.ws.rsadapter.jdbc.WSJdbcDataSource.getConnection(WSJdbcDataSource.java:431)
at com.ibm.ws.rsadapter.jdbc.WSJdbcDataSource.getConnection(WSJdbcDataSource.java:400)
In both cases I won't the exception if I pass the credentials to the getConnection method
Thanks for your advice.
Short answer: external clients don't get to use the authentication alias data
Longer Answer:
From the WAS J2C connection factory documentation:
The alias that you configure for component-managed authentication does not apply to all clients that must access the secured resource. External Java clients with Java Naming and Directory Interface (JNDI) access can look up a Java 2 Connector (J2C) resource such as a data source or Java Message Service (JMS) queue. However, they are not permitted to take advantage of the component-managed authentication alias defined on the resource. This alias is the default value that is used when the getConnection() method does not specify any authentication data, like user and password, or a value for ConnectionSpec. If an external client needs to get a connection, it must assume responsibility for the authentication by passing it through arguments on the getConnection() call.
It's been a long time since I've done anything with WebSFEAR^H^H^H^Hphere, but it looks to me that you have a configuration problem. There was a special screen where you'd create credentials (user/pass) and later you'd apply those credentials to the created data source. It looks like that your configured data source hasn't got credentials applied.
Even after defining the user/password values as custom properties I found that the connections for Oracle weren't working. After many days, I just found that the development server is running an old WAS 6.1 version, the problem I'm having was fixed in WAS 6.1.0.5: PK32838: J2CA0046E WHEN USING USING CUSTOM PROP PASSWORD ON DATASOURECE
I tried my code in a different WAS server with an updated WAS fix pack level and... it worked without introducing a single change in the code or in the configuration. So the solution is to upgrade the WAS server.
Thanks.

Invalid Oracle URL specified: OracleDataSource.makeURL

I'm trying to connect to a local oracle database but I'm getting this cryptic error message:
Invalid Oracle URL specified: OracleDataSource.makeURL.
I'm pretty sure this is due to an error with the database connection parameters I'm passing, but really, this error message does not help me in any way. Any hints as to what I'm doing wrong would be greatly appreciated.
FYI: Code used to connect is below, except for the hardcoded strings this is what is used on our production environment and does work there.
OracleDataSource dataSource = new OracleDataSource();
dataSource.setServerName("localhost");
dataSource.setUser(userName);
dataSource.setPassword(password);
dataSource.setDatabaseName("orcl");
return dataSource.getConnection();
if you use setUrl (or if your container like glassfish does it)
make sure you use correct syntax
==== Notice the colon before # ====
jdbc:oracle:thin:#localhost:1521:sid
or
jdbc:oracle:thin:#localhost:1521/servicename
The datasource class tries to parse it and gives cryptic error if syntax has issues
Surprisingly, after adding the following two lines to the code which created the connection, it worked.
dataSource.setPortNumber(1521);
dataSource.setDriverType("thin");
I don't understand why we did not have that problem before, but that may have something to do with my local install. My biggest beef is with the error message not giving any detail about what is wrong though.
For WildFly users (v14.0.1.Final currently).
You need to add additional parameters for DataSource:
DataSource -> Connection -> Connection Properties
driverType=thin (press Enter to complite).
Also doublecheck you use right type of DataSource. In my case problem was solved by creating XA DataSource and pass URL to parameter.

Categories

Resources