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 2018/03/12 15:00:33 UTC
[15/32] tomee git commit: TOMEE-2172 Squashed commit of the following:
TOMEE-2172 Squashed commit of the following:
commit 98141ca28da6411e8b12c54eeb084019f9716dce
Author: Jonathan Gallimore <jo...@jrg.me.uk>
Date: Tue Feb 20 14:55:22 2018 +0000
Add test
commit 628798d93a973708c720c531a0fc4eb2284392b4
Author: Jonathan Gallimore <jo...@jrg.me.uk>
Date: Tue Feb 20 14:40:07 2018 +0000
Ensure instances are returned to the pool / discarded correctly if the transaction times out
Project: http://git-wip-us.apache.org/repos/asf/tomee/repo
Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/069c8a34
Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/069c8a34
Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/069c8a34
Branch: refs/heads/fb_tomee8
Commit: 069c8a34601259bfcb4692a3a0f10d60187b63b8
Parents: 53e21ef
Author: Jonathan Gallimore <jo...@jrg.me.uk>
Authored: Tue Feb 20 15:15:33 2018 +0000
Committer: Jonathan Gallimore <jo...@jrg.me.uk>
Committed: Tue Feb 20 15:16:20 2018 +0000
----------------------------------------------------------------------
.../openejb/core/mdb/MdbInstanceManager.java | 50 +++---
.../openejb/core/mdb/MdbPoolContainer.java | 8 +-
.../mdb/TxTimeoutPoolEndpointHandlerTest.java | 167 +++++++++++++++++++
3 files changed, 201 insertions(+), 24 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tomee/blob/069c8a34/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/MdbInstanceManager.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/MdbInstanceManager.java b/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/MdbInstanceManager.java
index a74dd03..23a460f 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/MdbInstanceManager.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/MdbInstanceManager.java
@@ -29,10 +29,7 @@ import org.apache.openejb.core.ThreadContext;
import org.apache.openejb.core.interceptor.InterceptorData;
import org.apache.openejb.core.interceptor.InterceptorStack;
import org.apache.openejb.loader.Options;
-import org.apache.openejb.monitoring.LocalMBeanServer;
-import org.apache.openejb.monitoring.ManagedMBean;
-import org.apache.openejb.monitoring.ObjectNameBuilder;
-import org.apache.openejb.monitoring.StatsInterceptor;
+import org.apache.openejb.monitoring.*;
import org.apache.openejb.spi.SecurityService;
import org.apache.openejb.util.DaemonThreadFactory;
import org.apache.openejb.util.Duration;
@@ -205,21 +202,21 @@ public class MdbInstanceManager {
data.setBaseContext(mdbContext);
beanContext.setContainerData(data);
+ final MBeanServer server = LocalMBeanServer.get();
+
+ final ObjectNameBuilder jmxName = new ObjectNameBuilder("openejb.management");
+ jmxName.set("J2EEServer", "openejb");
+ jmxName.set("J2EEApplication", null);
+ jmxName.set("EJBModule", beanContext.getModuleID());
+ jmxName.set("MessageDrivenBean", beanContext.getEjbName());
+ jmxName.set("j2eeType", "");
+ jmxName.set("name", beanContext.getEjbName());
+
// Create stats interceptor
if (StatsInterceptor.isStatsActivated()) {
final StatsInterceptor stats = new StatsInterceptor(beanContext.getBeanClass());
beanContext.addFirstSystemInterceptor(stats);
- final MBeanServer server = LocalMBeanServer.get();
-
- final ObjectNameBuilder jmxName = new ObjectNameBuilder("openejb.management");
- jmxName.set("J2EEServer", "openejb");
- jmxName.set("J2EEApplication", null);
- jmxName.set("EJBModule", beanContext.getModuleID());
- jmxName.set("MessageDrivenBean", beanContext.getEjbName());
- jmxName.set("j2eeType", "");
- jmxName.set("name", beanContext.getEjbName());
-
// register the invocation stats interceptor
try {
final ObjectName objectName = jmxName.set("j2eeType", "Invocations").build();
@@ -256,12 +253,12 @@ public class MdbInstanceManager {
logger.info("Not auto-activating endpoint for " + beanContext.getDeploymentID());
}
- String jmxName = beanContext.getActivationProperties().get("MdbJMXControl");
- if (jmxName == null) {
- jmxName = "true";
+ String jmxControlName = beanContext.getActivationProperties().get("MdbJMXControl");
+ if (jmxControlName == null) {
+ jmxControlName = "true";
}
- addJMxControl(beanContext, jmxName, activationContext);
+ addJMxControl(beanContext, jmxControlName, activationContext);
} catch (final ResourceException e) {
throw new OpenEJBException(e);
@@ -278,10 +275,22 @@ public class MdbInstanceManager {
try {
es.awaitTermination(5, TimeUnit.MINUTES);
} catch (final InterruptedException e) {
- logger.error("can't fill the stateless pool", e);
+ logger.error("can't fill the message driven bean pool", e);
}
}
+ // register the pool
+ try {
+ final ObjectName objectName = jmxName.set("j2eeType", "Pool").build();
+ if (server.isRegistered(objectName)) {
+ server.unregisterMBean(objectName);
+ }
+ server.registerMBean(new ManagedMBean(data.pool), objectName);
+ data.add(objectName);
+ } catch (final Exception e) {
+ logger.error("Unable to register MBean ", e);
+ }
+
data.getPool().start();
}
@@ -497,7 +506,7 @@ public class MdbInstanceManager {
instance.setPoolEntry(entry);
}
} catch (final TimeoutException e) {
- final String msg = "No instances available in Session Bean pool. Waited " + data.getAccessTimeout().toString();
+ final String msg = "No instances available in Message Driven Bean pool. Waited " + data.getAccessTimeout().toString();
final ConcurrentAccessTimeoutException timeoutException = new ConcurrentAccessTimeoutException(msg);
timeoutException.fillInStackTrace();
throw new ApplicationException(timeoutException);
@@ -688,5 +697,4 @@ public class MdbInstanceManager {
this.baseContext = baseContext;
}
}
-
}
http://git-wip-us.apache.org/repos/asf/tomee/blob/069c8a34/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/MdbPoolContainer.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/MdbPoolContainer.java b/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/MdbPoolContainer.java
index 4b3ac2d..d8d50b2 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/MdbPoolContainer.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/MdbPoolContainer.java
@@ -419,6 +419,10 @@ public class MdbPoolContainer implements RpcContainer, BaseMdbContainer {
// invoke the tx after method
try {
afterInvoke(mdbCallContext.txPolicy, callContext);
+ } catch (final ApplicationException e) {
+ callContext.setDiscardInstance(true);
+ throw new SystemException("Should never get an Application exception", e);
+ } finally {
if (instance != null) {
if (callContext.isDiscardInstance()) {
this.instanceManager.discardInstance(callContext, instance);
@@ -431,9 +435,7 @@ public class MdbPoolContainer implements RpcContainer, BaseMdbContainer {
}
}
- } catch (final ApplicationException e) {
- throw new SystemException("Should never get an Application exception", e);
- } finally {
+
ThreadContext.exit(mdbCallContext.oldCallContext);
}
}
http://git-wip-us.apache.org/repos/asf/tomee/blob/069c8a34/container/openejb-core/src/test/java/org/apache/openejb/core/mdb/TxTimeoutPoolEndpointHandlerTest.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/test/java/org/apache/openejb/core/mdb/TxTimeoutPoolEndpointHandlerTest.java b/container/openejb-core/src/test/java/org/apache/openejb/core/mdb/TxTimeoutPoolEndpointHandlerTest.java
new file mode 100644
index 0000000..3badf9c
--- /dev/null
+++ b/container/openejb-core/src/test/java/org/apache/openejb/core/mdb/TxTimeoutPoolEndpointHandlerTest.java
@@ -0,0 +1,167 @@
+/*
+ * 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.core.mdb;
+
+import org.apache.openejb.core.mdb.connector.api.InboundListener;
+import org.apache.openejb.core.mdb.connector.api.SampleConnection;
+import org.apache.openejb.core.mdb.connector.api.SampleConnectionFactory;
+import org.apache.openejb.core.mdb.connector.impl.SampleActivationSpec;
+import org.apache.openejb.core.mdb.connector.impl.SampleManagedConnectionFactory;
+import org.apache.openejb.core.mdb.connector.impl.SampleResourceAdapter;
+import org.apache.openejb.jee.MessageDrivenBean;
+import org.apache.openejb.junit.ApplicationComposer;
+import org.apache.openejb.monitoring.LocalMBeanServer;
+import org.apache.openejb.testing.Configuration;
+import org.apache.openejb.testing.Module;
+import org.apache.openejb.testng.PropertiesBuilder;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.Resource;
+import javax.ejb.ActivationConfigProperty;
+import javax.ejb.MessageDriven;
+import javax.jms.Queue;
+import javax.management.ObjectName;
+import java.util.List;
+import java.util.Properties;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
+
+import static org.junit.Assert.*;
+
+@RunWith(ApplicationComposer.class)
+public class TxTimeoutPoolEndpointHandlerTest {
+
+ private static final String TEXT = "foo";
+
+ @Configuration
+ public Properties config() {
+ return new PropertiesBuilder()
+
+ .p("myTransactionManager", "new://TransactionManager?type=TransactionManager")
+ .p("myTransactionManager.defaultTransactionTimeout", "5 seconds")
+
+ .p("sra", "new://Resource?class-name=" + SampleResourceAdapter.class.getName())
+
+ .p("mdbs", "new://Container?type=MESSAGE")
+ .p("mdbs.ResourceAdapter", "sra")
+ .p("mdbs.pool", "true")
+ .p("mdbs.maxSize", "2") // this is deliberately low
+ .p("mdbs.ActivationSpecClass", SampleActivationSpec.class.getName())
+ .p("mdbs.MessageListenerInterface", InboundListener.class.getName())
+
+ .p("cf", "new://Resource?type=" + SampleConnectionFactory.class.getName() + "&class-name=" + SampleManagedConnectionFactory.class.getName())
+ .p("cf.ResourceAdapter", "sra")
+ .p("cf.TransactionSupport", "none")
+ .build();
+ }
+
+ @Module
+ public MessageDrivenBean jar() {
+ return new MessageDrivenBean(Listener.class);
+ }
+
+ @Resource(name = "target")
+ private Queue destination;
+
+ @Resource(name = "cf")
+ private SampleConnectionFactory cf;
+
+ @Before
+ public void resetLatch() {
+ Listener.reset();
+ }
+
+ @Test
+ public void shouldSendMessage() throws Exception {
+ assertNotNull(cf);
+
+ for (int i = 0; i < 5; i++) {
+ final SampleConnection connection = cf.getConnection();
+ try {
+ connection.sendMessage(TEXT);
+ } finally {
+ connection.close();
+ }
+ }
+
+ // start MDB delivery
+ setControl("start");
+
+ assertTrue(Listener.sync());
+ assertEquals(5, Listener.COUNTER.get());
+ }
+
+ private void setControl(final String action) throws Exception {
+ LocalMBeanServer.get().invoke(
+ new ObjectName("default:type=test"),
+ action, new Object[0], new String[0]);
+ }
+
+ @MessageDriven(activationConfig = {
+ @ActivationConfigProperty(propertyName = "DeliveryActive", propertyValue = "false"),
+ @ActivationConfigProperty(propertyName = "MdbJMXControl", propertyValue = "default:type=test")
+ })
+ public static class Listener implements InboundListener {
+ public static CountDownLatch latch;
+ private static final List<Boolean> BOOLEANS = new CopyOnWriteArrayList<Boolean>();
+
+ static final AtomicLong COUNTER = new AtomicLong();
+
+ @PostConstruct
+ public void postConstruct() {
+ COUNTER.incrementAndGet();
+ }
+
+ public static void reset() {
+ latch = new CountDownLatch(100);
+ BOOLEANS.clear();
+ }
+
+ public static boolean sync() throws InterruptedException {
+ latch.await(1, TimeUnit.MINUTES);
+ for (boolean result : BOOLEANS) {
+ if(!result) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public void receiveMessage(String message) {
+ try {
+ boolean ok = TEXT.equals(message);
+ BOOLEANS.add(ok);
+ } finally {
+ latch.countDown();
+ }
+
+ // this should be long enough to make the transaction time out
+ try {
+ Thread.sleep(10000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+}
\ No newline at end of file