There is a String object called detailMessage in java.lang.Throwable class, which says the reason of any exception thrown in java code.
This object is initialized through a constructor using super(string message) statement or setter or whatever from subclasses like Exception and again from its subclasses like SQLException.
When SQLException is thrown, error message can be displayed using sqlExceptionObject.getMessage();
The error message in sqlExceptionObject.getMessage() is same as in MySQL tool (Incase of any error in query execution)
So is the error message copied from MySQL? If yes, then from where?
The JDBC driver is responsible for that. It could translate an error code it gets from the DB to a string or it could get the error string directly from the DB. I don't know which one is the case for MySQL.
Related
While connecting to Derby database using OpenJPA, i have encountered this PersistenceException, which says connection could not be obtained for Derby EmbeddedDriver driver class, but that is not important (i know how to fix it):
77 RegistryManagement INFO [JavaFX Application Thread] openjpa.jdbc.JDBC - Using dictionary class "org.apache.openjp
a.jdbc.sql.DerbyDictionary".
<openjpa-3.1.2-r66d2a72 nonfatal general error> org.apache.openjpa.persistence.PersistenceException: There were errors i
nitializing your configuration: <openjpa-3.1.2-r66d2a72 fatal user error> org.apache.openjpa.util.UserException: A conne
ction could not be obtained for driver class "org.apache.derby.jdbc.EmbeddedDriver" and URL "jdbc:derby:db". You may ha
ve specified an invalid URL.
....
Important is that there is this Caused by in that exception:
....
Caused by: ERROR XJ004: XJ004.C : [0] db
at
....
which is one of Derby error codes (https://db.apache.org/derby/docs/10.5/ref/rrefexcept71493.html).
This PersistenceException was thrown when calling .createEntityManager(). Is it pretty long when it comes to text length.
I can catch that PersistenceException by wrapping .createEntityManager() with try-catch, but i can not figure out how to find more information about what is the cause, aka. get the error code, because PersistenceException can be thrown for various reasons. And i can not wrap it with catching SQLException or UserException, because my IDE says that method does not throw these exceptions.
I tried calling .getMessage() or .getCause() on that PersistenceException, but i got almost same long text.
When i called .getCause() it returns RuntimeException and I could see this, that Derby thrown SQLException:
....
Caused by: java.sql.SQLException: XJ004.C : [0] db
at
....
calling .getCause() again returns null.
I do not want to search the whole message (String) for occurences of some error codes, because that might be resource heavy. I think this problem might not be specific to Derby and happen while using other sql dbs, which might also throw some exception.
My code:
public class DatabaseManager
{
private EntityManagerFactory managerFactory;
private EntityManager manager;
public DatabaseManager(String persistenceUnitName, Map<String, String> properties)
{
managerFactory = Persistence.createEntityManagerFactory(persistenceUnitName, properties);
try
{
manager = managerFactory.createEntityManager();
}
catch(PersistenceException e)
{
//stuff
}
}
....
EntityManagerFactory is an interface from javax.persistence package:
public interface EntityManagerFactory {
public EntityManager createEntityManager();
....
As i was debugging, found this methods in PersistenceExceptions class, which are
from OpenJPA:
#Override
public RuntimeException translate(RuntimeException re) {
return PersistenceExceptions.toPersistenceException(re);
}
this method translates caught RuntimeException, which is in question's case OpenJPA's UserException caused by SQLException, and then creates new PersistenceException based on it here and returns it:
/**
* Translate the given general exception.
*/
private static Throwable translateGeneralException(OpenJPAException ke) {
Exception e = new org.apache.openjpa.persistence.PersistenceException
(ke.getMessage(), getNestedThrowables(ke),
getFailedObject(ke), ke.isFatal());
e.setStackTrace(ke.getStackTrace());
return e;
}
As you can see creating new org.apache.openjpa.persistence.PersistenceException based on OpenJPAException values (and not itself) causes that it is not possible to retrieve lower cause.
OpenJPA version 3.1.2
I recently came across norm of a SystemWide Exception class with enum for failure types
Class SystemWideException extends RuntimeException{
ErrorCause cause; //enum
ErrorCode code; //enum
Module where; //enum
Map<key,value> properties map
...
Here is how it is thrown
throw new SystemException(ThisModule.moduleX,ErrorCause.causeY,Errorcode.codeZ)
.set("field", field)
.set("value", value)
.set("min-length", MIN_LENGTH);
}
A system wide exception can be useful like the one mentioned here but i doubt if there is any use to have the component where exception occured and why it occured in the exception object?
I have a restful web service where i use a ExceptionMapper.I can use central logging here and the stacktrace gives why and where.Information about response status and body come from the exception object
Is there any use case where it would be meaningful to have Component,What,Why in the exception object?
Update: one use i have seen is multilingual support of error messages where Component+Error code form the key
For example, i created a exception that extends RuntimeException.
My exception has a new field called "code". I want to handle this exception in Oracle Service Bus process and retrieve this code to throws another exception with a XML structure that includes the code.
Is there a way to do that ?
I don't think that you will be able to retrieve just the "code". But certainly you can retrieve the details of the exception which will include your code.
Try it out.
I'm using JUnit4 to test my code.
Now, I'm aware that the following annotation allows me to expect an exception of a certain type
#Test(expected = NipException.class)
However, I have an 'errorCode' property in my exception class which I would also like to verify.
This is because the same exception is thrown at three places in the same method with different error codes.
How do I access 'errorCode' of the thrown exception?
Just catch the exception and assert the errorCode.
How to make SQLExceptions thrown by DB2 JDBC driver more descriptive?
Currently I am getting this kind of exceptions. It is cumbersome to work with these cryptic SQLCODE and SQLSTATE numeric values. Is there a way where to make the SQL exception to contain code description.
Caused by: com.ibm.db2.jcc.b.SqlException: DB2 SQL error: SQLCODE: -302,
SQLSTATE: 22001, SQLERRMC: null
at com.ibm.db2.jcc.b.hh.c(hh.java:1662)
at com.ibm.db2.jcc.b.hh.a(hh.java:1238)
at com.ibm.db2.jcc.c.db.n(db.java:737)
....
e.g. SQLSTATE 22001 has this description:
Character data, right truncation occurred; for example, an update or insert value is a string that is too long for the column, or a datetime value cannot be assigned to a host variable, because it is too small.
Edit: I am also using Spring and Hibernate frameworks.
Set the JDBC driver property retrieveMessagesFromServerOnGetMessage to true. Example connection url:
jdbc:db2://host:50128/MYDB:retrieveMessagesFromServerOnGetMessage=true;
See also DB2 11.1 Documentation
Check that the exception implements com.ibm.db2.jcc.DB2Diagnosable
On a DB2Diagnosable, you can call getSqlca() to get a DB2Sqlca. It will return the SQL error code (getSqlCode()), the state (getSqlState()) and you can call getMessage() to get a properly formatted and readable error message.
There is probably a smart reason why IBM didn't map this to getMessage() of the exception. My guess is that they didn't because DB2Sqlca.getMessage() can throw nasty exceptions, so you must wrap it in try-catch.
Spring contains translators for SQLException which convert the database-specific codes and states into a description exception class hierarchy.
It's part of the larger Spring API, but there's nothing stopping you from using just that class.
For example, if you have a DAO which extends JdbcDaoSupport, then you can have code like this:
try {
// ... some code that throws SQLException
} catch (SQLException ex) {
throw getExceptionTranslator().translate(null, null, ex);
}
This translates and wraps the SQLException is Spring's own strongly typed exception hierarchy.
If you're not using JdbcDaoSupport, then you can use the getExceptionTranslator() method of JdbcTemplate (and if you're not using that, then look at the source to see how it works.)