You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by fh...@apache.org on 2009/07/09 00:34:40 UTC

svn commit: r792340 - in /tomcat/trunk/modules/jdbc-pool: ./ doc/ java/org/apache/tomcat/jdbc/pool/ java/org/apache/tomcat/jdbc/pool/interceptor/ resources/ test/org/apache/tomcat/jdbc/test/

Author: fhanik
Date: Wed Jul  8 22:34:40 2009
New Revision: 792340

URL: http://svn.apache.org/viewvc?rev=792340&view=rev
Log:
remove dependency on the modeler so that the pool can run outside of tomcat and still have jmx query notifications.


Added:
    tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmxMBean.java   (with props)
Modified:
    tomcat/trunk/modules/jdbc-pool/build.properties.default
    tomcat/trunk/modules/jdbc-pool/build.xml
    tomcat/trunk/modules/jdbc-pool/doc/jdbc-pool.xml
    tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java
    tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmx.java
    tomcat/trunk/modules/jdbc-pool/resources/MANIFEST.MF
    tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/CreateTestTable.java
    tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestSlowQueryReport.java

Modified: tomcat/trunk/modules/jdbc-pool/build.properties.default
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/build.properties.default?rev=792340&r1=792339&r2=792340&view=diff
==============================================================================
--- tomcat/trunk/modules/jdbc-pool/build.properties.default (original)
+++ tomcat/trunk/modules/jdbc-pool/build.properties.default Wed Jul  8 22:34:40 2009
@@ -82,7 +82,6 @@
 
 tomcat.home=${base.path}/apache-tomcat-6.0.20
 tomcat.dbcp.jar=${tomcat.home}/lib/tomcat-dbcp.jar
-tomcat.coyote.jar=${tomcat.home}/lib/tomcat-coyote.jar
 tomcat.juli.jar=${tomcat.home}/bin/tomcat-juli.jar
 tomcat.loc=http://archive.apache.org/dist/tomcat/tomcat-6/v6.0.20/bin/apache-tomcat-6.0.20.zip
 

Modified: tomcat/trunk/modules/jdbc-pool/build.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/build.xml?rev=792340&r1=792339&r2=792340&view=diff
==============================================================================
--- tomcat/trunk/modules/jdbc-pool/build.xml (original)
+++ tomcat/trunk/modules/jdbc-pool/build.xml Wed Jul  8 22:34:40 2009
@@ -51,7 +51,6 @@
   <!-- Classpath -->
   <path id="tomcat.jdbc.classpath">
     <pathelement location="${tomcat.classes}"/>
-    <pathelement location="${tomcat.coyote.jar}"/>
     <pathelement location="${tomcat.juli.jar}"/>
   </path>
   

Modified: tomcat/trunk/modules/jdbc-pool/doc/jdbc-pool.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/doc/jdbc-pool.xml?rev=792340&r1=792339&r2=792340&view=diff
==============================================================================
--- tomcat/trunk/modules/jdbc-pool/doc/jdbc-pool.xml (original)
+++ tomcat/trunk/modules/jdbc-pool/doc/jdbc-pool.xml Wed Jul  8 22:34:40 2009
@@ -444,8 +444,15 @@
     <p>Extends the <code>SlowQueryReport</code> and in addition to log entries it issues JMX notification
        for monitoring tools to react to. Inherits all the attributes from its parent class.
        This class uses Tomcat's JMX engine so it wont work outside of the Tomcat container.
+       By default, JMX notifications are sent through the ConnectionPool mbean if it is enabled.
+       The SlowQueryReportJmx can also register an MBean if <code>notifyPool=false</code>
     </p>   
     <attributes>
+      <attribute name="notifyPool" required="false">
+        <p>(boolean as String) Set to false if you want JMX notifications to go to the SlowQueryReportJmx MBean
+           The default value is <code>true</code>.
+        </p>
+      </attribute>
     </attributes>
   </subsection>
   <subsection name="org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer">
@@ -687,9 +694,8 @@
   <p>Other examples of Tomcat configuration for JDBC usage can be found <a href="http://tomcat.apache.org/tomcat-6.0-doc/jndi-datasource-examples-howto.html">in the Tomcat documentation</a>. </p>
   <subsection name="Building from source">
     <p>Building is pretty simple. The pool has a dependency on <code>tomcat-juli.jar</code> and in case you want the <code>SlowQueryReportJmx</code>
-    it also requires the <code>tomcat-coyote.jar</code> library.</p>
     <source>
-       javac -classpath tomcat-juli.jar:tomcat-coyote.jar \
+       javac -classpath tomcat-juli.jar \
              -d . \
              org/apache/tomcat/jdbc/pool/*.java \
              org/apache/tomcat/jdbc/pool/interceptor/*.java \

Modified: tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java?rev=792340&r1=792339&r2=792340&view=diff
==============================================================================
--- tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java (original)
+++ tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java Wed Jul  8 22:34:40 2009
@@ -21,6 +21,9 @@
 import java.sql.SQLException;
 import java.util.Iterator;
 import java.util.concurrent.Future;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
 
 import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
@@ -187,7 +190,13 @@
 
     protected void finalize() throws Throwable {
         //terminate the pool?
-        close(true);
+        ThreadPoolExecutor closer = new ThreadPoolExecutor(0,1,1000,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());
+        final Runnable r = new Runnable() {
+            public void run(){ 
+                close(true);                
+            }
+        };
+        closer.execute(r);
     }
 
     public int getPoolSize() throws SQLException{

Modified: tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmx.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmx.java?rev=792340&r1=792339&r2=792340&view=diff
==============================================================================
--- tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmx.java (original)
+++ tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmx.java Wed Jul  8 22:34:40 2009
@@ -16,19 +16,26 @@
  */
 package org.apache.tomcat.jdbc.pool.interceptor;
 
+import java.lang.management.ManagementFactory;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicLong;
 
-import javax.management.DynamicMBean;
 import javax.management.InstanceAlreadyExistsException;
 import javax.management.InstanceNotFoundException;
+import javax.management.ListenerNotFoundException;
 import javax.management.MBeanException;
+import javax.management.MBeanNotificationInfo;
+import javax.management.MBeanRegistrationException;
 import javax.management.MalformedObjectNameException;
 import javax.management.NotCompliantMBeanException;
 import javax.management.Notification;
+import javax.management.NotificationBroadcasterSupport;
+import javax.management.NotificationEmitter;
+import javax.management.NotificationFilter;
+import javax.management.NotificationListener;
 import javax.management.ObjectName;
 import javax.management.RuntimeOperationsException;
 import javax.management.openmbean.CompositeData;
@@ -40,16 +47,14 @@
 import org.apache.juli.logging.LogFactory;
 import org.apache.tomcat.jdbc.pool.ConnectionPool;
 import org.apache.tomcat.jdbc.pool.PooledConnection;
-import org.apache.tomcat.util.modeler.BaseModelMBean;
-import org.apache.tomcat.util.modeler.ManagedBean;
-import org.apache.tomcat.util.modeler.Registry;
+import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorProperty;
 /**
  * Publishes data to JMX and provides notifications 
  * when failures happen.
  * @author fhanik
  *
  */
-public class SlowQueryReportJmx extends SlowQueryReport {
+public class SlowQueryReportJmx extends SlowQueryReport implements NotificationEmitter, SlowQueryReportJmxMBean{
     public static final String SLOW_QUERY_NOTIFICATION = "SLOW QUERY";
     public static final String FAILED_QUERY_NOTIFICATION = "FAILED QUERY";
 
@@ -58,8 +63,35 @@
     protected static Log log = LogFactory.getLog(SlowQueryReportJmx.class);
     
     
-    protected static ConcurrentHashMap<String,DynamicMBean> mbeans = 
-        new ConcurrentHashMap<String,DynamicMBean>(); 
+    protected static ConcurrentHashMap<String,SlowQueryReportJmxMBean> mbeans = 
+        new ConcurrentHashMap<String,SlowQueryReportJmxMBean>(); 
+    
+    
+    //==============================JMX STUFF========================
+    protected volatile NotificationBroadcasterSupport notifier = new NotificationBroadcasterSupport();
+
+    public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws IllegalArgumentException {
+        notifier.addNotificationListener(listener, filter, handback);
+    }
+
+    
+    public MBeanNotificationInfo[] getNotificationInfo() {
+        return notifier.getNotificationInfo();
+    }
+
+    public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException {
+        notifier.removeNotificationListener(listener);
+        
+    }
+
+    public void removeNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws ListenerNotFoundException {
+        notifier.removeNotificationListener(listener, filter, handback);
+        
+    }
+
+    
+    
+    //==============================JMX STUFF========================    
     
     protected String poolName = null;
     
@@ -92,6 +124,7 @@
         if (parent!=null) {
             poolName = parent.getName();
             pool = parent;
+            registerJmx();
         }
     }
 
@@ -109,7 +142,6 @@
         this.pool = pool;
         super.poolStarted(pool);
         this.poolName = pool.getName();
-        registerJmx();
     }
 
     @Override
@@ -121,7 +153,6 @@
 
     protected void notifyJmx(String query, String type) {
         try {
-            DynamicMBean mbean = mbeans.get(poolName);
             long sequence = notifySequence.incrementAndGet();
             
             if (isNotifyPool()) {
@@ -129,25 +160,21 @@
                     this.pool.getJmxPool().notify(type, query);
                 }
             } else {
-                if (mbean!=null && mbean instanceof BaseModelMBean) {
+                if (notifier!=null) {
                     Notification notification = 
                         new Notification(type, 
-                                         mbean, 
+                                         this, 
                                          sequence, 
                                          System.currentTimeMillis(),
                                          query);
-                    BaseModelMBean bmbean = (BaseModelMBean)mbean;
-                    bmbean.sendNotification(notification);
+                    
+                    notifier.sendNotification(notification);
                 }
             }
         } catch (RuntimeOperationsException e) {
             if (log.isDebugEnabled()) {
                 log.debug("Unable to send failed query notification.",e);
             }
-        } catch (MBeanException e) {
-            if (log.isDebugEnabled()) {
-                log.debug("Unable to send failed query notification.",e);
-            }
         }
     }
 
@@ -221,16 +248,14 @@
     
     protected void deregisterJmx() {
         try {
-            DynamicMBean mbean = null;
-            if ((mbean=mbeans.remove(poolName))!=null) {
-                Registry registry = Registry.getRegistry(null, null);
-                ManagedBean managed = registry.findManagedBean(this.getClass().getName());
-                if (managed!=null) {
-                    ObjectName oname = new ObjectName(ConnectionPool.POOL_JMX_TYPE_PREFIX+getClass().getName()+",name=" + poolName);
-                    registry.unregisterComponent(oname);
-                    registry.removeManagedBean(managed);
-                }
+            if (mbeans.remove(poolName)!=null) {
+                ObjectName oname = getObjectName(getClass(),poolName);
+                ManagementFactory.getPlatformMBeanServer().unregisterMBean(oname);
             }
+        } catch (MBeanRegistrationException e) {
+            log.debug("Jmx deregistration failed.",e);
+        } catch (InstanceNotFoundException e) {
+            log.debug("Jmx deregistration failed.",e);
         } catch (MalformedObjectNameException e) {
             log.warn("Jmx deregistration failed.",e);
         } catch (RuntimeOperationsException e) {
@@ -238,6 +263,12 @@
         }
         
     }
+
+
+    public static ObjectName getObjectName(Class clazz, String poolName) throws MalformedObjectNameException {
+        ObjectName oname = new ObjectName(ConnectionPool.POOL_JMX_TYPE_PREFIX+clazz.getName()+",name=" + poolName);
+        return oname;
+    }
     
     protected void registerJmx() {
         try {
@@ -245,23 +276,15 @@
             if (isNotifyPool()) {
                 
             } else if (getCompositeType()!=null) {
-                ObjectName oname = new ObjectName(ConnectionPool.POOL_JMX_TYPE_PREFIX+"SlowQueryReport"+",name=" + poolName);
-                Registry registry = Registry.getRegistry(null, null);
-                registry.loadDescriptors(getClass().getPackage().getName(),getClass().getClassLoader());
-                ManagedBean managed = registry.findManagedBean(this.getClass().getName());
-                DynamicMBean mbean = managed!=null?managed.createMBean(this):null;
-                if (mbean!=null && mbeans.putIfAbsent(poolName, mbean)==null) {
-                    registry.getMBeanServer().registerMBean( mbean, oname);
-                } else if (mbean==null){
-                    log.warn(SlowQueryReport.class.getName()+ "- No JMX support, unable to initiate Tomcat JMX. This requires the system to run inside the Tomcat container.");
+                ObjectName oname = getObjectName(getClass(),poolName);
+                if (mbeans.putIfAbsent(poolName, this)==null) {
+                    ManagementFactory.getPlatformMBeanServer().registerMBean(this, oname);
                 }
             } else {
                 log.warn(SlowQueryReport.class.getName()+ "- No JMX support, composite type was not found.");
             }
         } catch (MalformedObjectNameException e) {
             log.error("Jmx registration failed, no JMX data will be exposed for the query stats.",e);
-        } catch (InstanceNotFoundException e) {
-            log.error("Jmx registration failed, no JMX data will be exposed for the query stats.",e);
         } catch (RuntimeOperationsException e) {
             log.error("Jmx registration failed, no JMX data will be exposed for the query stats.",e);
         } catch (MBeanException e) {
@@ -272,4 +295,16 @@
             log.error("Jmx registration failed, no JMX data will be exposed for the query stats.",e);
         }
     }
+    
+    @Override
+    public void setProperties(Map<String, InterceptorProperty> properties) {
+        super.setProperties(properties);
+        final String threshold = "notifyPool";
+        InterceptorProperty p1 = properties.get(threshold);
+        if (p1!=null) {
+            this.setNotifyPool(Boolean.parseBoolean(p1.getValue()));
+        }
+    }
+
+
 }

Added: tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmxMBean.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmxMBean.java?rev=792340&view=auto
==============================================================================
--- tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmxMBean.java (added)
+++ tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmxMBean.java Wed Jul  8 22:34:40 2009
@@ -0,0 +1,23 @@
+/* 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.tomcat.jdbc.pool.interceptor;
+
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.OpenDataException;
+
+public interface SlowQueryReportJmxMBean {
+    public CompositeData[] getSlowQueriesCD() throws OpenDataException;
+}

Propchange: tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmxMBean.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: tomcat/trunk/modules/jdbc-pool/resources/MANIFEST.MF
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/resources/MANIFEST.MF?rev=792340&r1=792339&r2=792340&view=diff
==============================================================================
--- tomcat/trunk/modules/jdbc-pool/resources/MANIFEST.MF (original)
+++ tomcat/trunk/modules/jdbc-pool/resources/MANIFEST.MF Wed Jul  8 22:34:40 2009
@@ -19,5 +19,4 @@
   javax.management.openmbean;version="0",
   javax.naming;version="0",
   javax.sql;version="0",
-  org.apache.juli.logging;version="[6.0.18, 7.0.0)",
-  org.apache.tomcat.util.modeler;version="[6.0.18, 7.0.0)"
+  org.apache.juli.logging;version="[6.0.18, 7.0.0)"

Modified: tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/CreateTestTable.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/CreateTestTable.java?rev=792340&r1=792339&r2=792340&view=diff
==============================================================================
--- tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/CreateTestTable.java (original)
+++ tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/CreateTestTable.java Wed Jul  8 22:34:40 2009
@@ -25,12 +25,12 @@
 
 public class CreateTestTable extends DefaultTestCase {
     
-    public static final boolean recreate = Boolean.getBoolean("recreate");
+    public static volatile boolean recreate = Boolean.getBoolean("recreate");
     
     public CreateTestTable(String name) {
         super(name);
     }
-    
+
     public void testCreateTestTable() throws Exception {
         this.init();
         Connection con = datasource.getConnection();
@@ -73,7 +73,7 @@
         }
         PreparedStatement ps = con.prepareStatement(insert);
         ps.setQueryTimeout(0);
-        for (int i=testCheckData(); i<1000000; i++) {
+        for (int i=testCheckData(); i<100000; i++) {
             ps.setInt(1,i);
             String s = getRandom();
             ps.setString(2, s);
@@ -107,5 +107,11 @@
         }
         return s.toString();
     }
+    
+    public static void main(String[] args) throws Exception {
+        recreate = true;
+        CreateTestTable test = new CreateTestTable("CreateTestTable");
+        test.testPopulateData();
+    }
 
 }

Modified: tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestSlowQueryReport.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestSlowQueryReport.java?rev=792340&r1=792339&r2=792340&view=diff
==============================================================================
--- tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestSlowQueryReport.java (original)
+++ tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestSlowQueryReport.java Wed Jul  8 22:34:40 2009
@@ -16,6 +16,7 @@
  */
 package org.apache.tomcat.jdbc.test;
 
+import java.lang.management.ManagementFactory;
 import java.sql.CallableStatement;
 import java.sql.Connection;
 import java.sql.PreparedStatement;
@@ -23,8 +24,13 @@
 import java.sql.Statement;
 import java.util.Map;
 
+import javax.management.AttributeChangeNotification;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+
 import org.apache.tomcat.jdbc.pool.ConnectionPool;
 import org.apache.tomcat.jdbc.pool.interceptor.SlowQueryReport;
+import org.apache.tomcat.jdbc.pool.interceptor.SlowQueryReportJmx;
 
 public class TestSlowQueryReport extends DefaultTestCase {
 
@@ -74,6 +80,56 @@
         assertNull(SlowQueryReport.getPoolStats(pool.getName()));
     }
 
+    public void testSlowSqlJmx() throws Exception {
+        int count = 1;
+        this.init();
+        this.datasource.setMaxActive(1);
+        this.datasource.setJdbcInterceptors(SlowQueryReportJmx.class.getName()+"(threshold=50,notifyPool=false)");
+        Connection con = this.datasource.getConnection();
+        String slowSql = "select count(1) from test where val1 like 'ewq%eq'";
+        for (int i=0; i<count; i++) {
+            Statement st = con.createStatement();
+            ResultSet rs = st.executeQuery(slowSql);
+            rs.close();
+            st.close();
+        }
+        Map<String,SlowQueryReport.QueryStats> map = SlowQueryReport.getPoolStats(datasource.getPool().getName());
+        assertNotNull(map);
+        assertEquals(1,map.size());
+        String key = map.keySet().iterator().next();
+        SlowQueryReport.QueryStats stats = map.get(key);
+        System.out.println("Stats:"+stats);
+        ClientListener listener = new ClientListener();
+        ConnectionPool pool = datasource.getPool();
+        ManagementFactory.getPlatformMBeanServer().addNotificationListener(
+                SlowQueryReportJmx.getObjectName(SlowQueryReportJmx.class, pool.getName()), 
+                listener,
+                null,
+                null);
+        
+        for (int i=0; i<count; i++) {
+            PreparedStatement st = con.prepareStatement(slowSql);
+            ResultSet rs = st.executeQuery();
+            rs.close();
+            st.close();
+        }
+        System.out.println("Stats:"+stats);
+        
+        for (int i=0; i<count; i++) {
+            CallableStatement st = con.prepareCall(slowSql);
+            ResultSet rs = st.executeQuery();
+            rs.close();
+            st.close();
+        }
+        System.out.println("Stats:"+stats);
+        assertEquals("Expecting to have received "+(2*count)+" notifications.",2*count, listener.notificationCount);
+        con.close();
+        tearDown();
+        //make sure we actually did clean up when the pool closed
+        assertNull(SlowQueryReport.getPoolStats(pool.getName()));
+    }
+
+    
     public void testFastSql() throws Exception {
         int count = 3;
         this.init();
@@ -125,7 +181,29 @@
         con.close();
         tearDown();
         assertNull(SlowQueryReport.getPoolStats(pool.getName()));
-    }    
+    }   
+    
+    
+    public class ClientListener implements NotificationListener {
+        volatile int notificationCount = 0;
+        public void handleNotification(Notification notification,
+                                       Object handback) {
+            notificationCount++;
+            System.out.println("\nReceived notification:");
+            System.out.println("\tClassName: " + notification.getClass().getName());
+            System.out.println("\tSource: " + notification.getSource());
+            System.out.println("\tType: " + notification.getType());
+            System.out.println("\tMessage: " + notification.getMessage());
+            if (notification instanceof AttributeChangeNotification) {
+                AttributeChangeNotification acn =
+                    (AttributeChangeNotification) notification;
+                System.out.println("\tAttributeName: " + acn.getAttributeName());
+                System.out.println("\tAttributeType: " + acn.getAttributeType());
+                System.out.println("\tNewValue: " + acn.getNewValue());
+                System.out.println("\tOldValue: " + acn.getOldValue());
+            }
+        }
+    }
 
 
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org