I created the ActiveMQ Connection with ActiveMQConnectionFactory,
connectionFactory = new ActiveMQConnectionFactory("nio://0.0.0.0:" + activeMqPort);
connection = connectionFactory.createConnection();
connection.start();
Later some point of time I am using the connection to get the session:
Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
While creating session from Connection it will fail with a NullPointerException (connection is null),
PS: Connection was working before, suddenly its null.
Can anyone explain it to me when this will happen and how to fix this ?
Your URI is incorrect for a client-side connection. nio:// is only relevant on the server-side, and specifying "0.0.0.0" is used by the server-side to instruct the server to listen on all ip interfaces.
Try this instead to connect to an ActiveMQ server running on the same computer as this client code:
connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:" + activeMqPort);
connection = connectionFactory.createConnection();
connection.start();
Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
Bonus recommendations:
Externalize the entire client url, not just the port. This will allow you to specify multiple servers for failover, reconnect timeout parameters and other client connectivity settings that would otherwise require a code change.
Do not use CLIENT_ACKNOWLEDGE unless you really know what it does. Its is a source of a lot of pain and suffering if you don't clearly have a handle on how it works. If you want per-message Acknowledgement, use ActiveMQSession.INDIVIDUAL_ACKNOWLEDGE. For non-transacted, use Session.AUTO_ACKNOWLEDGE.
Related
I am trying to send a message to the Qpid broker over the AMQP 1.0 protocol. The queue is named queue2 and it is already created under default virtualhost. However, producer.send(message) is getting stuck forever. The same code is working for connecting to Azure Service Bus. I'm using qpid-jms-client 0.58. Producer code is:
Hashtable<String, String> hashtable = new Hashtable<>();
hashtable.put("connectionfactory.myFactoryLookup", protocol + "://" + url + "?amqp.idleTimeout=120000&amqp.traceFrames=true");
hashtable.put("queue.myQueueLookup", queueName);
hashtable.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.qpid.jms.jndi.JmsInitialContextFactory");
Context context = new InitialContext(hashtable);
ConnectionFactory factory = (ConnectionFactory) context.lookup("myFactoryLookup");
queue = (Destination) context.lookup("myQueueLookup");
Connection connection = factory.createConnection(username, password);
connection.setExceptionListener(new AmqpConnectionFactory.MyExceptionListener());
connection.start();
Session session=connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// session.createQueue("queue3");
Queue queue = new JmsQueue("queue2");
MessageProducer messageProducer = session.createProducer(queue);
TextMessage textMessage = session.createTextMessage("new message");
messageProducer.send(textMessage)
I can see Connection and session is successfully established on Qpid broker dashboard:
Thread dump for application at time of producing
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x000000078327c550> (a org.apache.qpid.jms.provider.ProgressiveProviderFuture)
at java.lang.Object.wait(Object.java:502)
at org.apache.qpid.jms.provider.ProgressiveProviderFuture.sync(ProgressiveProviderFuture.java:154)
- locked <0x000000078327c550> (a org.apache.qpid.jms.provider.ProgressiveProviderFuture)
at org.apache.qpid.jms.JmsConnection.send(JmsConnection.java:773)
at org.apache.qpid.jms.JmsNoTxTransactionContext.send(JmsNoTxTransactionContext.java:37)
at org.apache.qpid.jms.JmsSession.send(JmsSession.java:964)
at org.apache.qpid.jms.JmsSession.send(JmsSession.java:843)
at org.apache.qpid.jms.JmsMessageProducer.sendMessage(JmsMessageProducer.java:252)
at org.apache.qpid.jms.JmsMessageProducer.send(JmsMessageProducer.java:182)
I have tried to run this example which gave the same result.
In general if the client is not sending it is because the remote has not granted it credit to do so. You can debug the client state using the protocol trace feature (just set PN_TRACE_FRM=true and run the client).
Likely you have misconfigured the Broker-J somehow and the destination you've created doesn't allow any messages to be sent or you've sent enough that you've tripped the write limit. You should consult the configuration guide and review what you've already setup.
Okay Finally got the issue. Filesystem is over 90 per cent full, enforcing flow control. So deleted files from my machine and it started working.
https://qpid.apache.org/releases/qpid-broker-j-7.0.7/book/Java-Broker-Runtime-Disk-Space-Management.html
I'm using Apache Artemis ActiveMQ 2.6.3 as an MQTT broker embedded in a Spring 5 application:
#Bean(initMethod = "start", destroyMethod = "stop")
fun embeddedActiveMQ(securityManager: ActiveMQJAASSecurityManager) =
EmbeddedActiveMQ().apply {
setConfiguration(getEmbeddedActiveMQConfiguration())
setConfigResourcePath("activemq-broker.xml")
setSecurityManager(securityManager)
}
private fun getEmbeddedActiveMQConfiguration() =
ConfigurationImpl().apply {
addAcceptorConfiguration("netty", DefaultConnectionProperties.DEFAULT_BROKER_URL)
addAcceptorConfiguration("mqtt", "tcp://$host:$mqttPort?protocols=MQTT")
name = brokerName
bindingsDirectory = "$dataDir${File.separator}bindings"
journalDirectory = "$dataDir${File.separator}journal"
pagingDirectory = "$dataDir${File.separator}paging"
largeMessagesDirectory = "$dataDir${File.separator}largemessages"
isPersistenceEnabled = persistence
connectionTTLOverride = 60000
}
Although I'm setting the connection TTL to 60 seconds in the above Kotlin code as suggested in the documentation and the client disconnected and terminated an hour ago, the log shows the following entries:
2020-06-22 10:57:03,890 [Thread-29 (ActiveMQ-server-org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl$5#ade4717)] DEBUG o.a.a.a.core.server.impl.QueueImpl - Scanning for expires on client1.some-topic
2020-06-22 10:58:03,889 [Thread-35 (ActiveMQ-server-org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl$5#ade4717)] DEBUG o.a.a.a.core.server.impl.QueueImpl - Scanning for expires on client1.some-topic
Based on these log entries, I'm afraid that "dead" connection resources are never cleaned up by the server.
What should I do to actually remove the "dead" connections from the server to avoid leaking resources?
The broker will often create resources like addresses, queues, etc. to deal with clients. In the case of MQTT clients the broker will create queues which essentially represent the client's subscriptions.
In this particular case a queue named client1.some-topic has been created for an MQTT subscription and the broker is scanning that queue for expired messages. At this point it looks like the broker is working as designed.
When a client disconnects without unsubscribing what the broker does with the subscription depends on whether the client used a clean session or not.
If the client used a clean session then the broker will delete the subscription queue when the client disconnects (even in the event of a failure).
Otherwise the broker is obliged to hold on to the subscription queue and route messages to it. If the client never reconnects to unsubscribe then the subscription may fill up with lots of messages and trigger the broker's paging mode and eventually even limit message production altogether. In this case the client can either reconnect and unsubscribe or the subscription queue can be removed administratively.
I had a problem with connecting to the IBM MQ queue from Java. I tried to change the passwords for the service of the IBM MQ, create a connection without specifying a login and password, but nothing happens. I wrote the code:
Properties props = new Properties();
props.setProperty(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory");
props.setProperty(Context.PROVIDER_URL, "file:/D:/JNDI/");
try {
InitialContext initialContext = new InitialContext(props);
ConnectionFactory connectionFactory = (ConnectionFactory) initialContext.lookup(connectionFactoryName);
Destination destination = (Destination) initialContext.lookup(queueName);
initialContext.close();
Connection queueConnection = connectionFactory.createConnection("login", "password");// .createConnection();
which falls when I create a connection. I get an error:
JMSWMQ2013: Invalid credentials were passed to the queue manager QueueManager 'QM_LOCAL' in the 'Client' connection mode using the host 'localhost (1414)'.
Verify that the provided user name and password are correct in the queue administrator that you are connecting to.
can I turn off the authentication so that the method ".createConnection();" works? If not, where do I set the password? I Use the Windows.
Thanks.
p.s.: I get the completion code '2' ('MQCC_FAILED'), reason'2035' ('MQRC_NOT_AUTHORIZED').
I'm looking forward to implement a somewhat intelligent MQ comms module, which should be tolerant for the outages in the network connection. Basically it should try to reconnect each 5 seconds if connection was lost.
The problem is the following. I use the following code for reading:
queueMessage = new MQMessage();
queueMessage.Format = MQC.MQFMT_STRING;
queueGetMessageOptions = new MQGetMessageOptions();
queueGetMessageOptions.Options = MQC.MQGMO_SYNCPOINT + MQC.MQGMO_WAIT + MQC.MQGMO_FAIL_IF_QUIESCING;
queueGetMessageOptions.WaitInterval = 50;
producerQueue.Get(queueMessage, queueGetMessageOptions);
msg = queueMessage.ReadBytes(queueMessage.MessageLength);
(Of course I successfully connect to the queuemanager before etc.)
I got the following issue: when this routine runs, but at the time of .Get there's no connection, the code simply hangs and stays in the .Get.
I use a timer to see if there's a timeout (in theory even that shouldn't be necessary, is that right?) and at the timeout I try to reconnect. BUT when this timeout expires, I still see that the queuemanager reports that it's connected, while its clearly not (no physical connection is present anymore). This issue has popped up since I use SYNCPOINT, and I experience the same when I cut connection during writing, or in this case I try to force a Disconnect on the queuemanager. So please help, what settings shall I use to avoid getting stuck in Get and Put and rather have an MQException thrown or something controllable?
Thanks!
UPDATE: I used the following code to connect to the QueueManager.
Hashtable props = new Hashtable();
props.Add(MQC.HOST_NAME_PROPERTY, Host);
props.Add(MQC.PORT_PROPERTY, Port);
props.Add(MQC.CHANNEL_PROPERTY, ChannelInfo);
if(User!="") props.Add(MQC.USER_ID_PROPERTY, User);
if(Password!="") props.Add(MQC.PASSWORD_PROPERTY, Password);
props.Add(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_MANAGED);
queueManager = new MQQueueManager(QueueManagerName, props);
producerQueue = queueManager.AccessQueue(
ProducerQueueName,
MQC.MQOO_INPUT_AS_Q_DEF // open queue for input
+ MQC.MQOO_FAIL_IF_QUIESCING); // but not if MQM stopping
consumerQueue = queueManager.AccessQueue(
ConsumerQueueName,
MQC.MQOO_OUTPUT + MQC.MQOO_BROWSE + MQC.MQOO_INPUT_AS_Q_DEF // open queue for output
+ MQC.MQOO_FAIL_IF_QUIESCING); // but not if MQM stopping
Needless to say that normally the code works well. Read/Write, connect/disconnect works as it should, I only have to figure out the current issue.
Thanks!
What version of MQ are you using? For automatic reconnection to work the queue manager need to be at least at MQ v701 and MQ .NET client needs to be a MQ v7.1 level.
Assuming you are using MQ v7.1 .NET client, you need to specify reconnect option during connection create. You will need to enable reconnection by adding something like:
props.Add(MQC.CONNECT_OPTIONS_PROPERTY, MQC.MQCNO_RECONNECT);
Reconnection can be enabled/disabled from mqclient.ini file also.
But what is surprising is why the Get/Put are hanging when there is no network connection. Hope you are not connecting a queue manager running on the same machine as your application. There is no need to set any timer or something like that. You can issue MQ calls and if there is anything wrong with connection, an exception will be thrown.
Update:
I think you are referring to IsConnected property of MQQueueManager class. The documentation says the value of this property: "If true, a connection to the queue manager has been made, and is not known to be broken. Any calls to IsConnected do not actively attempt to reach the queue manager, so it is possible that physical connectivity can break, but IsConnected can still return true. The IsConnected state is only updated when activity, for example, putting a message, getting a message, is performed on the queue manager.
If false, a connection to the queue manager has not been made, or has been broken, or has been disconnected."
As you can see a True value does not mean the connection is still ON. My suggestion would be to call a method, Put/Get and handle any exception thrown.
Put/Get/Disconnect calls hanging appears to be a problem. My suggestion would be raise a PMR with IBM.
I am trying to publish a message to a remote JMS queue by a pretty standard mechanism:
TopicConnection tc = null;
TopicSession ts = null;
TopicPublisher tp = null;
Properties p = new Properties();
String providerUrl = "iiop://servername:9810";
String contextFactory = "com.ibm.websphere.naming.WsnInitialContextFactory".trim();
p.put(javax.naming.Context.PROVIDER_URL, providerUrl );
p.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, contextFactory );
InitialContext ct = new InitialContext(p);
{
Topic topic = (Topic)ct.lookup( "jms/customer_event" );
TopicConnectionFactory tcf = (TopicConnectionFactory)ct.lookup( "jms/TopicFactory2" );
tc = tcf.createTopicConnection();
....
..
..
}
Now, the Topic and TopicConnectionFactory lookups are fine but when it comes to tcf.createTopicConnection(), it throws:
javax.jms.JMSException: MQJMS2005: failed to create MQQueueManager for 'servername:QMGR1'
Inner exception(s):
com.ibm.mq.MQException: MQJE001: Completion Code 2, Reason 2059
java.net.ConnectException: Connection refused: connect
I opened up MQ explorer, and the topic is existing on the remote Queue manager. IS the TopicCoonectionFactory TopicFactory2 also supposed to reside on the queue manager? Because it does not.
What can be the cause of error?
When connecting, the details of host, port and channel must be correct. If the host or port are wrong, then the TCP socket is refused. If the channel name is wrong, then the queue manager will refuse the connection and close the socket. It is possible that you have all the details correct but that the listener on the queue manager is not running.
If the connection is getting as far as the queue manager then you will have an error in the [WMQ Install dir]/qmgrs/[QMgr name]/errors/AMQERR01.LOG file. If the connection gets to WMQ but cannot resolve the queue manager's name or specifies the wrong QMgr then the error will be in [WMQ Install dir]/errors/AMQERR01.LOG. If there is no entry in either of these then the connection isn't making it to WMQ and you need to check the listener or the network.
2059 connection refused is highly likely a network error or a typeo in the MQ server hostname and/or port. Double check your config in WebSphere and the network connection.
JavaDoc for ConnectException also states this http://docs.oracle.com/javase/6/docs/api/java/net/ConnectException.html
Signals that an error occurred while attempting to connect a socket to a remote address and port. Typically, the connection was refused remotely (e.g., no process is listening on the remote address/port).