How to differ between MSSQL JDBC error codes? - java

My server calls sometimes the MSSQL JDBC CallableStatement.execute() that works with a previously connected connection. Everything is ok while the connection is alive. But if the connection is disconnected somehow (e.g. somebody turn SQL server down) the execute() call throws SQLException. I need to differ between 'connection was dropped' error and any other JDBC error (like table I'm trying to use doesn't exist). Since if I hit the connection error - I need to reconnect. And in any other case I need just to give error message to the user.
SQLException.getSQLState() always returns null and getErrorCode() always returns 0.
Thanks

I am no Java expert but this seems to be mainly based on Java.
You'd need to catch the exception from the .execute() command and query the string to see what the error is, then make a decision on which method to execute next based on that information.

Related

Detect invalid credentials being passed to c3p0 connection pool

I'm writing a program that does some stuff on the database. Users are allowed to configure db processes, by passing db host port, type and credentials. It all works fine when values are correct. But when user passes invalid credentials I would like to show an error. So here is the part where I create my connection pool
ComboPooledDataSource cpds = new ComboPooledDataSource();
cpds.setJdbcUrl( connectionUrl );
cpds.setUser(username);
cpds.setPassword(password);
And later to verify if all is ok with the connection I do
cpds.getConnection()
I would expect to get some SQLException with vendor specific error saying that credentials are invalid (which happens when you use typical DriverManager way of getting the connection), but instead the process waits until a connection checkout exception is thrown
java.sql.SQLException: An attempt by a client to checkout a Connection has timed out.
at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:118)
at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:77)
at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutPooledConnection(C3P0PooledConnectionPool.java:690)
....
Caused by: com.mchange.v2.resourcepool.TimeoutException: A client timed out while waiting to acquire a resource from com.mchange.v2.resourcepool.BasicResourcePool#20014b8 -- timeout at awaitAvailable()
at com.mchange.v2.resourcepool.BasicResourcePool.awaitAvailable(BasicResourcePool.java:1467)
at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:644)
at com.mchange.v2.resourcepool.BasicResourcePool.checkoutResource(BasicResourcePool.java:554)
at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutAndMarkConnectionInUse(C3P0PooledConnectionPool.java:758)
at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutPooledConnection(C3P0PooledConnectionPool.java:685)
... 66 more
How can I identify that there is a invalid credential issue with c3p0?
Your best way to validate provided credentials/JDBC params is to avoid connection pool at all.
Open dedicated connection just for this purpose and try to execute simplest SQL against new connection (eg SELECT 1 or similar).
After success, you can pass them to C3P0 otherwise propagate error back to user.
JDBC providers are free to create whatever error/exception messages they want. So you need to be ready to parse the error message of each provider in order to make sense of what is happening.
You can also try to get information from exception types if the JDBC provider segregates errors in separate types.
As a side note, giving too much information regarding why the connection failed may be considered a security breach. So one should not expect the JDBC driver to give you such information. For instance, why would any database collaborate with invasion attempts by saying "the username is correct, but the password is not."?

How to make a stable tcp-socket connection without a server response?

I need some help with the following problem:
I open a tcp-socket in the constructor then proceed to provide a object over an object output-stream to the server. I have no control over the server and don't get any response back.
How can I detect that the connection was lost? Will I always get the IOExeption-Error when trying to write? Because according to javadoc once a connection was successfully made most of the checks are basically useless to me.
Additionally what is the best way to reconnect a socket? Set the reference to "Null" then create a new one?
Here is my current approach:
I have a status-list in which I have the following statuses:
SocketSuccess; SocketFailure; MessageSuccess; MessageFailure;
My idea is kind of like a state-machine so check first what the last status was. If the connection was successfull or the last message was successfull then try to send the message. When I get a IOExeption then set the status MessageFailure, save the Message locally till I get a successfull connection again.
Or are there any recommended patterns for this kind of situation?
Clearing all your douts. If the connection with the server is lost then the client will throw IOException and that will kill the application but if you have handled the exception and tried to reconnect with the server and Re-establish the input output stream the your message function will start again. The predefined messages you are using will travel only when there is a connection between server and client. So when the connection is lost you will get IOException and when you handle that exception and try to reconnect a new input output stream should be established that will carry your messaging service.

Set timeout for Statement.executeBatch

I would like to find out how I can set a timeout for a Statement.executeBatch() in Java. The code works well when the database is up, but when I block the db IP in iptables, the JVM hangs at executeBatch(). I tried using .setQueryTimeout(10) but an exception is thrown:
SQLException cannot be cast to SybSQLException
On database side I use Sybase and jdbc2 for connection
Thank you.
PS: I can't post the code because it is company copyrighted.

Java - Check if an SqlSessionFactory is valid

I generate an SqlSessionFactory from an SqlSessionFactoryBean, and catch exceptions to determine if it successfully created for a given data-source.
However, I have found that method fails if the database exists, but has no listener. No exception is generated and an exception only occurs later when I actually try create an open session of the SqlSessionFactory.
What's the best way for me to check if I am working with a valid database, accepting normal sessions?
Edit: It doesn't actually appear to be that opening a session throws the exception ... it may only happen at my first actual update/retrieve call.
Many connection pools have a connection validation query option, which can be configured to execute something simple like SELECT 1 (depends on the database, of course) to validate the connection is valid. It's the same premise, though: attempt to execute the query and catch the exception.
If you are already using a connection pool, and it supports such an option, I wonder if this would solve your problem.

java.sql.Exception ClosedConnection

I am getting the following error:
java.sql.SQLException: Closed
Connection 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.PhysicalConnection.getMetaData(PhysicalConnection.java:1508)
at
com.ibatis.sqlmap.engine.execution.SqlExecutor.moveToNextResultsSafely(SqlExecutor.java:348)
at
com.ibatis.sqlmap.engine.execution.SqlExecutor.handleMultipleResults(SqlExecutor.java:320)
at
com.ibatis.sqlmap.engine.execution.SqlExecutor.executeQueryProcedure(SqlExecutor.java:277)
at
com.ibatis.sqlmap.engine.mapping.statement.ProcedureStatement.sqlExecuteQuery(ProcedureStatement.java:34)
at
com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQueryWithCallback(GeneralStatement.java:173)
at
com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQueryForList(GeneralStatement.java:123)
at
com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForList(SqlMapExecutorDelegate.java:614)
at
com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForList(SqlMapExecutorDelegate.java:588)
at
com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.queryForList(SqlMapSessionImpl.java:118)
at
org.springframework.orm.ibatis.SqlMapClientTemplate$3.doInSqlMapClient(SqlMapClientTemplate.java:268)
at
org.springframework.orm.ibatis.SqlMapClientTemplate.execute(SqlMapClientTemplate.java:193)
at
org.springframework.orm.ibatis.SqlMapClientTemplate.executeWithListResult(SqlMapClientTemplate.java:219)
at
org.springframework.orm.ibatis.SqlMapClientTemplate.queryForList(SqlMapClientTemplate.java:266)
at
gov.hud.pih.eiv.web.authentication.AuthenticationUserDAO.isPihUserDAO(AuthenticationUserDAO.java:24)
at
gov.hud.pih.eiv.web.authorization.AuthorizationProxy.isAuthorized(AuthorizationProxy.java:125)
at
gov.hud.pih.eiv.web.authorization.AuthorizationFilter.doFilter(AuthorizationFilter.java:224)
at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:246)
at
I am really stumped and can't figure out what could be causing this error. I am not able to reproduce the error on my machine but on production it is coming a lot of times. I am using iBatis in the whole application so there are no chances of my code not closing connections.
We do have stored procedures that run for a long time before they return results (around 15 seconds).
does anyone have any ideas on what could be causing this? I dont think raising the # of connections on the application server will fix this issue buecause if connections were running out then we'd see "Error on allocating connections"
Sample code snippet:
this.setSqlMapClientTemplate(getSqlTempl());
getSqlMapClientTemplate().queryForList("authentication.isUserDAO", parmMap);
this.setSqlMapClientTemplate(getSqlTemplDW());
List results = (List) parmMap.get("Result0");
I am using validate in my connection pool.
Based on the stack trace, the likely cause is that you are continuing to use a ResultSet after close() was called on the Connection that generated the ResultSet.
What is your DataSource framework? Apache Commons DBCP?
do you use poolPrepareStatement property in data source configuration?
Check the following:
Make sure testOnBorrow and testOnReturn are true and place a simple validationQuery like select 0 from dual.
Do you use au
do you use autoCommit? Are you using START TRANSACTION, COMMIT in your stored procedures? After several days of debugging we found out that you can't mix transaction management both in Java and in SQL - you have to decide on one place to do it. Where are you doing yours?
Edit your question with answers to this, an we'll continue from there.
When a db server reboots, or there are some problems with a network, all the connections in the connection pool are broken and this usuall requires a reboot of application server
And if broken connection detected, you shold create a new one to replace it in connection pool. It's common problem called deadly connections.

Categories