Search in sources :

Example 1 with QueueQuery

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);
}
Also used : MessageEndpointFactory(javax.resource.spi.endpoint.MessageEndpointFactory) XAResource(javax.transaction.xa.XAResource) HashMap(java.util.HashMap) SimpleString(org.apache.activemq.artemis.api.core.SimpleString) SimpleString(org.apache.activemq.artemis.api.core.SimpleString) QueueQuery(org.apache.activemq.artemis.api.core.client.ClientSession.QueueQuery)

Example 2 with QueueQuery

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);
    }
}
Also used : IllegalStateException(javax.jms.IllegalStateException) AddressQuery(org.apache.activemq.artemis.api.core.client.ClientSession.AddressQuery) ActiveMQException(org.apache.activemq.artemis.api.core.ActiveMQException) ActiveMQQueueExistsException(org.apache.activemq.artemis.api.core.ActiveMQQueueExistsException) SimpleString(org.apache.activemq.artemis.api.core.SimpleString) InvalidDestinationException(javax.jms.InvalidDestinationException) SimpleString(org.apache.activemq.artemis.api.core.SimpleString) ClientConsumer(org.apache.activemq.artemis.api.core.client.ClientConsumer) QueueQuery(org.apache.activemq.artemis.api.core.client.ClientSession.QueueQuery)

Example 3 with QueueQuery

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();
}
Also used : AddressSettings(org.apache.activemq.artemis.core.settings.impl.AddressSettings) ClientSession(org.apache.activemq.artemis.api.core.client.ClientSession) SimpleString(org.apache.activemq.artemis.api.core.SimpleString) QueueQuery(org.apache.activemq.artemis.api.core.client.ClientSession.QueueQuery) Test(org.junit.Test)

Example 4 with QueueQuery

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());
}
Also used : ActiveMQActivation(org.apache.activemq.artemis.ra.inflow.ActiveMQActivation) ClientSession(org.apache.activemq.artemis.api.core.client.ClientSession) SimpleString(org.apache.activemq.artemis.api.core.SimpleString) ActiveMQResourceAdapter(org.apache.activemq.artemis.ra.ActiveMQResourceAdapter) ClientMessage(org.apache.activemq.artemis.api.core.client.ClientMessage) ActiveMQActivationSpec(org.apache.activemq.artemis.ra.inflow.ActiveMQActivationSpec) CountDownLatch(java.util.concurrent.CountDownLatch) ClientProducer(org.apache.activemq.artemis.api.core.client.ClientProducer) QueueQuery(org.apache.activemq.artemis.api.core.client.ClientSession.QueueQuery) Test(org.junit.Test)

Example 5 with QueueQuery

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();
}
Also used : ClientSession(org.apache.activemq.artemis.api.core.client.ClientSession) SimpleString(org.apache.activemq.artemis.api.core.SimpleString) ClientProducer(org.apache.activemq.artemis.api.core.client.ClientProducer) QueueQuery(org.apache.activemq.artemis.api.core.client.ClientSession.QueueQuery) Test(org.junit.Test)

Aggregations

QueueQuery (org.apache.activemq.artemis.api.core.client.ClientSession.QueueQuery)10 SimpleString (org.apache.activemq.artemis.api.core.SimpleString)9 ClientSession (org.apache.activemq.artemis.api.core.client.ClientSession)4 Test (org.junit.Test)4 IllegalStateException (javax.jms.IllegalStateException)3 InvalidDestinationException (javax.jms.InvalidDestinationException)3 ActiveMQException (org.apache.activemq.artemis.api.core.ActiveMQException)3 ClientProducer (org.apache.activemq.artemis.api.core.client.ClientProducer)2 HashMap (java.util.HashMap)1 CountDownLatch (java.util.concurrent.CountDownLatch)1 MessageEndpointFactory (javax.resource.spi.endpoint.MessageEndpointFactory)1 XAResource (javax.transaction.xa.XAResource)1 ActiveMQQueueExistsException (org.apache.activemq.artemis.api.core.ActiveMQQueueExistsException)1 ClientConsumer (org.apache.activemq.artemis.api.core.client.ClientConsumer)1 ClientMessage (org.apache.activemq.artemis.api.core.client.ClientMessage)1 AddressQuery (org.apache.activemq.artemis.api.core.client.ClientSession.AddressQuery)1 AddressSettings (org.apache.activemq.artemis.core.settings.impl.AddressSettings)1 ActiveMQResourceAdapter (org.apache.activemq.artemis.ra.ActiveMQResourceAdapter)1 ActiveMQActivation (org.apache.activemq.artemis.ra.inflow.ActiveMQActivation)1 ActiveMQActivationSpec (org.apache.activemq.artemis.ra.inflow.ActiveMQActivationSpec)1