Author: rmannibucau
Date: Wed Jan 9 10:02:21 2013
New Revision: 1430756
URL: http://svn.apache.org/viewvc?rev=1430756&view=rev
Log:
OPENEJB-1985 validation of managedconnectionfactory
Modified:
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/resource/GeronimoConnectionManagerFactory.java
Modified:
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
URL:
http://svn.apache.org/viewvc/openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java?rev=1430756&r1=1430755&r2=1430756&view=diff
==============================================================================
---
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
(original)
+++
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
Wed Jan 9 10:02:21 2013
@@ -137,7 +137,6 @@ import javax.naming.InitialContext;
import javax.naming.NameAlreadyBoundException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
-import javax.resource.cci.ConnectionFactory;
import javax.resource.spi.BootstrapContext;
import javax.resource.spi.ConnectionManager;
import javax.resource.spi.ManagedConnectionFactory;
Modified:
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/resource/GeronimoConnectionManagerFactory.java
URL:
http://svn.apache.org/viewvc/openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/resource/GeronimoConnectionManagerFactory.java?rev=1430756&r1=1430755&r2=1430756&view=diff
==============================================================================
---
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/resource/GeronimoConnectionManagerFactory.java
(original)
+++
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/resource/GeronimoConnectionManagerFactory.java
Wed Jan 9 10:02:21 2013
@@ -16,7 +16,16 @@
*/
package org.apache.openejb.resource;
+import
org.apache.geronimo.connector.outbound.AbstractSinglePoolConnectionInterceptor;
+import org.apache.geronimo.connector.outbound.ConnectionInfo;
+import org.apache.geronimo.connector.outbound.ConnectionInterceptor;
+import org.apache.geronimo.connector.outbound.ConnectionReturnAction;
import org.apache.geronimo.connector.outbound.GenericConnectionManager;
+import org.apache.geronimo.connector.outbound.ManagedConnectionInfo;
+import org.apache.geronimo.connector.outbound.MultiPoolConnectionInterceptor;
+import org.apache.geronimo.connector.outbound.SinglePoolConnectionInterceptor;
+import
org.apache.geronimo.connector.outbound.SinglePoolMatchAllConnectionInterceptor;
+import org.apache.geronimo.connector.outbound.SubjectSource;
import
org.apache.geronimo.connector.outbound.connectionmanagerconfig.LocalTransactions;
import org.apache.geronimo.connector.outbound.connectionmanagerconfig.NoPool;
import
org.apache.geronimo.connector.outbound.connectionmanagerconfig.NoTransactions;
@@ -29,8 +38,12 @@ import org.apache.geronimo.transaction.m
import org.apache.geronimo.transaction.manager.RecoverableTransactionManager;
import org.apache.openejb.OpenEJBRuntimeException;
import org.apache.openejb.util.Duration;
+import org.apache.openejb.util.reflection.Reflections;
+import javax.resource.ResourceException;
+import javax.resource.spi.ManagedConnection;
import javax.resource.spi.ManagedConnectionFactory;
+import javax.resource.spi.ValidatingManagedConnectionFactory;
import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
import javax.transaction.InvalidTransactionException;
@@ -39,7 +52,14 @@ import javax.transaction.RollbackExcepti
import javax.transaction.SystemException;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Timer;
+import java.util.TimerTask;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.ReadWriteLock;
public class GeronimoConnectionManagerFactory {
private String name;
@@ -59,10 +79,9 @@ public class GeronimoConnectionManagerFa
private boolean allConnectionsEqual = true;
private int connectionMaxWaitMilliseconds = 5000;
private int connectionMaxIdleMinutes = 15;
+ private int validationInterval = -1;
private ManagedConnectionFactory mcf;
-
-
public ManagedConnectionFactory getMcf() {
return mcf;
}
@@ -175,6 +194,22 @@ public class GeronimoConnectionManagerFa
setConnectionMaxIdleMinutes((int) minutes);
}
+ public int getValidationInterval() {
+ return validationInterval;
+ }
+
+ public void setValidationInterval(int validationInterval) {
+ this.validationInterval = validationInterval;
+ }
+
+ public void setValidationInterval(final Duration validationInterval) {
+ if (validationInterval.getUnit() == null) {
+ validationInterval.setUnit(TimeUnit.MINUTES);
+ }
+ final long minutes =
TimeUnit.MINUTES.convert(validationInterval.getTime(),
validationInterval.getUnit());
+ setValidationInterval((int) minutes);
+ }
+
public GenericConnectionManager create() {
PoolingSupport poolingSupport = createPoolingSupport();
@@ -194,6 +229,13 @@ public class GeronimoConnectionManagerFa
}
tm = new SimpleRecoverableTransactionManager(transactionManager);
}
+
+ if (validationInterval >= 0 && mcf instanceof
ValidatingManagedConnectionFactory) {
+ return new ValidatingGenericConnectionManager(txSupport,
poolingSupport,
+ null, new AutoConnectionTracker(), tm,
+ mcf, name, classLoader, validationInterval);
+ }
+
return new GenericConnectionManager(txSupport, poolingSupport,
null, new AutoConnectionTracker(), tm,
mcf, name, classLoader);
@@ -323,4 +365,114 @@ public class GeronimoConnectionManagerFa
return delegate.suspend();
}
}
+
+ private static class ValidatingGenericConnectionManager extends
GenericConnectionManager {
+ private static final Timer TIMER = new
Timer("ValidatingGenericConnectionManagerTimer", true);
+
+ private final TimerTask validatingTask;
+ private final long validationInterval;
+
+ private final ReadWriteLock lock;
+ private final Object pool;
+
+ public ValidatingGenericConnectionManager(final TransactionSupport
txSupport, final PoolingSupport poolingSupport, final SubjectSource o, final
AutoConnectionTracker autoConnectionTracker, final
RecoverableTransactionManager tm, final ManagedConnectionFactory mcf, final
String name, final ClassLoader classLoader, final long interval) {
+ super(txSupport, poolingSupport, o, autoConnectionTracker, tm,
mcf, name, classLoader);
+ validationInterval = interval;
+
+ final ConnectionInterceptor stack = interceptors.getStack();
+
+ ReadWriteLock foundLock = null;
+ if (stack instanceof AbstractSinglePoolConnectionInterceptor) {
+ try {
+ foundLock = (ReadWriteLock)
AbstractSinglePoolConnectionInterceptor.class.getField("resizeLock").get(stack);
+ } catch (IllegalAccessException e) {
+ // no-op
+ } catch (NoSuchFieldException e) {
+ // no-op
+ }
+ }
+ this.lock = foundLock;
+
+ Object foundPool = null;
+ if (stack instanceof AbstractSinglePoolConnectionInterceptor) {
+ foundPool = Reflections.get(stack, "pool");
+ } else if (stack instanceof MultiPoolConnectionInterceptor) {
+ log.warn("validation on stack " + stack + " not supported");
+ }
+ this.pool = foundPool;
+
+ if (pool != null) {
+ validatingTask = new ValidatingTask(stack, lock, pool);
+ } else {
+ validatingTask = null;
+ }
+ }
+
+ @Override
+ public void doStart() throws Exception {
+ super.doStart();
+ if (validatingTask != null) {
+ TIMER.schedule(validatingTask, validationInterval,
validationInterval);
+ }
+ }
+
+ @Override
+ public void doStop() throws Exception {
+ if (validatingTask != null) {
+ validatingTask.cancel();
+ }
+ super.doStop();
+ }
+
+ private class ValidatingTask extends TimerTask {
+ private final ConnectionInterceptor stack;
+ private final ReadWriteLock lock;
+ private final Object pool;
+
+ public ValidatingTask(final ConnectionInterceptor stack, final
ReadWriteLock lock, final Object pool) {
+ this.stack = stack;
+ this.lock = lock;
+ this.pool = pool;
+ }
+
+ @Override
+ public void run() {
+ if (lock != null) {
+ lock.writeLock().lock();
+ }
+
+ try {
+ final Map<ManagedConnection, ManagedConnectionInfo>
connections;
+ if (stack instanceof SinglePoolConnectionInterceptor) {
+ connections = new HashMap<ManagedConnection,
ManagedConnectionInfo>();
+ for (final ManagedConnectionInfo info :
(List<ManagedConnectionInfo>) pool) {
+ connections.put(info.getManagedConnection(), info);
+ }
+ } else if (stack instanceof
SinglePoolMatchAllConnectionInterceptor) {
+ connections = (Map<ManagedConnection,
ManagedConnectionInfo>) pool;
+ } else {
+ log.warn("stack " + stack + " currently not
supported");
+ return;
+ }
+
+ // destroy invalid connections
+ try {
+ final Set<ManagedConnection> invalids =
ValidatingManagedConnectionFactory.class.cast(getManagedConnectionFactory())
+ .getInvalidConnections(connections.keySet());
+ if (invalids != null) {
+ for (final ManagedConnection invalid : invalids) {
+ stack.returnConnection(new
ConnectionInfo(connections.get(invalid)), ConnectionReturnAction.DESTROY);
+ }
+ }
+ } catch (ResourceException e) {
+ log.error(e.getMessage(), e);
+ }
+ } finally {
+ if (lock != null) {
+ lock.writeLock().unlock();
+ }
+ }
+ }
+ }
+ }
}