Hi, The idea of Jackrabbit managing DataSources didn't gain much support, so I decided to try implementing something much less intrusive. I have abstracted connection creation/closing (ConnectionProvider[1]) from the components that use database connections. There is one instance of ConnectionProvider per repository, configurable in repository.xml, but possibly with a sane default implementation so no configuration is necessary.
The rest of jackrabbit (components that touch the database) would use ConnectionProvider to get the connections instead of just creating them and keeping opened. So far I've converted BundleDbPersistenceManager (and it's subclasses) to this approach. I would also tweak DatabasePersistenceManager and DbFileSystem to just borrow the connections instead of keeping them. As for journal, keeping one opened connection per repository probably doesn't make much difference. The benefit of this approach is that there is zero change in repository configuration, unless user wants to specify it's own ConnectionProvider class, which can be specified as a simple bean with element name ConnectionProvider. ConnectionProvider implementation that supports pooling must take different things into account, such as there can be request to various connections from different databases with different URLs. The manager must be intelligent enough to possibly maintain group of pools (e..g per database or even per connection URL) There is a SimplePoolingConnectionProvider implementation included in the patch that implements connection pooling, but it's only meant as proof of concept and doesn't try to substitute "real" connection pooling alternatives (dbcp, etc.) I've attached the first patch to https://issues.apache.org/jira/browse/JCR-1456 Kind regards, -Matej [1] ConnectionProvider class /** * Class responsible for providing SQL [EMAIL PROTECTED] Connection}s. * <p> * Implementation of this class can do connection pooling, in which case it must * take [EMAIL PROTECTED] ConnectionProperties} into account and only return connection * that matches the specified properties. */ public interface ConnectionProvider { /** * Returns connection with given properties. * * @param properties * connection properties * @return SQL [EMAIL PROTECTED] Connection} * * @throws RepositoryException * @throws SQLException */ public Connection getConnection(ConnectionProperties properties) throws RepositoryException, SQLException; /** * Closes the given connection. Classes that obtain connections through * [EMAIL PROTECTED] ConnectionProvider} must never call [EMAIL PROTECTED] Connection#close()} * directly. They are required to call [EMAIL PROTECTED] #closeConnection(Connection)} * instead. * * @param connection * SQL [EMAIL PROTECTED] Connection} * * @throws SQLException */ public void closeConnection(Connection connection) throws SQLException; /** * Invoked when the repository is being shut down. * * @throws RepositoryException */ public void dispose() throws RepositoryException; /** * Bean that holds properties necessary to create or identify a SQL * [EMAIL PROTECTED] Connection}. */ public final static class ConnectionProperties { private String user; private String password; private String url; private String driver; public String getUser() { return user; } public void setUser(String user) { this.user = user; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public void setDriver(String driver) { this.driver = driver; } public String getDriver() { return driver; } private boolean equals(String s1, String s2) { return s1 == s2 || (s1 != null && s1.equals(s2)); } public boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof ConnectionProperties == false) { return false; } ConnectionProperties cp = (ConnectionProperties) obj; return equals(user, cp.user) && equals(password, cp.password) && equals(url, cp.url) && equals(driver, cp.driver); } private int hashCode(String s) { return s != null ? s.hashCode() : 0; } public int hashCode() { return hashCode(user) + 37 * hashCode(password) + 373 & hashCode(url) + 1187 * hashCode(driver); } } }
