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 <[email protected]>: > 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); >> + } >> + } >> + } >> +} >> >>
