/*
* 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.activemq.artemis.jms.tests;
import javax.jms.CompletionListener;
import javax.jms.Connection;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.InvalidDestinationException;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.jms.ActiveMQJMSClient;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.core.server.impl.AddressInfo;
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
import org.apache.activemq.artemis.jms.tests.message.SimpleJMSMessage;
import org.apache.activemq.artemis.jms.tests.message.SimpleJMSTextMessage;
import org.apache.activemq.artemis.jms.tests.util.ProxyAssertSupport;
import org.junit.Test;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
public class MessageProducerTest extends JMSTestCase {
@Test
public void testSendForeignWithForeignDestinationSet() throws Exception {
Connection conn = createConnection();
Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer p = sess.createProducer(queue1);
MessageConsumer c = sess.createConsumer(queue1);
conn.start();
Message foreign = new SimpleJMSMessage(new SimpleDestination());
foreign.setJMSDestination(new SimpleDestination());
// the producer destination should override the foreign destination and the send should succeed
p.send(foreign);
Message m = c.receive(1000);
ProxyAssertSupport.assertNotNull(m);
}
private static class SimpleDestination implements Destination, Serializable {
/**
*
*/
private static final long serialVersionUID = -2553676986492799801L;
}
@Test
public void testSendToQueuePersistent() throws Exception {
sendToQueue(true);
}
@Test
public void testSendToQueueNonPersistent() throws Exception {
sendToQueue(false);
}
private void sendToQueue(final boolean persistent) throws Exception {
Connection pconn = null;
Connection cconn = null;
try {
pconn = createConnection();
cconn = createConnection();
Session ps = pconn.createSession(false, Session.AUTO_ACKNOWLEDGE);
Session cs = cconn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer p = ps.createProducer(queue1);
MessageConsumer c = cs.createConsumer(queue1);
cconn.start();
TextMessage m = ps.createTextMessage("test");
p.send(m);
TextMessage r = (TextMessage) c.receive(3000);
ProxyAssertSupport.assertEquals(m.getJMSMessageID(), r.getJMSMessageID());
ProxyAssertSupport.assertEquals("test", r.getText());
} finally {
if (pconn != null) {
pconn.close();
}
if (cconn != null) {
cconn.close();
}
}
}
@Test
public void testTransactedSendPersistent() throws Exception {
transactedSend(true);
}
@Test
public void testTransactedSendNonPersistent() throws Exception {
transactedSend(false);
}
private void transactedSend(final boolean persistent) throws Exception {
Connection pconn = null;
Connection cconn = null;
try {
pconn = createConnection();
cconn = createConnection();
cconn.start();
Session ts = pconn.createSession(true, -1);
Session cs = cconn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer p = ts.createProducer(queue1);
MessageConsumer c = cs.createConsumer(queue1);
TextMessage m = ts.createTextMessage("test");
p.send(m);
ts.commit();
TextMessage r = (TextMessage) c.receive();
ProxyAssertSupport.assertEquals(m.getJMSMessageID(), r.getJMSMessageID());
ProxyAssertSupport.assertEquals("test", r.getText());
} finally {
pconn.close();
cconn.close();
}
}
// I moved this into it's own class so we can catch any exception that occurs
// Since this test intermittently fails.
// (As an aside, technically this test is invalid anyway since the sessions is used for sending
// and consuming concurrently - and sessions are supposed to be single threaded)
private class Sender implements Runnable {
volatile Exception ex;
MessageProducer prod;
Message m;
Sender(final MessageProducer prod, final Message m) {
this.prod = prod;
this.m = m;
}
@Override
public synchronized void run() {
try {
prod.send(m);
} catch (Exception e) {
log.error(e);
ex = e;
}
}
}
@Test
public void testPersistentSendToTopic() throws Exception {
sendToTopic(true);
}
@Test
public void testNonPersistentSendToTopic() throws Exception {
sendToTopic(false);
}
private void sendToTopic(final boolean persistent) throws Exception {
Connection pconn = createConnection();
Connection cconn = createConnection();
try {
Session ps = pconn.createSession(false, Session.AUTO_ACKNOWLEDGE);
Session cs = cconn.createSession(false, Session.AUTO_ACKNOWLEDGE);
final MessageProducer p = ps.createProducer(ActiveMQServerTestCase.topic1);
p.setDeliveryMode(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
MessageConsumer c = cs.createConsumer(ActiveMQServerTestCase.topic1);
cconn.start();
TextMessage m1 = ps.createTextMessage("test");
Sender sender = new Sender(p, m1);
Thread t = new Thread(sender, "Producer Thread");
t.start();
TextMessage m2 = (TextMessage) c.receive(5000);
if (sender.ex != null) {
// If an exception was caught in sending we rethrow here so as not to lose it
throw sender.ex;
}
ProxyAssertSupport.assertEquals(m2.getJMSMessageID(), m1.getJMSMessageID());
ProxyAssertSupport.assertEquals("test", m2.getText());
t.join();
} finally {
pconn.close();
cconn.close();
}
}
/**
* Test sending via anonymous producer
*/
@Test
public void testSendDestination() throws Exception {
Connection pconn = createConnection();
Connection cconn = createConnection();
try {
Session ps = pconn.createSession(false, Session.AUTO_ACKNOWLEDGE);
Session cs = cconn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageConsumer c2 = cs.createConsumer(ActiveMQServerTestCase.topic2);
final Message m1 = ps.createMessage();
cconn.start();
final MessageProducer anonProducer = ps.createProducer(null);
new Thread(new Runnable() {
@Override
public void run() {
try {
anonProducer.send(ActiveMQServerTestCase.topic2, m1);
} catch (Exception e) {
log.error(e);
}
}
}, "Producer Thread").start();
Message m2 = c2.receive(3000);
ProxyAssertSupport.assertEquals(m1.getJMSMessageID(), m2.getJMSMessageID());
log.debug("ending test");
} finally {
pconn.close();
cconn.close();
}
}
@Test
public void testSendForeignMessage() throws Exception {
Connection pconn = createConnection();
Connection cconn = createConnection();
try {
Session ps = pconn.createSession(false, Session.AUTO_ACKNOWLEDGE);
Session cs = cconn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer p = ps.createProducer(queue1);
MessageConsumer c = cs.createConsumer(queue1);
// send a message that is not created by the session
cconn.start();
Message m = new SimpleJMSTextMessage("something");
p.send(m);
TextMessage rec = (TextMessage) c.receive(3000);
ProxyAssertSupport.assertEquals("something", rec.getText());
} finally {
pconn.close();
cconn.close();
}
}
@Test
public void testGetDestination() throws Exception {
Connection pconn = createConnection();
try {
Session ps = pconn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer p = ps.createProducer(ActiveMQServerTestCase.topic1);
Destination dest = p.getDestination();
ProxyAssertSupport.assertEquals(dest, ActiveMQServerTestCase.topic1);
} finally {
pconn.close();
}
}
@Test
public void testGetDestinationOnClosedProducer() throws Exception {
Connection pconn = createConnection();
try {
Session ps = pconn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer p = ps.createProducer(ActiveMQServerTestCase.topic1);
p.close();
try {
p.getDestination();
ProxyAssertSupport.fail("should throw exception");
} catch (javax.jms.IllegalStateException e) {
// OK
}
} finally {
pconn.close();
}
}
@Test
public void testCreateProducerOnInexistentDestination() throws Exception {
getJmsServer().getAddressSettingsRepository().addMatch("#", new AddressSettings().setAutoCreateQueues(false));
getJmsServer().getAddressSettingsRepository().addMatch("#", new AddressSettings().setAutoCreateAddresses(false));
Connection pconn = createConnection();
try {
Session ps = pconn.createSession(false, Session.AUTO_ACKNOWLEDGE);
try {
ps.createProducer(ActiveMQJMSClient.createTopic("NoSuchTopic"));
ProxyAssertSupport.fail("should throw exception");
} catch (InvalidDestinationException e) {
// OK
}
} finally {
pconn.close();
}
}
//
// disabled MessageID tests
//
@Test
public void testGetDisableMessageID() throws Exception {
Connection pconn = createConnection();
try {
Session ps = pconn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer p = ps.createProducer(ActiveMQServerTestCase.topic1);
ProxyAssertSupport.assertFalse(p.getDisableMessageID());
} finally {
pconn.close();
}
}
@Test
public void testGetDisableMessageIDOnClosedProducer() throws Exception {
Connection pconn = createConnection();
try {
Session ps = pconn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer p = ps.createProducer(ActiveMQServerTestCase.topic1);
p.close();
try {
p.getDisableMessageID();
ProxyAssertSupport.fail("should throw exception");
} catch (javax.jms.IllegalStateException e) {
// OK
}
} finally {
pconn.close();
}
}
//
// disabled timestamp tests
//
@Test
public void testDefaultTimestampDisabled() throws Exception {
Connection pconn = createConnection();
try {
Session ps = pconn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer tp = ps.createProducer(ActiveMQServerTestCase.topic1);
MessageProducer qp = ps.createProducer(queue1);
ProxyAssertSupport.assertFalse(tp.getDisableMessageTimestamp());
ProxyAssertSupport.assertFalse(qp.getDisableMessageTimestamp());
} finally {
pconn.close();
}
}
@Test
public void testSetTimestampDisabled() throws Exception {
Connection pconn = createConnection();
Connection cconn = createConnection();
try {
Session ps = pconn.createSession(false, Session.AUTO_ACKNOWLEDGE);
Session cs = cconn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer p = ps.createProducer(queue1);
MessageConsumer c = cs.createConsumer(queue1);
cconn.start();
p.setDisableMessageTimestamp(true);
ProxyAssertSupport.assertTrue(p.getDisableMessageTimestamp());
p.send(ps.createMessage());
Message m = c.receive(3000);
ProxyAssertSupport.assertEquals(0L, m.getJMSTimestamp());
p.setDisableMessageTimestamp(false);
ProxyAssertSupport.assertFalse(p.getDisableMessageTimestamp());
long t1 = System.currentTimeMillis();
p.send(ps.createMessage());
m = c.receive(3000);
long t2 = System.currentTimeMillis();
long timestamp = m.getJMSTimestamp();
ProxyAssertSupport.assertTrue(timestamp >= t1);
ProxyAssertSupport.assertTrue(timestamp <= t2);
} finally {
pconn.close();
cconn.close();
}
}
@Test
public void testGetTimestampDisabledOnClosedProducer() throws Exception {
Connection pconn = createConnection();
try {
Session ps = pconn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer p = ps.createProducer(ActiveMQServerTestCase.topic1);
p.close();
try {
p.getDisableMessageTimestamp();
ProxyAssertSupport.fail("should throw exception");
} catch (javax.jms.IllegalStateException e) {
// OK
}
} finally {
pconn.close();
}
}
//
// DeliverMode tests
//
@Test
public void testDefaultDeliveryMode() throws Exception {
Connection pconn = createConnection();
try {
Session ps = pconn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer tp = ps.createProducer(ActiveMQServerTestCase.topic1);
MessageProducer qp = ps.createProducer(queue1);
ProxyAssertSupport.assertEquals(DeliveryMode.PERSISTENT, tp.getDeliveryMode());
ProxyAssertSupport.assertEquals(DeliveryMode.PERSISTENT, qp.getDeliveryMode());
} finally {
pconn.close();
}
}
@Test
public void testSetDeliveryMode() throws Exception {
Connection pconn = createConnection();
try {
Session ps = pconn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer p = ps.createProducer(ActiveMQServerTestCase.topic1);
p.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
ProxyAssertSupport.assertEquals(DeliveryMode.NON_PERSISTENT, p.getDeliveryMode());
p.setDeliveryMode(DeliveryMode.PERSISTENT);
ProxyAssertSupport.assertEquals(DeliveryMode.PERSISTENT, p.getDeliveryMode());
} finally {
pconn.close();
}
}
@Test
public void testGetDeliveryModeOnClosedProducer() throws Exception {
Connection pconn = createConnection();
try {
Session ps = pconn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer p = ps.createProducer(ActiveMQServerTestCase.topic1);
p.close();
try {
p.getDeliveryMode();
ProxyAssertSupport.fail("should throw exception");
} catch (javax.jms.IllegalStateException e) {
// OK
}
} finally {
pconn.close();
}
}
//
// Priority tests
//
@Test
public void testDefaultPriority() throws Exception {
Connection pconn = createConnection();
try {
Session ps = pconn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer tp = ps.createProducer(ActiveMQServerTestCase.topic1);
MessageProducer qp = ps.createProducer(queue1);
ProxyAssertSupport.assertEquals(4, tp.getPriority());
ProxyAssertSupport.assertEquals(4, qp.getPriority());
} finally {
pconn.close();
}
}
@Test
public void testSetPriority() throws Exception {
Connection pconn = createConnection();
try {
Session ps = pconn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer p = ps.createProducer(ActiveMQServerTestCase.topic1);
p.setPriority(9);
ProxyAssertSupport.assertEquals(9, p.getPriority());
p.setPriority(0);
ProxyAssertSupport.assertEquals(0, p.getPriority());
} finally {
pconn.close();
}
}
@Test
public void testGetPriorityOnClosedProducer() throws Exception {
Connection pconn = createConnection();
try {
Session ps = pconn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer p = ps.createProducer(ActiveMQServerTestCase.topic1);
p.close();
try {
p.getPriority();
ProxyAssertSupport.fail("should throw exception");
} catch (javax.jms.IllegalStateException e) {
// OK
}
} finally {
pconn.close();
}
}
//
// TimeToLive test
//
@Test
public void testDefaultTimeToLive() throws Exception {
Connection pconn = createConnection();
Session ps = pconn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer tp = ps.createProducer(ActiveMQServerTestCase.topic1);
MessageProducer qp = ps.createProducer(queue1);
ProxyAssertSupport.assertEquals(0L, tp.getTimeToLive());
ProxyAssertSupport.assertEquals(0L, qp.getTimeToLive());
}
@Test
public void testSetTimeToLive() throws Exception {
Connection pconn = createConnection();
Session ps = pconn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer p = ps.createProducer(ActiveMQServerTestCase.topic1);
p.setTimeToLive(100L);
ProxyAssertSupport.assertEquals(100L, p.getTimeToLive());
p.setTimeToLive(0L);
ProxyAssertSupport.assertEquals(0L, p.getTimeToLive());
}
@Test
public void testGetTimeToLiveOnClosedProducer() throws Exception {
Connection pconn = createConnection();
Session ps = pconn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer p = ps.createProducer(ActiveMQServerTestCase.topic1);
p.close();
try {
p.setTimeToLive(100L);
ProxyAssertSupport.fail("should throw exception");
} catch (javax.jms.IllegalStateException e) {
// OK
}
}
@Test
public void testProducerCloseInCompletionListener() throws Exception {
Connection pconn = createConnection();
Session ps = pconn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer p = ps.createProducer(ActiveMQServerTestCase.topic1);
CountDownLatch latch = new CountDownLatch(1);
CloseCompletionListener listener = new CloseCompletionListener(p, latch);
p.send(ps.createMessage(), DeliveryMode.NON_PERSISTENT, Message.DEFAULT_PRIORITY, 0L, listener);
ProxyAssertSupport.assertTrue(latch.await(5, TimeUnit.SECONDS));
ProxyAssertSupport.assertNotNull(listener.exception);
ProxyAssertSupport.assertTrue(listener.exception instanceof javax.jms.IllegalStateException);
}
@Test
public void testConnectionCloseInCompletionListener() throws Exception {
Connection pconn = createConnection();
Session ps = pconn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer p = ps.createProducer(ActiveMQServerTestCase.topic1);
CountDownLatch latch = new CountDownLatch(1);
ConnectionCloseCompletionListener listener = new ConnectionCloseCompletionListener(pconn, latch);
p.send(ps.createMessage(), DeliveryMode.NON_PERSISTENT, Message.DEFAULT_PRIORITY, 0L, listener);
ProxyAssertSupport.assertTrue(latch.await(5, TimeUnit.SECONDS));
ProxyAssertSupport.assertNotNull(listener.exception);
ProxyAssertSupport.assertTrue(listener.exception instanceof javax.jms.IllegalStateException);
}
@Test
public void testSessionCloseInCompletionListener() throws Exception {
Connection pconn = createConnection();
Session ps = pconn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer p = ps.createProducer(ActiveMQServerTestCase.topic1);
CountDownLatch latch = new CountDownLatch(1);
SessionCloseCompletionListener listener = new SessionCloseCompletionListener(ps, latch);
p.send(ps.createMessage(), DeliveryMode.NON_PERSISTENT, Message.DEFAULT_PRIORITY, 0L, listener);
ProxyAssertSupport.assertTrue(latch.await(5, TimeUnit.SECONDS));
ProxyAssertSupport.assertNotNull(listener.exception);
ProxyAssertSupport.assertTrue(listener.exception instanceof javax.jms.IllegalStateException);
}
@Test
public void testSendToQueueOnlyWhenTopicWithSameAddress() throws Exception {
SimpleString addr = SimpleString.toSimpleString("testAddr");
Set<RoutingType> supportedRoutingTypes = new HashSet<>();
supportedRoutingTypes.add(RoutingType.ANYCAST);
supportedRoutingTypes.add(RoutingType.MULTICAST);
servers.get(0).getActiveMQServer().addAddressInfo(new AddressInfo(addr, supportedRoutingTypes));
servers.get(0).getActiveMQServer().createQueue(addr, RoutingType.ANYCAST, addr, null, false, false);
Connection pconn = createConnection();
pconn.start();
Session ps = pconn.createSession(false, Session.AUTO_ACKNOWLEDGE);
Queue queue = ps.createQueue(addr.toString());
Topic topic = ps.createTopic(addr.toString());
MessageConsumer queueConsumer = ps.createConsumer(queue);
MessageConsumer topicConsumer = ps.createConsumer(topic);
MessageProducer queueProducer = ps.createProducer(queue);
queueProducer.send(ps.createMessage());
assertNotNull(queueConsumer.receive(1000));
assertNull(topicConsumer.receive(1000));
MessageProducer topicProducer = ps.createProducer(topic);
topicProducer.send(ps.createMessage());
assertNull(queueConsumer.receive(1000));
assertNotNull(topicConsumer.receive(1000));
}
// Package protected ---------------------------------------------
// Protected -----------------------------------------------------
// Private -------------------------------------------------------
// Inner classes -------------------------------------------------
private static class CloseCompletionListener implements CompletionListener {
private MessageProducer p;
private CountDownLatch latch;
private JMSException exception;
private CloseCompletionListener(MessageProducer p, CountDownLatch latch) {
this.p = p;
this.latch = latch;
}
@Override
public void onCompletion(Message message) {
try {
p.close();
} catch (JMSException e) {
this.exception = e;
}
latch.countDown();
}
@Override
public void onException(Message message, Exception exception) {
}
}
private static class ConnectionCloseCompletionListener implements CompletionListener {
private CountDownLatch latch;
private JMSException exception;
private Connection conn;
private ConnectionCloseCompletionListener(Connection conn, CountDownLatch latch) {
this.conn = conn;
this.latch = latch;
}
@Override
public void onCompletion(Message message) {
try {
conn.close();
} catch (JMSException e) {
this.exception = e;
}
latch.countDown();
}
@Override
public void onException(Message message, Exception exception) {
}
}
private static class SessionCloseCompletionListener implements CompletionListener {
private CountDownLatch latch;
private JMSException exception;
private Session session;
private SessionCloseCompletionListener(Session session, CountDownLatch latch) {
this.session = session;
this.latch = latch;
}
@Override
public void onCompletion(Message message) {
try {
session.close();
} catch (JMSException e) {
this.exception = e;
}
latch.countDown();
}
@Override
public void onException(Message message, Exception exception) {
}
}
}