use of org.apache.activemq.artemis.api.core.client.ClientSession.QueueQuery in project activemq-artemis by apache.
the class ActiveMQMessageHandler method setup.
public void setup() throws Exception {
if (logger.isTraceEnabled()) {
logger.trace("setup()");
}
ActiveMQActivationSpec spec = activation.getActivationSpec();
String selector = spec.getMessageSelector();
// Create the message consumer
SimpleString selectorString = selector == null || selector.trim().equals("") ? null : new SimpleString(selector);
if (activation.isTopic() && spec.isSubscriptionDurable()) {
SimpleString queueName = ActiveMQDestination.createQueueNameForSubscription(true, spec.getClientID(), spec.getSubscriptionName());
QueueQuery subResponse = session.queueQuery(queueName);
if (!subResponse.isExists()) {
session.createQueue(activation.getAddress(), queueName, selectorString, true);
} else {
// As a deployed MDB could set up multiple instances in order to process messages in parallel.
if (sessionNr == 0 && subResponse.getConsumerCount() > 0) {
if (!spec.isShareSubscriptions()) {
throw ActiveMQRALogger.LOGGER.canNotCreatedNonSharedSubscriber();
} else if (ActiveMQRALogger.LOGGER.isDebugEnabled()) {
logger.debug("the mdb on destination " + queueName + " already had " + subResponse.getConsumerCount() + " consumers but the MDB is configured to share subscriptions, so no exceptions are thrown");
}
}
SimpleString oldFilterString = subResponse.getFilterString();
boolean selectorChanged = selector == null && oldFilterString != null || oldFilterString == null && selector != null || (oldFilterString != null && selector != null && !oldFilterString.toString().equals(selector));
SimpleString oldTopicName = subResponse.getAddress();
boolean topicChanged = !oldTopicName.equals(activation.getAddress());
if (selectorChanged || topicChanged) {
// Delete the old durable sub
session.deleteQueue(queueName);
// Create the new one
session.createQueue(activation.getAddress(), queueName, selectorString, true);
}
}
consumer = (ClientConsumerInternal) session.createConsumer(queueName, null, false);
} else {
SimpleString tempQueueName;
if (activation.isTopic()) {
if (activation.getTopicTemporaryQueue() == null) {
tempQueueName = new SimpleString(UUID.randomUUID().toString());
session.createTemporaryQueue(activation.getAddress(), tempQueueName, selectorString);
activation.setTopicTemporaryQueue(tempQueueName);
} else {
tempQueueName = activation.getTopicTemporaryQueue();
QueueQuery queueQuery = session.queueQuery(tempQueueName);
if (!queueQuery.isExists()) {
// this is because we could be using remote servers (in cluster maybe)
// and the queue wasn't created on that node yet.
session.createTemporaryQueue(activation.getAddress(), tempQueueName, selectorString);
}
}
} else {
tempQueueName = activation.getAddress();
}
consumer = (ClientConsumerInternal) session.createConsumer(tempQueueName, selectorString);
}
// Create the endpoint, if we are transacted pass the session so it is enlisted, unless using Local TX
MessageEndpointFactory endpointFactory = activation.getMessageEndpointFactory();
useLocalTx = !activation.isDeliveryTransacted() && activation.getActivationSpec().isUseLocalTx();
transacted = activation.isDeliveryTransacted();
if (activation.isDeliveryTransacted() && !activation.getActivationSpec().isUseLocalTx()) {
Map<String, Object> xaResourceProperties = new HashMap<>();
xaResourceProperties.put(ActiveMQXAResourceWrapper.ACTIVEMQ_JNDI_NAME, ((ActiveMQResourceAdapter) spec.getResourceAdapter()).getJndiName());
xaResourceProperties.put(ActiveMQXAResourceWrapper.ACTIVEMQ_NODE_ID, ((ClientSessionFactoryInternal) cf).getLiveNodeId());
xaResourceProperties.put(ActiveMQXAResourceWrapper.ACTIVEMQ_PRODUCT_NAME, ActiveMQResourceAdapter.PRODUCT_NAME);
xaResourceProperties.put(ActiveMQXAResourceWrapper.ACTIVEMQ_PRODUCT_VERSION, VersionLoader.getVersion().getFullVersion());
XAResource xaResource = ServiceUtils.wrapXAResource(session, xaResourceProperties);
endpoint = endpointFactory.createEndpoint(xaResource);
useXA = true;
} else {
endpoint = endpointFactory.createEndpoint(null);
useXA = false;
}
connected = true;
session.addFailoverListener(this);
consumer.setMessageHandler(this);
}
use of org.apache.activemq.artemis.api.core.client.ClientSession.QueueQuery 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.ClientSession.QueueQuery in project activemq-artemis by apache.
the class SessionTest method testQueueQueryNoQ.
@Test
public void testQueueQueryNoQ() throws Exception {
server.getAddressSettingsRepository().addMatch("#", new AddressSettings().setAutoCreateQueues(false));
cf = createSessionFactory(locator);
ClientSession clientSession = cf.createSession(false, true, true);
QueueQuery resp = clientSession.queueQuery(new SimpleString(queueName));
Assert.assertFalse(resp.isExists());
Assert.assertFalse(resp.isAutoCreateQueues());
Assert.assertEquals(null, resp.getAddress());
clientSession.close();
}
use of org.apache.activemq.artemis.api.core.client.ClientSession.QueueQuery in project activemq-artemis by apache.
the class ActiveMQMessageHandlerTest method testNonDurableSubscriptionDeleteAfterCrash.
// https://issues.jboss.org/browse/JBPAPP-8017
@Test
public void testNonDurableSubscriptionDeleteAfterCrash() throws Exception {
ActiveMQResourceAdapter qResourceAdapter = newResourceAdapter();
MyBootstrapContext ctx = new MyBootstrapContext();
qResourceAdapter.start(ctx);
ActiveMQActivationSpec spec = new ActiveMQActivationSpec();
spec.setResourceAdapter(qResourceAdapter);
spec.setUseJNDI(false);
spec.setDestinationType("javax.jms.Topic");
spec.setDestination("mdbTopic");
qResourceAdapter.setConnectorClassName(INVM_CONNECTOR_FACTORY);
CountDownLatch latch = new CountDownLatch(1);
DummyMessageEndpoint endpoint = new DummyMessageEndpoint(latch);
DummyMessageEndpointFactory endpointFactory = new DummyMessageEndpointFactory(endpoint, false);
qResourceAdapter.endpointActivation(endpointFactory, spec);
ClientSession session = locator.createSessionFactory().createSession();
ClientProducer clientProducer = session.createProducer("mdbTopic");
ClientMessage message = session.createMessage(true);
message.getBodyBuffer().writeString("1");
clientProducer.send(message);
latch.await(5, TimeUnit.SECONDS);
assertNotNull(endpoint.lastMessage);
assertEquals(endpoint.lastMessage.getCoreMessage().getBodyBuffer().readString(), "1");
ActiveMQActivation activation = lookupActivation(qResourceAdapter);
SimpleString tempQueueName = activation.getTopicTemporaryQueue();
QueueQuery query = session.queueQuery(tempQueueName);
assertTrue(query.isExists());
// this should be enough to simulate the crash
qResourceAdapter.getDefaultActiveMQConnectionFactory().close();
qResourceAdapter.stop();
query = session.queueQuery(tempQueueName);
assertFalse(query.isExists());
}
use of org.apache.activemq.artemis.api.core.client.ClientSession.QueueQuery in project activemq-artemis by apache.
the class SessionTest method testQueueQuery.
@Test
public void testQueueQuery() throws Exception {
cf = createSessionFactory(locator);
ClientSession clientSession = cf.createSession(false, true, true);
clientSession.createQueue("a1", queueName, false);
clientSession.createConsumer(queueName);
clientSession.createConsumer(queueName);
ClientProducer cp = clientSession.createProducer("a1");
cp.send(clientSession.createMessage(true));
cp.send(clientSession.createMessage(true));
flushQueue();
QueueQuery resp = clientSession.queueQuery(new SimpleString(queueName));
Assert.assertEquals(new SimpleString("a1"), resp.getAddress());
Assert.assertEquals(2, resp.getConsumerCount());
Assert.assertEquals(2, resp.getMessageCount());
Assert.assertEquals(null, resp.getFilterString());
clientSession.close();
}
Aggregations