How can I set the exclusive/non-exclusive property of a tibco queue programmatically? I want to be able to set the queue as non-exclusive when I crate it in my application.
For example, if I use the following code to craete the queue:
QueueConnectionFactory factory = new TIBCO.EMS.QueueConnectionFactory(serverUrl);
QueueConnection connection = factory.CreateQueueConnection(userName, password);
QueueSession session = connection.CreateQueueSession(false, Session.AUTO_ACKNOWLEDGE);
TIBCO.EMS.Queue queue = session.CreateQueue(queueName);
How can I set the queue's properties?
You will need the TibjmsAdmin API to do that. The JavaDoc of the API can be found here
Then try this:
TibjmsAdmin jmsAdmin = new TibjmsAdmin("tcp://localhost:7222", "admin", "admin");
QueueInfo qi = jmsAdmin.getQueue("my.queue");
qi.setExclusive(true);
HTH,
Hendrik
Related
Brocker C++ , Client java jms
It is correct to send a message to a topic and just after create a consumer on this Topic ?
connection = connectionFactory.createConnection();
connection.start();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
topic = (Destination) context.lookup("topicSend");
Destination tempTopic = (Destination) context.lookup("topicSend");
MessageProducer messageProducer = session.createProducer(topic);
messageProducer.send(messageToSend);
... and just subsequent create a Consumer on the SAME Session and topic (topicSend is equal as tempTopic
MessageConsumer messageConsumer = session.createConsumer(tempTopic, MESSAGE_SELECTOR);
Yes. That should be fine. Just be sure to close your producer if you're done with it.
I will suggest to use separate Session for producer and consumer to avoid any issues.
I understand if both the message queues (receiver and response) are present in the same server location I can use the JNDI connection factory and queue name
jms/myqueue_qcf1
jms/myqueue1, to connect to the queue and send message to jms/myqueue_qcf2, jms/myqueue2
But in case of Interserver connectivity, will this be the same
When the firewall b/w both the servers is opened.
The MQ myqueue2 is setup as remote mq in Websphere.
Any help with code reference would be appreciable.
public void myAppListener extends MessageListener{ //getting message from MQ1 -
//sent by some other application - MQ1 is Local
//in appServer1
private static final String JMS_LC_JNDI_NAME = "jms/liftcargo_lara_qcf";
private static final String JMS_LC_QUEUE_NAME = "jms/APP.OUT.REQUEST";
public void onMessage(Message msg){
try{
TextMessage requestMessage = (TextMessage) msg;
String reqMessage = requestMessage.getText();
String correlationId = requestMessage.getJMSCorrelationID();
sendXMLToNextAppMQ(reqMessage , correlationId)
}
}
public static void sendXMLToNextAppMQ(String message, String correlID) throws JMSException { //The MQ to which the message is forwarded to is a Remote MQ, in different server appServer2
try {
InitialContext context = new InitialContext();
QueueConnectionFactory queueConnectionFactory =
(QueueConnectionFactory)context.lookup(JMS_LC_JNDI_NAME);
System.out.println("Connection Factory data :: "+queueConnectionFactory.toString());
Queue queue = (Queue) context.lookup(JMS_LC_QUEUE_NAME);
System.out.println("Check Queue Name :: "+queue.toString());
QueueConnection queueConnection = queueConnectionFactory.createQueueConnection();
QueueSession session = queueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
QueueSender queueSender = session.createSender(queue);
TextMessage message1 = session.createTextMessage();
message1.setText(message);
message1.setJMSType("Tunnel message from CCAM.LARA.OUT.REQUEST MQ to
LIFTCARGO.OUT.LARA.REQUEST MQ");
message1.setJMSDestination(queue);
message1.setJMSCorrelationID(correlID);
queueSender.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
queueSender.send(message1);
} catch (NamingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}catch (JMSException e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
In Method sendXMLToNextAppMQ (i.e., tunnel the msg recieved in MQ1 in appServer1 to MQ2 in appServer2) is there any other jndi properties needed to mention to connect appServer1 to MQ2 in appServer2 (firewall is opened b/w appServer1 & appServer2)
If your target request queue is on a different server, your application will still have the same code, but the name you supply will not be the name of a QLOCAL on the queue manager you are connected to, but instead will be a QREMOTE. If you are using JNDI to refer to your queues, you don't even have to change the name of the queue, only the referenced real MQ queue name need be changed.
For example, if you were using the command line JMSAdmin tool, you'd change the name in the QUEUE attribute only:-
DEFINE Q(myqueue2) QUEUE(Q.FOR.REQUESTS)
Then on your two queue managers, there would be definitions that look something like these:-
Local QM (QM1)
DEFINE QREMOTE(Q.FOR.REQUESTS) RNAME(WORK.QUEUE) RQMNAME(QM2) XMITQ(QM2)
DEFINE QLOCAL(QM2) USAGE(XMITQ) DESCR('Transmission queue for messages to QM2')
DEFINE QLOCAL(MY.REPLY.Q) DESCR('My application queue for responses')
DEFINE CHANNEL(TO.QM2) CHLTYPE(SDR) CONNAME('(qm2.machine.com(1414)') XMITQ(QM2)
DEFINE CHANNEL(TO.QM1) CHLTYPE(RCVR)
Remote QM (QM2)
DEFINE QLOCAL(WORK.QUEUE)
DEFINE QLOCAL(QM1) USAGE(XMITQ) DESCR('Transmission queue for messages to QM1')
DEFINE CHANNEL(TO.QM2) CHLTYPE(RCVR)
DEFINE CHANNEL(TO.QM1) CHLTYPE(SDR) CONNAME('qm1.machine.com(1414)') XMITQ(QM1)
In addition, it is good practice in a request/reply application, to provide the name of the queue where the response should be sent as part of the request message, and to code the responding application to read those fields (ReplyTo fields) and use them to send the reply message back, thus not requiring an extra QREMOTE definition on the Remote QM (QM2 in my example).
Spring Boot ActiveMQ consumer connection pool is needed to configure? I have only one consumer in spring boot application (as a micro service), producers are in another application. I am little confused by the below: (extracted from http://activemq.apache.org/spring-support.html)
Note: while the PooledConnectionFactory does allow the creation of a collection of active consumers, it does not 'pool' consumers. Pooling makes sense for connections, sessions and producers, which can be seldom-used resources, are expensive to create and can remain idle a minimal cost. Consumers, on the other hand, are usually just created at startup and left going, handling incoming messages as they come. When a consumer is complete, it's preferred to shut down it down rather than leave it idle and return it to a pool for later reuse: this is because, even if the consumer is idle, ActiveMQ will keep delivering messages to the consumer's prefetch buffer, where they'll get held up until the consumer is active again.
At the same page, I can see this: You can use the activemq-pool org.apache.activemq.pool.PooledConnectionFactory for efficient pooling of the connections and sessions for your collection of consumers, or you can use the Spring JMS org.springframework.jms.connection.CachingConnectionFactory to achieve the same effect
I tried CachingConnectionFactory (which can take ActiveMQConnectionFactory) where it has only few setter to hold cacheConsumers(boolean), cacheProducers(boolean), nothing related to pool the connection. I know that 1 connection can give you multiple session, then per session you have multiple consumer/producer. But my question is for Consumer how do we pool as the above statement is saying leave it to default. So I did this by just one method:#Bean
public JmsListenerContainerFactory myFactory(ConnectionFactory connectionFactory, DefaultJmsListenerContainerFactoryConfigurer configurer) {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
// This provides all boot's default to this factory, including the message converter
factory.setConcurrency("3-10");
configurer.configure(factory, connectionFactory);
// You could still override some of Boot's default if necessary.
return factory;
}</em><br>
Dynamic scaling this link also suggests this, but I could not find concrete solution. Did someone came across this kind of situation, please give your suggestion. Thanks for reading this post and any help greatly appreciated.
Additional details for Production: This consumer will receive ~500 message per sec. Using Spring Boot version 1.5.8.RELEASE, ActiveMQ 5.5 is my JMS
There is an package called org.apache.activemq.jms.pool in activemq which provides PooledConsumer. Below is the code for that. Please check and see if it works for you. I know its not the spring way but you can easily manage to customise your poll method.
PooledConnectionFactory pooledConFactory = null;
PooledConnection pooledConnection = null;
PooledSession pooledSession = null;
PooledMessageConsumer pooledConsumer = null;
Message message = null;
try
{
// Get the connection object from PooledConnectionFactory
pooledConFactory = ( PooledConnectionFactory ) this.jmsTemplateMap.getConnectionFactory();
pooledConnection = ( PooledConnection ) pooledConFactory.createConnection();
pooledConnection.start();
// Create the PooledSession from pooledConnection object
pooledSession = ( PooledSession ) pooledConnection.createSession( false, 1 );
// Create the PooledMessageConsumer from session with given ack mode and destination
pooledConsumer = ( PooledMessageConsumer ) pooledSession.
createConsumer( this.jmsTemplateMap.getDefaultDestination(), <messageFilter if any>);
while ( true )
{
message = pooledConsumer.receiveNoWait();
if ( message != null)
break;
}
}
catch ( JMSException ex )
{
LOGGER.error("JMS Exception occured, closing the session", ex );
}
return message;
I am using phoenix with transactions, as from phoenix.apache.org/transactions.html, I need to set phoenix.transactions.enabled=true from my client-side.
But how to set that in a java jdbc client?
I got it.
Properties info = new Properties();
info.setProperty("phoenix.transactions.enabled", Boolean.TRUE.toString());
con = DriverManager.getConnection(url, info);
I have a non durable Topic client which is supposed to receive messages asynchronously using a listener.
When message is published on Topic, i can see on admin console that message is published and consumed but my client never receives it.
Client is able to establish connection properly as i can track it on console.
Any suggestions?
EDIT:
Did some more analysis and found that issue is with API used for connection.
I was able to listen to messages when i use following code:
TopicConnection conn;
TopicSession session = conn.createTopicSession(false, TopicSession.AUTO_ACKNOWLEDGE);
Topic topic = session.createTopic(monacoSubscriberEmsTopic);
conn.start();
tsubs = session.createSubscriber(topic);
tsubs.setMessageListener(listener);
But when i use following code then it doesn't work:
DefaultMessageListenerContainer listenerContainer = createMessageListenerContainer();
private DefaultMessageListenerContainer createMessageListenerContainer() {
DefaultMessageListenerContainer listenerContainer = new DefaultMessageListenerContainer();
listenerContainer.setClientId(clientID);
listenerContainer.setDestinationName(destination);
listenerContainer.setConnectionFactory(connectionFactory);
listenerContainer.setConcurrentConsumers(minConsumerCount);
listenerContainer.setMaxConcurrentConsumers(maxConsumerCount);
listenerContainer.setPubSubDomain(true);
listenerContainer.setSessionAcknowledgeModeName(sessionAcknowledgeMode);
if (messageSelector != null)
listenerContainer.setMessageSelector(messageSelector);
listenerContainer.setSessionTransacted(true);
return listenerContainer;
}
listenerContainer.initialize();
listenerContainer.start();
What is wrong with second approach?