use of org.apache.activemq.artemis.api.core.client.ClientConsumer in project activemq-artemis by apache.
the class ActiveMQSession method createConsumer.
private ActiveMQMessageConsumer createConsumer(final ActiveMQDestination dest, final String subscriptionName, String selectorString, final boolean noLocal, ConsumerDurability durability) throws JMSException {
try {
selectorString = "".equals(selectorString) ? null : selectorString;
if (noLocal) {
connection.setHasNoLocal();
String filter;
if (connection.getClientID() != null) {
filter = ActiveMQConnection.CONNECTION_ID_PROPERTY_NAME.toString() + "<>'" + connection.getClientID() + "'";
} else {
filter = ActiveMQConnection.CONNECTION_ID_PROPERTY_NAME.toString() + "<>'" + connection.getUID() + "'";
}
if (selectorString != null) {
selectorString += " AND " + filter;
} else {
selectorString = filter;
}
}
SimpleString coreFilterString = null;
if (selectorString != null) {
coreFilterString = new SimpleString(SelectorTranslator.convertToActiveMQFilterString(selectorString));
}
ClientConsumer consumer;
SimpleString autoDeleteQueueName = null;
if (dest.isQueue()) {
AddressQuery response = session.addressQuery(dest.getSimpleAddress());
/* The address query will send back exists=true even if the node only has a REMOTE binding for the destination.
* Therefore, we must check if the queue names list contains the exact name of the address to know whether or
* not a LOCAL binding for the address exists. If no LOCAL binding exists then it should be created here.
*/
if (!response.isExists() || !response.getQueueNames().contains(dest.getSimpleAddress())) {
if (response.isAutoCreateQueues()) {
try {
createQueue(dest, RoutingType.ANYCAST, dest.getSimpleAddress(), null, true, true, response.getDefaultMaxConsumers(), response.isDefaultPurgeOnNoConsumers(), response.isDefaultExclusive(), response.isDefaultLastValueQueue());
} catch (ActiveMQQueueExistsException e) {
// The queue was created by another client/admin between the query check and send create queue packet
}
} else {
throw new InvalidDestinationException("Destination " + dest.getName() + " does not exist");
}
}
connection.addKnownDestination(dest.getSimpleAddress());
consumer = session.createConsumer(dest.getSimpleAddress(), coreFilterString, false);
} else {
AddressQuery response = session.addressQuery(dest.getSimpleAddress());
if (!response.isExists()) {
if (response.isAutoCreateAddresses()) {
session.createAddress(dest.getSimpleAddress(), RoutingType.MULTICAST, true);
} else {
throw new InvalidDestinationException("Topic " + dest.getName() + " does not exist");
}
}
connection.addKnownDestination(dest.getSimpleAddress());
SimpleString queueName;
if (subscriptionName == null) {
if (durability != ConsumerDurability.NON_DURABLE)
throw new RuntimeException("Subscription name cannot be null for durable topic consumer");
// Non durable sub
queueName = new SimpleString(UUID.randomUUID().toString());
createTemporaryQueue(dest, RoutingType.MULTICAST, queueName, coreFilterString, response.getDefaultMaxConsumers(), response.isDefaultPurgeOnNoConsumers(), response.isDefaultExclusive(), response.isDefaultLastValueQueue());
consumer = session.createConsumer(queueName, null, false);
autoDeleteQueueName = queueName;
} else {
// Durable sub
if (durability != ConsumerDurability.DURABLE)
throw new RuntimeException("Subscription name must be null for non-durable topic consumer");
if (connection.getClientID() == null) {
throw new IllegalStateException("Cannot create durable subscription - client ID has not been set");
}
if (dest.isTemporary()) {
throw new InvalidDestinationException("Cannot create a durable subscription on a temporary topic");
}
queueName = ActiveMQDestination.createQueueNameForSubscription(true, connection.getClientID(), subscriptionName);
QueueQuery subResponse = session.queueQuery(queueName);
if (!subResponse.isExists()) {
// durable subscription queues are not technically considered to be auto-created
createQueue(dest, RoutingType.MULTICAST, queueName, coreFilterString, true, false, response.getDefaultMaxConsumers(), response.isDefaultPurgeOnNoConsumers(), response.isDefaultExclusive(), response.isDefaultLastValueQueue());
} else {
// Already exists
if (subResponse.getConsumerCount() > 0) {
throw new IllegalStateException("Cannot create a subscriber on the durable subscription since it already has subscriber(s)");
}
// From javax.jms.Session Javadoc (and also JMS 1.1 6.11.1):
// A client can change an existing durable subscription by
// creating a durable TopicSubscriber with the same name and
// a new topic and/or message selector.
// Changing a durable subscriber is equivalent to unsubscribing
// (deleting) the old one and creating a new one.
SimpleString oldFilterString = subResponse.getFilterString();
boolean selectorChanged = coreFilterString == null && oldFilterString != null || oldFilterString == null && coreFilterString != null || oldFilterString != null && coreFilterString != null && !oldFilterString.equals(coreFilterString);
SimpleString oldTopicName = subResponse.getAddress();
boolean topicChanged = !oldTopicName.equals(dest.getSimpleAddress());
if (selectorChanged || topicChanged) {
// Delete the old durable sub
session.deleteQueue(queueName);
// Create the new one
createQueue(dest, RoutingType.MULTICAST, queueName, coreFilterString, true, false, response.getDefaultMaxConsumers(), response.isDefaultPurgeOnNoConsumers(), response.isDefaultExclusive(), response.isDefaultLastValueQueue());
}
}
consumer = session.createConsumer(queueName, null, false);
}
}
ActiveMQMessageConsumer jbc = new ActiveMQMessageConsumer(options, connection, this, consumer, noLocal, dest, selectorString, autoDeleteQueueName);
consumers.add(jbc);
return jbc;
} catch (ActiveMQException e) {
throw JMSExceptionHelper.convertFromActiveMQException(e);
}
}
use of org.apache.activemq.artemis.api.core.client.ClientConsumer in project activemq-artemis by apache.
the class ConsumerWindowSizeTest method testMultipleImmediate.
@Test
public void testMultipleImmediate() throws Exception {
final int NUMBER_OF_MESSAGES = 200;
ActiveMQServer server = createServer(false, isNetty());
server.start();
locator.setConsumerWindowSize(0);
final ClientSessionFactory sf = createSessionFactory(locator);
{
ClientSession session = sf.createSession(false, false, false);
session.createQueue("testWindow", "testWindow", true);
session.close();
}
Thread[] threads = new Thread[10];
final AtomicInteger errors = new AtomicInteger(0);
final CountDownLatch latchStart = new CountDownLatch(1);
final AtomicInteger received = new AtomicInteger(0);
for (int i = 0; i < threads.length; i++) {
threads[i] = new Thread() {
@Override
public void run() {
try {
ClientSession session = sf.createSession(false, false);
ClientConsumer consumer = session.createConsumer("testWindow");
session.start();
latchStart.await(10, TimeUnit.SECONDS);
while (true) {
ClientMessage msg = consumer.receiveImmediate();
if (msg == null) {
break;
}
msg.acknowledge();
session.commit();
received.incrementAndGet();
}
} catch (Throwable e) {
e.printStackTrace();
errors.incrementAndGet();
}
}
};
threads[i].start();
}
ClientSession senderSession = sf.createSession(false, false);
ClientProducer producer = senderSession.createProducer("testWindow");
ClientMessage sent = senderSession.createMessage(true);
sent.putStringProperty("hello", "world");
for (int i = 0; i < NUMBER_OF_MESSAGES; i++) {
producer.send(sent);
senderSession.commit();
}
latchStart.countDown();
for (Thread t : threads) {
t.join();
}
Assert.assertEquals(0, errors.get());
Assert.assertEquals(NUMBER_OF_MESSAGES, received.get());
}
use of org.apache.activemq.artemis.api.core.client.ClientConsumer in project activemq-artemis by apache.
the class ConsumerWindowSizeTest method internalTestSlowConsumerNoBuffer.
private void internalTestSlowConsumerNoBuffer(final boolean largeMessages) throws Exception {
ActiveMQServer server = createServer(false, isNetty());
ClientSession sessionB = null;
ClientSession session = null;
try {
final int numberOfMessages = 100;
server.start();
locator.setConsumerWindowSize(0);
if (largeMessages) {
locator.setMinLargeMessageSize(100);
}
ClientSessionFactory sf = createSessionFactory(locator);
session = sf.createSession(false, true, true);
SimpleString ADDRESS = addressA;
session.createQueue(ADDRESS, ADDRESS, true);
sessionB = sf.createSession(false, true, true);
sessionB.start();
session.start();
ClientConsumerInternal consNeverUsed = (ClientConsumerInternal) sessionB.createConsumer(ADDRESS);
ClientProducer prod = session.createProducer(ADDRESS);
// This will force a credit to be sent, but if the message wasn't received we need to take out that credit from
// the server
// or the client will be buffering messages
Assert.assertNull(consNeverUsed.receive(1));
ClientMessage msg = createTextMessage(session, "This one will expire");
if (largeMessages) {
msg.getBodyBuffer().writeBytes(new byte[600]);
}
msg.setExpiration(System.currentTimeMillis() + 100);
prod.send(msg);
msg = createTextMessage(session, "First-on-non-buffered");
prod.send(msg);
Thread.sleep(110);
// It will be able to receive another message, but it shouldn't send a credit again, as the credit was already
// sent
msg = consNeverUsed.receive(TIMEOUT * 1000);
Assert.assertNotNull(msg);
Assert.assertEquals("First-on-non-buffered", getTextMessage(msg));
msg.acknowledge();
ClientConsumer cons1 = session.createConsumer(ADDRESS);
for (int i = 0; i < numberOfMessages; i++) {
msg = createTextMessage(session, "Msg" + i);
if (largeMessages) {
msg.getBodyBuffer().writeBytes(new byte[600]);
}
prod.send(msg);
}
for (int i = 0; i < numberOfMessages; i++) {
msg = cons1.receive(1000);
Assert.assertNotNull("expected message at i = " + i, msg);
Assert.assertEquals("Msg" + i, getTextMessage(msg));
msg.acknowledge();
}
Assert.assertEquals(0, consNeverUsed.getBufferSize());
session.close();
session = null;
sessionB.close();
sessionB = null;
Assert.assertEquals(0, getMessageCount(server, ADDRESS.toString()));
} finally {
try {
if (session != null) {
session.close();
}
if (sessionB != null) {
sessionB.close();
}
} catch (Exception ignored) {
}
}
}
use of org.apache.activemq.artemis.api.core.client.ClientConsumer in project activemq-artemis by apache.
the class ConsumerWindowSizeTest method testSendWindowSize.
/*
* tests send window size. we do this by having 2 receivers on the q. since we roundrobin the consumer for delivery we
* know if consumer 1 has received n messages then consumer 2 must have also have received n messages or at least up
* to its window size
* */
@Test
public void testSendWindowSize() throws Exception {
ActiveMQServer messagingService = createServer(false, isNetty());
locator.setBlockOnNonDurableSend(false);
messagingService.start();
int numMessage = 100;
locator.setConsumerWindowSize(numMessage * getMessageEncodeSize(addressA));
ClientSessionFactory cf = createSessionFactory(locator);
ClientSession sendSession = cf.createSession(false, true, true);
ClientSession receiveSession = cf.createSession(false, true, true);
sendSession.createQueue(addressA, queueA, false);
ClientConsumer receivingConsumer = receiveSession.createConsumer(queueA);
ClientSession session = cf.createSession(false, true, true);
ClientProducer cp = sendSession.createProducer(addressA);
ClientConsumer cc = session.createConsumer(queueA);
session.start();
receiveSession.start();
for (int i = 0; i < numMessage * 4; i++) {
cp.send(sendSession.createMessage(false));
}
for (int i = 0; i < numMessage * 2; i++) {
ClientMessage m = receivingConsumer.receive(5000);
Assert.assertNotNull(m);
m.acknowledge();
}
receiveSession.close();
for (int i = 0; i < numMessage * 2; i++) {
ClientMessage m = cc.receive(5000);
Assert.assertNotNull(m);
m.acknowledge();
}
session.close();
sendSession.close();
Assert.assertEquals(0, getMessageCount(messagingService, queueA.toString()));
}
use of org.apache.activemq.artemis.api.core.client.ClientConsumer in project activemq-artemis by apache.
the class ConsumerWindowSizeTest method testReceiveImmediateWithZeroWindow3.
// https://jira.jboss.org/jira/browse/HORNETQ-385
@Test
public void testReceiveImmediateWithZeroWindow3() throws Exception {
ActiveMQServer server = createServer(false, isNetty());
server.start();
locator.setConsumerWindowSize(0);
ClientSessionFactory sf = createSessionFactory(locator);
ClientSession session = sf.createSession(false, false, false);
session.createQueue("testWindow", "testWindow", true);
session.close();
int numConsumers = 5;
ArrayList<ClientConsumer> consumers = new ArrayList<>();
ArrayList<ClientSession> sessions = new ArrayList<>();
for (int i = 0; i < numConsumers; i++) {
ClientSession session1 = sf.createSession();
ClientConsumer consumer = session1.createConsumer("testWindow");
consumers.add(consumer);
session1.start();
sessions.add(session1);
consumer.receive(10);
}
ClientSession senderSession = sf.createSession(false, false);
ClientProducer producer = senderSession.createProducer("testWindow");
ClientMessage sent = senderSession.createMessage(true);
sent.putStringProperty("hello", "world");
producer.send(sent);
senderSession.commit();
senderSession.start();
ClientConsumer consumer = consumers.get(2);
ClientMessage received = consumer.receive(1000);
Assert.assertNotNull(received);
for (ClientSession tmpSess : sessions) {
tmpSess.close();
}
senderSession.close();
}
Aggregations