How to handle database connection fail with Hibernate, C3P0 on Java EE?

♀尐吖头ヾ 提交于 2019-12-13 00:35:31

问题


I am working on Java EE JSF application using Hibernate with C3P0 connection pool. I have tried to search anything possible and impossible and tried many things, but couldnt figure this out.

The problem is handling database connection fail, for example when database is shut down. I couldn't find a way how to catch ecfeption which I could use to show error status on user interface. The only thing I could do is see some exceptions in console:

com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Could not create connection to database server. Attempted reconnect 3 times. Giving up.
    at sun.reflect.GeneratedConstructorAccessor408.newInstance(Unknown Source)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
    at com.mysql.jdbc.Util.getInstance(Util.java:386)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1015)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:989)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:975)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:920)
    at com.mysql.jdbc.ConnectionImpl.connectWithRetries(ConnectionImpl.java:2404)
    at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2325)
    at com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:834)
    at com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:46)
    at sun.reflect.GeneratedConstructorAccessor407.newInstance(Unknown Source)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
    at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:416)
    at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:347)
    at com.mchange.v2.c3p0.DriverManagerDataSource.getConnection(DriverManagerDataSource.java:146)
    at com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:195)
    at com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:184)
    at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.acquireResource(C3P0PooledConnectionPool.java:200)
    at com.mchange.v2.resourcepool.BasicResourcePool.doAcquire(BasicResourcePool.java:1086)
    at com.mchange.v2.resourcepool.BasicResourcePool.doAcquireAndDecrementPendingAcquiresWithinLockOnSuccess(BasicResourcePool.java:1073)
    at com.mchange.v2.resourcepool.BasicResourcePool.access$800(BasicResourcePool.java:44)
    at com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask.run(BasicResourcePool.java:1810)
    at com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:648)
Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
    at sun.reflect.GeneratedConstructorAccessor404.newInstance(Unknown Source)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
    at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1129)
    at com.mysql.jdbc.MysqlIO.<init>(MysqlIO.java:358)
    at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2498)
    at com.mysql.jdbc.ConnectionImpl.connectWithRetries(ConnectionImpl.java:2343)
    ... 18 more
Caused by: java.net.ConnectException: Connection timed out: connect
    at java.net.DualStackPlainSocketImpl.connect0(Native Method)
    at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:79)
    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
    at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
    at java.net.Socket.connect(Socket.java:579)
    at java.net.Socket.connect(Socket.java:528)
    at java.net.Socket.<init>(Socket.java:425)
    at java.net.Socket.<init>(Socket.java:241)
    at com.mysql.jdbc.StandardSocketFactory.connect(StandardSocketFactory.java:256)
    at com.mysql.jdbc.MysqlIO.<init>(MysqlIO.java:308)
    ... 20 more
]]

But I can't catch this, it's just on console and it's not even printed in web browser response (client thread does not receive any exception, it's just hanging while trying to load the page for infinity).

Here is my C3P0 configuration:

c3p0.testConnectionOnCheckout=true
c3p0.idleConnectionTestPeriod=60
c3p0.acquireIncrement=1
c3p0.preferredTestQuery=SELECT 1
c3p0.acquireRetryAttempts=1

My question is: How to handle case of database connection fail in the user-friendly way?


回答1:


You could use the Omnifaces FullAjaxExceptionHandler to display whatever you want for the exception. See the following link to documentation:

http://showcase.omnifaces.org/exceptionhandlers/FullAjaxExceptionHandler




回答2:


OK, after of few days of work I have constructed a solution.

The problem was that just typical Hibernate session did not throw any exception while using it without database connected. But this piece of code does throw an exception when database not connected (so it can be used as a test):

Properties p = hibernateConnection.getCfg().getProperties();

String url = p.getProperty("hibernate.connection.url");
String user = p.getProperty("hibernate.connection.username");
String password = p.getProperty("hibernate.connection.password");

DriverManager.getConnection(url, user, password).close();

So, simple try-catch can be used. If an exception is caught, connection is dead.

I used this for regular checking of database connection. On application deploy, a TimerTask is scheduled to run every minute. When it catches an exception, it sets a static variable dbAvailable to false (otherwise to true). This variable is being checked on every HTTP client request and if it's true, error 503 is sent back in response.

For scheduling the timer I used ServletContextListener. C3P0 configuration mentioned in the question.



来源:https://stackoverflow.com/questions/22847853/how-to-handle-database-connection-fail-with-hibernate-c3p0-on-java-ee

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!