Postgres JDBC: Especific error code of PSQLException? - java

When writing java code that uses an Oracle database, one can always catch SQLException an read an specific Oracle error with e.getErrorCode(). For example, error 28001 means expired password, 28000 is blocked account, 1017 is wrong user/passsword, etc.
That way I can manage different errors the appropiate way.
But with PostgreSQL databases e.getErrorCode() always returns 0, even when catching Postgres-specific PSQLException.
The Question
Is there a way that I don't know of to get an specific error code for a Postgres database exception in Java other than trying to parse the error message (which by the way could be in any localized language)?

Have you tried looking at getSqlState() instead? See also: http://www.postgresql.org/docs/9.3/static/errcodes-appendix.html

Related

Best way to solve conflict between EclipseLink #Version Timestamp-Field and DB2

In the current project I'm working on, we are using EclipseLink as JPA-Provider. In the background is a DB2-database.
We want to introduce "Optimistic Locking" with the restriction only using Timestamp-fields. Furthermore, these timestamp fields are CURRENT TIMESTAMP fields, so when updating an entity, the CURRENT TIMESTAMP field updates the value itself. This is necessary to guarantee the reliability of the whole system.
When annotating the attribute of an entity with #Version, I get the following error message:
Internal Exception: com.ibm.websphere.ce.cm.StaleConnectionException: THE SQL STATEMENT IS NOT SUPPORTED. SQLCODE=-142, SQLSTATE=42612, DRIVER=4.22.29
Error Code: -142
Call: VALUES CURRENT TIMESTAMP
Query: ValueReadQuery(sql="VALUES CURRENT TIMESTAMP")
at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl$1.handleException(EntityManagerSetupImpl.java:767)
at org.eclipse.persistence.transaction.AbstractSynchronizationListener.handleException(AbstractSynchronizationListener.java:275)
[…]
Note: I only get this error message when using the mentioned annotation.
My research resulted in the following:
Internal Exception: com.ibm.websphere.ce.cm.StaleConnectionException:
--> A StaleConnectionException is an exception that is generated by the WebSphere Application Server database connection code when a JDBC driver returns a fatal error from a connection request or operation. In WebSphere Application Server, the StaleConnectionException is issued when the database vendor issues an exception indicating that a connection currently in the connection pool is no longer valid. ( https://developer.ibm.com/answers/questions/205910/how-to-resolve-the-staleconnectionexception-in-web/ )
THE SQL STATEMENT IS NOT SUPPORTED. SQLCODE=-142,
--> An SQL statement was detected that is not supported by the database. The statement might be valid for other IBM® relational database products or it might be valid in another context. For example, statements such as VALUES and SIGNAL or RESIGNAL SQLSTATE can be used only in certain contexts, such as in a trigger body or in an SQL Procedure. ( https://www.ibm.com/support/knowledgecenter/en/SSEPEK_10.0.0/codes/src/tpc/n142.html )
SQLSTATE=42612,
--> Seems to be internal, nothing for my relevance
After getting more into the topic, I came across the following link, which appears as the most encouraging so far:
https://www.idug.org/p/fo/et/thread=36380
In summary, the suggested way is to extend org.eclipse.persistence.platform.database.DB2MainframePlatform and manipulate the generated SQL-statement.
My expectation is, that there should be a better way, since this should be a standard-case for the framework. If not, is there an more proper/better way to solve this problem?

Azure SQL : error code for Connection is closed exception's

I am getting below exceptions at times in my java code which connects to Azure SQL server. For this, I need to implement retry logic i.e. when I face below exception I will retry 1) Create new connection 2) Re-execute the SQL query 3) Commit the transaction.
But, I am unable to get the Azure SQL server error code for below error. Please let me know the error code ? I do not see the error code when I run below query:
SELECT * FROM sys.messages WHERE language_id = 1033
Exception:
com.microsoft.sqlserver.jdbc.SQLServerException: The connection is closed.
at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDriverError(SQLServerException.java:227)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.checkClosed(SQLServerConnection.java:796)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.commit(SQLServerConnection.java:2681)
Also, is it a good practice to use e.getMessage() and check if return string is "The connection is closed." and retry my logic ?
I do not see the error code in Error codes from SQL
This exception seems to be related to an attempt to convert from a supported data type to an unsupported data type. This is a good example.
Try another version of the JDBC driver.

Hibernate 4 upgrade, COMMIT not being issued

I am attempting to upgrade our code base from Hibernate 3.6 to 4.0 (just as a first step into getting us more up to date). I am hitting an issue where a COMMIT is not being issued even though we are calling the commit() after making sure the transaction is isActive().
When running some queries successfully against the Postgres database, I see this in the Postgres logs:
2014-12-30 20:09:39 CST LOG: execute <unnamed>: SET extra_float_digits=3
2014-12-30 20:09:39 CST LOG: execute S_1: BEGIN
2014-12-30 20:09:39 CST LOG: execute <unnamed>: -- This script........
Notice the BEGIN there, and then here's an example of the simple commit call:
if (sf.getCurrentSession().getTransaction().isActive()) {
sf.getCurrentSession().getTransaction().commit();
}
I have debugged down into AbstractTransactionImpl and am looking at a Jdbc4Connection commit() method, and see that the actual COMMIT call is being skipped.....but I don't know why. Here's the if statement that this is failing on (it is in AbstractJdbc2Connection).
if (protoConnection.getTransactionState() != ProtocolConnection.TRANSACTION_IDLE)
executeTransactionCommand(commitQuery);
So, apparently our transactionstate is == ProtocolConnection.TRANSACTION_IDLE. However, I'm not entirely sure what that entails, and why are we getting this issue when the transaction says it isActive()?
NOTE: this same exact code worked for us on Hibernate 3.6.
Thanks.
UPDATE: I debugged further, and it looks like there are many ProtocoalConnectionImpl objects being constructed, does that indicate a problem on our software side that is doing something it shouldn't? Like does that indicate that we're opening connections that are just hanging around? Thanks for any more insight.
So it turns out I was doing something incorrect (surprise). There's a good reason that the TransactionState was showing as TRANSACTION_IDLE and not issuing a commit.
I had seen in multiple places on the internetz where people were getting access to a JDBC connection in the new Hibernate 4.x land by getting access to the underlying ConnectionProvider (sort of like this: https://stackoverflow.com/a/21271019/115694).
However, the problem with doing that is that you are getting a BRAND NEW connection....instead of the connection associated with the current session. This is a pretty big no-no, or at least for us it was.
You do have to in fact do what the person says in this answer:
https://stackoverflow.com/a/3526626/115694
Basically, you MUST use the Work API.

What is the proper way to handle login errors in Sybase, from a JDBC connection?

I access a Sybase database from a Java application. I can connect to it, execute statements, all of this works fine.
My issue is that I would like to handle correctly the cases when connection fails.
From my understanding, it can fail for the following reasons:
Incorrect password
Password expired
Account is locked
So my question is: how can I properly handle these error cases, how can I recognize which one happened?
From several tests, I found out the different cases:
Expired password
In this case, the database allows a connection, but a very limited one. The only thing you can call is the procedure to change password. The connection returned comes with a SQLWarning with the errorcode 4022, and a description stating:
The password has expired, but you are
still allowed to log in. You must
change your password before you can
continue. If a login trigger is set,
it will not be executed.
Thanks to the specific error code, it is possible to recognized the error, and propose to change the password in the client program.
Invalid password and Locked account
There is no difference for both cases. When requesting a connection, it throws a SQLException which links to a SQLWarning as next exception, with the error code 4002, and a very simple description:
Login failed.
As such, there is not really a way to handle these cases specifically.
Bonus case: password expiring soon
When a password will expire soon, the connection returned will contain a SQLWarning with the code 4023, stating:
Your password will expire in %s days.
This allows to show a warning in the client program, proposing the change the password already.
Handle it like you would other messages from the database. Catch the exception a log the message (this will help you identify the cause. At the same time display a message to the user that either a database error occurred or that the database could not be accessed.

How to fetch data from a Microsoft Access database through JDBC and insert the table as a test field in an Applet

I have made a small letter game as a Java Applet. I have made a Microsoft Access Database through JBDC for the high scores.
I have managed to insert values (scores) into the database, but I am having trouble fetching them and displaying the table in the textArea of an ajFrame. I am not even sure if the connection is established. I have created the SQL statement for it.
If you've connected successfully then
connection=DriverManager.getConnection("jdbc:odbc:databaseName");
should return you a connection object and not throw a SqlException.
So I would first check that the above is in fact the case.
Note that an applet can only talk back to its originating server (this is a security feature). So if your applet is served from server A, and your database is on server B, you should get security exceptions.
Check your query with sql prompt.
verify object name used (Drivermanager,Connection,TextField)
Include Exception handling code for sql statements (try and catch )

Categories

Resources