You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by rm...@apache.org on 2015/08/09 20:51:37 UTC

tomee git commit: TOMEE-1625 ResetOnError datasource flag + fixing datasource proxy unwrapping - was working for only 1 level

Repository: tomee
Updated Branches:
  refs/heads/master e3411b761 -> 5fdf755bf


TOMEE-1625 ResetOnError datasource flag + fixing datasource proxy unwrapping - was working for only 1 level


Project: http://git-wip-us.apache.org/repos/asf/tomee/repo
Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/5fdf755b
Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/5fdf755b
Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/5fdf755b

Branch: refs/heads/master
Commit: 5fdf755bfa31c037caaa353b0e916e428b803436
Parents: e3411b7
Author: Romain Manni-Bucau <rm...@starbucks.com>
Authored: Sun Aug 9 11:51:02 2015 -0700
Committer: Romain Manni-Bucau <rm...@starbucks.com>
Committed: Sun Aug 9 11:51:02 2015 -0700

----------------------------------------------------------------------
 container/openejb-core/pom.xml                  |   1 +
 .../resource/jdbc/DataSourceFactory.java        | 128 +++++++++++----
 .../resource/jdbc/DelegatableHandler.java       |  24 +++
 .../jdbc/FlushableDataSourceHandler.java        |  86 ++++++----
 .../jdbc/ResettableDataSourceHandler.java       | 156 ++++++++++++++++++
 .../jdbc/dbcp/DbcpDataSourceCreator.java        |   2 +-
 .../resource/jdbc/driver/AlternativeDriver.java |   5 +-
 .../jdbc/logging/LoggingSqlDataSource.java      |  10 +-
 .../jdbc/pool/DefaultDataSourceCreator.java     |  11 --
 .../jdbc/pool/PoolDataSourceCreator.java        |   8 +-
 .../openejb/core/singleton/DependsOnTest.java   |   3 +
 .../jdbc/ResettableDataSourceHandlerTest.java   | 159 +++++++++++++++++++
 pom.xml                                         |   2 +-
 .../openejb/bonecp/BoneCPDataSourceCreator.java |   2 +
 tck/cdi-embedded/src/test/resources/failing.xml |   6 +-
 .../tomee/jdbc/TomEEDataSourceCreator.java      |  10 ++
 16 files changed, 530 insertions(+), 83 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tomee/blob/5fdf755b/container/openejb-core/pom.xml
----------------------------------------------------------------------
diff --git a/container/openejb-core/pom.xml b/container/openejb-core/pom.xml
index d29a0bc..df13f18 100644
--- a/container/openejb-core/pom.xml
+++ b/container/openejb-core/pom.xml
@@ -315,6 +315,7 @@
         <version>2.17</version>
         <configuration>
           <reuseForks>false</reuseForks>
+          <forkCount>2</forkCount>
           <testNGArtifactName>none:none</testNGArtifactName>
           <argLine>
             -javaagent:${project.basedir}/target/openejb-javaagent-${project.version}.jar

http://git-wip-us.apache.org/repos/asf/tomee/blob/5fdf755b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/DataSourceFactory.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/DataSourceFactory.java b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/DataSourceFactory.java
index 6f4f113..49b1fb1 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/DataSourceFactory.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/DataSourceFactory.java
@@ -32,10 +32,11 @@ import org.apache.openejb.resource.jdbc.pool.DefaultDataSourceCreator;
 import org.apache.openejb.util.Duration;
 import org.apache.openejb.util.LogCategory;
 import org.apache.openejb.util.Logger;
-import org.apache.openejb.util.PropertiesHelper;
 import org.apache.openejb.util.SuperProperties;
+import org.apache.xbean.recipe.ExecutionContext;
 import org.apache.xbean.recipe.ObjectRecipe;
 import org.apache.xbean.recipe.Option;
+import org.apache.xbean.recipe.Recipe;
 
 import javax.sql.CommonDataSource;
 import javax.sql.DataSource;
@@ -48,8 +49,10 @@ import java.lang.reflect.Proxy;
 import java.sql.Driver;
 import java.sql.SQLException;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Properties;
+import java.util.Set;
 import java.util.TreeMap;
 import java.util.concurrent.TimeUnit;
 
@@ -65,15 +68,17 @@ public class DataSourceFactory {
     public static final String LOG_SQL_PROPERTY = "LogSql";
     public static final String LOG_SQL_PACKAGE_PROPERTY = "LogSqlPackages";
     public static final String FLUSHABLE_PROPERTY = "Flushable";
+    public static final String RESET_PROPERTY = "ResetOnError";
+    public static final String RESET_METHODS_PROPERTY = "ResetOnErrorMethods";
     public static final String GLOBAL_LOG_SQL_PROPERTY = "openejb.jdbc.log";
     public static final String GLOBAL_LOG_SQL_PACKAGE_PROPERTY = "openejb.jdbc.log.packages";
     public static final String GLOBAL_FLUSH_PROPERTY = "openejb.jdbc.flushable";
     public static final String POOL_PROPERTY = "openejb.datasource.pool";
     public static final String DATA_SOURCE_CREATOR_PROP = "DataSourceCreator";
 
-    private static final Map<CommonDataSource, AlternativeDriver> driverByDataSource = new HashMap<CommonDataSource, AlternativeDriver>();
+    private static final Map<CommonDataSource, AlternativeDriver> driverByDataSource = new HashMap<>();
 
-    private static final Map<CommonDataSource, DataSourceCreator> creatorByDataSource = new HashMap<CommonDataSource, DataSourceCreator>();
+    private static final Map<CommonDataSource, DataSourceCreator> creatorByDataSource = new HashMap<>();
     private static final Map<String, String> KNOWN_CREATORS = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER) {{
         put("simple", "org.apache.openejb.resource.jdbc.SimpleDataSourceCreator"); // use user provided DS, pooling not supported
         put("dbcp", "org.apache.openejb.resource.jdbc.pool.DefaultDataSourceCreator"); // the original one
@@ -90,20 +95,10 @@ public class DataSourceFactory {
                                           final Duration timeBetweenEvictionRuns,
                                           final Duration minEvictableIdleTime) throws IllegalAccessException, InstantiationException, IOException {
         final Properties properties = asProperties(definition);
+        final Set<String> originalKeys = properties.stringPropertyNames();
 
-        final boolean flushable = SystemInstance.get().getOptions().get(GLOBAL_FLUSH_PROPERTY,
+        boolean flushable = SystemInstance.get().getOptions().get(GLOBAL_FLUSH_PROPERTY,
             "true".equalsIgnoreCase((String) properties.remove(FLUSHABLE_PROPERTY)));
-        final FlushableDataSourceHandler.FlushConfig flushConfig;
-        if (flushable) {
-            properties.remove("flushable"); // don't let it wrap the delegate again
-
-            flushConfig = new FlushableDataSourceHandler.FlushConfig(
-                name, configuredManaged,
-                impl, PropertiesHelper.propertiesToString(properties),
-                maxWaitTime, timeBetweenEvictionRuns, minEvictableIdleTime);
-        } else {
-            flushConfig = null;
-        }
 
         convert(properties, maxWaitTime, "maxWaitTime", "maxWait");
         convert(properties, timeBetweenEvictionRuns, "timeBetweenEvictionRuns", "timeBetweenEvictionRunsMillis");
@@ -139,8 +134,10 @@ public class DataSourceFactory {
             "true".equalsIgnoreCase((String) properties.remove(LOG_SQL_PROPERTY)));
         final String logPackages = SystemInstance.get().getProperty(GLOBAL_LOG_SQL_PACKAGE_PROPERTY, (String) properties.remove(LOG_SQL_PACKAGE_PROPERTY));
         final DataSourceCreator creator = creator(properties.remove(DATA_SOURCE_CREATOR_PROP), logSql);
+        final String resetOnError = (String) properties.remove(RESET_PROPERTY);
+        final String resetMethods = (String) properties.remove(RESET_METHODS_PROPERTY); // before setProperties()
 
-        boolean useContainerLoader = "true".equalsIgnoreCase(SystemInstance.get().getProperty("openejb.resources.use-container-loader", "true")) && (impl == null || impl.getClassLoader() == DataSourceFactory.class.getClassLoader());
+        boolean useContainerLoader = "true".equalsIgnoreCase(SystemInstance.get().getProperty("openejb.resources.use-container-loader", "true")) && impl.getClassLoader() == DataSourceFactory.class.getClassLoader();
         final ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
         if (useContainerLoader) {
             final ClassLoader containerLoader = DataSourceFactory.class.getClassLoader();
@@ -206,11 +203,76 @@ public class DataSourceFactory {
                 driverByDataSource.put(ds, driver);
             }
 
-            if (logSql) {
-                ds = makeItLogging(ds, logPackages);
-            }
-            if (flushable) {
-                ds = makeFlushable(ds, flushConfig);
+            final boolean doResetOnError = resetOnError != null && !"false".equals(resetOnError);
+            if (doResetOnError || logSql || flushable) { // will get proxied
+                ObjectRecipe objectRecipe = null;
+                ResettableDataSourceHandler existingResettableHandler = null;
+                FlushableDataSourceHandler flushableDataSourceHandler = null;
+                if (ExecutionContext.isContextSet()) {
+                    final ExecutionContext context = ExecutionContext.getContext();
+                    final List<Recipe> stack = context.getStack();
+                    if (stack.size() > 0) {
+                        objectRecipe = ObjectRecipe.class.cast(stack.get(0));
+                        existingResettableHandler = ResettableDataSourceHandler.class.cast(objectRecipe.getProperty("resettableHandler"));
+                        flushableDataSourceHandler = FlushableDataSourceHandler.class.cast(objectRecipe.getProperty("flushableHandler"));
+
+                        final Map<String, Object> props = objectRecipe.getProperties();
+                        for (final String key : originalKeys) {
+                            props.remove(key);
+                        }
+
+                        // meta properties, not needed here so gain few cycles removing them
+                        props.remove("properties");
+                        props.remove("Definition");
+                        props.remove("ServiceId");
+                        props.remove("resettableHandler");
+                        props.remove("flushableHandler");
+
+                        //we create a proxy so we cant get txmgr etc in another manner or we cant extend (= break) this method
+                        new ObjectRecipe(ds.getClass()) {{
+                            allow(Option.CASE_INSENSITIVE_PROPERTIES);
+                            allow(Option.IGNORE_MISSING_PROPERTIES);
+                            allow(Option.NAMED_PARAMETERS);
+                            allow(Option.PRIVATE_PROPERTIES);
+                            setAllProperties(props);
+                        }}.setProperties(ds);
+                    }
+                }
+
+                if (logSql) {
+                    ds = makeItLogging(ds, logPackages);
+                }
+
+                final ResettableDataSourceHandler resettableDataSourceHandler;
+                if (doResetOnError) { // needs to be done after flushable
+                    // ensure we reuse the same handle instance otherwise we loose state
+                    resettableDataSourceHandler = existingResettableHandler != null ?
+                        existingResettableHandler :
+                        new ResettableDataSourceHandler(ds, resetOnError, resetMethods);
+                } else {
+                    resettableDataSourceHandler = null;
+                }
+
+                if (flushable || doResetOnError) {
+                    if (flushableDataSourceHandler == null) {
+                        final FlushableDataSourceHandler.FlushConfig flushConfig;
+                        properties.remove("flushable"); // don't let it wrap the delegate again
+
+                        final Map<String, Object> recipeProps = new HashMap<>(objectRecipe == null ? new HashMap<String, Object>() : objectRecipe.getProperties());
+                        recipeProps.remove("properties");
+
+                        flushConfig = new FlushableDataSourceHandler.FlushConfig(recipeProps);
+                        flushableDataSourceHandler = new FlushableDataSourceHandler(ds, flushConfig, resettableDataSourceHandler);
+                    } else {
+                        flushableDataSourceHandler.updateDataSource(ds);
+                    }
+                    ds = makeSerializableFlushableDataSourceProxy(ds, flushableDataSourceHandler);
+                }
+                if (doResetOnError) { // needs to be done after flushable
+                    // ensure we reuse the same handle instance otherwise we loose state
+                    resettableDataSourceHandler.updateDelegate(ds);
+                    ds = makeSerializableFlushableDataSourceProxy(ds, resettableDataSourceHandler);
+                }
             }
 
             return ds;
@@ -221,6 +283,13 @@ public class DataSourceFactory {
         }
     }
 
+    public static CommonDataSource makeSerializableFlushableDataSourceProxy(final CommonDataSource ds, final InvocationHandler handler) {
+        return (CommonDataSource) Proxy.newProxyInstance(
+            Thread.currentThread().getContextClassLoader(),
+            new Class<?>[]{DataSource.class.isInstance(ds) ? DataSource.class : XADataSource.class, Serializable.class, Flushable.class},
+            handler);
+    }
+
     private static boolean basicChecksThatDataSourceCanBeCreatedFromContainerLoader(final Properties properties, final ClassLoader containerLoader) {
         // check basic some classes can be loaded from container otherwise don't force it
         try {
@@ -249,13 +318,6 @@ public class DataSourceFactory {
         return true;
     }
 
-    private static CommonDataSource makeFlushable(final CommonDataSource ds, final FlushableDataSourceHandler.FlushConfig flushConfig) {
-        return (CommonDataSource) Proxy.newProxyInstance(
-            Thread.currentThread().getContextClassLoader(),
-            new Class<?>[]{DataSource.class.isInstance(ds) ? DataSource.class : XADataSource.class, Flushable.class, Serializable.class},
-            new FlushableDataSourceHandler(ds, flushConfig));
-    }
-
     public static void setCreatedWith(final DataSourceCreator creator, final CommonDataSource ds) {
         creatorByDataSource.put(ds, creator);
     }
@@ -364,7 +426,7 @@ public class DataSourceFactory {
     }
 
     public static boolean knows(final Object object) {
-        return object instanceof CommonDataSource && creatorByDataSource.containsKey(realInstance(object));
+        return object instanceof CommonDataSource && creatorByDataSource.containsKey(CommonDataSource.class.cast(realInstance(object)));
     }
 
     // TODO: should we get a get and a clear method instead of a single one?
@@ -405,11 +467,9 @@ public class DataSourceFactory {
 
         Object ds = o;
         while (Proxy.isProxyClass(ds.getClass())) {
-            final InvocationHandler handler = Proxy.getInvocationHandler(o);
-            if (LoggingSqlDataSource.class.isInstance(handler)) {
-                ds = LoggingSqlDataSource.class.cast(handler).getDelegate();
-            } else if (FlushableDataSourceHandler.class.isInstance(handler)) {
-                ds = FlushableDataSourceHandler.class.cast(handler).getDelegate();
+            final InvocationHandler handler = Proxy.getInvocationHandler(ds);
+            if (DelegatableHandler.class.isInstance(handler)) {
+                ds = DelegatableHandler.class.cast(handler).getDelegate();
             } else {
                 break;
             }

http://git-wip-us.apache.org/repos/asf/tomee/blob/5fdf755b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/DelegatableHandler.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/DelegatableHandler.java b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/DelegatableHandler.java
new file mode 100644
index 0000000..d2f9a9d
--- /dev/null
+++ b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/DelegatableHandler.java
@@ -0,0 +1,24 @@
+/*
+ * 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.openejb.resource.jdbc;
+
+import javax.sql.CommonDataSource;
+import java.lang.reflect.InvocationHandler;
+
+public interface DelegatableHandler extends InvocationHandler {
+    CommonDataSource getDelegate();
+}

http://git-wip-us.apache.org/repos/asf/tomee/blob/5fdf755b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/FlushableDataSourceHandler.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/FlushableDataSourceHandler.java b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/FlushableDataSourceHandler.java
index 316565b..811180e 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/FlushableDataSourceHandler.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/FlushableDataSourceHandler.java
@@ -16,38 +16,56 @@
  */
 package org.apache.openejb.resource.jdbc;
 
-import org.apache.openejb.util.Duration;
 import org.apache.openejb.util.LogCategory;
 import org.apache.openejb.util.Logger;
+import org.apache.xbean.recipe.ObjectRecipe;
+import org.apache.xbean.recipe.Option;
 
+import javax.sql.CommonDataSource;
 import java.io.Flushable;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
-import javax.sql.CommonDataSource;
 
-public class FlushableDataSourceHandler implements InvocationHandler {
+public class FlushableDataSourceHandler implements DelegatableHandler {
     private static final Logger LOGGER = Logger.getInstance(LogCategory.OPENEJB, FlushableDataSourceHandler.class);
+    public static final String[] FACTORY_ARGS = new String[]{
+        "ServiceId", "JtaManaged", "JdbcDriver", "Definition", "MaxWaitTime", "TimeBetweenEvictionRuns", "MinEvictableIdleTime"
+    };
 
     private final FlushConfig config;
     private final ReadWriteLock lock = new ReentrantReadWriteLock();
-    private volatile CommonDataSource delegate;
+    private AtomicReference<CommonDataSource> delegate = new AtomicReference<>();
+    private final ResettableDataSourceHandler resettableHandler;
 
-    public FlushableDataSourceHandler(final CommonDataSource original, final FlushConfig config) {
+    public FlushableDataSourceHandler(final CommonDataSource original, final FlushConfig config, final ResettableDataSourceHandler resettableHandler) {
         this.config = config;
-        this.delegate = original;
+        this.delegate.set(original);
+        this.resettableHandler = resettableHandler;
     }
 
     private void createANewDelegate() {
-        final CommonDataSource old = delegate;
+        final CommonDataSource old = delegate.get();
         try {
-            this.delegate = DataSourceFactory.create(config.name, config.configuredManaged, config.impl, config.definition, config.maxWaitTime, config.timeBetweenEvictionRuns, config.minEvictableIdleTime);
+            final ObjectRecipe recipe = new ObjectRecipe(DataSourceFactory.class.getName(), "create", FACTORY_ARGS);
+            recipe.allow(Option.CASE_INSENSITIVE_PROPERTIES);
+            recipe.allow(Option.IGNORE_MISSING_PROPERTIES);
+            recipe.allow(Option.NAMED_PARAMETERS);
+            recipe.allow(Option.PRIVATE_PROPERTIES);
+            recipe.setAllProperties(config.properties);
+
+            recipe.setProperty("resettableHandler", resettableHandler);
+            recipe.setProperty("flushableHandler", this);
+
+            updateDataSource(CommonDataSource.class.cast(recipe.create()));
         } catch (final Exception e) {
             LOGGER.error("Can't recreate the datasource, keeping old one", e);
-            this.delegate = old;
             return;
         }
 
@@ -62,18 +80,27 @@ public class FlushableDataSourceHandler implements InvocationHandler {
 
     @Override
     public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
+        final CommonDataSource actualDelegate = delegate.get();
         if (Object.class == method.getDeclaringClass()) {
             if ("hashCode".equals(method.getName())) {
                 return hashCode();
             }
+            if ("toString".equals(method.getName())) {
+                return "Flushable[" + actualDelegate.toString() + "]";
+            }
         }
         if (Flushable.class == method.getDeclaringClass()) {
             final Lock l = lock.writeLock();
             l.lock();
             try {
                 createANewDelegate();
-                if (Flushable.class.isInstance(delegate)) {
-                    Flushable.class.cast(delegate).flush();
+                if (Flushable.class.isInstance(actualDelegate)) { // these sanity could be enhanced
+                    if (!Proxy.isProxyClass(actualDelegate.getClass()) ||
+                            // reset implies flush so we need to check both
+                            (!FlushableDataSourceHandler.class.isInstance(Proxy.getInvocationHandler(actualDelegate)) &&
+                            !ResettableDataSourceHandler.class.isInstance(Proxy.getInvocationHandler(actualDelegate)))) {
+                        Flushable.class.cast(actualDelegate).flush();
+                    }
                 }
             } finally {
                 l.unlock();
@@ -84,7 +111,7 @@ public class FlushableDataSourceHandler implements InvocationHandler {
         final Lock l = lock.readLock();
         l.lock();
         try {
-            return method.invoke(delegate, args);
+            return method.invoke(getDelegate(), args);
         } catch (final InvocationTargetException ite) {
             throw ite.getCause();
         } finally {
@@ -92,27 +119,30 @@ public class FlushableDataSourceHandler implements InvocationHandler {
         }
     }
 
+    @Override
     public CommonDataSource getDelegate() {
-        return delegate;
+        return delegate.get();
+    }
+
+    public void updateDataSource(final CommonDataSource ds) { // order is important, check DataSourceFactory
+        CommonDataSource current = ds;
+        while (Proxy.isProxyClass(current.getClass())) {
+            final InvocationHandler handler = Proxy.getInvocationHandler(current);
+            if (FlushableDataSourceHandler.class.isInstance(handler) ||
+                ResettableDataSourceHandler.class.isInstance(handler)) {
+                current = DelegatableHandler.class.cast(handler).getDelegate();
+            } else {
+                break;
+            }
+        }
+        delegate.set(current);
     }
 
     public static class FlushConfig {
-        public final String name;
-        public final boolean configuredManaged;
-        public final Class impl;
-        public final String definition;
-        public final Duration maxWaitTime;
-        public final Duration timeBetweenEvictionRuns;
-        public final Duration minEvictableIdleTime;
+        public final Map<String, Object> properties;
 
-        public FlushConfig(final String name, final boolean configuredManaged, final Class impl, final String definition, final Duration maxWaitTime, final Duration timeBetweenEvictionRuns, final Duration minEvictableIdleTime) {
-            this.name = name;
-            this.impl = impl;
-            this.configuredManaged = configuredManaged;
-            this.definition = definition;
-            this.maxWaitTime = maxWaitTime;
-            this.timeBetweenEvictionRuns = timeBetweenEvictionRuns;
-            this.minEvictableIdleTime = minEvictableIdleTime;
+        public FlushConfig(final Map<String, Object> properties) {
+            this.properties = properties;
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/tomee/blob/5fdf755b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/ResettableDataSourceHandler.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/ResettableDataSourceHandler.java b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/ResettableDataSourceHandler.java
new file mode 100644
index 0000000..d69c508
--- /dev/null
+++ b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/ResettableDataSourceHandler.java
@@ -0,0 +1,156 @@
+/*
+ * 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.openejb.resource.jdbc;
+
+import org.apache.openejb.util.LogCategory;
+import org.apache.openejb.util.Logger;
+
+import javax.sql.CommonDataSource;
+import java.io.Flushable;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.sql.SQLException;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+
+import static java.util.Arrays.asList;
+
+public class ResettableDataSourceHandler implements DelegatableHandler {
+    private static final Logger LOGGER = Logger.getInstance(LogCategory.OPENEJB, ResettableDataSourceHandler.class.getName());
+
+    private final AtomicReference<CommonDataSource> delegate = new AtomicReference<>();
+    private final RetryStrategy strategy; // TODO: add pause/exp backoff strategy
+    private Set<String> retryMethods = new HashSet<>();
+
+    public ResettableDataSourceHandler(final CommonDataSource ds, final String value, final String methods) {
+        this.delegate.set(ds);
+
+        if (!"*".equals(methods)) {
+            this.retryMethods.addAll(asList(methods == null ? new String[]{"getConnection", "getXAConnection"} : methods.split(" *, *")));
+        }
+
+        final Runnable recreate = new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    Flushable.class.cast(delegate.get()).flush();
+                } catch (final IOException ioe) {
+                    LOGGER.error("Can't flush connection pool: " + ioe.getMessage());
+                }
+            }
+        };
+
+        RetryStrategy tmp;
+        if (value.equals("true")) {
+            tmp = new CountRetryStrategy(recreate, 1);
+        } else if (value.startsWith("retry(") && value.endsWith(")")) {
+            tmp = new CountRetryStrategy(recreate, Integer.parseInt(value.substring("retry(".length(), value.length() - 1)));
+        } else {
+            try {
+                tmp = new CountRetryStrategy(recreate, Integer.parseInt(value.trim()));
+            } catch (final NumberFormatException nfe) {
+                try {
+                    tmp = RetryStrategy.class.cast(Thread.currentThread().getContextClassLoader().loadClass(value)
+                        .getConstructor(Runnable.class, String.class).newInstance(recreate, value));
+                } catch (final InstantiationException | IllegalAccessException | ClassNotFoundException | NoSuchMethodException | InvocationTargetException e) {
+                    throw new IllegalArgumentException("Unknown retry strategy: " + value, e);
+                }
+            }
+        }
+        strategy = tmp;
+    }
+
+    @Override
+    public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
+        if (Object.class == method.getDeclaringClass() && "toString".equals(method.getName())) {
+            return "Resettable[" + getDelegate().toString() + "]";
+        }
+
+        Result retry = null;
+        do {
+            try {
+                return method.invoke(getDelegate(), args);
+            } catch (final InvocationTargetException ite) {
+                final Throwable cause = ite.getCause();
+                if (SQLException.class.isInstance(cause) && isRetryMethod(method)) {
+                    retry = strategy.shouldRetry(cause, retry);
+                    if (!retry.status) {
+                        throw cause;
+                    } else {
+                        continue;
+                    }
+                }
+                throw cause;
+            }
+        } while (true);
+    }
+
+    private boolean isRetryMethod(final Method method) {
+        return retryMethods.isEmpty() /* wildcard */ || retryMethods.contains(method.getName());
+    }
+
+    @Override
+    public CommonDataSource getDelegate() {
+        return delegate.get();
+    }
+
+    public void updateDelegate(final CommonDataSource ds) {
+        delegate.set(ds);
+    }
+
+    public interface RetryStrategy {
+        Result shouldRetry(Throwable cause, Result previous);
+    }
+
+    public static class Result {
+        private final boolean status;
+
+        public Result(final boolean status) {
+            this.status = status;
+        }
+    }
+
+    private static class CountRetryStrategy implements RetryStrategy {
+        private final Runnable task;
+        private final int max;
+
+        public CountRetryStrategy(final Runnable recreate, final int max) {
+            this.task = recreate;
+            this.max = max;
+        }
+
+        @Override
+        public Result shouldRetry(final Throwable cause, final Result previous) {
+            LOGGER.error("SQLException, resetting the connection pool.", cause);
+
+            final Integer count = previous == null ? 1 : CountResult.class.cast(previous).count + 1;
+            task.run();
+            return new CountResult(count <= max, count);
+        }
+    }
+
+    private static class CountResult extends Result {
+        private int count;
+
+        public CountResult(final boolean status, final int count) {
+            super(status);
+            this.count = count;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/tomee/blob/5fdf755b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/dbcp/DbcpDataSourceCreator.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/dbcp/DbcpDataSourceCreator.java b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/dbcp/DbcpDataSourceCreator.java
index 10be9a8..4e07d84 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/dbcp/DbcpDataSourceCreator.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/dbcp/DbcpDataSourceCreator.java
@@ -24,12 +24,12 @@ import org.apache.openejb.resource.jdbc.managed.xa.ManagedXADataSource;
 import org.apache.openejb.resource.jdbc.pool.PoolDataSourceCreator;
 import org.apache.openejb.resource.jdbc.pool.XADataSourceResource;
 
-import java.util.Properties;
 import javax.sql.CommonDataSource;
 import javax.sql.DataSource;
 import javax.sql.XADataSource;
 import javax.transaction.TransactionManager;
 import javax.transaction.TransactionSynchronizationRegistry;
+import java.util.Properties;
 
 // just a sample showing how to implement a datasourcecreator
 // this one will probably not be used since dbcp has already the integration we need

http://git-wip-us.apache.org/repos/asf/tomee/blob/5fdf755b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/driver/AlternativeDriver.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/driver/AlternativeDriver.java b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/driver/AlternativeDriver.java
index 3c171f7..f2028cd 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/driver/AlternativeDriver.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/driver/AlternativeDriver.java
@@ -115,7 +115,10 @@ public class AlternativeDriver implements Driver {
 
     @Override
     public Connection connect(final String url, final Properties info) throws SQLException {
-        return getDelegate().connect(url, info);
+        if (acceptsURL(url)) {
+            return getDelegate().connect(url, info);
+        }
+        return null;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/tomee/blob/5fdf755b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/logging/LoggingSqlDataSource.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/logging/LoggingSqlDataSource.java b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/logging/LoggingSqlDataSource.java
index 8dbc3d7..96fc62e 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/logging/LoggingSqlDataSource.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/logging/LoggingSqlDataSource.java
@@ -17,14 +17,15 @@
 
 package org.apache.openejb.resource.jdbc.logging;
 
+import org.apache.openejb.resource.jdbc.DelegatableHandler;
+
 import javax.sql.CommonDataSource;
-import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
 import java.sql.Connection;
 
-public class LoggingSqlDataSource implements InvocationHandler {
+public class LoggingSqlDataSource implements DelegatableHandler {
     private static final Class<?>[] INTERFACES = new Class<?>[]{Connection.class};
 
     private final CommonDataSource delegate;
@@ -37,6 +38,10 @@ public class LoggingSqlDataSource implements InvocationHandler {
 
     @Override
     public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
+        if (Object.class == method.getDeclaringClass() && "toString".equals(method.getName())) {
+            return "Logging[" + delegate.toString() + "]";
+        }
+
         final Object result;
         try {
             result = method.invoke(delegate, args);
@@ -51,6 +56,7 @@ public class LoggingSqlDataSource implements InvocationHandler {
         return result;
     }
 
+    @Override
     public CommonDataSource getDelegate() {
         return delegate;
     }

http://git-wip-us.apache.org/repos/asf/tomee/blob/5fdf755b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/pool/DefaultDataSourceCreator.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/pool/DefaultDataSourceCreator.java b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/pool/DefaultDataSourceCreator.java
index 9f5be66..c4dba88 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/pool/DefaultDataSourceCreator.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/pool/DefaultDataSourceCreator.java
@@ -29,7 +29,6 @@ import javax.sql.CommonDataSource;
 import javax.sql.DataSource;
 import java.util.Properties;
 
-// TODO: remove it and replace it with org.apache.openejb.resource.jdbc.dbcp.DbcpDataSourceCreator
 public class DefaultDataSourceCreator extends DbcpDataSourceCreator {
     @Override
     public DataSource managed(final String name, final CommonDataSource ds) {
@@ -69,14 +68,4 @@ public class DefaultDataSourceCreator extends DbcpDataSourceCreator {
         build(BasicManagedDataSource.class, ds, properties);
         return ds;
     }
-
-    @Override
-    public void destroy(final Object object) throws Throwable {
-        ((org.apache.commons.dbcp2.BasicDataSource) object).close();
-    }
-
-    @Override
-    protected void doDestroy(final CommonDataSource dataSource) throws Throwable {
-        ((org.apache.commons.dbcp2.BasicDataSource) dataSource).close();
-    }
 }

http://git-wip-us.apache.org/repos/asf/tomee/blob/5fdf755b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/pool/PoolDataSourceCreator.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/pool/PoolDataSourceCreator.java b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/pool/PoolDataSourceCreator.java
index 31360a7..2929117 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/pool/PoolDataSourceCreator.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/pool/PoolDataSourceCreator.java
@@ -27,15 +27,15 @@ import org.apache.openejb.util.PassthroughFactory;
 import org.apache.xbean.recipe.ObjectRecipe;
 import org.apache.xbean.recipe.Option;
 
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Properties;
 import javax.sql.CommonDataSource;
 import javax.sql.DataSource;
 import javax.sql.XADataSource;
 import javax.transaction.TransactionManager;
 import javax.transaction.TransactionSynchronizationRegistry;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
 
 public abstract class PoolDataSourceCreator implements DataSourceCreator {
     protected final Map<Object, ObjectRecipe> recipes = new HashMap<Object, ObjectRecipe>();

http://git-wip-us.apache.org/repos/asf/tomee/blob/5fdf755b/container/openejb-core/src/test/java/org/apache/openejb/core/singleton/DependsOnTest.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/test/java/org/apache/openejb/core/singleton/DependsOnTest.java b/container/openejb-core/src/test/java/org/apache/openejb/core/singleton/DependsOnTest.java
index 1522337..9005ea8 100644
--- a/container/openejb-core/src/test/java/org/apache/openejb/core/singleton/DependsOnTest.java
+++ b/container/openejb-core/src/test/java/org/apache/openejb/core/singleton/DependsOnTest.java
@@ -33,6 +33,8 @@ import org.apache.openejb.jee.EjbJar;
 import org.apache.openejb.jee.SingletonBean;
 import org.apache.openejb.jee.StatelessBean;
 import org.junit.AfterClass;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
 
 import javax.annotation.PostConstruct;
 import javax.annotation.PreDestroy;
@@ -78,6 +80,7 @@ public class DependsOnTest extends TestCase {
 
         final StatelessSessionContainerInfo statelessContainer = config.configureService(StatelessSessionContainerInfo.class);
         statelessContainer.properties.setProperty("MinSize", "1");
+        statelessContainer.properties.setProperty("MaxSize", "1");
         assembler.createContainer(statelessContainer);
 
         actual.clear();

http://git-wip-us.apache.org/repos/asf/tomee/blob/5fdf755b/container/openejb-core/src/test/java/org/apache/openejb/resource/jdbc/ResettableDataSourceHandlerTest.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/test/java/org/apache/openejb/resource/jdbc/ResettableDataSourceHandlerTest.java b/container/openejb-core/src/test/java/org/apache/openejb/resource/jdbc/ResettableDataSourceHandlerTest.java
new file mode 100644
index 0000000..8eeb5c5
--- /dev/null
+++ b/container/openejb-core/src/test/java/org/apache/openejb/resource/jdbc/ResettableDataSourceHandlerTest.java
@@ -0,0 +1,159 @@
+package org.apache.openejb.resource.jdbc;
+
+import org.apache.openejb.junit.ApplicationComposer;
+import org.apache.openejb.testing.Classes;
+import org.apache.openejb.testing.ContainerProperties;
+import org.apache.openejb.testing.SimpleLog;
+import org.hsqldb.jdbcDriver;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import javax.annotation.Resource;
+import javax.ejb.EJB;
+import javax.ejb.Singleton;
+import javax.sql.DataSource;
+import java.io.Flushable;
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.Driver;
+import java.sql.DriverManager;
+import java.sql.DriverPropertyInfo;
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
+import java.sql.Statement;
+import java.util.Properties;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.logging.Logger;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+@SimpleLog
+@ContainerProperties({
+    @ContainerProperties.Property(name = "db", value = "new://Resource?type=DataSource"),
+    @ContainerProperties.Property(name = "db.ResetOnError", value = "true"), // = retry(1)
+    // @ContainerProperties.Property(name = "db.ResetOnErrorMethods", value = "*"),
+    @ContainerProperties.Property(name = "db.JdbcDriver", value = "org.apache.openejb.resource.jdbc.ResettableDataSourceHandlerTest$DsTestDriver"),
+})
+@Classes(innerClassesAsBean = true)
+@RunWith(ApplicationComposer.class)
+public class ResettableDataSourceHandlerTest {
+    @EJB
+    private DsAccessor accessor;
+
+    @Resource
+    private DataSource ds;
+
+    @Test
+    public void run() throws IOException {
+        actualTest(ds); // no tx
+        Flushable.class.cast(ds).flush(); // ensure we dont reuse previous checks cached connection
+        accessor.doTest(); // tx
+    }
+
+    public static void actualTest(final DataSource ds) {
+        DsTestDriver.getConnectionCount.set(0);
+
+        DsTestDriver.fail = true; // fail first otherwise we can get a cached connection with our test driver - ie hsqldb
+        try {
+            useConnection(ds);
+        } catch (final SQLException e) {
+            // no-op
+        }
+        assertEquals(0, DsTestDriver.getConnectionCount.get());
+
+        DsTestDriver.fail = false;
+        DsTestDriver.resilient = true; // will work since we retry by default
+        try {
+            useConnection(ds);
+        } catch (final SQLException e) {
+            // no-op
+        }
+        assertEquals(1 /* our conn */ + 1 /* the one created to validate the pool */, DsTestDriver.getConnectionCount.get());
+
+        DsTestDriver.resilient = false;
+        try {
+            useConnection(ds);
+            assertEquals(2 /* reuse existing */, DsTestDriver.getConnectionCount.get());
+        } catch (final SQLException e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+    }
+
+    private static void useConnection(final DataSource ds) throws SQLException {
+        try (final Connection connection = ds.getConnection()) {
+            try (final Statement unused = connection.createStatement()) {
+                // just touched a method to force connection init
+            }
+        }
+    }
+
+    @Singleton
+    public static class DsAccessor {
+        @Resource
+        private DataSource ds;
+
+        public void doTest() {
+            actualTest(ds);
+        }
+    }
+
+    public static class DsTestDriver implements Driver {
+        private static volatile boolean fail;
+        private static boolean resilient;
+        private static AtomicInteger getConnectionCount = new AtomicInteger();
+
+        public DsTestDriver() {
+            jdbcDriver.class.getName();
+        }
+
+        @Override
+        public Connection connect(final String url, final Properties info) throws SQLException {
+            if (fail) {
+                throw new SQLException();
+            }
+            if (resilient) {
+                resilient = false;
+                throw new SQLException();
+            }
+
+            getConnectionCount.incrementAndGet();
+            try {
+                return DriverManager.getConnection("jdbc:hsqldb:mem:resettabletest");
+            } catch (final SQLException e) {
+                throw new IllegalStateException(e);
+            }
+        }
+
+        @Override
+        public boolean acceptsURL(final String url) throws SQLException {
+            return true;
+        }
+
+        @Override
+        public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {
+            return new DriverPropertyInfo[0];
+        }
+
+        @Override
+        public int getMajorVersion() {
+            return 0;
+        }
+
+        @Override
+        public int getMinorVersion() {
+            return 0;
+        }
+
+        @Override
+        public boolean jdbcCompliant() {
+            return false;
+        }
+
+        @Override
+        public Logger getParentLogger() throws SQLFeatureNotSupportedException {
+            return null;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/tomee/blob/5fdf755b/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index c83caa9..6e540b1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -95,7 +95,7 @@
     <tomee.version>7.0.0-SNAPSHOT</tomee.version>
 
     <openjpa.version>2.4.0</openjpa.version>
-    <org.apache.openwebbeans.version>1.6.2-SNAPSHOT</org.apache.openwebbeans.version>
+    <org.apache.openwebbeans.version>1.6.2</org.apache.openwebbeans.version>
     <jcs.version>2.0-SNAPSHOT</jcs.version>
 
     <!-- Maven module versions -->

http://git-wip-us.apache.org/repos/asf/tomee/blob/5fdf755b/server/openejb-bonecp/src/main/java/org/apache/openejb/bonecp/BoneCPDataSourceCreator.java
----------------------------------------------------------------------
diff --git a/server/openejb-bonecp/src/main/java/org/apache/openejb/bonecp/BoneCPDataSourceCreator.java b/server/openejb-bonecp/src/main/java/org/apache/openejb/bonecp/BoneCPDataSourceCreator.java
index 2deed33..11c30db 100644
--- a/server/openejb-bonecp/src/main/java/org/apache/openejb/bonecp/BoneCPDataSourceCreator.java
+++ b/server/openejb-bonecp/src/main/java/org/apache/openejb/bonecp/BoneCPDataSourceCreator.java
@@ -69,6 +69,8 @@ public class BoneCPDataSourceCreator extends PoolDataSourceCreator {
         return pool;
     }
 
+
+
     private BoneCPDataSource createPool(final Properties properties) {
         final BoneCPConfig config;
         try {

http://git-wip-us.apache.org/repos/asf/tomee/blob/5fdf755b/tck/cdi-embedded/src/test/resources/failing.xml
----------------------------------------------------------------------
diff --git a/tck/cdi-embedded/src/test/resources/failing.xml b/tck/cdi-embedded/src/test/resources/failing.xml
index ea96a64..11df52f 100644
--- a/tck/cdi-embedded/src/test/resources/failing.xml
+++ b/tck/cdi-embedded/src/test/resources/failing.xml
@@ -16,6 +16,9 @@
   limitations under the License.
   -->
 <suite name="CDI TCK" verbose="0">
+  <listeners>
+    <listener class-name="org.jboss.cdi.tck.impl.testng.SingleTestClassMethodInterceptor"/>
+  </listeners>
   <test name="CDI TCK">
     <!-- runner helping properties
     -ea
@@ -32,7 +35,8 @@
     -Dopenejb.cdi.conversation.http.use-get-parameter=true
     -->
     <classes>
-      <class name="org.jboss.cdi.tck.tests.implementation.simple.lifecycle.SimpleBeanLifecycleTest" />
+      <class name="org.jboss.cdi.tck.tests.context.NormalContextTest" />
+      <class name="org.jboss.cdi.tck.tests.context.ContextDestroysBeansTest" />
     </classes>
   </test>
 </suite>

http://git-wip-us.apache.org/repos/asf/tomee/blob/5fdf755b/tomee/tomee-jdbc/src/main/java/org/apache/tomee/jdbc/TomEEDataSourceCreator.java
----------------------------------------------------------------------
diff --git a/tomee/tomee-jdbc/src/main/java/org/apache/tomee/jdbc/TomEEDataSourceCreator.java b/tomee/tomee-jdbc/src/main/java/org/apache/tomee/jdbc/TomEEDataSourceCreator.java
index cb813ee..388487f 100644
--- a/tomee/tomee-jdbc/src/main/java/org/apache/tomee/jdbc/TomEEDataSourceCreator.java
+++ b/tomee/tomee-jdbc/src/main/java/org/apache/tomee/jdbc/TomEEDataSourceCreator.java
@@ -44,9 +44,19 @@ import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
 import java.sql.SQLException;
 import java.util.Properties;
+import java.util.logging.Logger;
 
 public class TomEEDataSourceCreator extends PoolDataSourceCreator {
     @Override
+    public void resetConnections(final CommonDataSource ds) {
+        if (TomEEDataSource.class.isInstance(ds)) {
+            TomEEDataSource.class.cast(ds).purge();
+        } else {
+            super.resetConnections(ds);
+        }
+    }
+
+    @Override
     public DataSource pool(final String name, final DataSource ds, final Properties properties) {
         final PoolConfiguration config = build(TomEEPoolProperties.class, createProperties(name, properties));
         config.setDataSource(ds);