You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomee.apache.org by Thiago Veronezi <th...@veronezi.org> on 2015/11/20 21:23:18 UTC
Re: tomee git commit: better cleaning of our thread after execution
Hi Romain,
It looks like this commit breaks the build here...
https://github.com/apache/tomee/blob/master/container/openejb-core/src/main/java/org/apache/openejb/testing/ApplicationComposers.java#L736
Is that right?
Nov 19, 2015 4:34:40 PM org.apache.openejb.util.LogStreamAsync run
INFO: Undeploying app:
/home/buildslave18/slave18/tomee-trunk-ubuntu/build/container/openejb-core/target/AppTests
run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 1.397 sec
<<< FAILURE! - in
org.apache.openejb.junit.ContainerApplicationRuleTest
run(org.apache.openejb.junit.ContainerApplicationRuleTest) Time
elapsed: 1.346 sec <<< ERROR!
java.lang.NullPointerException: null
at org.apache.openejb.testing.ApplicationComposers.deployApp(ApplicationComposers.java:736)
at org.apache.openejb.junit.ApplicationRule$1.evaluate(ApplicationRule.java:45)
at org.apache.openejb.junit.ContainerRule$1.evaluate(ContainerRule.java:45)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:264)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:124)
at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:200)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:153)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103)
On Wed, Nov 18, 2015 at 6:30 PM, <rm...@apache.org> wrote:
> Repository: tomee
> Updated Branches:
> refs/heads/master dd28c89b2 -> 456a16d56
>
>
> better cleaning of our thread after execution
>
>
> Project: http://git-wip-us.apache.org/repos/asf/tomee/repo
> Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/456a16d5
> Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/456a16d5
> Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/456a16d5
>
> Branch: refs/heads/master
> Commit: 456a16d5610e79d3fb2ce57ec2362949bee41378
> Parents: dd28c89
> Author: Romain Manni-Bucau <rm...@gmail.com>
> Authored: Wed Nov 18 15:30:01 2015 -0800
> Committer: Romain Manni-Bucau <rm...@gmail.com>
> Committed: Wed Nov 18 15:30:01 2015 -0800
>
> ----------------------------------------------------------------------
> .../openejb/assembler/classic/Assembler.java | 14 ++
> .../core/security/AbstractSecurityService.java | 8 +-
> .../core/stateless/StatelessContainer.java | 8 +-
> .../stateless/StatelessInstanceManager.java | 26 +++
> .../GeronimoTransactionManagerFactory.java | 32 ++-
> .../openejb/testing/ApplicationComposers.java | 11 +-
> .../activemq/ProperConnectionShutdownTest.java | 227 +++++++++++++++++++
> 7 files changed, 321 insertions(+), 5 deletions(-)
> ----------------------------------------------------------------------
>
>
>
> http://git-wip-us.apache.org/repos/asf/tomee/blob/456a16d5/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
> ----------------------------------------------------------------------
> diff --git
> a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
> b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
> index 69149ef..7064052 100644
> ---
> a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
> +++
> b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
> @@ -1808,6 +1808,20 @@ public class Assembler extends AssemblerTool
> implements org.apache.openejb.spi.A
> systemInstance.removeComponent(EjbResolver.class);
> systemInstance.fireEvent(new AssemblerDestroyed());
> systemInstance.removeObservers();
> +
> + if
> (DestroyableResource.class.isInstance(this.securityService)) {
> +
> DestroyableResource.class.cast(this.securityService).destroyResource();
> + }
> + if
> (DestroyableResource.class.isInstance(this.transactionManager)) {
> +
> DestroyableResource.class.cast(this.transactionManager).destroyResource();
> + }
> +
> + for (final Container c : this.containerSystem.containers()) {
> + if (DestroyableResource.class.isInstance(c)) { // TODO:
> should we use auto closeable there?
> + DestroyableResource.class.cast(c).destroyResource();
> + }
> + }
> +
> SystemInstance.reset();
> } finally {
> l.unlock();
>
>
> http://git-wip-us.apache.org/repos/asf/tomee/blob/456a16d5/container/openejb-core/src/main/java/org/apache/openejb/core/security/AbstractSecurityService.java
> ----------------------------------------------------------------------
> diff --git
> a/container/openejb-core/src/main/java/org/apache/openejb/core/security/AbstractSecurityService.java
> b/container/openejb-core/src/main/java/org/apache/openejb/core/security/AbstractSecurityService.java
> index c894adc..2c1a798 100644
> ---
> a/container/openejb-core/src/main/java/org/apache/openejb/core/security/AbstractSecurityService.java
> +++
> b/container/openejb-core/src/main/java/org/apache/openejb/core/security/AbstractSecurityService.java
> @@ -19,6 +19,7 @@ package org.apache.openejb.core.security;
>
> import org.apache.openejb.BeanContext;
> import org.apache.openejb.InterfaceType;
> +import org.apache.openejb.api.resource.DestroyableResource;
> import org.apache.openejb.core.ThreadContext;
> import org.apache.openejb.core.ThreadContextListener;
> import org.apache.openejb.core.security.jaas.GroupPrincipal;
> @@ -58,7 +59,7 @@ import java.util.concurrent.ConcurrentHashMap;
> * to clients, is mostly secure, and can be deserialized in a client vm
> without
> * addition openejb-core classes.
> */
> -public abstract class AbstractSecurityService implements
> SecurityService<UUID>, ThreadContextListener,
> BasicPolicyConfiguration.RoleResolver {
> +public abstract class AbstractSecurityService implements
> DestroyableResource, SecurityService<UUID>, ThreadContextListener,
> BasicPolicyConfiguration.RoleResolver {
>
> private static final Map<Object, Identity> identities = new
> ConcurrentHashMap<Object, Identity>();
> protected static final ThreadLocal<Identity> clientIdentity = new
> ThreadLocal<Identity>();
> @@ -84,6 +85,11 @@ public abstract class AbstractSecurityService
> implements SecurityService<UUID>,
>
> SystemInstance.get().setComponent(BasicPolicyConfiguration.RoleResolver.class,
> this);
> }
>
> + @Override
> + public void destroyResource() {
> + // no-op
> + }
> +
> public String getRealmName() {
> return realmName;
> }
>
>
> http://git-wip-us.apache.org/repos/asf/tomee/blob/456a16d5/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java
> ----------------------------------------------------------------------
> diff --git
> a/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java
> b/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java
> index 62bee31..11f43e0 100644
> ---
> a/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java
> +++
> b/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java
> @@ -23,6 +23,7 @@ import org.apache.openejb.InterfaceType;
> import org.apache.openejb.OpenEJBException;
> import org.apache.openejb.ProxyInfo;
> import org.apache.openejb.SystemException;
> +import org.apache.openejb.api.resource.DestroyableResource;
> import org.apache.openejb.cdi.CurrentCreationalContext;
> import org.apache.openejb.core.ExceptionType;
> import org.apache.openejb.core.Operation;
> @@ -59,7 +60,7 @@ import static
> org.apache.openejb.core.transaction.EjbTransactionUtil.handleSyste
> /**
> * @org.apache.xbean.XBean element="statelessContainer"
> */
> -public class StatelessContainer implements
> org.apache.openejb.RpcContainer {
> +public class StatelessContainer implements
> org.apache.openejb.RpcContainer, DestroyableResource {
>
> private final ConcurrentMap<Class<?>, List<Method>> interceptorCache
> = new ConcurrentHashMap<Class<?>, List<Method>>();
> private final StatelessInstanceManager instanceManager;
> @@ -325,4 +326,9 @@ public class StatelessContainer implements
> org.apache.openejb.RpcContainer {
> }
> return annotated;
> }
> +
> + @Override
> + public void destroyResource() {
> + this.instanceManager.destroy();
> + }
> }
>
>
> http://git-wip-us.apache.org/repos/asf/tomee/blob/456a16d5/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java
> ----------------------------------------------------------------------
> diff --git
> a/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java
> b/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java
> index aa6617c..c8986f7 100644
> ---
> a/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java
> +++
> b/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java
> @@ -70,6 +70,9 @@ import java.util.concurrent.ThreadFactory;
> import java.util.concurrent.ThreadPoolExecutor;
> import java.util.concurrent.TimeUnit;
> import java.util.concurrent.TimeoutException;
> +import java.util.logging.Level;
> +
> +import static java.util.concurrent.TimeUnit.MILLISECONDS;
>
> public class StatelessInstanceManager {
> private static final Logger logger =
> Logger.getInstance(LogCategory.OPENEJB,
> "org.apache.openejb.util.resources");
> @@ -168,6 +171,29 @@ public class StatelessInstanceManager {
> }
> }
>
> + public void destroy() {
> + if (executor != null) {
> + executor.shutdown();
> + try {
> + if (!executor.awaitTermination(10000, MILLISECONDS)) {
> +
> java.util.logging.Logger.getLogger(this.getClass().getName()).log(Level.WARNING,
> getClass().getSimpleName() + " pool timeout expired");
> + }
> + } catch (final InterruptedException e) {
> + Thread.interrupted();
> + }
> + }
> + if (scheduledExecutor != null) {
> + scheduledExecutor.shutdown();
> + try {
> + if (!scheduledExecutor.awaitTermination(10000,
> MILLISECONDS)) {
> +
> java.util.logging.Logger.getLogger(this.getClass().getName()).log(Level.WARNING,
> getClass().getSimpleName() + " pool timeout expired");
> + }
> + } catch (final InterruptedException e) {
> + Thread.interrupted();
> + }
> + }
> + }
> +
> /**
> * Removes an instance from the pool and returns it for use
> * by the container in business methods.
>
>
> http://git-wip-us.apache.org/repos/asf/tomee/blob/456a16d5/container/openejb-core/src/main/java/org/apache/openejb/resource/GeronimoTransactionManagerFactory.java
> ----------------------------------------------------------------------
> diff --git
> a/container/openejb-core/src/main/java/org/apache/openejb/resource/GeronimoTransactionManagerFactory.java
> b/container/openejb-core/src/main/java/org/apache/openejb/resource/GeronimoTransactionManagerFactory.java
> index 9681b92..5facdd4 100644
> ---
> a/container/openejb-core/src/main/java/org/apache/openejb/resource/GeronimoTransactionManagerFactory.java
> +++
> b/container/openejb-core/src/main/java/org/apache/openejb/resource/GeronimoTransactionManagerFactory.java
> @@ -19,8 +19,10 @@
> package org.apache.openejb.resource;
>
> import org.apache.geronimo.transaction.log.HOWLLog;
> +import
> org.apache.geronimo.transaction.manager.ExponentialtIntervalRetryScheduler;
> import org.apache.geronimo.transaction.manager.GeronimoTransactionManager;
> import org.apache.geronimo.transaction.manager.TransactionLog;
> +import org.apache.geronimo.transaction.manager.TransactionManagerImpl;
> import org.apache.geronimo.transaction.manager.WrapperNamedXAResource;
> import org.apache.geronimo.transaction.manager.XidFactory;
> import org.apache.geronimo.transaction.manager.XidFactoryImpl;
> @@ -29,12 +31,16 @@ import org.apache.openejb.api.jmx.Description;
> import org.apache.openejb.api.jmx.MBean;
> import org.apache.openejb.api.jmx.ManagedAttribute;
> import org.apache.openejb.api.jmx.ManagedOperation;
> +import org.apache.openejb.api.resource.DestroyableResource;
> import org.apache.openejb.loader.SystemInstance;
> import org.apache.openejb.monitoring.LocalMBeanServer;
> import org.apache.openejb.monitoring.ObjectNameBuilder;
> import org.apache.openejb.util.Duration;
>
> +import javax.transaction.xa.XAException;
> import javax.transaction.xa.XAResource;
> +import java.lang.reflect.Field;
> +import java.util.Timer;
> import java.util.concurrent.TimeUnit;
>
> /**
> @@ -102,7 +108,7 @@ public class GeronimoTransactionManagerFactory {
> ((HOWLLog) txLog).doStart();
> }
>
> - final GeronimoTransactionManager geronimoTransactionManager = new
> GeronimoTransactionManager(defaultTransactionTimeoutSeconds, xidFactory,
> txLog);
> + final GeronimoTransactionManager geronimoTransactionManager = new
> DestroyableTransactionManager(defaultTransactionTimeoutSeconds, xidFactory,
> txLog);
> final ObjectNameBuilder jmxName = new
> ObjectNameBuilder("openejb.management")
> .set("j2eeType", "TransactionManager");
> LocalMBeanServer.registerDynamicWrapperSilently(
> @@ -112,6 +118,30 @@ public class GeronimoTransactionManagerFactory {
> return geronimoTransactionManager;
> }
>
> + public static class DestroyableTransactionManager extends
> GeronimoTransactionManager implements DestroyableResource {
> + public DestroyableTransactionManager(final int
> defaultTransactionTimeoutSeconds, final XidFactory xidFactory, final
> TransactionLog transactionLog) throws XAException {
> + super(defaultTransactionTimeoutSeconds, xidFactory,
> transactionLog);
> + }
> +
> + @Override
> + public void destroyResource() {
> + // try to clean up
> + try {
> + final Field f =
> TransactionManagerImpl.class.getDeclaredField("retryScheduler");
> + f.setAccessible(true);
> + final ExponentialtIntervalRetryScheduler rs =
> ExponentialtIntervalRetryScheduler.class.cast(f.get(this));
> +
> + final Field t =
> ExponentialtIntervalRetryScheduler.class.getDeclaredField("timer");
> + t.setAccessible(true);
> +
> + final Timer timer = Timer.class.cast(t.get(rs));
> + timer.cancel();
> + } catch (final Throwable notImportant) {
> + // no-op
> + }
> + }
> + }
> +
> public static class GeronimoXAResourceWrapper implements
> XAResourceWrapper {
> public XAResource wrap(final XAResource xaResource, final String
> name) {
> return new WrapperNamedXAResource(xaResource, name);
>
>
> http://git-wip-us.apache.org/repos/asf/tomee/blob/456a16d5/container/openejb-core/src/main/java/org/apache/openejb/testing/ApplicationComposers.java
> ----------------------------------------------------------------------
> diff --git
> a/container/openejb-core/src/main/java/org/apache/openejb/testing/ApplicationComposers.java
> b/container/openejb-core/src/main/java/org/apache/openejb/testing/ApplicationComposers.java
> index 4b83058..ef07bf9 100644
> ---
> a/container/openejb-core/src/main/java/org/apache/openejb/testing/ApplicationComposers.java
> +++
> b/container/openejb-core/src/main/java/org/apache/openejb/testing/ApplicationComposers.java
> @@ -182,7 +182,10 @@ public class ApplicationComposers {
> testClassFinders.put(this, new ClassFinder(ancestors(klass))); //
> using this temporary since we don't have yet the instance
> if (additionalModules != null) {
> for (final Object o : additionalModules) {
> - testClassFinders.put(o, new
> ClassFinder(ancestors(o.getClass())));
> + final Class<?> aClass = o.getClass();
> + if (aClass != klass) {
> + testClassFinders.put(o, new
> ClassFinder(ancestors(aClass)));
> + }
> }
> }
>
> @@ -349,7 +352,11 @@ public class ApplicationComposers {
> annotatedMethods = newAnnotatedMethods;
> map.put(key, annotatedMethods);
> } else {
> - annotatedMethods.addAll(newAnnotatedMethods);
> + for (final Method m : newAnnotatedMethods) {
> + if (!annotatedMethods.contains(m)) {
> + annotatedMethods.add(m);
> + }
> + }
> }
> }
> return map;
>
>
> http://git-wip-us.apache.org/repos/asf/tomee/blob/456a16d5/container/openejb-core/src/test/java/org/apache/openejb/resource/activemq/ProperConnectionShutdownTest.java
> ----------------------------------------------------------------------
> diff --git
> a/container/openejb-core/src/test/java/org/apache/openejb/resource/activemq/ProperConnectionShutdownTest.java
> b/container/openejb-core/src/test/java/org/apache/openejb/resource/activemq/ProperConnectionShutdownTest.java
> new file mode 100644
> index 0000000..49d9a27
> --- /dev/null
> +++
> b/container/openejb-core/src/test/java/org/apache/openejb/resource/activemq/ProperConnectionShutdownTest.java
> @@ -0,0 +1,227 @@
> +/**
> + *
> + * 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.activemq;
> +
> +import org.apache.openejb.jee.WebApp;
> +import org.apache.openejb.junit.DeployApplication;
> +import org.apache.openejb.testing.ApplicationComposers;
> +import org.apache.openejb.testing.Classes;
> +import org.apache.openejb.testing.Configuration;
> +import org.apache.openejb.testing.Module;
> +import org.apache.openejb.testng.PropertiesBuilder;
> +import org.apache.openejb.util.Join;
> +import org.apache.openejb.util.NetworkUtil;
> +import org.junit.Ignore;
> +import org.junit.Test;
> +import org.junit.runners.model.Statement;
> +
> +import javax.annotation.Resource;
> +import javax.ejb.EJB;
> +import javax.ejb.Stateless;
> +import javax.jms.Connection;
> +import javax.jms.ConnectionFactory;
> +import javax.jms.DeliveryMode;
> +import javax.jms.JMSException;
> +import javax.jms.MessageConsumer;
> +import javax.jms.MessageProducer;
> +import javax.jms.Queue;
> +import javax.jms.Session;
> +import javax.jms.TextMessage;
> +import java.util.Locale;
> +import java.util.Properties;
> +import java.util.concurrent.atomic.AtomicReference;
> +
> +import static org.junit.Assert.assertEquals;
> +import static org.junit.Assert.assertTrue;
> +
> +// inspired from MessagingBeanTest in examples
> +public class ProperConnectionShutdownTest {
> + @Test
> + @Ignore("https://issues.apache.org/jira/browse/AMQ-6051")
> + public void run() throws Throwable {
> + final Thread[] threadsBefore = listThreads();
> + final AtomicReference<Thread[]> threadWhile = new
> AtomicReference<>();
> +
> + // run test
> + final Statement testInContainer = new Statement() {
> + @Override
> + public void evaluate() throws Throwable {
> + messages.sendMessage("Hello World!");
> + messages.sendMessage("How are you?");
> +
> + threadWhile.set(listThreads());
> +
> + messages.sendMessage("Still spinning?");
> +
> + assertEquals(messages.receiveMessage(), "Hello World!");
> + assertEquals(messages.receiveMessage(), "How are you?");
> + assertEquals(messages.receiveMessage(), "Still
> spinning?");
> +
> + /* TODO: activate it when AMQ-6051 is fixed
> +
> + // all worked, now hold a connection
> + new Thread(new Runnable() { // not daemon!
> + @Override
> + public void run() {
> + messages.blockConnection(); // oops, I forgot to
> close it
> + }
> + }).start();
> + */
> + }
> + };
> + new DeployApplication(this, testInContainer, new
> ApplicationComposers(this)).evaluate();
> +
> + Thread.sleep(2250); // AMQ state (started) polling for transport
> thread is 1s
> + while (Join.join("", listThreads()).contains("ActiveMQ Session
> Task")) { // let few sec to AMQ to leave the holding task
> + Thread.sleep(1000);
> + }
> +
> + // ensure no connection are leaking
> + final Thread[] threadsAfter = listThreads();
> +
> + int countAMQ = 0;
> + int countOthers = 0;
> + for (final Thread t : threadsAfter) {
> + if (!t.isAlive()) {
> + continue;
> + }
> + if (t.getName().contains("AMQ") ||
> t.getName().toLowerCase(Locale.ENGLISH).contains("activemq")) {
> + countAMQ++;
> + } else {
> + countOthers++;
> + }
> + }
> +
> + final String debugMessage = Join.join(", ", threadsAfter);
> +
> + assertEquals(debugMessage, 0, countAMQ);
> +
> + // geronimo libs spawn 2 threads we know: PoolIdleReleaseTimer
> and CurrentTime so we can get initial + 2 threads there
> + assertTrue(debugMessage, countOthers <= threadsBefore.length + 2);
> + }
> +
> + private Thread[] listThreads() {
> + final Thread[] threads = new Thread[Thread.activeCount()];
> + final int count = Thread.enumerate(threads);
> + if (count < threads.length) {
> + final Thread[] copy = new Thread[count];
> + System.arraycopy(threads, 0, copy, 0, count);
> + return copy;
> + }
> + return threads;
> + }
> +
> + @EJB
> + private Messages messages;
> +
> + @Configuration
> + public Properties config() {
> + return new PropertiesBuilder()
> + .p("Default JMS Resource Adapter.BrokerXmlConfig",
> "broker:(tcp://localhost:" + NetworkUtil.getNextAvailablePort() +
> ")?useJmx=false")
> + .build();
> + }
> +
> + @Module
> + @Classes(innerClassesAsBean = true)
> + public WebApp app() {
> + return new WebApp();
> + }
> +
> + @Stateless
> + public static class Messages {
> +
> + @Resource
> + private ConnectionFactory connectionFactory;
> +
> + @Resource
> + private Queue chatQueue;
> +
> + public void sendMessage(String text) throws JMSException {
> +
> + Connection connection = null;
> + Session session = null;
> +
> + try {
> + connection = connectionFactory.createConnection();
> + connection.start();
> +
> + // Create a Session
> + session = connection.createSession(false,
> Session.AUTO_ACKNOWLEDGE);
> +
> + // Create a MessageProducer from the Session to the Topic
> or Queue
> + MessageProducer producer =
> session.createProducer(chatQueue);
> + producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
> +
> + // Create a message
> + TextMessage message = session.createTextMessage(text);
> +
> + // Tell the producer to send the message
> + producer.send(message);
> + } finally {
> + // Clean up
> + if (session != null) {
> + session.close();
> + }
> + if (connection != null) {
> + connection.close();
> + }
> + }
> + }
> +
> + public String receiveMessage() throws JMSException {
> +
> + Connection connection = null;
> + Session session = null;
> + MessageConsumer consumer = null;
> + try {
> + connection = connectionFactory.createConnection();
> + connection.start();
> +
> + // Create a Session
> + session = connection.createSession(false,
> Session.AUTO_ACKNOWLEDGE);
> +
> + // Create a MessageConsumer from the Session to the Topic
> or Queue
> + consumer = session.createConsumer(chatQueue);
> +
> + // Wait for a message
> + TextMessage message = (TextMessage)
> consumer.receive(1000);
> +
> + return message.getText();
> + } finally {
> + if (consumer != null) {
> + consumer.close();
> + }
> + if (session != null) {
> + session.close();
> + }
> + if (connection != null) {
> + connection.close();
> + }
> + }
> +
> + }
> +
> + public void blockConnection() {
> + try {
> + connectionFactory.createConnection();
> + } catch (final JMSException e) {
> + throw new IllegalStateException(e);
> + }
> + }
> + }
> +}
>
>
Re: tomee git commit: better cleaning of our thread after execution
Posted by Romain Manni-Bucau <rm...@gmail.com>.
should be fine now, thanks for the heads up
Romain Manni-Bucau
@rmannibucau | Blog | Github | LinkedIn | Tomitriber
2015-11-20 12:23 GMT-08:00 Thiago Veronezi <th...@veronezi.org>:
> Hi Romain,
> It looks like this commit breaks the build here...
>
> https://github.com/apache/tomee/blob/master/container/openejb-core/src/main/java/org/apache/openejb/testing/ApplicationComposers.java#L736
>
> Is that right?
>
> Nov 19, 2015 4:34:40 PM org.apache.openejb.util.LogStreamAsync run
> INFO: Undeploying app:
> /home/buildslave18/slave18/tomee-trunk-ubuntu/build/container/openejb-core/target/AppTests
> run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 1.397 sec
> <<< FAILURE! - in
> org.apache.openejb.junit.ContainerApplicationRuleTest
> run(org.apache.openejb.junit.ContainerApplicationRuleTest) Time
> elapsed: 1.346 sec <<< ERROR!
> java.lang.NullPointerException: null
> at org.apache.openejb.testing.ApplicationComposers.deployApp(ApplicationComposers.java:736)
> at org.apache.openejb.junit.ApplicationRule$1.evaluate(ApplicationRule.java:45)
> at org.apache.openejb.junit.ContainerRule$1.evaluate(ContainerRule.java:45)
> at org.junit.rules.RunRules.evaluate(RunRules.java:20)
> at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
> at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
> at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
> at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
> at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
> at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
> at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
> at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
> at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
> at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:264)
> at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153)
> at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:124)
> at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:200)
> at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:153)
> at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103)
>
>
>
>
> On Wed, Nov 18, 2015 at 6:30 PM, <rm...@apache.org> wrote:
>
>> Repository: tomee
>> Updated Branches:
>> refs/heads/master dd28c89b2 -> 456a16d56
>>
>>
>> better cleaning of our thread after execution
>>
>>
>> Project: http://git-wip-us.apache.org/repos/asf/tomee/repo
>> Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/456a16d5
>> Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/456a16d5
>> Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/456a16d5
>>
>> Branch: refs/heads/master
>> Commit: 456a16d5610e79d3fb2ce57ec2362949bee41378
>> Parents: dd28c89
>> Author: Romain Manni-Bucau <rm...@gmail.com>
>> Authored: Wed Nov 18 15:30:01 2015 -0800
>> Committer: Romain Manni-Bucau <rm...@gmail.com>
>> Committed: Wed Nov 18 15:30:01 2015 -0800
>>
>> ----------------------------------------------------------------------
>> .../openejb/assembler/classic/Assembler.java | 14 ++
>> .../core/security/AbstractSecurityService.java | 8 +-
>> .../core/stateless/StatelessContainer.java | 8 +-
>> .../stateless/StatelessInstanceManager.java | 26 +++
>> .../GeronimoTransactionManagerFactory.java | 32 ++-
>> .../openejb/testing/ApplicationComposers.java | 11 +-
>> .../activemq/ProperConnectionShutdownTest.java | 227 +++++++++++++++++++
>> 7 files changed, 321 insertions(+), 5 deletions(-)
>> ----------------------------------------------------------------------
>>
>>
>>
>> http://git-wip-us.apache.org/repos/asf/tomee/blob/456a16d5/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
>> ----------------------------------------------------------------------
>> diff --git
>> a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
>> b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
>> index 69149ef..7064052 100644
>> ---
>> a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
>> +++
>> b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
>> @@ -1808,6 +1808,20 @@ public class Assembler extends AssemblerTool
>> implements org.apache.openejb.spi.A
>> systemInstance.removeComponent(EjbResolver.class);
>> systemInstance.fireEvent(new AssemblerDestroyed());
>> systemInstance.removeObservers();
>> +
>> + if
>> (DestroyableResource.class.isInstance(this.securityService)) {
>> +
>> DestroyableResource.class.cast(this.securityService).destroyResource();
>> + }
>> + if
>> (DestroyableResource.class.isInstance(this.transactionManager)) {
>> +
>> DestroyableResource.class.cast(this.transactionManager).destroyResource();
>> + }
>> +
>> + for (final Container c : this.containerSystem.containers()) {
>> + if (DestroyableResource.class.isInstance(c)) { // TODO:
>> should we use auto closeable there?
>> + DestroyableResource.class.cast(c).destroyResource();
>> + }
>> + }
>> +
>> SystemInstance.reset();
>> } finally {
>> l.unlock();
>>
>>
>> http://git-wip-us.apache.org/repos/asf/tomee/blob/456a16d5/container/openejb-core/src/main/java/org/apache/openejb/core/security/AbstractSecurityService.java
>> ----------------------------------------------------------------------
>> diff --git
>> a/container/openejb-core/src/main/java/org/apache/openejb/core/security/AbstractSecurityService.java
>> b/container/openejb-core/src/main/java/org/apache/openejb/core/security/AbstractSecurityService.java
>> index c894adc..2c1a798 100644
>> ---
>> a/container/openejb-core/src/main/java/org/apache/openejb/core/security/AbstractSecurityService.java
>> +++
>> b/container/openejb-core/src/main/java/org/apache/openejb/core/security/AbstractSecurityService.java
>> @@ -19,6 +19,7 @@ package org.apache.openejb.core.security;
>>
>> import org.apache.openejb.BeanContext;
>> import org.apache.openejb.InterfaceType;
>> +import org.apache.openejb.api.resource.DestroyableResource;
>> import org.apache.openejb.core.ThreadContext;
>> import org.apache.openejb.core.ThreadContextListener;
>> import org.apache.openejb.core.security.jaas.GroupPrincipal;
>> @@ -58,7 +59,7 @@ import java.util.concurrent.ConcurrentHashMap;
>> * to clients, is mostly secure, and can be deserialized in a client vm
>> without
>> * addition openejb-core classes.
>> */
>> -public abstract class AbstractSecurityService implements
>> SecurityService<UUID>, ThreadContextListener,
>> BasicPolicyConfiguration.RoleResolver {
>> +public abstract class AbstractSecurityService implements
>> DestroyableResource, SecurityService<UUID>, ThreadContextListener,
>> BasicPolicyConfiguration.RoleResolver {
>>
>> private static final Map<Object, Identity> identities = new
>> ConcurrentHashMap<Object, Identity>();
>> protected static final ThreadLocal<Identity> clientIdentity = new
>> ThreadLocal<Identity>();
>> @@ -84,6 +85,11 @@ public abstract class AbstractSecurityService
>> implements SecurityService<UUID>,
>>
>> SystemInstance.get().setComponent(BasicPolicyConfiguration.RoleResolver.class,
>> this);
>> }
>>
>> + @Override
>> + public void destroyResource() {
>> + // no-op
>> + }
>> +
>> public String getRealmName() {
>> return realmName;
>> }
>>
>>
>> http://git-wip-us.apache.org/repos/asf/tomee/blob/456a16d5/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java
>> ----------------------------------------------------------------------
>> diff --git
>> a/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java
>> b/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java
>> index 62bee31..11f43e0 100644
>> ---
>> a/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java
>> +++
>> b/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java
>> @@ -23,6 +23,7 @@ import org.apache.openejb.InterfaceType;
>> import org.apache.openejb.OpenEJBException;
>> import org.apache.openejb.ProxyInfo;
>> import org.apache.openejb.SystemException;
>> +import org.apache.openejb.api.resource.DestroyableResource;
>> import org.apache.openejb.cdi.CurrentCreationalContext;
>> import org.apache.openejb.core.ExceptionType;
>> import org.apache.openejb.core.Operation;
>> @@ -59,7 +60,7 @@ import static
>> org.apache.openejb.core.transaction.EjbTransactionUtil.handleSyste
>> /**
>> * @org.apache.xbean.XBean element="statelessContainer"
>> */
>> -public class StatelessContainer implements
>> org.apache.openejb.RpcContainer {
>> +public class StatelessContainer implements
>> org.apache.openejb.RpcContainer, DestroyableResource {
>>
>> private final ConcurrentMap<Class<?>, List<Method>> interceptorCache
>> = new ConcurrentHashMap<Class<?>, List<Method>>();
>> private final StatelessInstanceManager instanceManager;
>> @@ -325,4 +326,9 @@ public class StatelessContainer implements
>> org.apache.openejb.RpcContainer {
>> }
>> return annotated;
>> }
>> +
>> + @Override
>> + public void destroyResource() {
>> + this.instanceManager.destroy();
>> + }
>> }
>>
>>
>> http://git-wip-us.apache.org/repos/asf/tomee/blob/456a16d5/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java
>> ----------------------------------------------------------------------
>> diff --git
>> a/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java
>> b/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java
>> index aa6617c..c8986f7 100644
>> ---
>> a/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java
>> +++
>> b/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java
>> @@ -70,6 +70,9 @@ import java.util.concurrent.ThreadFactory;
>> import java.util.concurrent.ThreadPoolExecutor;
>> import java.util.concurrent.TimeUnit;
>> import java.util.concurrent.TimeoutException;
>> +import java.util.logging.Level;
>> +
>> +import static java.util.concurrent.TimeUnit.MILLISECONDS;
>>
>> public class StatelessInstanceManager {
>> private static final Logger logger =
>> Logger.getInstance(LogCategory.OPENEJB,
>> "org.apache.openejb.util.resources");
>> @@ -168,6 +171,29 @@ public class StatelessInstanceManager {
>> }
>> }
>>
>> + public void destroy() {
>> + if (executor != null) {
>> + executor.shutdown();
>> + try {
>> + if (!executor.awaitTermination(10000, MILLISECONDS)) {
>> +
>> java.util.logging.Logger.getLogger(this.getClass().getName()).log(Level.WARNING,
>> getClass().getSimpleName() + " pool timeout expired");
>> + }
>> + } catch (final InterruptedException e) {
>> + Thread.interrupted();
>> + }
>> + }
>> + if (scheduledExecutor != null) {
>> + scheduledExecutor.shutdown();
>> + try {
>> + if (!scheduledExecutor.awaitTermination(10000,
>> MILLISECONDS)) {
>> +
>> java.util.logging.Logger.getLogger(this.getClass().getName()).log(Level.WARNING,
>> getClass().getSimpleName() + " pool timeout expired");
>> + }
>> + } catch (final InterruptedException e) {
>> + Thread.interrupted();
>> + }
>> + }
>> + }
>> +
>> /**
>> * Removes an instance from the pool and returns it for use
>> * by the container in business methods.
>>
>>
>> http://git-wip-us.apache.org/repos/asf/tomee/blob/456a16d5/container/openejb-core/src/main/java/org/apache/openejb/resource/GeronimoTransactionManagerFactory.java
>> ----------------------------------------------------------------------
>> diff --git
>> a/container/openejb-core/src/main/java/org/apache/openejb/resource/GeronimoTransactionManagerFactory.java
>> b/container/openejb-core/src/main/java/org/apache/openejb/resource/GeronimoTransactionManagerFactory.java
>> index 9681b92..5facdd4 100644
>> ---
>> a/container/openejb-core/src/main/java/org/apache/openejb/resource/GeronimoTransactionManagerFactory.java
>> +++
>> b/container/openejb-core/src/main/java/org/apache/openejb/resource/GeronimoTransactionManagerFactory.java
>> @@ -19,8 +19,10 @@
>> package org.apache.openejb.resource;
>>
>> import org.apache.geronimo.transaction.log.HOWLLog;
>> +import
>> org.apache.geronimo.transaction.manager.ExponentialtIntervalRetryScheduler;
>> import org.apache.geronimo.transaction.manager.GeronimoTransactionManager;
>> import org.apache.geronimo.transaction.manager.TransactionLog;
>> +import org.apache.geronimo.transaction.manager.TransactionManagerImpl;
>> import org.apache.geronimo.transaction.manager.WrapperNamedXAResource;
>> import org.apache.geronimo.transaction.manager.XidFactory;
>> import org.apache.geronimo.transaction.manager.XidFactoryImpl;
>> @@ -29,12 +31,16 @@ import org.apache.openejb.api.jmx.Description;
>> import org.apache.openejb.api.jmx.MBean;
>> import org.apache.openejb.api.jmx.ManagedAttribute;
>> import org.apache.openejb.api.jmx.ManagedOperation;
>> +import org.apache.openejb.api.resource.DestroyableResource;
>> import org.apache.openejb.loader.SystemInstance;
>> import org.apache.openejb.monitoring.LocalMBeanServer;
>> import org.apache.openejb.monitoring.ObjectNameBuilder;
>> import org.apache.openejb.util.Duration;
>>
>> +import javax.transaction.xa.XAException;
>> import javax.transaction.xa.XAResource;
>> +import java.lang.reflect.Field;
>> +import java.util.Timer;
>> import java.util.concurrent.TimeUnit;
>>
>> /**
>> @@ -102,7 +108,7 @@ public class GeronimoTransactionManagerFactory {
>> ((HOWLLog) txLog).doStart();
>> }
>>
>> - final GeronimoTransactionManager geronimoTransactionManager = new
>> GeronimoTransactionManager(defaultTransactionTimeoutSeconds, xidFactory,
>> txLog);
>> + final GeronimoTransactionManager geronimoTransactionManager = new
>> DestroyableTransactionManager(defaultTransactionTimeoutSeconds, xidFactory,
>> txLog);
>> final ObjectNameBuilder jmxName = new
>> ObjectNameBuilder("openejb.management")
>> .set("j2eeType", "TransactionManager");
>> LocalMBeanServer.registerDynamicWrapperSilently(
>> @@ -112,6 +118,30 @@ public class GeronimoTransactionManagerFactory {
>> return geronimoTransactionManager;
>> }
>>
>> + public static class DestroyableTransactionManager extends
>> GeronimoTransactionManager implements DestroyableResource {
>> + public DestroyableTransactionManager(final int
>> defaultTransactionTimeoutSeconds, final XidFactory xidFactory, final
>> TransactionLog transactionLog) throws XAException {
>> + super(defaultTransactionTimeoutSeconds, xidFactory,
>> transactionLog);
>> + }
>> +
>> + @Override
>> + public void destroyResource() {
>> + // try to clean up
>> + try {
>> + final Field f =
>> TransactionManagerImpl.class.getDeclaredField("retryScheduler");
>> + f.setAccessible(true);
>> + final ExponentialtIntervalRetryScheduler rs =
>> ExponentialtIntervalRetryScheduler.class.cast(f.get(this));
>> +
>> + final Field t =
>> ExponentialtIntervalRetryScheduler.class.getDeclaredField("timer");
>> + t.setAccessible(true);
>> +
>> + final Timer timer = Timer.class.cast(t.get(rs));
>> + timer.cancel();
>> + } catch (final Throwable notImportant) {
>> + // no-op
>> + }
>> + }
>> + }
>> +
>> public static class GeronimoXAResourceWrapper implements
>> XAResourceWrapper {
>> public XAResource wrap(final XAResource xaResource, final String
>> name) {
>> return new WrapperNamedXAResource(xaResource, name);
>>
>>
>> http://git-wip-us.apache.org/repos/asf/tomee/blob/456a16d5/container/openejb-core/src/main/java/org/apache/openejb/testing/ApplicationComposers.java
>> ----------------------------------------------------------------------
>> diff --git
>> a/container/openejb-core/src/main/java/org/apache/openejb/testing/ApplicationComposers.java
>> b/container/openejb-core/src/main/java/org/apache/openejb/testing/ApplicationComposers.java
>> index 4b83058..ef07bf9 100644
>> ---
>> a/container/openejb-core/src/main/java/org/apache/openejb/testing/ApplicationComposers.java
>> +++
>> b/container/openejb-core/src/main/java/org/apache/openejb/testing/ApplicationComposers.java
>> @@ -182,7 +182,10 @@ public class ApplicationComposers {
>> testClassFinders.put(this, new ClassFinder(ancestors(klass))); //
>> using this temporary since we don't have yet the instance
>> if (additionalModules != null) {
>> for (final Object o : additionalModules) {
>> - testClassFinders.put(o, new
>> ClassFinder(ancestors(o.getClass())));
>> + final Class<?> aClass = o.getClass();
>> + if (aClass != klass) {
>> + testClassFinders.put(o, new
>> ClassFinder(ancestors(aClass)));
>> + }
>> }
>> }
>>
>> @@ -349,7 +352,11 @@ public class ApplicationComposers {
>> annotatedMethods = newAnnotatedMethods;
>> map.put(key, annotatedMethods);
>> } else {
>> - annotatedMethods.addAll(newAnnotatedMethods);
>> + for (final Method m : newAnnotatedMethods) {
>> + if (!annotatedMethods.contains(m)) {
>> + annotatedMethods.add(m);
>> + }
>> + }
>> }
>> }
>> return map;
>>
>>
>> http://git-wip-us.apache.org/repos/asf/tomee/blob/456a16d5/container/openejb-core/src/test/java/org/apache/openejb/resource/activemq/ProperConnectionShutdownTest.java
>> ----------------------------------------------------------------------
>> diff --git
>> a/container/openejb-core/src/test/java/org/apache/openejb/resource/activemq/ProperConnectionShutdownTest.java
>> b/container/openejb-core/src/test/java/org/apache/openejb/resource/activemq/ProperConnectionShutdownTest.java
>> new file mode 100644
>> index 0000000..49d9a27
>> --- /dev/null
>> +++
>> b/container/openejb-core/src/test/java/org/apache/openejb/resource/activemq/ProperConnectionShutdownTest.java
>> @@ -0,0 +1,227 @@
>> +/**
>> + *
>> + * 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.activemq;
>> +
>> +import org.apache.openejb.jee.WebApp;
>> +import org.apache.openejb.junit.DeployApplication;
>> +import org.apache.openejb.testing.ApplicationComposers;
>> +import org.apache.openejb.testing.Classes;
>> +import org.apache.openejb.testing.Configuration;
>> +import org.apache.openejb.testing.Module;
>> +import org.apache.openejb.testng.PropertiesBuilder;
>> +import org.apache.openejb.util.Join;
>> +import org.apache.openejb.util.NetworkUtil;
>> +import org.junit.Ignore;
>> +import org.junit.Test;
>> +import org.junit.runners.model.Statement;
>> +
>> +import javax.annotation.Resource;
>> +import javax.ejb.EJB;
>> +import javax.ejb.Stateless;
>> +import javax.jms.Connection;
>> +import javax.jms.ConnectionFactory;
>> +import javax.jms.DeliveryMode;
>> +import javax.jms.JMSException;
>> +import javax.jms.MessageConsumer;
>> +import javax.jms.MessageProducer;
>> +import javax.jms.Queue;
>> +import javax.jms.Session;
>> +import javax.jms.TextMessage;
>> +import java.util.Locale;
>> +import java.util.Properties;
>> +import java.util.concurrent.atomic.AtomicReference;
>> +
>> +import static org.junit.Assert.assertEquals;
>> +import static org.junit.Assert.assertTrue;
>> +
>> +// inspired from MessagingBeanTest in examples
>> +public class ProperConnectionShutdownTest {
>> + @Test
>> + @Ignore("https://issues.apache.org/jira/browse/AMQ-6051")
>> + public void run() throws Throwable {
>> + final Thread[] threadsBefore = listThreads();
>> + final AtomicReference<Thread[]> threadWhile = new
>> AtomicReference<>();
>> +
>> + // run test
>> + final Statement testInContainer = new Statement() {
>> + @Override
>> + public void evaluate() throws Throwable {
>> + messages.sendMessage("Hello World!");
>> + messages.sendMessage("How are you?");
>> +
>> + threadWhile.set(listThreads());
>> +
>> + messages.sendMessage("Still spinning?");
>> +
>> + assertEquals(messages.receiveMessage(), "Hello World!");
>> + assertEquals(messages.receiveMessage(), "How are you?");
>> + assertEquals(messages.receiveMessage(), "Still
>> spinning?");
>> +
>> + /* TODO: activate it when AMQ-6051 is fixed
>> +
>> + // all worked, now hold a connection
>> + new Thread(new Runnable() { // not daemon!
>> + @Override
>> + public void run() {
>> + messages.blockConnection(); // oops, I forgot to
>> close it
>> + }
>> + }).start();
>> + */
>> + }
>> + };
>> + new DeployApplication(this, testInContainer, new
>> ApplicationComposers(this)).evaluate();
>> +
>> + Thread.sleep(2250); // AMQ state (started) polling for transport
>> thread is 1s
>> + while (Join.join("", listThreads()).contains("ActiveMQ Session
>> Task")) { // let few sec to AMQ to leave the holding task
>> + Thread.sleep(1000);
>> + }
>> +
>> + // ensure no connection are leaking
>> + final Thread[] threadsAfter = listThreads();
>> +
>> + int countAMQ = 0;
>> + int countOthers = 0;
>> + for (final Thread t : threadsAfter) {
>> + if (!t.isAlive()) {
>> + continue;
>> + }
>> + if (t.getName().contains("AMQ") ||
>> t.getName().toLowerCase(Locale.ENGLISH).contains("activemq")) {
>> + countAMQ++;
>> + } else {
>> + countOthers++;
>> + }
>> + }
>> +
>> + final String debugMessage = Join.join(", ", threadsAfter);
>> +
>> + assertEquals(debugMessage, 0, countAMQ);
>> +
>> + // geronimo libs spawn 2 threads we know: PoolIdleReleaseTimer
>> and CurrentTime so we can get initial + 2 threads there
>> + assertTrue(debugMessage, countOthers <= threadsBefore.length + 2);
>> + }
>> +
>> + private Thread[] listThreads() {
>> + final Thread[] threads = new Thread[Thread.activeCount()];
>> + final int count = Thread.enumerate(threads);
>> + if (count < threads.length) {
>> + final Thread[] copy = new Thread[count];
>> + System.arraycopy(threads, 0, copy, 0, count);
>> + return copy;
>> + }
>> + return threads;
>> + }
>> +
>> + @EJB
>> + private Messages messages;
>> +
>> + @Configuration
>> + public Properties config() {
>> + return new PropertiesBuilder()
>> + .p("Default JMS Resource Adapter.BrokerXmlConfig",
>> "broker:(tcp://localhost:" + NetworkUtil.getNextAvailablePort() +
>> ")?useJmx=false")
>> + .build();
>> + }
>> +
>> + @Module
>> + @Classes(innerClassesAsBean = true)
>> + public WebApp app() {
>> + return new WebApp();
>> + }
>> +
>> + @Stateless
>> + public static class Messages {
>> +
>> + @Resource
>> + private ConnectionFactory connectionFactory;
>> +
>> + @Resource
>> + private Queue chatQueue;
>> +
>> + public void sendMessage(String text) throws JMSException {
>> +
>> + Connection connection = null;
>> + Session session = null;
>> +
>> + try {
>> + connection = connectionFactory.createConnection();
>> + connection.start();
>> +
>> + // Create a Session
>> + session = connection.createSession(false,
>> Session.AUTO_ACKNOWLEDGE);
>> +
>> + // Create a MessageProducer from the Session to the Topic
>> or Queue
>> + MessageProducer producer =
>> session.createProducer(chatQueue);
>> + producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
>> +
>> + // Create a message
>> + TextMessage message = session.createTextMessage(text);
>> +
>> + // Tell the producer to send the message
>> + producer.send(message);
>> + } finally {
>> + // Clean up
>> + if (session != null) {
>> + session.close();
>> + }
>> + if (connection != null) {
>> + connection.close();
>> + }
>> + }
>> + }
>> +
>> + public String receiveMessage() throws JMSException {
>> +
>> + Connection connection = null;
>> + Session session = null;
>> + MessageConsumer consumer = null;
>> + try {
>> + connection = connectionFactory.createConnection();
>> + connection.start();
>> +
>> + // Create a Session
>> + session = connection.createSession(false,
>> Session.AUTO_ACKNOWLEDGE);
>> +
>> + // Create a MessageConsumer from the Session to the Topic
>> or Queue
>> + consumer = session.createConsumer(chatQueue);
>> +
>> + // Wait for a message
>> + TextMessage message = (TextMessage)
>> consumer.receive(1000);
>> +
>> + return message.getText();
>> + } finally {
>> + if (consumer != null) {
>> + consumer.close();
>> + }
>> + if (session != null) {
>> + session.close();
>> + }
>> + if (connection != null) {
>> + connection.close();
>> + }
>> + }
>> +
>> + }
>> +
>> + public void blockConnection() {
>> + try {
>> + connectionFactory.createConnection();
>> + } catch (final JMSException e) {
>> + throw new IllegalStateException(e);
>> + }
>> + }
>> + }
>> +}
>>
>>