Unable to push message into ActiveMQ - java

I'm successfully pushing message into ActiveMQ from local Eclipse setup. However, the same code does not push message when I try to execute from server as a cron job. It does not even throw an exception during code execution.
Java environment - 1.8
Supporting jars used:
slf4j-api-1.8.0-beta2.jar
javax.annotation-api-1.2.jar
javax.jms-api-2.0.1.jar
management-api-1.1-rev-1.jar
activemq-core-5.7.0.jar
Code:
try {
map = getMessageDetails(session,"MessageQueueEmail");
userName = map.get("userName");
password = map.get("password");
hostName = map.get("mqHostName");
queue = map.get("queueName");
// Create a ConnectionFactory
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(userName, password, hostName);
// Create a Connection
connection = factory.createConnection();
// start the Connection
connection.start();
System.out.println("MQ started connection");
// Create a Session
sessionMQ = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// Create the destination Queue
Destination destination = sessionMQ.createQueue(queue);
// Create a MessageProducer from the Session to the Queue
messageProducer = sessionMQ.createProducer(destination);
messageProducer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
// Create a message
Message message = sessionMQ.createTextMessage(textMsg);
System.out.println("MQ Message sent successfully");
// Tell the producer to send the message
messageProducer.send(message);
} catch(Exception e) {
e.printStackTrace();
System.out.println("\n::::::::::::Error occurred sendEmailMessageToIntranet::::::::::::: " + e.getMessage());
}

Thanks everyone for response. The issue is resolved after importing correct certificate file to the server. Wondering, why MQ attempts failure notification had not logged

Your code looks ok except you might have expiration going. Try with PERSISTENT and most likely is the issues that you are not redirecting stderr in your cronjob ? Make sure you do something like this:
*/1 * * * * /something/send.sh &>> /something/out.log
And then check in the morning.

Related

ActiveMQ browser needs long time for last .hasMoreElements()

I try to implement a queue browser for ActiveMQ.
The code shown below should display the text messages in the queue named 'Q1'. There are two messages in there. In general it works but the last e.hasMoreElements() call needs up to 20 seconds. I wanted to update the list every 500 millis. Why is that so slow?When i press 'update' in the browser view for http://localhost:8161/admin/browse.jsp?JMSDestination=Q1 e.hasMoreElements() returns immediately. What's going on here? How to achieve a 'realtime' view?
//init:
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616");
Connection connection = connectionFactory.createConnection();
connection.start();
Session session = connection.createSession(true, Session.CLIENT_ACKNOWLEDGE);
Queue queue = session.createQueue("Q1");
boolean run = true;
while (run) {
LOG.info("--------------------------------------------------------------------------------");
QueueBrowser browser = session.createBrowser(queue);
Enumeration e = browser.getEnumeration();
while (e.hasMoreElements()) { //<- very slow before returning false after last message. why?
Object o = e.nextElement();
if (o instanceof ActiveMQTextMessage) {
LOG.info(((ActiveMQTextMessage) o).getText());
} else {
LOG.info(o.toString());
}
}
Thread.sleep(500);
browser.close();
}
session.close();
connection.close();
After my previous comment, I've discovered that calling setTransactedIndividualAck(true) on the connection factory solves the problem
ActiveMQConnectionFactory cf2 = new ActiveMQConnectionFactory(...);
cf2.setTransactedIndividualAck(true);
I'm not sure that this is the right thing to do for the problem but at least it works now. See the message on the ActiveMQ user forum here:
http://activemq.2283324.n4.nabble.com/JMS-browser-getEnumeration-hasMoreElements-takes-15s-on-last-element-td4709969.html
I had the same issue. But changing the acknowledgment on the session eliminated the delay.
Try this:
Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
I found that calling Session.commit() within my hasMoreElements() loop stopped the hanging using activemq-broker version 5.14.5:
while(enumeration.hasMoreElements()) {
final Message message = (Message)enumeration.nextElement();
final TextMessage textMessage = (TextMessage)message;
session.commit();
}
I did more research to see if this was a bug with ActiveMQ or not and found that activemq-broker version 5.15.1 did not hang, even without calling commit() after each iteration. All prior versions of the broker hanged on the final call to hasMoreElements(). It doesn't seem like the contributors deliberately fixed this particular issue, since the bug report on JIRA that the change referenced was for something different. The change that fixed this issue changed part of the iterate() method of the org.apache.activemq.broker.region.Queue class from:
// are we done browsing? no new messages paged
if (!added || browser.atMax()) {
browser.decrementQueueRef();
browserDispatches.remove(browserDispatch);
}
to
// are we done browsing? no new messages paged
if (!added || browser.atMax()) {
browser.decrementQueueRef();
browserDispatches.remove(browserDispatch);
} else {
wakeup();
}
To confirm this was the change that fixed the issue, I went to the previous version, 5.15.0 and forced wakeup() to be called using a debugger and the call to hasMoreElements() did not hang.
After some research and try i switched to the more up-to-date JMX technology. There are no performance issues while walking through the queues.
Some code:
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi");
JMXConnector connector = JMXConnectorFactory.connect(url, null);
connector.connect();
connection = connector.getMBeanServerConnection();
ObjectName name = new ObjectName(getObjectNameByBrokerName(brokerName));
brokerMBean = (BrokerViewMBean) MBeanServerInvocationHandler.newProxyInstance(connection, name, BrokerViewMBean.class, true);
ObjectName[] objNames = brokerMBean.getQueues();
for (ObjectName objName : objNames) {
QueueViewMBean queueMBean = (QueueViewMBean) MBeanServerInvocationHandler.newProxyInstance(connection, objName, QueueViewMBean.class, true);
System.out.println(queueMBean.getName());
}
You have to activate jmx in the configuration. It's de-activated by default.

getting ConnectTransportException while fetching TransportClient instance in elasticsearch

I'm using TransportClient to create elasticsearch client instance with below code.
public static Client getInstance() {
String ipAddress = MessageTranslator.getMessage("es.cluster.ip");
int transportClientPort = Integer.parseInt(MessageTranslator
.getMessage("es.transportclient.port"));
logger.debug("got the client ip as :" + ipAddress + " and port :"
+ transportClientPort);
if (instance == null) {
logger.debug("the client instance is null, creating a new instance");
ImmutableSettings.Builder settings = ImmutableSettings
.settingsBuilder();
settings.put("node.client", true);
settings.put("node.data", false);
settings.put("node.name", "node-client");
settings.put("cluster.name", "elasticsearch");
settings.build();
instance = new TransportClient(settings)
.addTransportAddress(new InetSocketTransportAddress(
ipAddress, transportClientPort));
logger.debug("returning the new created client instance...");
return instance;
}
logger.debug("returning the existing transport client object connection.");
return instance;
}
The issue is some times the code is working and indexing data, but some times I'm getting the below issue.
14-08-2014 12:49:07,846 DEBUG
[elasticsearch[node-client][transport_client_worker][T#8]{New I/O
worker #8}] org.elasticsearch.common.logging.log4j.Log4jESLogger 104 -
[node-client] disconnected from [[Nuke - Frank
Simpson][P_OU-PZbTXyimWCOvkC7ow][aricloudvmserver3.aricent.com][inet[/10.203.238.139:9300]]],
channel closed event 14-08-2014 12:49:11,134 DEBUG
[elasticsearch[node-client][generic][T#1]]
org.elasticsearch.common.logging.log4j.Log4jESLogger 109 -
[node-client] failed to connect to node
[[#transport#-1][BGHWV2099][inet[/10.203.238.139:9300]]], removed from
nodes list org.elasticsearch.transport.ConnectTransportException:
[][inet[/10.203.238.139:9300]] connect_timeout[30s] at
org.elasticsearch.transport.netty.NettyTransport.connectToChannelsLight(NettyTransport.java:683)
at
org.elasticsearch.transport.netty.NettyTransport.connectToNode(NettyTransport.java:643)
at
org.elasticsearch.transport.netty.NettyTransport.connectToNodeLight(NettyTransport.java:610)
Please help me to find the issue.
Thanks
Your code looks correct to me. If this is an intermittent issue, it can be attributed to:
Lost connectivity
Also as suggested in the previous post, remove the node related settings and try setting below mentioned properties
settingsBuilder.put("cluster.name", searchClusterName);
settingsBuilder.put("client.transport.sniff", true);
settingsBuilder.put("http.enabled", "false");
Try this out and share your findings

Publishing message on JMS queue?

i am new to JMS and going thru the example of Active MQ Hello world. Say i have a scenario whenever i make entry
under employee table in DB, i have to put the message in queue.here is the producer code snippet from hello world example
public static class HelloWorldProducer {
public void createMessageOnQueue() {
try {
// Create a ConnectionFactory
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("vm://localhost");
// Create a Connection
Connection connection = connectionFactory.createConnection();
connection.start();
// Create a Session
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// Create the destination (Topic or Queue)
Destination destination = session.createQueue("TEST.FOO");
// Create a MessageProducer from the Session to the Topic or Queue
MessageProducer producer = session.createProducer(destination);
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
// Create a messages
String text = "Hello world! From: " + Thread.currentThread().getName() + " : " + this.hashCode();
TextMessage message = session.createTextMessage(text);
// Tell the producer to send the message
System.out.println("Sent message: "+ message.hashCode() + " : " + Thread.currentThread().getName());
producer.send(message);
// Clean up
session.close();
connection.close();
}
catch (Exception e) {
System.out.println("Caught: " + e);
e.printStackTrace();
}
}
}
Now my question is if i close the connection and session, will it close the queue also? If yes,what will happen if message has not been consumed yet?
Second question is if i need to publish the message on same queue(i.e "TEST.FOO") second time , do i need to call createMessageOnQueue method second time. If yes, will it not create new queue with session.createQueue("TEST.FOO")?
Now my question is if i close the connection and session, will it
close the queue also? If yes,what will happen if message has not been
consumed yet?
message will still be on queue. No such thing as 'closing a queue'.
Second question is if i need to publish the message on same queue(i.e
"TEST.FOO") second time , do i need to call createMessageOnQueue
method second time. If yes, will it not create new queue with
session.createQueue("TEST.FOO")?
session.createQueue("TEST.FOO") does not necessarily create queue, it just get a reference to existing queue.
javadoc of session#createQueue()
Note that this method simply creates an object that encapsulates the
name of a topic. It does not create the physical topic in the JMS
provider. JMS does not provide a method to create the physical topic,
since this would be specific to a given JMS provider. Creating a
physical topic is provider-specific and is typically an administrative
task performed by an administrator, though some providers may create
them automatically when needed.
The queue is created once and only you can delete it manually.
Once the message is sent to a queue, it will wait on the queue until it's consumed (unlike topics).
You don't need to re-create the message if you want to send it twice. But then again, why would you send it two times?
I feel that your problem might be solved using JMS transactions.

java websphere MQ

My aim is to put n number of messages in a for loop to a WebSphere MQ queue using WebSphere MQ java programming.
My java program will run as a standalone program.
If any exception in between , I need to rollback all the messages.
If no exception then I should commit all the messages .
The outside world should not see my messages in the queue until I complete fully.
How do I achieve this?
Updated with sample code as per reply from T.Rob:
Please check if sample code is fine ?
Does setting MQGMO_SYNCPOINT is only related to my program's invocation ?
(because similar programs running parallely will also be putting messages on the same queue and those messages should not gett affected by my program's SYNCPOINT.)
public void sendMsg() {
MQQueue queue = null;
MQQueueManager queueManager = null;
MQMessage mqMessage = null;
MQPutMessageOptions pmo = null;
System.out.println("Entering..");
try {
MQEnvironment.hostname = "x.x.x.x";
MQEnvironment.channel = "xxx.SVRCONN";
MQEnvironment.port = 9999;
queueManager = new MQQueueManager("XXXQMANAGER");
int openOptions = MQConstants.MQOO_OUTPUT;
queue = queueManager.accessQueue("XXX_QUEUENAME", openOptions, null, null, null);
pmo = new MQPutMessageOptions();
pmo.options = CMQC.MQGMO_SYNCPOINT;
String input = "testing";
System.out.println("sending messages....");
for (int i = 0; i < 10; i++) {
input = input + ": " + i;
mqMessage = new MQMessage();
mqMessage.writeString(input);
System.out.println("Putting message: " + i);
queue.put(mqMessage, pmo);
}
queueManager.commit();
System.out.println("Exiting..");
} catch (Exception e) {
e.printStackTrace();
try {
System.out.println("rolling back messages");
if (queueManager != null)
queueManager.backout();
} catch (MQException e1) {
e1.printStackTrace();
}
} finally {
try {
if (queue != null)
queue.close();
if (queueManager != null)
queueManager.close();
} catch (MQException e) {
e.printStackTrace();
}
}
}
WMQ supports both local and global (XA) units of work. The local units of work are available simply by specifying the option. Global XA transactions require a transaction manager, as mentioned by keithkreissl in another answer.
For what you described, a POJO doing messaging under syncpoint, specify MQC.MQGMO_SYNCPOINT in your MQGetMessageOptions. When you are ready to commit, issue the MQQManager.commit() or MQQManager.backout() call.
Note that the response and doc provided by ggrandes refers to the JMS and not Java classes. The Java classes use Java equivalents of the WMQ procedural API, can support many threads (doc) and even provide connection pooling (doc). Please refer to the Java documentation rather than the JMS documentation for the correct behavior. Also, I've linked to the WMQ V7.5 documentation which goes with the latest WMQ Java V7.5 client. The later clients have a lot more local functionality (tracing, flexible install path, MQClient.ini, etc.) and work with back-level QMgrs. It is highly recommended to be using the latest client and the download is free.
you only need to create a session with transaction enabled.
Session session;
// ...
boolean transacted = true;
session = connection.createSession(transacted, Session.AUTO_ACKNOWLEDGE);
try {
// ...do things...
session.commit();
} catch (Exception e) {
session.rollback();
}
// ...
WARN-NOTE: Sessions are not thread-safe ;-)
Doc Websphere MQ/JMS
If you have access to a transaction manager and more importantly an XATransaction wired up to your MQ access, you can start a transaction at the beginning of your message processing put all the messages on the queue then commit the transaction. Using the XATransactions it will not put any messages until the transaction commits. If you don't have access to that, you can do a little more plumbing by placing your messages in a local data object, wrap your code in a try/catch if no exceptions iterate through the local data object sending the messages. The issue with the later approach is that it will commit all your other processing but if a problem occurs in the sending of messages your other processing will not be rolled back.

Remove a JMS message from MQ Queue using JMSMessageID

Is there a way to remove a JMS message from an IBM MQ Queue using JMSMessageId ina Java application(not using tools)? Also are such operations vendor-specific?
Looked through the API for receive operations which are used to remove messages, but for removing specific messages, do we need to filter using MessageSelector and remove appropriately, or is there a more simple way? [checking for any available method which can be directly used]
Can you please provide tutorials/examples [can be links too] to show the API usage for such operations?
When you use JMSMessageID as the only message property in a selector, WMQ optimizes the lookup to be the same as a native WMQ API get by MQMD.MessageID which is an indexed field in the queue. Please see the JMS Message Selection topic for more details.
QueueReceiver rcvr = sess.createReceiver(inputQ, "JMSCorrelationID = '"+msgId+"'")
You can also do the same thing using native WMQ API calls using Java native code. You would do a normal GET operation but specify the message ID in the MQMD structure.
myMsg.messageId = someMsgID;
MQGetMessageOptions gmo = new MQGetMessageOptions();
myQueue.get(myMsg, gmo);
How to delete specific message form queue by using messageid?
I also have like your problem, I provide the resuable function. You just need to pass MessageId and Queue name. It is ok for me.
private void deleteMessage(String messageId, String queueName) {
try {
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi");
JMXConnector jmxc = JMXConnectorFactory.connect(url);
MBeanServerConnection conn = jmxc.getMBeanServerConnection();
ObjectName name = new ObjectName("org.apache.activemq:type=Broker,brokerName=localhost");
BrokerViewMBean proxy = (BrokerViewMBean)MBeanServerInvocationHandler.newProxyInstance(conn, name, BrokerViewMBean.class, true);
for (ObjectName queue : proxy.getQueues()) {
QueueViewMBean queueBean = (QueueViewMBean) MBeanServerInvocationHandler.newProxyInstance(conn, queue, QueueViewMBean.class, true);
if(queueBean.getName().equals(queueName)) {
System.out.println("Deleted : " + messageId);
queueBean.removeMessage(messageId);
return;
}
}
} catch(Exception e) {
e.printStackTrace();
}
}
I use activemq-all-5.8.0.jar.

Categories

Resources