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, <[email protected]> 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 <[email protected]>
> Authored: Wed Nov 18 15:30:01 2015 -0800
> Committer: Romain Manni-Bucau <[email protected]>
> 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);
> + }
> + }
> + }
> +}
>
>