I integrate MySQL into Apache Felix. First, I use bndtools to generate MySQL bundle and c3p0 bundle. Then I add them all into my Apache Felix environment. I create a class for connection pool like below:
public final class C3P0Manager { private static C3P0Manager instance; private DataSource pooled; private C3P0Manager() { // Of course, it is better to put all properties into a configuration file. // I just list them here for easy reading. ComboPooledDataSource cpds = new ComboPooledDataSource(); cpds.setDriverClass("com.mysql.jdbc.Driver")); cpds.setJdbcUrl("jdbc:mysql://localhost/my-database?autoReconnect=true&characterSetResults=UTF-8&characterEncoding=UTF-8&useUnicode=yes"); cpds.setUser("user"); cpds.setPassword("password"); cpds.setInitialPoolSize(3); cpds.setMaxPoolSize(15); cpds.setMaxIdleTime(1800); cpds.setAutoCommitOnClose(true); pooled(cpds); } public static C3P0Manager instance() throws Exception { if (instance == null) { instance = new C3P0Manager(); } return instance; } public DataSource getPooled() throws SQLException { return pooled; } }
It works fine if I run JUnit test. But failed when running on my Apache Felix bundle with exception message. Usage in Activator class:
Class.forName("com.mysql.jdbc.Driver"); DataSource pooled = C3P0Manager.instance().getPooled(); Connection con = pooled.getConnection(); PreparedStatement stmt = null; ResultSet rs = null; int total; try { stmt = con.prepareStatement("SELECT count(*) FROM users", Statement.NO_GENERATED_KEYS); rs = stmt.executeQuery(); if (rs.next()) { total = rs.getInt(1); } } catch (Exception e) { e.printStackTrace(); } finally { try { rs.close(); stmt.close(); } catch (Exception ex) { ex.printStackTrace(); } } System.out.println("total = " + total);
Error messages:
java.sql.SQLException: Connections could not be acquired from the underlying database! at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:106) at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutPooledConnection(C3P0PooledConnectionPool.java:529) at com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource.getConnection(AbstractPoolBackedDataSource.java:128) ... Caused by: com.mchange.v2.resourcepool.CannotAcquireResourceException: A ResourcePool could not acquire a resource from its primary factory or source. at com.mchange.v2.resourcepool.BasicResourcePool.awaitAvailable(BasicResourcePool.java:1319) at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:557) at com.mchange.v2.resourcepool.BasicResourcePool.checkoutResource(BasicResourcePool.java:477) at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutPooledConnection(C3P0PooledConnectionPool.java:525) ...
MySQL works if I just use (without c3p0):
Class.forName("com.mysql.jdbc.Driver"); Connection con = DriverManager.getConnection("jdbc:mysql://localhost/my-database?autoReconnect=true&characterSetResults=UTF-8&characterEncoding=UTF-8&useUnicode=yes","user","password"); Statement statement = connect.createStatement(); ResultSet resultSet = statement.executeQuery("SELECT count(*) FROM users");
So I think the problem is due to c3p0. Please help me. Thanks.
I am lazy to modify c3p0 source and build new c3p0 bundle version again :). So I try Apache DBCP bundle instead:
org.apache.servicemix.bundles.commons-pool-1.5.4
org.apache.servicemix.bundles.commons-dbcp-1.4.0
(dbcp needs pool to work)
It is OK to CRUD MySQL database.
If anyone want to use those bundles, here they are:
http://mvnrepository.com/artifact/org.apache.servicemix.bundles/org.apache.servicemix.bundles.commons-pool
http://mvnrepository.com/artifact/org.apache.servicemix.bundles/org.apache.servicemix.bundles.commons-dbcp
When I have time, I will take a look at bonecp if someone already builds a bundle for it. Or modify c3p0 to use it.