You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by sk...@apache.org on 2007/09/11 09:39:11 UTC
svn commit: r574496 -
/myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/
Author: skitching
Date: Tue Sep 11 00:39:10 2007
New Revision: 574496
URL: http://svn.apache.org/viewvc?rev=574496&view=rev
Log:
Save old code that was deleted from the core module. It might be useful some day.
Added:
myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/
myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/AbstractConnectionManagerListener.java
myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/ConnectionManagerDataSource.java
myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/ConnectionManagerListener.java
myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/DisconnectableConnection.java
myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/DisconnectableConnectionFactory.java
myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/package.html
Added: myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/AbstractConnectionManagerListener.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/AbstractConnectionManagerListener.java?rev=574496&view=auto
==============================================================================
--- myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/AbstractConnectionManagerListener.java (added)
+++ myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/AbstractConnectionManagerListener.java Tue Sep 11 00:39:10 2007
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.orchestra.connectionManager;
+
+import java.sql.Connection;
+
+/**
+ * @see ConnectionManagerListener
+ */
+public abstract class AbstractConnectionManagerListener implements ConnectionManagerListener
+{
+ public void borrowConnection(Connection con)
+ {
+ }
+
+ public void releaseConnection(Connection con)
+ {
+ }
+}
Added: myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/ConnectionManagerDataSource.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/ConnectionManagerDataSource.java?rev=574496&view=auto
==============================================================================
--- myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/ConnectionManagerDataSource.java (added)
+++ myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/ConnectionManagerDataSource.java Tue Sep 11 00:39:10 2007
@@ -0,0 +1,237 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.orchestra.connectionManager;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.sql.DataSource;
+import java.io.PrintWriter;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Manage all borrowed connections and hand out
+ * {@link org.apache.myfaces.orchestra.connectionManager.DisconnectableConnection}
+ * objects so that we can close them again after the HTTP request has been finished.
+ * <p>
+ * This datasource can be configured as a "wrapper" for a real datasource. When a connection is
+ * requested from this object, a proxy is returned that simply forwards all calls transparently
+ * to the real connection. This manager keeps track of all the Connections borrowed by each
+ * thread. At some point (eg from a servlet filter) this object can be asked to check for
+ * unreturned connections held by the current thread. If any exist then the real connection
+ * is returned to the underlying datasource and the proxy's connection reference is set to null.
+ * This ensures that a thread cannot leak real database connections.
+ * <p>
+ * Of course all code should return its connections; this is only a workaround/hack useful when the
+ * real problem cannot be fixed. This is particularly useful for JPA implementations that do not free
+ * their connection again after a lazy-init.
+ *
+ * @see org.apache.myfaces.orchestra.connectionManager.DisconnectableConnection
+ */
+public class ConnectionManagerDataSource implements DataSource
+{
+ private DataSource dataSource;
+ private String jndiName;
+ private ConnectionManagerListener[] listeners;
+
+ // List of connections that have been borrowed by this thread but not returned.
+ // When using a threadpool, it is required that the releaseAllBorrowedConnections
+ // method be called before the thread is returned to the pool; that ensures this
+ // threadlocal is reset to null.
+ private static ThreadLocal borrowedConnections = new ThreadLocal()
+ {
+ protected Object initialValue()
+ {
+ return new HashSet();
+ }
+ };
+
+ public ConnectionManagerDataSource()
+ {
+ }
+
+ void onAfterBorrowConnection(Connection con)
+ {
+ ((Set) borrowedConnections.get()).add(con);
+
+ if (listeners != null)
+ {
+ for (int i = 0; i<listeners.length; i++)
+ {
+ listeners[i].borrowConnection(con);
+ }
+ }
+ }
+
+ public void onBeforeReleaseConnection(Connection con)
+ {
+ if (listeners != null)
+ {
+ for (int i = 0; i<listeners.length; i++)
+ {
+ listeners[i].releaseConnection(con);
+ }
+ }
+ }
+
+ void onAfterReleaseConnection(Connection con)
+ {
+ ((Set) borrowedConnections.get()).remove(con);
+ }
+
+ public static void releaseAllBorrowedConnections()
+ {
+ DisconnectableConnection[] connections = new DisconnectableConnection[((Set) borrowedConnections.get()).size()];
+ ((Set) borrowedConnections.get()).toArray(connections);
+
+ for (int i = 0; i<connections.length; i++)
+ {
+ DisconnectableConnection connection = connections[i];
+ connection.disconnect();
+ }
+
+ ((Set) borrowedConnections.get()).clear();
+ }
+
+ public void setListeners(ConnectionManagerListener[] listeners)
+ {
+ this.listeners = listeners;
+ }
+
+ public void setDataSource(DataSource dataSource)
+ {
+ this.dataSource = dataSource;
+ }
+
+ public DataSource getDataSource()
+ {
+ if (dataSource != null)
+ {
+ return dataSource;
+ }
+
+ try
+ {
+ Context ctx = new InitialContext();
+ dataSource = (DataSource) ctx.lookup(jndiName);
+ }
+ catch (NamingException e)
+ {
+ throw (IllegalArgumentException) new IllegalArgumentException(jndiName).initCause(e);
+ }
+
+ return dataSource;
+ }
+
+ public void setJndiName(String jndiName)
+ {
+ this.jndiName = jndiName;
+ }
+
+ public Connection getConnection() throws SQLException
+ {
+ return DisconnectableConnectionFactory.create(this);
+ }
+
+ public Connection getConnection(String username, String password) throws SQLException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public PrintWriter getLogWriter() throws SQLException
+ {
+ return getDataSource().getLogWriter();
+ }
+
+ public void setLogWriter(PrintWriter out) throws SQLException
+ {
+ getDataSource().setLogWriter(out);
+ }
+
+ public void setLoginTimeout(int seconds) throws SQLException
+ {
+ getDataSource().setLoginTimeout(seconds);
+ }
+
+ public int getLoginTimeout() throws SQLException
+ {
+ return getDataSource().getLoginTimeout();
+ }
+
+ public Object unwrap(Class iface) throws SQLException
+ {
+ throw new UnsupportedOperationException();
+ /*
+ try
+ {
+ if (iface.isAssignableFrom(dataSource.getClass()))
+ {
+ return dataSource;
+ }
+
+ Method method = dataSource.getClass().getMethod("unwrap", new Class[]{Class.class});
+ return method.invoke(dataSource, new Object[] { iface });
+ }
+ catch (NoSuchMethodException e)
+ {
+ throw new UnsupportedOperationException();
+ }
+ catch (IllegalAccessException e)
+ {
+ throw new SQLException(e);
+ }
+ catch (InvocationTargetException e)
+ {
+ throw new SQLException(e);
+ }
+ */
+ }
+
+ public boolean isWrapperFor(Class iface) throws SQLException
+ {
+ throw new UnsupportedOperationException();
+
+ /*
+ try
+ {
+ if (iface.isAssignableFrom(dataSource.getClass()))
+ {
+ return true;
+ }
+ Method method = dataSource.getClass().getMethod("isWrapperFor", new Class[]{Class.class});
+ return Boolean.TRUE.equals(method.invoke(dataSource, new Object[] { iface }));
+ }
+ catch (NoSuchMethodException e)
+ {
+ throw new UnsupportedOperationException();
+ }
+ catch (IllegalAccessException e)
+ {
+ throw new SQLException(e);
+ }
+ catch (InvocationTargetException e)
+ {
+ throw new SQLException(e);
+ }
+ */
+ }
+}
Added: myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/ConnectionManagerListener.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/ConnectionManagerListener.java?rev=574496&view=auto
==============================================================================
--- myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/ConnectionManagerListener.java (added)
+++ myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/ConnectionManagerListener.java Tue Sep 11 00:39:10 2007
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.orchestra.connectionManager;
+
+import java.sql.Connection;
+
+/**
+ * Implement this class if you would like to add a listener to the ConnectionManager which e.g. allows
+ * you to do some database setup/shutdown procedures.<br />
+ * Its recommended to extend from the {@link AbstractConnectionManagerListener} class to be prepared
+ * for future interface enhancements.
+ *
+ * @see org.apache.myfaces.orchestra.connectionManager.AbstractConnectionManagerListener
+ */
+public interface ConnectionManagerListener
+{
+ public void borrowConnection(Connection con);
+ public void releaseConnection(Connection con);
+}
Added: myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/DisconnectableConnection.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/DisconnectableConnection.java?rev=574496&view=auto
==============================================================================
--- myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/DisconnectableConnection.java (added)
+++ myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/DisconnectableConnection.java Tue Sep 11 00:39:10 2007
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.orchestra.connectionManager;
+
+import java.sql.Connection;
+
+/**
+ * A workaround to the lazy-init-in-view problem.<br />
+ *
+ * We hand out DisconnectableConnections to the JPA-implementation, now,
+ * if a lazy-init happens during the view rendering we are able to disconnect it again
+ * at the end of the request (using a servlet filter). Once the JPA-implementation would like to
+ * do something with the connection again, we simply request a new from the connection pool
+ */
+public interface DisconnectableConnection extends Connection
+{
+ public void disconnect();
+ public Connection getConnection();
+}
Added: myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/DisconnectableConnectionFactory.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/DisconnectableConnectionFactory.java?rev=574496&view=auto
==============================================================================
--- myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/DisconnectableConnectionFactory.java (added)
+++ myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/DisconnectableConnectionFactory.java Tue Sep 11 00:39:10 2007
@@ -0,0 +1,143 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.orchestra.connectionManager;
+
+import org.apache.commons.logging.LogFactory;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * Proxy connections to being able to handle disconnection.
+ *
+ * @see org.apache.myfaces.orchestra.connectionManager.DisconnectableConnection
+ */
+public class DisconnectableConnectionFactory
+{
+ private DisconnectableConnectionFactory()
+ {
+ }
+
+ public static DisconnectableConnection create(final ConnectionManagerDataSource connectionManager)
+ {
+ return (DisconnectableConnection) Proxy.newProxyInstance(
+
+ DisconnectableConnection.class.getClassLoader(),
+
+ new Class[]
+ {
+ DisconnectableConnection.class
+ },
+
+ new InvocationHandler()
+ {
+ private Map connectionConfiguration = new HashMap();
+ private Connection connection;
+
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
+ {
+ if ("equals".equals(method.getName()) || "hashCode".equals(method.getName())) // NON-NLS
+ {
+ // do not pass these methods to the connection as we dont want to change the
+ // identity of the connection proxy
+ return method.invoke(this, args);
+ }
+ else if ("close".equals(method.getName())) // NON-NLS
+ {
+ try
+ {
+ connectionManager.onBeforeReleaseConnection((Connection) proxy);
+ if (connection != null)
+ {
+ connection.close();
+ }
+ connection = null;
+ }
+ finally
+ {
+ connectionManager.onAfterReleaseConnection((Connection) proxy);
+ }
+ return null;
+ }
+ else if ("disconnect".equals(method.getName())) // NON-NLS
+ {
+ connectionManager.onBeforeReleaseConnection((Connection) proxy);
+ try
+ {
+ if (connection != null)
+ {
+ try
+ {
+ if (!connection.isClosed())
+ {
+ connection.close();
+ }
+ }
+ catch (SQLException e)
+ {
+ LogFactory.getLog(DisconnectableConnectionFactory.class).warn(e.getLocalizedMessage(), e);
+ }
+ }
+ }
+ finally
+ {
+ connectionManager.onAfterReleaseConnection((Connection) proxy);
+ connection = null;
+ }
+ return null;
+ }
+ else if ("getConnection".equals(method.getName())) // NON-NLS
+ {
+ return connection;
+ }
+
+ if (connection == null)
+ {
+ connection = connectionManager.getDataSource().getConnection();
+
+ // if we have a configuration, we have to replay it now
+ Iterator iterConfiguration = connectionConfiguration.entrySet().iterator();
+ while (iterConfiguration.hasNext())
+ {
+ Map.Entry config = (Map.Entry) iterConfiguration.next();
+ ((Method) config.getKey()).invoke(connection, (Object[]) config.getValue());
+ }
+
+ connectionManager.onAfterBorrowConnection((Connection) proxy);
+ }
+
+ Object ret = method.invoke(connection, args);
+
+ // capture the connection configuration
+ if (method.getName().startsWith("set")) // NON-NLS
+ {
+ connectionConfiguration.put(method, args);
+ }
+
+ return ret;
+ }
+ });
+ }
+}
Added: myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/package.html
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/package.html?rev=574496&view=auto
==============================================================================
--- myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/package.html (added)
+++ myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/package.html Tue Sep 11 00:39:10 2007
@@ -0,0 +1,13 @@
+<html>
+<body>
+The code in this package is a copy of code that was originally implemented in core, but
+which was later simplified.
+<p>
+This code does two things: track "leaked" database connections, and provide a generic
+mechanism for getting notifications when a connection is borrowed or returned from a
+datasource. This second feature was not actually needed for core Orchestra so was
+deleted. At some future time the code here might be worth modifying to provide
+ONLY this notification functionality. It might then find a home somewhere like
+apache commons dbcp.
+</body>
+</html>