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