I am running Weblogic 10.3 on Linux and I have setup a bridge to Webspere MQ. I am sending a TextMesasge from Weblogic and it is being transfered to MQ. But when I am reading the message on MQ side like
// Receiver reader - my class
reader.qMgr = new MQQueueManager(qManager);
int openOptions = MQOO_INPUT_AS_Q_DEF | MQOO_OUTPUT ;
MQQueue localQueue = reader.qMgr.accessQueue(queueName, openOptions);
MQMessage msg = new MQMessage();
MQGetMessageOptions gmo = new MQGetMessageOptions();
localQueue.get(msg, gmo);
int n = msg.getDataLength();
System.out.println("The message is " + n + " bytes long");
String msgText = msg.readStringOfByteLength(n);
System.out.println("The message is: " + msgText);
I am getting:
The message is 154 bytes long
The message is: RFH ��MQSTR � jms_text Hqueue:///Q113575850399442 ABCDE
"ABCDE" is my message.
Do I have somehow to instruct Websphere MQ to perform JMS->MQ conversion so the message will be read as simple 'ABCDE'?
Thanks
The program sending the messages should set the TARGCLIENT parm as described here.
Please bear in mind that all WMQ V6.x is out of support. If you were to use one of the supported versions (all the v7.x) you would be able to set the queue's PROPCTL attribute to cause the QMgr to strip the JMS headers without little or no code changes.
You can get the new version of WMQ through Passport Advantage if your company has a support agreement in place. The new client is available at no charge as SupportPac MQC75. You can mix client and QMgr versions and the new clients have a number of bug fixes and new features (many of which you can use even while connecting to an older QMgr). The newer client and QMgr will also have security patches not present on the V6 code. Please try to get to a supported version at least of the client since its free but preferably of the QMgr as well.
If you use the supported JMS API on the WebSphere MQ side, you don't have to perform any conversion to obtain the content of the message.
You can just invoke the javax.jms.TextMessage.getText() method that will return the content of the message (ABCDE).
Related
I'm very new to IBM MQ and feel like I'm missing something fairly easy.
I received the following files and I'm attempting to connect to an externally hosted MQ:
.crl
.kdb
.rdb
.sth
.tab
I've tried several different approaches, but the "furthest" I think I've gotten is:
MQRC_CONNECTION_BROKEN Reason: 2009 when I attempt to create a new Queue Manager connection.
Below is my most recent block of code, trying to get this to work:
using IBM.WMQ;
...
Hashtable connectionProperties = new Hashtable();
connectionProperties.Add(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_MANAGED);
connectionProperties.Add(MQC.HOST_NAME_PROPERTY, SOME_ADDRESS);
connectionProperties.Add(MQC.CHANNEL_PROPERTY, SOME_CHANNEL);
connectionProperties.Add(MQC.PORT_PROPERTY, SOME_PORT);
connectionProperties.Add(MQC.SSL_CERT_STORE_PROPERTY, PATH TO KDB FILE without .kdb);
connectionProperties.Add(MQC.SSL_CIPHER_SUITE_PROPERTY, SOME_CIPHER);
MQQueueManager qmgr = new MQQueueManager(SOME_VALUE, connectionProperties);
Prior to this I was attempting to set the MQ_CHANNEL_LIB and MQ_CHANNEL_TAB environment variables and call MQQueueManager qmgre = MQQueueManager() but that resulted in a 2277 error code.
I'm currently using the IBMMQDotnetClient/9.3.0 nuget package. Any help would be greatly appreciated.
The *.kdb file is a ssl keystore file containing certificates required to connect to queue manager. The *.kdb file can only be used with Transport type (TRANSPORT_PROPERTY property) MQC.TRANSPORT_MQSERIES_CLIENT. In this mode, MQ .NET client uses MQI C client underneath to communicate with queue manager.
The *.tab file is a client channel definition table (CCDT) file containing connection information like qm name, channel name, host name and few others required to connect to your queue manager.
Since you are using IBMMQDotnetClient/9.3.0 nuget package, TRANSPORT_MQSERIES_CLIENT transport type can't be used as the package doesn't contain MQI C client. With this nuget package you can only use TRANSPORT_MQSERIES_MANAGED. Ask your admins/management if they can provide you Redistributable MQ client. This package contains MQI C, .NET and other MQ clients libraries. You can choose to install the client libraries you want to use.
As Shashi mentioned if you need to use the Unmanaged mode,you need MQ C Client libraries as well.
You need to reference "amqmdnet.dll" which comes with IBM MQ Redistributable package to your .NET project. You can download IBM MQ Redistributable package from IBM Fix central.
To use CCDT, you need to set MQCHLLIB & MQCHLTAB environment variables.On how to create a CCDT file you can refer KC page:Configuring a binary format CCDT
After creating the CCDT File, i had used only the following code in my project to establish a successful connection
Environment.SetEnvironmentVariable("MQCHLLIB", #"C:\ProgramData\IBM\MQ\qmgrs\QMSSL\#ipcc");
Environment.SetEnvironmentVariable("MQCHLTAB", "AMQCLCHL.TAB");
Hashtable properties = new Hashtable();
properties.Add(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_CLIENT);
Environment.SetEnvironmentVariable("MQSSLKEYR", #"C:\temp\Certs\ForCclient\client");
try
{
queueManager = new MQQueueManager(queueManagerName, properties);
}
catch (MQException e)
{
Console.WriteLine("ERROR - Connect failed with unexpected MQRC {0}", e.ReasonCode);
throw e;
}
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 IBM MQ version 8.0.0.0 in a .NET application using C#. Now I'm trying to read messages from a queue. I'm using the below code to read the messages from the queue.
.....
Hashtable props = new Hashtable();
props.Add(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_MANAGED);
props.Add(MQC.CONNECT_OPTIONS_PROPERTY, MQC.MQCNO_RECONNECT_Q_MGR); // Reconnect option
openOptions = MQC.MQOO_INPUT_SHARED | MQC.MQOO_FAIL_IF_QUIESCING;
queueManager = new MQQueueManager(queueManagerName, props);
this.queue = queueManager.AccessQueue(queueName, openOptions);
....
MQGetMessageOptions gmo = new MQGetMessageOptions();
gmo.Options = MQC.MQGMO_FAIL_IF_QUIESCING
| MQC.MQGMO_WAIT | MQC.MQGMO_SYNCPOINT;
gmo.MatchOptions = MQC.MQMO_NONE;
gmo.WaitInterval = 5000; // I'm specifying this
var message = new MQMessage();
this.queue.Get(message, gmo); // Waits here forever in case connection is lost to IBM MQ.
.........
.........
Now in case, there is a loss of connectivity to the MQ server AFTER connection is established but BEFORE a queue.Get() call is issued, I'm seeing that the .GET() call waits forever and doesn't stop despite specifying the WAIT_INTERVAL.
Also, I observed that as soon as connectivity is restored, the .Get() call returns immediately with the message that it has read from the queue.
Am I doing something wrong?
Edit:
Added the queueManager Creation code with the properties, one of which instructs the client to reconnect if possible to the same queue manager.
From this observation:
Also, I observed that as soon as connectivity is restored, the .Get() call returns immediately with the message that it has read from the queue.
The connection to queue manager was lost when the GET call was in progress. So the MQ .NET client is attempting to reconnect to queue manager. While reconnection attempts are going on, the application will find the method call as 'hanging'. This is normal. So the question is have you enabled automatic reconnection in your application? Show complete code.
Update
It's a expected behavior because the Get call is internally attempting to reconnect to queue manager. You can:
1) Reduce the reconnection timeout in mqclient.ini file. An example below.
Channels:
MQReconnectTimeout = 100
2) Check why queue manager is down and bring it up.
I've been tasked with evaluating activemq-artemis for JMS clients. I have RabbmitMQ experience, but none with activemq-artemis/JMS.
I installed artemis to my local machine, created a new broker per the instructions, and set it up as a windows service. The windows service starts and stops just fine. I've made no changes to the broker.xml file.
For my first test I'm trying to perform a JMS Queue produce/consume from a stand alone java program. I'm using the code from the Artemis User Manual in the Using JMS section, (without using JNDI):
TransportConfiguration transportConfiguration = new TransportConfiguration(NettyConnectorFactory.class.getName());
ConnectionFactory cf = ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF,transportConfiguration);
Queue orderQueue = ActiveMQJMSClient.createQueue("OrderQueue");
Connection connection = cf.createConnection();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer producer = session.createProducer(orderQueue);
MessageConsumer consumer = session.createConsumer(orderQueue);
connection.start();
TextMessage message = session.createTextMessage("This is an order");
producer.send(message);
TextMessage receivedMessage = (TextMessage)consumer.receive();
System.out.println("Got order: " + receivedMessage.getText());
When I run this code, I get the following error:
WARN: AMQ212054: Destination address=jms.queue.OrderQueue is blocked. If the system is configured to block make sure you consume messages on this configuration.
My research hasn't been conclusive on if this is a server side setting, or having the producer send without blocking. I haven't been able to find a producer send method that has a blocking boolean, only persistence. Any ideas on where to focus? Thanks.
Edit: new address-setting element added to broker.xml dedicated to this Queue:
<address-setting match="jms.queue.OrderQueue">
<max-size-bytes>104857600</max-size-bytes>
<page-size-bytes>10485760</page-size-bytes>
<address-full-policy>PAGE</address-full-policy>
</address-setting>
I found this on further research in the user manual:
max-disk-usage The max percentage of data we should use from disks.
The System will block while the disk is full. Default=100
and in the log after service startup with no messages published yet:
WARN [org.apache.activemq.artemis.core.server] AMQ222210: Storage usage is beyond max-disk-usage. System will start blocking producers.
so I think no matter my address settings, it would start to block. Looking at the max-disk-usage setting in broker.xml, it was set to 90. Documentation default says 100, I set to that, no startup log warnings, and my test pub/sub code now works.
This warn message comes when address policy set to BLOCK and memory reached. Check address policy set in broker.xml. If it is set to BLOCK, change it to PAGE. Or consume pending messages from OrderQueue.
By default max-disk-usage value is set as 90(%) and if the remaining free space size is less than 10%, then this warn message will be shown and no messages will be received until you adjust the parameter or free up space beyond 10%.
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.